7th Edition(V7) File System support. and NetBSD symbolic-link, socket, FIFO extension. see newfs_v7fs(8).
This commit is contained in:
parent
846092f009
commit
9255b46fb4
@ -1,4 +1,4 @@
|
||||
# $NetBSD: mi,v 1.939 2011/05/20 01:59:14 msaitoh Exp $
|
||||
# $NetBSD: mi,v 1.940 2011/06/27 11:52:22 uch Exp $
|
||||
#
|
||||
# Note: Don't delete entries from here - mark them as "obsolete" instead,
|
||||
# unless otherwise stated below.
|
||||
@ -239,6 +239,7 @@
|
||||
./sbin/fsck_ffs base-sysutil-root
|
||||
./sbin/fsck_lfs base-sysutil-root
|
||||
./sbin/fsck_msdos base-sysutil-root
|
||||
./sbin/fsck_v7fs base-sysutil-root
|
||||
./sbin/fsdb base-sysutil-root
|
||||
./sbin/fsirand base-sysutil-root
|
||||
./sbin/gpt base-sysutil-root
|
||||
@ -289,6 +290,7 @@
|
||||
./sbin/mount_ufs base-sysutil-root
|
||||
./sbin/mount_umap base-miscfs-root
|
||||
./sbin/mount_union base-miscfs-root
|
||||
./sbin/mount_v7fs base-sysutil-root
|
||||
./sbin/mountd base-obsolete obsolete
|
||||
./sbin/newbtconf base-sysutil-root
|
||||
./sbin/newfs base-sysutil-root
|
||||
@ -297,6 +299,7 @@
|
||||
./sbin/newfs_msdos base-sysutil-root
|
||||
./sbin/newfs_sysvbfs base-sysutil-root
|
||||
./sbin/newfs_udf base-sysutil-root
|
||||
./sbin/newfs_v7fs base-sysutil-root
|
||||
./sbin/newlfs base-obsolete obsolete
|
||||
./sbin/nfsd base-obsolete obsolete
|
||||
./sbin/nfsiod base-obsolete obsolete
|
||||
@ -796,6 +799,7 @@
|
||||
./usr/include/fs/sysvbfs base-c-usr
|
||||
./usr/include/fs/tmpfs base-c-usr
|
||||
./usr/include/fs/udf base-c-usr
|
||||
./usr/include/fs/v7fs base-c-usr
|
||||
./usr/include/g++ base-cxx-usr
|
||||
./usr/include/g++/backward base-cxx-usr
|
||||
./usr/include/g++/bits base-cxx-usr
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: mi,v 1.1632 2011/06/26 16:42:40 christos Exp $
|
||||
# $NetBSD: mi,v 1.1633 2011/06/27 11:52:22 uch Exp $
|
||||
#
|
||||
# Note: don't delete entries from here - mark them as "obsolete" instead.
|
||||
#
|
||||
@ -663,6 +663,8 @@
|
||||
./usr/include/fs/tmpfs/tmpfs_args.h comp-c-include
|
||||
./usr/include/fs/udf/ecma167-udf.h comp-c-include
|
||||
./usr/include/fs/udf/udf_mount.h comp-c-include
|
||||
./usr/include/fs/v7fs/v7fs.h comp-c-include
|
||||
./usr/include/fs/v7fs/v7fs_args.h comp-c-include
|
||||
./usr/include/fstab.h comp-c-include
|
||||
./usr/include/fts.h comp-c-include
|
||||
./usr/include/ftw.h comp-c-include
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: mi,v 1.1321 2011/06/22 20:29:38 jruoho Exp $
|
||||
# $NetBSD: mi,v 1.1322 2011/06/27 11:52:23 uch Exp $
|
||||
#
|
||||
# Note: don't delete entries from here - mark them as "obsolete" instead.
|
||||
#
|
||||
@ -2245,6 +2245,7 @@
|
||||
./usr/share/man/cat8/fsck_ffs.0 man-sysutil-catman .cat
|
||||
./usr/share/man/cat8/fsck_lfs.0 man-sysutil-catman .cat
|
||||
./usr/share/man/cat8/fsck_msdos.0 man-sysutil-catman .cat
|
||||
./usr/share/man/cat8/fsck_v7fs.0 man-sysutil-catman .cat
|
||||
./usr/share/man/cat8/fsdb.0 man-sysutil-catman .cat
|
||||
./usr/share/man/cat8/fsinfo.0 man-sysutil-catman .cat
|
||||
./usr/share/man/cat8/fsirand.0 man-sysutil-catman .cat
|
||||
@ -2471,6 +2472,7 @@
|
||||
./usr/share/man/cat8/mount_ufs.0 man-sysutil-catman .cat
|
||||
./usr/share/man/cat8/mount_umap.0 man-miscfs-catman .cat
|
||||
./usr/share/man/cat8/mount_union.0 man-miscfs-catman .cat
|
||||
./usr/share/man/cat8/mount_v7fs.0 man-sysutil-catman .cat
|
||||
./usr/share/man/cat8/mountd.0 man-nfsserver-catman .cat
|
||||
./usr/share/man/cat8/moused.0 man-sysutil-catman .cat
|
||||
./usr/share/man/cat8/mrinfo.0 man-netutil-catman .cat
|
||||
@ -2509,6 +2511,7 @@
|
||||
./usr/share/man/cat8/newfs_msdos.0 man-sysutil-catman .cat
|
||||
./usr/share/man/cat8/newfs_sysvbfs.0 man-sysutil-catman .cat
|
||||
./usr/share/man/cat8/newfs_udf.0 man-sysutil-catman .cat
|
||||
./usr/share/man/cat8/newfs_v7fs.0 man-sysutil-catman .cat
|
||||
./usr/share/man/cat8/newlfs.0 man-obsolete obsolete
|
||||
./usr/share/man/cat8/news68k/MAKEDEV.0 man-obsolete obsolete
|
||||
./usr/share/man/cat8/news68k/makedev.0 man-obsolete obsolete
|
||||
@ -4877,6 +4880,7 @@
|
||||
./usr/share/man/html8/fsck_ffs.html man-sysutil-htmlman html
|
||||
./usr/share/man/html8/fsck_lfs.html man-sysutil-htmlman html
|
||||
./usr/share/man/html8/fsck_msdos.html man-sysutil-htmlman html
|
||||
./usr/share/man/html8/fsck_v7fs.html man-sysutil-htmlman html
|
||||
./usr/share/man/html8/fsdb.html man-sysutil-htmlman html
|
||||
./usr/share/man/html8/fsinfo.html man-sysutil-htmlman html
|
||||
./usr/share/man/html8/fsirand.html man-sysutil-htmlman html
|
||||
@ -5057,6 +5061,7 @@
|
||||
./usr/share/man/html8/mount_ufs.html man-sysutil-htmlman html
|
||||
./usr/share/man/html8/mount_umap.html man-miscfs-htmlman html
|
||||
./usr/share/man/html8/mount_union.html man-miscfs-htmlman html
|
||||
./usr/share/man/html8/mount_v7fs.html man-sysutil-htmlman html
|
||||
./usr/share/man/html8/mountd.html man-nfsserver-htmlman html
|
||||
./usr/share/man/html8/moused.html man-sysutil-htmlman html
|
||||
./usr/share/man/html8/mrinfo.html man-netutil-htmlman html
|
||||
@ -5083,6 +5088,7 @@
|
||||
./usr/share/man/html8/newfs_msdos.html man-sysutil-htmlman html
|
||||
./usr/share/man/html8/newfs_sysvbfs.html man-sysutil-htmlman html
|
||||
./usr/share/man/html8/newfs_udf.html man-sysutil-htmlman html
|
||||
./usr/share/man/html8/newfs_v7fs.html man-sysutil-htmlman html
|
||||
./usr/share/man/html8/newsyslog.html man-sysutil-htmlman html
|
||||
./usr/share/man/html8/next68k/boot.html man-sys-htmlman html
|
||||
./usr/share/man/html8/nfsd.html man-nfsserver-htmlman html
|
||||
@ -7601,6 +7607,7 @@
|
||||
./usr/share/man/man8/fsck_ffs.8 man-sysutil-man .man
|
||||
./usr/share/man/man8/fsck_lfs.8 man-sysutil-man .man
|
||||
./usr/share/man/man8/fsck_msdos.8 man-sysutil-man .man
|
||||
./usr/share/man/man8/fsck_v7fs.8 man-sysutil-man .man
|
||||
./usr/share/man/man8/fsdb.8 man-sysutil-man .man
|
||||
./usr/share/man/man8/fsinfo.8 man-sysutil-man .man
|
||||
./usr/share/man/man8/fsirand.8 man-sysutil-man .man
|
||||
@ -7828,6 +7835,7 @@
|
||||
./usr/share/man/man8/mount_ufs.8 man-sysutil-man .man
|
||||
./usr/share/man/man8/mount_umap.8 man-miscfs-man .man
|
||||
./usr/share/man/man8/mount_union.8 man-miscfs-man .man
|
||||
./usr/share/man/man8/mount_v7fs.8 man-sysutil-man .man
|
||||
./usr/share/man/man8/mountd.8 man-nfsserver-man .man
|
||||
./usr/share/man/man8/moused.8 man-sysutil-man .man
|
||||
./usr/share/man/man8/mrinfo.8 man-netutil-man .man
|
||||
@ -7866,6 +7874,7 @@
|
||||
./usr/share/man/man8/newfs_msdos.8 man-sysutil-man .man
|
||||
./usr/share/man/man8/newfs_sysvbfs.8 man-sysutil-man .man
|
||||
./usr/share/man/man8/newfs_udf.8 man-sysutil-man .man
|
||||
./usr/share/man/man8/newfs_v7fs.8 man-sysutil-man .man
|
||||
./usr/share/man/man8/newlfs.8 man-obsolete obsolete
|
||||
./usr/share/man/man8/news68k/MAKEDEV.8 man-obsolete obsolete
|
||||
./usr/share/man/man8/news68k/makedev.8 man-obsolete obsolete
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: Makefile,v 1.119 2011/02/08 03:20:15 haad Exp $
|
||||
# $NetBSD: Makefile,v 1.120 2011/06/27 11:52:23 uch Exp $
|
||||
# @(#)Makefile 8.5 (Berkeley) 3/31/94
|
||||
|
||||
# Not ported: XNSrouted enpload scsiformat startslip
|
||||
@ -21,6 +21,7 @@ SUBDIR+= newfs_lfs fsck_lfs dump_lfs resize_lfs
|
||||
SUBDIR+= newfs_msdos fsck_msdos
|
||||
SUBDIR+= newfs_sysvbfs
|
||||
SUBDIR+= newfs_udf
|
||||
SUBDIR+= newfs_v7fs fsck_v7fs
|
||||
SUBDIR+= mount_ados
|
||||
SUBDIR+= mount_cd9660
|
||||
SUBDIR+= mount_efs
|
||||
@ -47,6 +48,7 @@ SUBDIR+= mount_sysvbfs
|
||||
SUBDIR+= mount_tmpfs
|
||||
SUBDIR+= mount_umap
|
||||
SUBDIR+= mount_union
|
||||
SUBDIR+= mount_v7fs
|
||||
|
||||
.if (${MKCRYPTO} != "no")
|
||||
SUBDIR+= cgdconfig
|
||||
|
20
sbin/fsck_v7fs/Makefile
Normal file
20
sbin/fsck_v7fs/Makefile
Normal file
@ -0,0 +1,20 @@
|
||||
# $NetBSD: Makefile,v 1.1 2011/06/27 11:52:58 uch Exp $
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
PROG= fsck_v7fs
|
||||
MAN= fsck_v7fs.8
|
||||
SRCS= fsck_v7fs.c main.c pathname.c inode.c datablock.c freeblock.c \
|
||||
v7fs_datablock.c v7fs_io.c v7fs_superblock.c v7fs_inode.c v7fs_file.c \
|
||||
v7fs_dirent.c v7fs_endian.c v7fs_io_user.c v7fs_inode_util.c \
|
||||
v7fs_file_util.c v7fs_superblock_util.c fsutil.c progress.c
|
||||
|
||||
FSCK= ${NETBSDSRCDIR}/sbin/fsck
|
||||
V7FS= ${NETBSDSRCDIR}/sys/fs/v7fs
|
||||
CPPFLAGS+= -I${FSCK} -I${V7FS} -DV7FS_EI -g
|
||||
.PATH: ${FSCK} ${V7FS}
|
||||
|
||||
LDADD+=-lutil
|
||||
DPADD+=${LIBUTIL}
|
||||
|
||||
.include <bsd.prog.mk>
|
403
sbin/fsck_v7fs/datablock.c
Normal file
403
sbin/fsck_v7fs/datablock.c
Normal file
@ -0,0 +1,403 @@
|
||||
/* $NetBSD: datablock.c,v 1.1 2011/06/27 11:52:58 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: datablock.c,v 1.1 2011/06/27 11:52:58 uch Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "v7fs.h"
|
||||
#include "v7fs_endian.h"
|
||||
#include "v7fs_superblock.h"
|
||||
#include "v7fs_inode.h"
|
||||
#include "v7fs_impl.h"
|
||||
#include "v7fs_datablock.h"
|
||||
#include "v7fs_file.h"
|
||||
#include "fsck_v7fs.h"
|
||||
|
||||
static void datablock_dup_remove(struct v7fs_self *, v7fs_ino_t, v7fs_ino_t,
|
||||
v7fs_daddr_t);
|
||||
|
||||
struct loop_context {
|
||||
v7fs_ino_t i;
|
||||
v7fs_ino_t j;
|
||||
v7fs_daddr_t blk;
|
||||
};
|
||||
|
||||
/*
|
||||
* datablock vs freeblock
|
||||
*/
|
||||
static int
|
||||
freeblock_subr(struct v7fs_self *fs, void *ctx, v7fs_daddr_t freeblk)
|
||||
{
|
||||
struct loop_context *arg = (struct loop_context *)ctx;
|
||||
|
||||
progress(0);
|
||||
if (arg->blk == freeblk) {
|
||||
pwarn("*** ino%d(%s) data block %d found at freeblock",
|
||||
arg->i, filename(fs, arg->i), freeblk);
|
||||
if (reply("CORRECT?")) {
|
||||
freeblock_dup_remove(fs, freeblk);
|
||||
return V7FS_ITERATOR_ERROR; /* Rescan needed. */
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
datablock_subr(struct v7fs_self *fs, void *ctx, v7fs_daddr_t blk,
|
||||
size_t sz __unused)
|
||||
{
|
||||
struct loop_context *arg = (struct loop_context *)ctx;
|
||||
int ret;
|
||||
|
||||
arg->blk = blk;
|
||||
if ((ret = v7fs_freeblock_foreach(fs, freeblock_subr, ctx)) ==
|
||||
V7FS_ITERATOR_ERROR)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
inode_subr(struct v7fs_self *fs, void *ctx, struct v7fs_inode *p,
|
||||
v7fs_ino_t ino)
|
||||
{
|
||||
struct loop_context *arg = (struct loop_context *)ctx;
|
||||
int ret;
|
||||
|
||||
arg->i = ino;
|
||||
|
||||
if ((ret = v7fs_datablock_foreach(fs, p, datablock_subr, ctx)) ==
|
||||
V7FS_ITERATOR_ERROR)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
datablock_vs_freeblock_check(struct v7fs_self *fs)
|
||||
{
|
||||
struct v7fs_superblock *sb = &fs->superblock;
|
||||
int nfree = sb->total_freeblock;
|
||||
int ndata = sb->volume_size - sb->datablock_start_sector - nfree;
|
||||
int ret;
|
||||
|
||||
progress(&(struct progress_arg){ .label = "data-free", .tick = (ndata /
|
||||
PROGRESS_BAR_GRANULE) * nfree });
|
||||
|
||||
if ((ret = v7fs_ilist_foreach(fs, inode_subr, &(struct loop_context)
|
||||
{ .i = 0, .blk = 0 })) == V7FS_ITERATOR_ERROR)
|
||||
return FSCK_EXIT_UNRESOLVED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* datablock vs datablock
|
||||
*/
|
||||
static int
|
||||
datablock_i_j(struct v7fs_self *fs, void *ctx, v7fs_daddr_t blk, size_t sz
|
||||
__unused)
|
||||
{
|
||||
struct loop_context *arg = (struct loop_context *)ctx;
|
||||
|
||||
progress(0);
|
||||
if (blk == arg->blk) {
|
||||
pwarn("*** duplicated block found."
|
||||
"#%d(%s) and #%d(%s) refer block %d",
|
||||
arg->i, filename(fs, arg->i),
|
||||
arg->j, filename(fs, arg->j), blk);
|
||||
if (reply("CORRECT?")) {
|
||||
datablock_dup_remove(fs, arg->i, arg->j, blk);
|
||||
return V7FS_ITERATOR_ERROR; /* Rescan needed. */
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
loopover_j(struct v7fs_self *fs, void *ctx, struct v7fs_inode *p,
|
||||
v7fs_ino_t ino)
|
||||
{
|
||||
struct loop_context *arg = (struct loop_context *)ctx;
|
||||
int ret;
|
||||
|
||||
arg->j = ino;
|
||||
|
||||
if (arg->j >= arg->i)
|
||||
return V7FS_ITERATOR_BREAK;
|
||||
|
||||
if ((ret = v7fs_datablock_foreach(fs, p, datablock_i_j, ctx)) ==
|
||||
V7FS_ITERATOR_ERROR)
|
||||
return V7FS_ITERATOR_ERROR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
datablock_i(struct v7fs_self *fs, void *ctx, v7fs_daddr_t blk,
|
||||
size_t sz __unused)
|
||||
{
|
||||
struct loop_context *arg = (struct loop_context *)ctx;
|
||||
int ret;
|
||||
|
||||
arg->blk = blk;
|
||||
|
||||
if ((ret = v7fs_ilist_foreach(fs, loopover_j, ctx)) ==
|
||||
V7FS_ITERATOR_ERROR)
|
||||
return V7FS_ITERATOR_ERROR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
loopover_i(struct v7fs_self *fs, void *ctx, struct v7fs_inode *inode,
|
||||
v7fs_ino_t ino)
|
||||
{
|
||||
struct loop_context *arg = (struct loop_context *)ctx;
|
||||
int ret;
|
||||
|
||||
arg->i = ino;
|
||||
|
||||
if ((ret = v7fs_datablock_foreach(fs, inode, datablock_i, ctx)) ==
|
||||
V7FS_ITERATOR_ERROR)
|
||||
return V7FS_ITERATOR_ERROR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
datablock_vs_datablock_check(struct v7fs_self *fs)
|
||||
{
|
||||
const struct v7fs_superblock *sb = &fs->superblock;
|
||||
int n = sb->volume_size - sb->total_freeblock;
|
||||
int ret;
|
||||
|
||||
progress(&(struct progress_arg){ .label = "data-data", .tick = (n / 2)
|
||||
* ((n - 1) / PROGRESS_BAR_GRANULE) });
|
||||
|
||||
if ((ret = v7fs_ilist_foreach(fs, loopover_i, &(struct loop_context){
|
||||
.i = 0, .j = 0 })) == V7FS_ITERATOR_ERROR)
|
||||
return FSCK_EXIT_UNRESOLVED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove duplicated block.
|
||||
*/
|
||||
static void
|
||||
copy_block(struct v7fs_self *fs, v7fs_daddr_t dst, v7fs_daddr_t src)
|
||||
{
|
||||
void *buf;
|
||||
|
||||
if (!(buf = scratch_read(fs, src)))
|
||||
return;
|
||||
fs->io.write(fs->io.cookie, buf, dst);
|
||||
scratch_free(fs, buf);
|
||||
|
||||
pwarn("copy block %d->%d\n", src, dst);
|
||||
}
|
||||
|
||||
static void
|
||||
replace_block_direct(struct v7fs_self *fs, struct v7fs_inode *p, int dupidx,
|
||||
v7fs_daddr_t newblk)
|
||||
{
|
||||
v7fs_daddr_t oldblk;
|
||||
|
||||
oldblk = p->addr[dupidx];
|
||||
p->addr[dupidx] = newblk;
|
||||
v7fs_inode_writeback(fs, p); /* endian conversion done by here. */
|
||||
|
||||
copy_block(fs, newblk, oldblk);
|
||||
}
|
||||
|
||||
static void
|
||||
prepare_list(struct v7fs_self *fs, v7fs_daddr_t listblk, v7fs_daddr_t *p)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
fs->io.read(fs->io.cookie, (void *)p, listblk);
|
||||
for (i = 0; i < V7FS_DADDR_PER_BLOCK; i++)
|
||||
p[i] = V7FS_VAL32(fs, p[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
replace_block_indexed(struct v7fs_self *fs, v7fs_daddr_t listblk, int dupidx,
|
||||
v7fs_daddr_t newblk)
|
||||
{
|
||||
void *buf;
|
||||
v7fs_daddr_t *list;
|
||||
v7fs_daddr_t oldblk;
|
||||
|
||||
if (!(buf = scratch_read(fs, listblk)))
|
||||
return;
|
||||
list = (v7fs_daddr_t *)buf;
|
||||
oldblk = V7FS_VAL32(fs, list[dupidx]);
|
||||
list[dupidx] = V7FS_VAL32(fs, newblk);
|
||||
fs->io.write(fs->io.cookie, buf, listblk);
|
||||
scratch_free(fs, buf);
|
||||
|
||||
copy_block(fs, newblk, oldblk);
|
||||
pwarn("dup block replaced by %d\n", newblk);
|
||||
}
|
||||
|
||||
static bool
|
||||
dupfind_loop1(struct v7fs_self *fs, v7fs_daddr_t listblk, v7fs_daddr_t dupblk,
|
||||
v7fs_daddr_t newblk)
|
||||
{
|
||||
v7fs_daddr_t list[V7FS_DADDR_PER_BLOCK];
|
||||
size_t i;
|
||||
|
||||
prepare_list(fs, listblk, list);
|
||||
for (i = 0; i < V7FS_DADDR_PER_BLOCK; i++) {
|
||||
if (list[i] == dupblk) {
|
||||
replace_block_indexed(fs, listblk, i, newblk);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
dupfind_loop2(struct v7fs_self *fs, v7fs_daddr_t listblk, v7fs_daddr_t dupblk,
|
||||
v7fs_daddr_t newblk)
|
||||
{
|
||||
v7fs_daddr_t list[V7FS_DADDR_PER_BLOCK];
|
||||
v7fs_daddr_t blk;
|
||||
size_t i;
|
||||
|
||||
prepare_list(fs, listblk, list);
|
||||
for (i = 0; i < V7FS_DADDR_PER_BLOCK; i++) {
|
||||
if ((blk = list[i]) == dupblk) {
|
||||
replace_block_indexed(fs, listblk, i, newblk);
|
||||
return true;
|
||||
}
|
||||
if (dupfind_loop1(fs, blk, dupblk, newblk))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
do_replace(struct v7fs_self *fs, struct v7fs_inode *p, v7fs_daddr_t dupblk,
|
||||
v7fs_daddr_t newblk)
|
||||
{
|
||||
size_t i;
|
||||
v7fs_daddr_t blk, blk2;
|
||||
v7fs_daddr_t list[V7FS_DADDR_PER_BLOCK];
|
||||
|
||||
/* Direct */
|
||||
for (i = 0; i < V7FS_NADDR_DIRECT; i++) {
|
||||
if (p->addr[i] == dupblk) {
|
||||
replace_block_direct(fs, p, i, newblk);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Index 1 */
|
||||
if ((blk = p->addr[V7FS_NADDR_INDEX1]) == dupblk) {
|
||||
replace_block_direct(fs, p, V7FS_NADDR_INDEX1, newblk);
|
||||
return;
|
||||
}
|
||||
if (dupfind_loop1(fs, blk, dupblk, newblk))
|
||||
return;
|
||||
|
||||
/* Index 2 */
|
||||
if ((blk = p->addr[V7FS_NADDR_INDEX2]) == dupblk) {
|
||||
replace_block_direct(fs, p, V7FS_NADDR_INDEX2, newblk);
|
||||
return;
|
||||
}
|
||||
if (dupfind_loop2(fs, blk, dupblk, newblk))
|
||||
return;
|
||||
|
||||
/* Index 3 */
|
||||
if ((blk = p->addr[V7FS_NADDR_INDEX3]) == dupblk) {
|
||||
replace_block_direct(fs, p, V7FS_NADDR_INDEX3, newblk);
|
||||
return;
|
||||
}
|
||||
prepare_list(fs, blk, list);
|
||||
for (i = 0; i < V7FS_DADDR_PER_BLOCK; i++) {
|
||||
if ((blk2 = list[i]) == dupblk) {
|
||||
replace_block_indexed(fs, blk, i, newblk);
|
||||
return;
|
||||
}
|
||||
if (dupfind_loop2(fs, blk2, dupblk, newblk))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
datablock_dup_remove(struct v7fs_self *fs, v7fs_ino_t i, v7fs_ino_t j,
|
||||
v7fs_daddr_t dupblk)
|
||||
{
|
||||
struct v7fs_inode inode;
|
||||
v7fs_ino_t victim;
|
||||
v7fs_daddr_t newblk;
|
||||
int error;
|
||||
|
||||
pwarn("Is victim %s (%s is preserved)", filename(fs, i),
|
||||
filename(fs, j));
|
||||
if (reply("?")) {
|
||||
victim = i;
|
||||
} else {
|
||||
pwarn("Is victim %s (%s is preserved)",
|
||||
filename(fs, j), filename(fs, i));
|
||||
if (reply("?")) {
|
||||
victim = j;
|
||||
} else {
|
||||
pwarn("Don't correct.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((error = v7fs_inode_load(fs, &inode, victim)))
|
||||
return;
|
||||
|
||||
/* replace block. */
|
||||
if ((error = v7fs_datablock_allocate(fs, &newblk))) {
|
||||
pwarn("Can't allocate substitute block.");
|
||||
return;
|
||||
}
|
||||
|
||||
do_replace(fs, &inode, dupblk, newblk);
|
||||
}
|
||||
|
294
sbin/fsck_v7fs/freeblock.c
Normal file
294
sbin/fsck_v7fs/freeblock.c
Normal file
@ -0,0 +1,294 @@
|
||||
/* $NetBSD: freeblock.c,v 1.1 2011/06/27 11:52:58 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: freeblock.c,v 1.1 2011/06/27 11:52:58 uch Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "v7fs.h"
|
||||
#include "v7fs_superblock.h"
|
||||
#include "v7fs_inode.h"
|
||||
#include "v7fs_impl.h"
|
||||
#include "v7fs_datablock.h"
|
||||
#include "fsck_v7fs.h"
|
||||
|
||||
struct freeblock_arg {
|
||||
v7fs_daddr_t i;
|
||||
v7fs_daddr_t j;
|
||||
v7fs_daddr_t blk;
|
||||
};
|
||||
|
||||
static int
|
||||
freeblock_subr_cnt(struct v7fs_self *fs __unused, void *ctx,
|
||||
v7fs_daddr_t blk __unused)
|
||||
{
|
||||
((struct freeblock_arg *)ctx)->blk++;
|
||||
progress(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
freeblock_subr_j(struct v7fs_self *fs, void *ctx, v7fs_daddr_t blk)
|
||||
{
|
||||
struct freeblock_arg *arg = (struct freeblock_arg *)ctx;
|
||||
|
||||
if (!datablock_number_sanity(fs, blk)) {
|
||||
pwarn("invalid block#%d in freeblock", blk);
|
||||
/* This problem should be fixed at freeblock_check(). */
|
||||
return FSCK_EXIT_CHECK_FAILED;
|
||||
}
|
||||
|
||||
if (arg->j >= arg->i)
|
||||
return V7FS_ITERATOR_BREAK;
|
||||
|
||||
progress(0);
|
||||
|
||||
if (arg->blk == blk) {
|
||||
pwarn("freeblock duplicate %d %d blk=%d", arg->i, arg->j, blk);
|
||||
if (reply("CORRECT?")) {
|
||||
freeblock_dup_remove(fs, blk);
|
||||
}
|
||||
return FSCK_EXIT_UNRESOLVED; /* Rescan needed. */
|
||||
}
|
||||
|
||||
arg->j++;
|
||||
|
||||
return 0; /*continue */
|
||||
}
|
||||
|
||||
static int
|
||||
freeblock_subr_i(struct v7fs_self *fs, void *ctx, v7fs_daddr_t blk)
|
||||
{
|
||||
struct freeblock_arg *arg = (struct freeblock_arg *)ctx;
|
||||
int ret;
|
||||
|
||||
if (!datablock_number_sanity(fs, blk)) {
|
||||
pwarn("invalid block#%d in freeblock", blk);
|
||||
/* This problem should be fixed at freeblock_check(). */
|
||||
return FSCK_EXIT_CHECK_FAILED;
|
||||
}
|
||||
|
||||
arg->j = 0;
|
||||
arg->blk = blk;
|
||||
ret = v7fs_freeblock_foreach(fs, freeblock_subr_j, ctx);
|
||||
if (!((ret == 0) || (ret == V7FS_ITERATOR_BREAK)))
|
||||
return ret;
|
||||
|
||||
arg->i++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
freeblock_vs_freeblock_check(struct v7fs_self *fs)
|
||||
{
|
||||
struct v7fs_superblock *sb = &fs->superblock;
|
||||
int n = sb->total_freeblock;
|
||||
|
||||
progress(&(struct progress_arg){ .label = "free-free", .tick = (n / 2)
|
||||
* ((n - 1) / PROGRESS_BAR_GRANULE) });
|
||||
|
||||
return v7fs_freeblock_foreach(fs, freeblock_subr_i,
|
||||
&(struct freeblock_arg){ .i = 0 });
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove duplicated block.
|
||||
*/
|
||||
void
|
||||
freeblock_dup_remove(struct v7fs_self *fs, v7fs_daddr_t dupblk)
|
||||
{
|
||||
struct v7fs_superblock *sb = &fs->superblock;
|
||||
struct v7fs_freeblock *fb;
|
||||
int i, total, n;
|
||||
void *buf;
|
||||
v7fs_daddr_t blk;
|
||||
|
||||
n = sb->total_freeblock;
|
||||
|
||||
/* Superblock cache. */
|
||||
total = 0;
|
||||
for (i = sb->nfreeblock - 1; (i > 0) && (n >= 0); i--, n--, total++) {
|
||||
if (sb->freeblock[i] == dupblk) { /* Duplicate found. */
|
||||
memmove(sb->freeblock + i, sb->freeblock + i + 1,
|
||||
sb->nfreeblock - 1 - i);
|
||||
sb->nfreeblock--;
|
||||
sb->modified = 1;
|
||||
v7fs_superblock_writeback(fs);
|
||||
pwarn("remove duplicated freeblock %d"
|
||||
"from superblock", dupblk);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!n)
|
||||
return;
|
||||
blk = sb->freeblock[0];
|
||||
|
||||
do {
|
||||
if (!blk)
|
||||
break;
|
||||
buf = scratch_read(fs, blk);
|
||||
fb = (struct v7fs_freeblock *)buf;
|
||||
v7fs_freeblock_endian_convert(fs, fb);
|
||||
|
||||
if (blk == dupblk) {
|
||||
/* This is difficult probrem. give up! */
|
||||
/* or newly allocate block, and copy it and link. */
|
||||
pwarn("duplicated block is freeblock list."
|
||||
"Shortage freeblock %d->%d.",
|
||||
sb->nfreeblock, total);
|
||||
sb->nfreeblock = total; /*shotage freeblock list. */
|
||||
sb->modified = 1;
|
||||
v7fs_superblock_writeback(fs);
|
||||
return;
|
||||
}
|
||||
total++;
|
||||
|
||||
blk = fb->freeblock[0]; /* next freeblock list */
|
||||
|
||||
for (i = fb->nfreeblock - 1; (i > 0) && (n >= 0);
|
||||
i--, n--, total++) {
|
||||
if (fb->freeblock[i] == dupblk) {
|
||||
pwarn("remove duplicated freeblock"
|
||||
"%d from list %d", dupblk, blk);
|
||||
memmove(fb->freeblock + i, fb->freeblock + i +
|
||||
1, fb->nfreeblock - 1 - i);
|
||||
/* Writeback superblock. */
|
||||
sb->nfreeblock--;
|
||||
sb->modified = 1;
|
||||
v7fs_superblock_writeback(fs);
|
||||
/* Writeback freeblock list block. */
|
||||
v7fs_freeblock_endian_convert(fs, fb);
|
||||
fs->io.write(fs->io.cookie, buf, blk);
|
||||
return;
|
||||
}
|
||||
}
|
||||
scratch_free(fs, buf);
|
||||
} while (n);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_freeblock_foreach(struct v7fs_self *fs,
|
||||
int (*func)(struct v7fs_self *, void *, v7fs_daddr_t), void *ctx)
|
||||
{
|
||||
struct v7fs_superblock *sb = &fs->superblock;
|
||||
struct v7fs_freeblock *fb;
|
||||
int i, n;
|
||||
void *buf;
|
||||
v7fs_daddr_t blk;
|
||||
int ret;
|
||||
|
||||
n = sb->total_freeblock;
|
||||
|
||||
/* Superblock cache. */
|
||||
for (i = sb->nfreeblock - 1; (i > 0) && (n >= 0); i--, n--) {
|
||||
if ((ret = func(fs, ctx, sb->freeblock[i])))
|
||||
return ret;
|
||||
}
|
||||
if (!n)
|
||||
return 0;
|
||||
blk = sb->freeblock[0];
|
||||
if (!datablock_number_sanity(fs, blk)) {
|
||||
pwarn("invalid freeblock list block#%d.", blk);
|
||||
return 0;
|
||||
}
|
||||
do {
|
||||
if (!blk)
|
||||
break;
|
||||
if (!(buf = scratch_read(fs, blk)))
|
||||
return 0;
|
||||
fb = (struct v7fs_freeblock *)buf;
|
||||
|
||||
if (v7fs_freeblock_endian_convert(fs, fb)) {
|
||||
pwarn("***corrupt freeblock list blk#%d", blk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* freeblock list is used as freeblock. */
|
||||
if ((ret = func(fs, ctx, blk)))
|
||||
return ret;
|
||||
|
||||
blk = fb->freeblock[0]; /* next freeblock list */
|
||||
|
||||
for (i = fb->nfreeblock - 1; (i > 0) && (n >= 0); i--, n--)
|
||||
if ((ret = func(fs, ctx, fb->freeblock[i]))) {
|
||||
scratch_free(fs, buf);
|
||||
return ret;
|
||||
}
|
||||
scratch_free(fs, buf);
|
||||
} while (n);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
freeblock_check(struct v7fs_self *fs)
|
||||
{
|
||||
struct v7fs_superblock *sb = &fs->superblock;
|
||||
struct freeblock_arg freeblock_arg = { .blk = 0 };
|
||||
v7fs_daddr_t blk;
|
||||
v7fs_daddr_t datablock_size = sb->volume_size -
|
||||
sb->datablock_start_sector;
|
||||
int error = 0;
|
||||
struct progress_arg progress_arg = { .label = "freeblock", .tick =
|
||||
sb->total_freeblock / PROGRESS_BAR_GRANULE };
|
||||
|
||||
progress(&progress_arg);
|
||||
v7fs_freeblock_foreach(fs, freeblock_subr_cnt, &freeblock_arg);
|
||||
progress(&progress_arg);
|
||||
|
||||
blk = freeblock_arg.blk;
|
||||
pwarn("\ndatablock usage: %d/%d (%d)\n", datablock_size - blk,
|
||||
datablock_size, blk);
|
||||
|
||||
if (sb->total_freeblock != blk) {
|
||||
pwarn("corrupt # of freeblocks. %d(sb) != %d(cnt)",
|
||||
sb->total_freeblock, blk);
|
||||
if (reply_trivial("CORRECT?")) {
|
||||
sb->total_freeblock = blk;
|
||||
sb->modified = 1;
|
||||
v7fs_superblock_writeback(fs);
|
||||
} else {
|
||||
error = FSCK_EXIT_CHECK_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return error;
|
||||
}
|
94
sbin/fsck_v7fs/fsck_v7fs.8
Normal file
94
sbin/fsck_v7fs/fsck_v7fs.8
Normal file
@ -0,0 +1,94 @@
|
||||
.\" $NetBSD: fsck_v7fs.8,v 1.1 2011/06/27 11:52:58 uch Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||
.\" by UCHIYAMA Yasushi.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 29, 2011
|
||||
.Dt FSCK_V7FS 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm fsck_v7fs
|
||||
.Nd 7th Edition(V7) filesystem consistency checker
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl o Ar options
|
||||
.Op Fl B Ar byteorder
|
||||
.Op Fl nypP
|
||||
.Op Fl F
|
||||
.Ar filesystem ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility verifies and repairs
|
||||
.Tn Version 7
|
||||
filesystems
|
||||
.Pp
|
||||
The following flags are interpreted by
|
||||
.Nm .
|
||||
.Bl -tag -width XBXbyteorderXX -offset indent
|
||||
.It Fl B Ar byteorder
|
||||
Convert the file system metadata to
|
||||
.Ar byteorder
|
||||
byte order if needed.
|
||||
Valid byte orders are
|
||||
.Dq be
|
||||
and
|
||||
.Dq le
|
||||
and
|
||||
.Dq pdp .
|
||||
.It Fl F
|
||||
Check file system to a regular file.
|
||||
.It Fl n
|
||||
Don't correct file system.
|
||||
.It Fl y
|
||||
Causes
|
||||
.Nm
|
||||
to assume yes as the answer to all operator questions.
|
||||
.It Fl p
|
||||
preen mode. See fsck(8)
|
||||
.It Fl P
|
||||
Display a progress meter for the file system check.
|
||||
.It Fl o
|
||||
Options are specified with a
|
||||
.Fl o
|
||||
flag followed by a comma separated string of options.
|
||||
The following options are available:
|
||||
.Bl -tag -width data
|
||||
.It Cm data
|
||||
.Tn Check data block duplication.
|
||||
.It Cm free
|
||||
.Tn Check free block duplication.
|
||||
.El
|
||||
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr fsck 8 ,
|
||||
.Xr mount_v7fs 8 ,
|
||||
.Xr newfs_v7fs 8
|
||||
.Sh BUGS
|
||||
.Nm
|
||||
is still under construction.
|
223
sbin/fsck_v7fs/fsck_v7fs.c
Normal file
223
sbin/fsck_v7fs/fsck_v7fs.c
Normal file
@ -0,0 +1,223 @@
|
||||
/* $NetBSD: fsck_v7fs.c,v 1.1 2011/06/27 11:52:58 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2004, 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: fsck_v7fs.c,v 1.1 2011/06/27 11:52:58 uch Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <err.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/disklabel.h>
|
||||
|
||||
#include <fs/v7fs/v7fs.h>
|
||||
#include "v7fs_impl.h"
|
||||
#include "fsck_v7fs.h"
|
||||
#include "progress.h"
|
||||
|
||||
static void usage(void) __dead;
|
||||
static void catopt(char **, const char *);
|
||||
|
||||
enum fsck_operate fsck_operate;
|
||||
bool verbose = true;
|
||||
#define VPRINTF(fmt, args...) { if (verbose) printf(fmt, ##args); }
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
const char *device;
|
||||
struct disklabel d;
|
||||
struct partition *p;
|
||||
struct stat st;
|
||||
int Fflag = 0;
|
||||
int part;
|
||||
int fd, ch;
|
||||
int endian = _BYTE_ORDER;
|
||||
int openflags = O_RDWR;
|
||||
size_t part_sectors;
|
||||
int fsck_flags = 0;
|
||||
char *options = 0;
|
||||
bool progress_bar_enable = false;
|
||||
|
||||
fsck_operate = ASK;
|
||||
|
||||
if (argc < 2)
|
||||
usage();
|
||||
|
||||
while ((ch = getopt(argc, argv, "pPqynfx:dFB:o:")) != -1) {
|
||||
switch (ch) {
|
||||
/*
|
||||
* generic fsck options
|
||||
*/
|
||||
case 'd': /* Not supported */
|
||||
break;
|
||||
case 'f': /* Always forced */
|
||||
break;
|
||||
case 'p':
|
||||
fsck_operate = PREEN;
|
||||
break;
|
||||
case 'y':
|
||||
fsck_operate = ALWAYS_YES;
|
||||
break;
|
||||
case 'n':
|
||||
fsck_operate = ALWAYS_NO;
|
||||
openflags = O_RDONLY;
|
||||
break;
|
||||
case 'P':
|
||||
progress_bar_enable = true;
|
||||
break;
|
||||
case 'q': /* Not supported */
|
||||
break;
|
||||
case 'x': /* Not supported */
|
||||
break;
|
||||
/*
|
||||
* v7fs fsck options
|
||||
*/
|
||||
case 'F':
|
||||
Fflag = 1;
|
||||
break;
|
||||
case 'B':
|
||||
switch (optarg[0]) {
|
||||
case 'l':
|
||||
endian = _LITTLE_ENDIAN;
|
||||
break;
|
||||
case 'b':
|
||||
endian = _BIG_ENDIAN;
|
||||
break;
|
||||
case 'p':
|
||||
endian = _PDP_ENDIAN;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'o': /* datablock, freeblock duplication check */
|
||||
if (*optarg)
|
||||
catopt(&options, optarg);
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 1)
|
||||
usage();
|
||||
device = argv[0];
|
||||
|
||||
if (options) {
|
||||
if (strstr(options, "data"))
|
||||
fsck_flags |= V7FS_FSCK_DATABLOCK_DUP;
|
||||
if (strstr(options, "free"))
|
||||
fsck_flags |= V7FS_FSCK_FREEBLOCK_DUP;
|
||||
}
|
||||
|
||||
if (Fflag) {
|
||||
if ((fd = open(device, openflags)) == -1) {
|
||||
pfatal("%s", device);
|
||||
}
|
||||
if (fstat(fd, &st)) {
|
||||
pfatal("stat");
|
||||
}
|
||||
part_sectors = st.st_size >> V7FS_BSHIFT;
|
||||
setcdevname(device, fsck_operate == PREEN);
|
||||
} else {
|
||||
/* blockcheck sets 'hot' */
|
||||
device = blockcheck(device);
|
||||
setcdevname(device, fsck_operate == PREEN);
|
||||
|
||||
if ((fd = open(device, openflags)) == -1) {
|
||||
pfatal("%s", device);
|
||||
}
|
||||
part = DISKPART(st.st_rdev);
|
||||
|
||||
if (ioctl(fd, DIOCGDINFO, &d) == -1) {
|
||||
pfatal("DIOCGDINFO");
|
||||
}
|
||||
p = &d.d_partitions[part];
|
||||
part_sectors = p->p_size;
|
||||
VPRINTF("partition=%d size=%d offset=%d fstype=%d secsize=%d\n",
|
||||
part, p->p_size, p->p_offset, p->p_fstype, d.d_secsize);
|
||||
if (p->p_fstype != FS_V7) {
|
||||
pfatal("not a Version 7 partition.");
|
||||
}
|
||||
}
|
||||
|
||||
progress_switch(progress_bar_enable);
|
||||
progress_init();
|
||||
progress(&(struct progress_arg){ .cdev = device });
|
||||
|
||||
struct v7fs_mount_device mount;
|
||||
mount.device.fd = fd;
|
||||
mount.endian = endian;
|
||||
mount.sectors = part_sectors;
|
||||
int error = v7fs_fsck(&mount, fsck_flags);
|
||||
|
||||
close(fd);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static void
|
||||
catopt(char **sp, const char *o)
|
||||
{
|
||||
char *s, *n;
|
||||
|
||||
s = *sp;
|
||||
if (s) {
|
||||
if (asprintf(&n, "%s,%s", s, o) < 0)
|
||||
err(1, "asprintf");
|
||||
free(s);
|
||||
s = n;
|
||||
} else
|
||||
s = strdup(o);
|
||||
*sp = s;
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
(void)fprintf(stderr, "usage: %s [-ynpP] [-o options] [-B endian] "
|
||||
"special-device\n",
|
||||
getprogname());
|
||||
(void)fprintf(stderr, "usage: %s -F [-ynpP] [-o options] [-B endian] "
|
||||
"file\n",
|
||||
getprogname());
|
||||
|
||||
exit(FSCK_EXIT_USAGE);
|
||||
}
|
82
sbin/fsck_v7fs/fsck_v7fs.h
Normal file
82
sbin/fsck_v7fs/fsck_v7fs.h
Normal file
@ -0,0 +1,82 @@
|
||||
/* $NetBSD: fsck_v7fs.h,v 1.1 2011/06/27 11:52:58 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SBIN_FSCK_V7FS_FSCK_V7FS_H_
|
||||
#define _SBIN_FSCK_V7FS_FSCK_V7FS_H_
|
||||
|
||||
enum fsck_operate {
|
||||
PREEN,
|
||||
ASK,
|
||||
ALWAYS_YES,
|
||||
ALWAYS_NO,
|
||||
};
|
||||
|
||||
#define V7FS_FSCK_DATABLOCK_DUP 0x01
|
||||
#define V7FS_FSCK_FREEBLOCK_DUP 0x02
|
||||
|
||||
#define PROGRESS_BAR_GRANULE 100
|
||||
struct progress_arg {
|
||||
const char *cdev;
|
||||
const char *label;
|
||||
off_t tick;
|
||||
off_t cnt;
|
||||
off_t total;
|
||||
};
|
||||
|
||||
__BEGIN_DECLS
|
||||
char *filename(struct v7fs_self *, v7fs_ino_t);
|
||||
void progress(const struct progress_arg *);
|
||||
|
||||
int v7fs_fsck(const struct v7fs_mount_device *, int);
|
||||
int reply(const char *);
|
||||
int reply_trivial(const char *);
|
||||
|
||||
int pathname_check(struct v7fs_self *);
|
||||
int ilist_check(struct v7fs_self *);
|
||||
int freeinode_check(struct v7fs_self *);
|
||||
int freeblock_check(struct v7fs_self *);
|
||||
int datablock_vs_datablock_check(struct v7fs_self *);
|
||||
int datablock_vs_freeblock_check(struct v7fs_self *);
|
||||
int freeblock_vs_freeblock_check(struct v7fs_self *);
|
||||
|
||||
void freeblock_dup_remove(struct v7fs_self *, v7fs_daddr_t);
|
||||
|
||||
int v7fs_freeblock_foreach(struct v7fs_self *,
|
||||
int (*)(struct v7fs_self *, void *, v7fs_daddr_t), void *);
|
||||
__END_DECLS
|
||||
|
||||
extern enum fsck_operate fsck_operate;
|
||||
extern struct v7fs_inode lost_and_found;
|
||||
|
||||
#include "fsutil.h"
|
||||
#include "exitvalues.h"
|
||||
|
||||
#endif /*!_SBIN_FSCK_V7FS_FSCK_V7FS_H_ */
|
160
sbin/fsck_v7fs/inode.c
Normal file
160
sbin/fsck_v7fs/inode.c
Normal file
@ -0,0 +1,160 @@
|
||||
/* $NetBSD: inode.c,v 1.1 2011/06/27 11:52:58 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: inode.c,v 1.1 2011/06/27 11:52:58 uch Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "v7fs.h"
|
||||
#include "v7fs_impl.h"
|
||||
#include "v7fs_inode.h"
|
||||
#include "v7fs_superblock.h"
|
||||
#include "fsck_v7fs.h"
|
||||
|
||||
struct ilistcheck_arg {
|
||||
int total;
|
||||
int alloc;
|
||||
};
|
||||
|
||||
int
|
||||
freeinode_check(struct v7fs_self *fs)
|
||||
{
|
||||
struct v7fs_superblock *sb = &fs->superblock;
|
||||
v7fs_ino_t *f = sb->freeinode;
|
||||
int16_t n = sb->nfreeinode;
|
||||
int16_t i, j;
|
||||
int bogus = false;
|
||||
|
||||
/* Check # of cached free inode. */
|
||||
if (n > V7FS_MAX_FREEINODE || n < 0) {
|
||||
pwarn("*** corrupt nfreeinode %d (0-%d)***", n,
|
||||
V7FS_MAX_FREEINODE);
|
||||
|
||||
if (reply("PURGE?")) {
|
||||
sb->nfreeinode = 0;
|
||||
sb->modified = 1;
|
||||
v7fs_superblock_writeback(fs);
|
||||
return FSCK_EXIT_UNRESOLVED;
|
||||
}
|
||||
return FSCK_EXIT_CHECK_FAILED;
|
||||
}
|
||||
|
||||
/* Check dup. */
|
||||
for (i = 0; i < n; i++)
|
||||
for (j = 0; j < i; j++)
|
||||
if (f[i] == f[j]) {
|
||||
pwarn("*** freeinode DUP %d %d", i, j);
|
||||
bogus = true;
|
||||
}
|
||||
if (bogus) {
|
||||
if (reply("PURGE?")) {
|
||||
memset(sb->freeinode, 0, sizeof(*sb->freeinode));
|
||||
sb->nfreeinode = 0;
|
||||
sb->modified = 1;
|
||||
v7fs_superblock_writeback(fs);
|
||||
return FSCK_EXIT_UNRESOLVED;
|
||||
} else {
|
||||
return FSCK_EXIT_CHECK_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return FSCK_EXIT_OK;
|
||||
}
|
||||
|
||||
/* Counting freeinode and find partialy allocated inode. */
|
||||
static int
|
||||
v7fs_inode_check(struct v7fs_self *fs, struct v7fs_inode *p, v7fs_ino_t ino)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
if (v7fs_inode_allocated(p) && !p->nlink) {
|
||||
pwarn("*** partialy allocated inode #%d", ino);
|
||||
v7fs_inode_dump(p);
|
||||
if (reply_trivial("REMOVE?")) {
|
||||
memset(p, 0, sizeof(*p));
|
||||
v7fs_inode_deallocate(fs, ino);
|
||||
} else {
|
||||
error = FSCK_EXIT_CHECK_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
ilistcheck_subr(struct v7fs_self *fs, void *ctx, struct v7fs_inode *p,
|
||||
v7fs_ino_t ino)
|
||||
{
|
||||
struct ilistcheck_arg *arg = (struct ilistcheck_arg *)ctx;
|
||||
int error = 0;
|
||||
|
||||
if (ino != 1)
|
||||
error = v7fs_inode_check(fs, p, ino);
|
||||
|
||||
arg->total++;
|
||||
if (v7fs_inode_allocated(p))
|
||||
arg->alloc++;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
ilist_check(struct v7fs_self *fs)
|
||||
{
|
||||
struct v7fs_superblock *sb = &fs->superblock;
|
||||
struct ilistcheck_arg arg = { .total = 0, .alloc = 0 };
|
||||
int error = 0;
|
||||
|
||||
if ((error = v7fs_ilist_foreach(fs, ilistcheck_subr, &arg)))
|
||||
return error;
|
||||
int nfree = arg.total - arg.alloc;
|
||||
|
||||
if (nfree != sb->total_freeinode) {
|
||||
pwarn("*** corrupt total freeinode. %d(sb) != %d(cnt)\n",
|
||||
sb->total_freeinode, nfree);
|
||||
if (reply_trivial("CORRECT?")) {
|
||||
sb->total_freeinode = nfree;
|
||||
sb->modified = true;
|
||||
v7fs_superblock_writeback(fs);
|
||||
v7fs_superblock_dump(fs);
|
||||
} else {
|
||||
error = FSCK_EXIT_CHECK_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
pwarn("\ninode usage: %d/%d (%d)\n", arg.alloc, arg.total, nfree);
|
||||
return error;
|
||||
}
|
263
sbin/fsck_v7fs/main.c
Normal file
263
sbin/fsck_v7fs/main.c
Normal file
@ -0,0 +1,263 @@
|
||||
/* $NetBSD: main.c,v 1.1 2011/06/27 11:52:58 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: main.c,v 1.1 2011/06/27 11:52:58 uch Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <err.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "v7fs.h"
|
||||
#include "v7fs_impl.h"
|
||||
#include "v7fs_superblock.h"
|
||||
#include "v7fs_inode.h"
|
||||
#include "v7fs_file.h"
|
||||
|
||||
#include "fsck_v7fs.h"
|
||||
#include "progress.h"
|
||||
|
||||
static int check_filesystem(struct v7fs_self *, int);
|
||||
static int make_lost_and_found(struct v7fs_self *, struct v7fs_inode *);
|
||||
|
||||
struct v7fs_inode lost_and_found;
|
||||
|
||||
int
|
||||
v7fs_fsck(const struct v7fs_mount_device *mount, int flags)
|
||||
{
|
||||
struct v7fs_self *fs;
|
||||
int error;
|
||||
|
||||
if ((error = v7fs_io_init(&fs, mount, V7FS_BSIZE))) {
|
||||
pfatal("I/O setup failed");
|
||||
return FSCK_EXIT_CHECK_FAILED;
|
||||
}
|
||||
|
||||
if ((error = v7fs_superblock_load(fs))) {
|
||||
if ((error != EINVAL)) {
|
||||
pfatal("Can't load superblock");
|
||||
return FSCK_EXIT_CHECK_FAILED;
|
||||
}
|
||||
pwarn("Inavalid superblock");
|
||||
if (!reply_trivial("CONTINUE?")) {
|
||||
return FSCK_EXIT_CHECK_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
error = check_filesystem(fs, flags);
|
||||
|
||||
printf("write backing...(no progress report)"); fflush(stdout);
|
||||
v7fs_io_fini(fs);
|
||||
printf("done.\n");
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
check_filesystem(struct v7fs_self *fs, int flags)
|
||||
{
|
||||
int error;
|
||||
|
||||
/* Check superblock cached freeinode list. */
|
||||
pwarn("[Superblock information]\n");
|
||||
v7fs_superblock_dump(fs);
|
||||
pwarn("[1] checking free inode in superblock...\n");
|
||||
if ((error = freeinode_check(fs)))
|
||||
return error;
|
||||
|
||||
/* Check free block linked list. */
|
||||
pwarn("[2] checking free block link...\n");
|
||||
if ((error = freeblock_check(fs)))
|
||||
return error;
|
||||
|
||||
/* Check inode all. */
|
||||
pwarn("[3] checking all ilist...\n");
|
||||
if ((error = ilist_check(fs)))
|
||||
return error;
|
||||
|
||||
/* Setup lost+found. */
|
||||
pwarn("prepare lost+found\n");
|
||||
if ((error = make_lost_and_found(fs, &lost_and_found)))
|
||||
return FSCK_EXIT_CHECK_FAILED;
|
||||
|
||||
/* Check path(child and parent). Orphans are linked to lost+found. */
|
||||
pwarn("[4] checking path name...\n");
|
||||
if ((error = pathname_check(fs)))
|
||||
return error;
|
||||
|
||||
if (flags & V7FS_FSCK_FREEBLOCK_DUP) {
|
||||
/* Check duplicated block in freeblock. */
|
||||
pwarn("[5] checking freeblock duplication...\n");
|
||||
if ((error = freeblock_vs_freeblock_check(fs)))
|
||||
return error;
|
||||
}
|
||||
|
||||
if (flags & V7FS_FSCK_DATABLOCK_DUP) {
|
||||
/* Check duplicated block in datablock. */
|
||||
pwarn("[6] checking datablock duplication(vs datablock)...\n");
|
||||
if ((error = datablock_vs_datablock_check(fs)))
|
||||
return error;
|
||||
}
|
||||
|
||||
if ((flags & V7FS_FSCK_DATABLOCK_DUP) && (flags &
|
||||
V7FS_FSCK_FREEBLOCK_DUP)) {
|
||||
/* Check off-diagonal. */
|
||||
pwarn("[7] checking datablock duplication (vs freeblock)...\n");
|
||||
if ((error = datablock_vs_freeblock_check(fs)))
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
reply_subr(const char *str, bool trivial)
|
||||
{
|
||||
int c;
|
||||
char *line = NULL;
|
||||
size_t linesize = 0;
|
||||
ssize_t linelen;
|
||||
|
||||
printf("%s ", str);
|
||||
switch (fsck_operate) {
|
||||
case PREEN:
|
||||
return trivial;
|
||||
case ALWAYS_YES:
|
||||
printf("[Y]\n");
|
||||
return 1;
|
||||
case ALWAYS_NO:
|
||||
if (strstr(str, "CONTINUE")) {
|
||||
printf("[Y]\n");
|
||||
return 1;
|
||||
}
|
||||
printf("[N]\n");
|
||||
return 0;
|
||||
case ASK:
|
||||
break;
|
||||
}
|
||||
fflush(stdout);
|
||||
|
||||
if ((linelen = getline(&line, &linesize, stdin)) == -1) {
|
||||
clearerr(stdin);
|
||||
return 0;
|
||||
}
|
||||
c = line[0];
|
||||
|
||||
return c == 'y' || c == 'Y';
|
||||
}
|
||||
|
||||
int
|
||||
reply(const char *str)
|
||||
{
|
||||
return reply_subr(str, false);
|
||||
}
|
||||
|
||||
int
|
||||
reply_trivial(const char *str)
|
||||
{
|
||||
return reply_subr(str, true);
|
||||
}
|
||||
|
||||
void
|
||||
progress(const struct progress_arg *p)
|
||||
{
|
||||
static struct progress_arg Progress;
|
||||
static char cdev[32];
|
||||
static char label[32];
|
||||
|
||||
if (p) {
|
||||
if (Progress.tick) {
|
||||
progress_done();
|
||||
}
|
||||
Progress = *p;
|
||||
if (p->cdev)
|
||||
strcpy(cdev, p->cdev);
|
||||
if (p->label)
|
||||
strcpy(label, p->label);
|
||||
}
|
||||
|
||||
if (fsck_operate == PREEN)
|
||||
return;
|
||||
if (!Progress.tick)
|
||||
return;
|
||||
if (++Progress.cnt > Progress.tick) {
|
||||
Progress.cnt = 0;
|
||||
Progress.total++;
|
||||
progress_bar(cdev, label, Progress.total, PROGRESS_BAR_GRANULE);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
make_lost_and_found(struct v7fs_self *fs, struct v7fs_inode *p)
|
||||
{
|
||||
struct v7fs_inode root_inode;
|
||||
struct v7fs_fileattr attr;
|
||||
v7fs_ino_t ino;
|
||||
int error = 0;
|
||||
|
||||
if ((error = v7fs_inode_load(fs, &root_inode, V7FS_ROOT_INODE))) {
|
||||
errno = error;
|
||||
warn("(%s) / missing.", __func__);
|
||||
return error;
|
||||
}
|
||||
|
||||
memset(&attr, 0, sizeof(attr));
|
||||
attr.uid = 0;
|
||||
attr.gid = 0;
|
||||
attr.mode = V7FS_IFDIR | 0755;
|
||||
attr.device = 0;
|
||||
attr.ctime = attr.mtime = attr.atime = (v7fs_time_t)time(NULL);
|
||||
|
||||
/* If lost+found already exists, returns EEXIST */
|
||||
if (!(error = v7fs_file_allocate
|
||||
(fs, &root_inode, "lost+found", &attr, &ino)))
|
||||
v7fs_superblock_writeback(fs);
|
||||
|
||||
if (error == EEXIST)
|
||||
error = 0;
|
||||
|
||||
if (error) {
|
||||
errno = error;
|
||||
warn("(%s) Couldn't create lost+found", __func__);
|
||||
return error;
|
||||
}
|
||||
|
||||
if ((error = v7fs_inode_load(fs, p, ino))) {
|
||||
errno = error;
|
||||
warn("(%s:)lost+found is created, but missing.", __func__);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
349
sbin/fsck_v7fs/pathname.c
Normal file
349
sbin/fsck_v7fs/pathname.c
Normal file
@ -0,0 +1,349 @@
|
||||
/* $NetBSD: pathname.c,v 1.1 2011/06/27 11:52:58 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: pathname.c,v 1.1 2011/06/27 11:52:58 uch Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/syslimits.h> /*PATH_MAX */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "v7fs.h"
|
||||
#include "v7fs_impl.h"
|
||||
#include "v7fs_inode.h"
|
||||
#include "v7fs_datablock.h"
|
||||
#include "v7fs_superblock.h"
|
||||
#include "v7fs_dirent.h"
|
||||
#include "v7fs_file.h"
|
||||
#include "fsck_v7fs.h"
|
||||
|
||||
/*
|
||||
* Check pathname. for each inode, check parent, if it is directory,
|
||||
* check child.
|
||||
*/
|
||||
|
||||
static int
|
||||
connect_lost_and_found(struct v7fs_self *fs, v7fs_ino_t ino)
|
||||
{
|
||||
char name[V7FS_NAME_MAX];
|
||||
v7fs_time_t t;
|
||||
|
||||
if (!lost_and_found.mode || !reply("CONNECT?"))
|
||||
return FSCK_EXIT_CHECK_FAILED;
|
||||
|
||||
snprintf(name, sizeof(name), "%d", ino);
|
||||
v7fs_directory_add_entry(fs, &lost_and_found, ino, name);
|
||||
t = (v7fs_time_t)time(NULL);
|
||||
lost_and_found.mtime = lost_and_found.atime = t;
|
||||
v7fs_inode_writeback(fs, &lost_and_found);
|
||||
v7fs_superblock_writeback(fs); /* # of freeblocks may change. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check child (dir) */
|
||||
struct lookup_child_arg {
|
||||
int dir_cnt;
|
||||
bool print;
|
||||
struct v7fs_inode *parent;
|
||||
};
|
||||
|
||||
static int
|
||||
lookup_child_subr(struct v7fs_self *fs, void *ctx, v7fs_daddr_t blk, size_t sz)
|
||||
{
|
||||
struct lookup_child_arg *arg = (struct lookup_child_arg *)ctx;
|
||||
void *buf;
|
||||
int error = 0;
|
||||
|
||||
if (!(buf = scratch_read(fs, blk)))
|
||||
return 0;
|
||||
struct v7fs_dirent *dir = (struct v7fs_dirent *)buf;
|
||||
size_t i, n = sz / sizeof(*dir);
|
||||
if (!v7fs_dirent_endian_convert(fs, dir, n)) {
|
||||
pwarn("*** bogus entry found *** dir#%d entry=%zu\n",
|
||||
arg->parent->inode_number, n);
|
||||
arg->print = true;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++, dir++) {
|
||||
struct v7fs_inode inode;
|
||||
if (arg->print)
|
||||
pwarn("%s %d\n", dir->name, dir->inode_number);
|
||||
/* Bogus enties are removed here. */
|
||||
if ((error = v7fs_inode_load(fs, &inode, dir->inode_number)))
|
||||
{
|
||||
pwarn("entry #%d not found.", dir->inode_number);
|
||||
if (reply("REMOVE?"))
|
||||
v7fs_directory_remove_entry(fs, arg->parent,
|
||||
dir->name);
|
||||
} else {
|
||||
/* Count child dir. */
|
||||
if (v7fs_inode_isdir(&inode))
|
||||
arg->dir_cnt++;
|
||||
}
|
||||
}
|
||||
scratch_free(fs, buf);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
lookup_child_from_dir(struct v7fs_self *fs, struct v7fs_inode *p, bool print)
|
||||
{
|
||||
struct lookup_child_arg arg = { .dir_cnt = 0, .print = print,
|
||||
.parent = p };
|
||||
|
||||
v7fs_datablock_foreach(fs, p, lookup_child_subr, &arg);
|
||||
|
||||
return arg.dir_cnt;
|
||||
}
|
||||
|
||||
/* Find parent directory (file) */
|
||||
struct lookup_parent_arg {
|
||||
v7fs_ino_t target_ino;
|
||||
v7fs_ino_t parent_ino;
|
||||
};
|
||||
|
||||
static int
|
||||
lookup_parent_from_file_subr(struct v7fs_self *fs, void *ctx,
|
||||
struct v7fs_inode *p, v7fs_ino_t ino)
|
||||
{
|
||||
struct lookup_parent_arg *arg = (struct lookup_parent_arg *)ctx;
|
||||
|
||||
if (!v7fs_inode_isdir(p))
|
||||
return 0;
|
||||
|
||||
if (v7fs_file_lookup_by_number(fs, p, arg->target_ino, NULL)) {
|
||||
arg->parent_ino = ino; /* My inode found. */
|
||||
return V7FS_ITERATOR_BREAK;
|
||||
}
|
||||
|
||||
return 0; /* not found. */
|
||||
}
|
||||
|
||||
|
||||
static v7fs_ino_t
|
||||
lookup_parent_from_file(struct v7fs_self *fs, v7fs_ino_t ino)
|
||||
{
|
||||
struct lookup_parent_arg arg = { .target_ino = ino, .parent_ino = 0 };
|
||||
|
||||
v7fs_ilist_foreach(fs, lookup_parent_from_file_subr, &arg);
|
||||
|
||||
return arg.parent_ino;
|
||||
}
|
||||
|
||||
/* Find parent directory (dir) */
|
||||
static int
|
||||
lookup_parent_from_dir_subr(struct v7fs_self *fs, void *ctx, v7fs_daddr_t blk,
|
||||
size_t sz)
|
||||
{
|
||||
struct lookup_parent_arg *arg = (struct lookup_parent_arg *)ctx;
|
||||
void *buf;
|
||||
int ret = 0;
|
||||
|
||||
if (!(buf = scratch_read(fs, blk)))
|
||||
return 0;
|
||||
struct v7fs_dirent *dir = (struct v7fs_dirent *)buf;
|
||||
size_t i, n = sz / sizeof(*dir);
|
||||
if (!v7fs_dirent_endian_convert(fs, dir, n)) {
|
||||
scratch_free(fs, buf);
|
||||
return V7FS_ITERATOR_ERROR;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++, dir++) {
|
||||
if (strncmp(dir->name, "..", 2) != 0)
|
||||
continue;
|
||||
|
||||
arg->parent_ino = dir->inode_number;
|
||||
ret = V7FS_ITERATOR_BREAK;
|
||||
break;
|
||||
}
|
||||
|
||||
scratch_free(fs, buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static v7fs_ino_t
|
||||
lookup_parent_from_dir(struct v7fs_self *fs, struct v7fs_inode *p)
|
||||
{
|
||||
struct lookup_parent_arg arg = { .target_ino = 0, .parent_ino = 0 };
|
||||
|
||||
/* Search parent("..") from my dirent. */
|
||||
v7fs_datablock_foreach(fs, p, lookup_parent_from_dir_subr, &arg);
|
||||
|
||||
return arg.parent_ino;
|
||||
}
|
||||
|
||||
static int
|
||||
pathname_check_file(struct v7fs_self *fs, struct v7fs_inode *p, v7fs_ino_t ino)
|
||||
{
|
||||
v7fs_ino_t parent_ino;
|
||||
struct v7fs_inode parent_inode;
|
||||
int error = 0;
|
||||
|
||||
if (ino == 1) /* reserved. */
|
||||
return 0;
|
||||
|
||||
/* Check parent. */
|
||||
if (!(parent_ino = lookup_parent_from_file(fs, ino)) ||
|
||||
(error = v7fs_inode_load(fs, &parent_inode, parent_ino)) ||
|
||||
!v7fs_inode_isdir(&parent_inode)) {
|
||||
pwarn("*** inode#%d don't have parent.", ino);
|
||||
v7fs_inode_dump(p);
|
||||
error = connect_lost_and_found(fs, ino);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
pathname_check_dir(struct v7fs_self *fs, struct v7fs_inode *p, v7fs_ino_t ino)
|
||||
{
|
||||
v7fs_ino_t parent_ino;
|
||||
struct v7fs_inode parent_inode;
|
||||
int error = 0;
|
||||
|
||||
/* Check parent */
|
||||
if (!(parent_ino = lookup_parent_from_dir(fs, p)) ||
|
||||
(error = v7fs_inode_load(fs, &parent_inode, parent_ino)) ||
|
||||
!v7fs_inode_isdir(&parent_inode)) {
|
||||
pwarn("*** ino#%d parent dir missing parent=%d", ino,
|
||||
parent_ino);
|
||||
/* link to lost+found */
|
||||
v7fs_inode_dump(p);
|
||||
if ((error = connect_lost_and_found(fs, ino)))
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Check child */
|
||||
int cnt = lookup_child_from_dir(fs, p, false);
|
||||
if ((error = (cnt != p->nlink))) {
|
||||
pwarn("*** ino#%d corrupt link # of child"
|
||||
" dir:%d(inode) != %d(cnt)", ino, p->nlink, cnt);
|
||||
v7fs_inode_dump(p);
|
||||
lookup_child_from_dir(fs, p, true);
|
||||
|
||||
if (reply("CORRECT?")) {
|
||||
p->nlink = cnt;
|
||||
v7fs_inode_writeback(fs, p);
|
||||
error = 0;
|
||||
} else {
|
||||
error = FSCK_EXIT_CHECK_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
pathname_subr(struct v7fs_self *fs, void *ctx __unused, struct v7fs_inode *p,
|
||||
v7fs_ino_t ino)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
if (!v7fs_inode_allocated(p))
|
||||
return 0;
|
||||
|
||||
progress(0);
|
||||
|
||||
if (v7fs_inode_isdir(p)) {
|
||||
error = pathname_check_dir(fs, p, ino);
|
||||
} else if (v7fs_inode_isfile(p)) {
|
||||
error = pathname_check_file(fs, p, ino);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
pathname_check(struct v7fs_self *fs)
|
||||
{
|
||||
struct v7fs_superblock *sb = &fs->superblock;
|
||||
int inodes = V7FS_MAX_INODE(sb) - sb->total_freeinode;
|
||||
|
||||
progress(&(struct progress_arg){ .label = "pathname", .tick = inodes /
|
||||
PROGRESS_BAR_GRANULE });
|
||||
|
||||
return v7fs_ilist_foreach(fs, pathname_subr, 0);
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
filename(struct v7fs_self *fs, v7fs_ino_t ino)
|
||||
{
|
||||
static char path[V7FS_PATH_MAX];
|
||||
struct v7fs_inode inode;
|
||||
v7fs_ino_t parent;
|
||||
int error;
|
||||
char name[V7FS_NAME_MAX + 1];
|
||||
char *p = path + V7FS_PATH_MAX;
|
||||
size_t n;
|
||||
|
||||
if ((error = v7fs_inode_load(fs, &inode, ino)))
|
||||
return 0;
|
||||
|
||||
/* Lookup the 1st parent. */
|
||||
if (v7fs_inode_isdir(&inode))
|
||||
parent = lookup_parent_from_dir(fs, &inode);
|
||||
else
|
||||
parent = lookup_parent_from_file(fs, ino);
|
||||
|
||||
if ((error = v7fs_inode_load(fs, &inode, parent)))
|
||||
return 0;
|
||||
|
||||
if (!v7fs_file_lookup_by_number(fs, &inode, ino, name))
|
||||
return 0;
|
||||
|
||||
n = strlen(name) + 1;
|
||||
strcpy(p -= n, name);
|
||||
|
||||
/* Lookup until / */
|
||||
ino = parent;
|
||||
while (parent != V7FS_ROOT_INODE) {
|
||||
parent = lookup_parent_from_dir(fs, &inode);
|
||||
if ((error = v7fs_inode_load(fs, &inode, parent)))
|
||||
return 0;
|
||||
if (!v7fs_file_lookup_by_number(fs, &inode, ino, name))
|
||||
return 0;
|
||||
ino = parent;
|
||||
n = strlen(name) + 1;
|
||||
strcpy(p - n, name);
|
||||
p[-1] = '/';
|
||||
p -= n;
|
||||
}
|
||||
*--p = '/';
|
||||
|
||||
return p;
|
||||
}
|
16
sbin/mount_v7fs/Makefile
Normal file
16
sbin/mount_v7fs/Makefile
Normal file
@ -0,0 +1,16 @@
|
||||
# $NetBSD: Makefile,v 1.1 2011/06/27 11:52:58 uch Exp $
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
PROG= mount_v7fs
|
||||
SRCS= mount_v7fs.c fattr.c pathadj.c
|
||||
MAN= mount_v7fs.8
|
||||
|
||||
MOUNT= ${NETBSDSRCDIR}/sbin/mount
|
||||
CPPFLAGS+= -I${MOUNT}
|
||||
.PATH: ${MOUNT}
|
||||
|
||||
DPADD+=${LIBUTIL}
|
||||
LDADD+=-lutil
|
||||
|
||||
.include <bsd.prog.mk>
|
112
sbin/mount_v7fs/mount_v7fs.8
Normal file
112
sbin/mount_v7fs/mount_v7fs.8
Normal file
@ -0,0 +1,112 @@
|
||||
.\" $NetBSD: mount_v7fs.8,v 1.1 2011/06/27 11:52:58 uch Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||
.\" by UCHIYAMA Yasushi.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\" Copyright (c) 1980, 1989, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)mount.8 8.7 (Berkeley) 3/27/94
|
||||
.\"
|
||||
.Dd April 29, 2011
|
||||
.Dt MOUNT_V7FS 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm mount_v7fs
|
||||
.Nd mount a 7th Edition(V7) File System
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl B Ar byte-order
|
||||
.Op Fl o Ar options
|
||||
.Ar special node
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
command attaches the 7th Edition(V7) File System on the
|
||||
.Ar special
|
||||
device on to the file system tree at point
|
||||
.Ar node .
|
||||
Both
|
||||
.Ar special
|
||||
and
|
||||
.Ar node
|
||||
are converted to absolute paths before use.
|
||||
.Pp
|
||||
This command is normally executed by
|
||||
.Xr mount 8
|
||||
at boot time.
|
||||
The options are as follows:
|
||||
.Bl -tag -width Fl
|
||||
.It Fl B Ar byte-order
|
||||
Specify the metadata byte order of the file system.
|
||||
Valid byte orders are
|
||||
.Sq be
|
||||
and
|
||||
.Sq le
|
||||
and
|
||||
.Sq pdp .
|
||||
If no byte order is specified, the file system is mounted in host
|
||||
byte order.
|
||||
.It Fl o
|
||||
Options are specified with a
|
||||
.Fl o
|
||||
flag followed by a comma separated string of options.
|
||||
See the
|
||||
.Xr mount 8
|
||||
man page for possible options and their meanings.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr mount 2 ,
|
||||
.Xr unmount 2 ,
|
||||
.Xr fstab 5 ,
|
||||
.Xr mount 8
|
||||
.Sh BUGS
|
||||
The v7fs support is still experimental.
|
191
sbin/mount_v7fs/mount_v7fs.c
Normal file
191
sbin/mount_v7fs/mount_v7fs.c
Normal file
@ -0,0 +1,191 @@
|
||||
/* $NetBSD: mount_v7fs.c,v 1.1 2011/06/27 11:52:58 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*-
|
||||
* Copyright (c) 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: mount_v7fs.c,v 1.1 2011/06/27 11:52:58 uch Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <mntopts.h>
|
||||
|
||||
#include "mountprog.h"
|
||||
#include "mount_v7fs.h"
|
||||
|
||||
static const struct mntopt mopts[] = {
|
||||
MOPT_STDOPTS,
|
||||
MOPT_UPDATE,
|
||||
MOPT_GETARGS,
|
||||
MOPT_NULL,
|
||||
};
|
||||
|
||||
static void v7fs_usage(void) __dead;
|
||||
|
||||
#ifndef MOUNT_NOMAIN
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
|
||||
return mount_v7fs(argc, argv);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
mount_v7fs(int argc, char *argv[])
|
||||
{
|
||||
struct v7fs_args args;
|
||||
char canon_dev[MAXPATHLEN], canon_dir[MAXPATHLEN];
|
||||
const char *errcause;
|
||||
int mntflags;
|
||||
|
||||
mount_v7fs_parseargs(argc, argv, &args, &mntflags,
|
||||
canon_dev, canon_dir);
|
||||
|
||||
if (mount(MOUNT_V7FS, canon_dir, mntflags, &args, sizeof args) == -1) {
|
||||
switch (errno) {
|
||||
case EMFILE:
|
||||
errcause = "mount table full";
|
||||
break;
|
||||
case EINVAL:
|
||||
if (mntflags & MNT_UPDATE)
|
||||
errcause =
|
||||
"specified device does not match mounted device";
|
||||
else
|
||||
errcause = "incorrect super block";
|
||||
break;
|
||||
default:
|
||||
errcause = strerror(errno);
|
||||
break;
|
||||
}
|
||||
errx(EXIT_FAILURE, "%s on %s: %s", canon_dev, canon_dir,
|
||||
errcause);
|
||||
}
|
||||
|
||||
if (mntflags & MNT_GETARGS) {
|
||||
printf("endian=%d\n", args.endian);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
mount_v7fs_parseargs(int argc, char **argv, struct v7fs_args *args,
|
||||
int *mntflags, char *canon_dev, char *canon_dir)
|
||||
{
|
||||
int ch;
|
||||
mntoptparse_t mp;
|
||||
int endian = _BYTE_ORDER;
|
||||
*mntflags = 0;
|
||||
optind = optreset = 1; /* Reset for parse of new argv. */
|
||||
while ((ch = getopt(argc, argv, "o:B:")) != -1)
|
||||
switch (ch) {
|
||||
case 'o':
|
||||
mp = getmntopts(optarg, mopts, mntflags, 0);
|
||||
if (mp == NULL)
|
||||
err(1, "getmntopts");
|
||||
freemntopts(mp);
|
||||
break;
|
||||
case 'B':
|
||||
switch (optarg[0]) {
|
||||
case 'l':
|
||||
endian = _LITTLE_ENDIAN;
|
||||
break;
|
||||
case 'b':
|
||||
endian = _BIG_ENDIAN;
|
||||
break;
|
||||
case 'p':
|
||||
endian = _PDP_ENDIAN;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case '?':
|
||||
|
||||
default:
|
||||
v7fs_usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 2)
|
||||
v7fs_usage();
|
||||
|
||||
pathadj(argv[0], canon_dev);
|
||||
args->endian = endian;
|
||||
args->fspec = canon_dev;
|
||||
pathadj(argv[1], canon_dir);
|
||||
}
|
||||
|
||||
static void
|
||||
v7fs_usage(void)
|
||||
{
|
||||
|
||||
fprintf(stderr, "usage: \n %s [-o options] [-B endian] special node\n",
|
||||
getprogname());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
38
sbin/mount_v7fs/mount_v7fs.h
Normal file
38
sbin/mount_v7fs/mount_v7fs.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* $NetBSD: mount_v7fs.h,v 1.1 2011/06/27 11:52:58 uch Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008, 2011 The NetBSD Foundation. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SBIN_MOUNT_V7FS_MOUNT_V7FS_H_
|
||||
#define _SBIN_MOUNT_V7FS_MOUNT_V7FS_H_
|
||||
|
||||
#include <fs/v7fs/v7fs_args.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
int mount_v7fs(int, char **);
|
||||
void mount_v7fs_parseargs(int, char **, struct v7fs_args *, int *,
|
||||
char *, char *);
|
||||
__END_DECLS
|
||||
#endif /* _SBIN_MOUNT_V7FS_MOUNT_V7FS_H_ */
|
23
sbin/newfs_v7fs/Makefile
Normal file
23
sbin/newfs_v7fs/Makefile
Normal file
@ -0,0 +1,23 @@
|
||||
# $NetBSD: Makefile,v 1.1 2011/06/27 11:52:58 uch Exp $
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
V7FS = ${NETBSDSRCDIR}/sys/fs/v7fs
|
||||
PROG= newfs_v7fs
|
||||
MAN= newfs_v7fs.8
|
||||
SRCS= newfs_v7fs.c main.c v7fs_endian.c v7fs_superblock.c v7fs_inode.c \
|
||||
v7fs_datablock.c v7fs_dirent.c v7fs_io.c v7fs_io_user.c progress.c
|
||||
|
||||
# use progress meter.
|
||||
FSCK= ${NETBSDSRCDIR}/sbin/fsck
|
||||
|
||||
DPADD+= ${LIBUTIL}
|
||||
LDADD+= -lutil
|
||||
CPPFLAGS+=-DV7FS_EI -I${V7FS} -I${FSCK} -g
|
||||
.PATH: ${V7FS} ${FSCK}
|
||||
|
||||
.if defined(HAVE_GCC) && ${HAVE_GCC} == 4
|
||||
COPTS.newfs_v7fs.c+= -Wno-pointer-sign
|
||||
.endif
|
||||
|
||||
.include <bsd.prog.mk>
|
277
sbin/newfs_v7fs/main.c
Normal file
277
sbin/newfs_v7fs/main.c
Normal file
@ -0,0 +1,277 @@
|
||||
/* $NetBSD: main.c,v 1.1 2011/06/27 11:52:58 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: main.c,v 1.1 2011/06/27 11:52:58 uch Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <err.h>
|
||||
|
||||
#include "v7fs.h"
|
||||
#include "v7fs_impl.h"
|
||||
#include "v7fs_endian.h"
|
||||
#include "v7fs_superblock.h"
|
||||
#include "v7fs_inode.h"
|
||||
#include "v7fs_datablock.h" /*v7fs_datablock_expand/last */
|
||||
#include "newfs_v7fs.h"
|
||||
#include "progress.h" /*../sbin/fsck */
|
||||
|
||||
#define VPRINTF(fmt, args...) { if (verbose) printf(fmt, ##args); }
|
||||
|
||||
static v7fs_daddr_t
|
||||
determine_ilist_size(v7fs_daddr_t volume_size, int32_t files)
|
||||
{
|
||||
v7fs_daddr_t ilist_size;
|
||||
|
||||
if (files)
|
||||
ilist_size = roundup2(files, V7FS_INODE_PER_BLOCK) /
|
||||
V7FS_INODE_PER_BLOCK;
|
||||
else
|
||||
ilist_size = volume_size / 25; /* 4% */
|
||||
if (ilist_size > (v7fs_daddr_t)V7FS_ILISTBLK_MAX)
|
||||
ilist_size = V7FS_ILISTBLK_MAX;
|
||||
|
||||
return ilist_size;
|
||||
}
|
||||
|
||||
static int
|
||||
make_root(struct v7fs_self *fs)
|
||||
{
|
||||
struct v7fs_inode inode;
|
||||
struct v7fs_dirent *dir;
|
||||
int error;
|
||||
|
||||
/* INO 1 badblk (don't used) */
|
||||
memset(&inode, 0, sizeof(inode));
|
||||
inode.inode_number = 1;
|
||||
inode.mode = V7FS_IFREG; /* V7 manner */
|
||||
v7fs_inode_writeback(fs, &inode);
|
||||
|
||||
/* INO 2 root */
|
||||
v7fs_ino_t ino;
|
||||
if ((error = v7fs_inode_allocate(fs, &ino))) {
|
||||
errno = error;
|
||||
warn("Can't allocate / inode");
|
||||
return error;
|
||||
}
|
||||
|
||||
memset(&inode, 0, sizeof(inode));
|
||||
inode.inode_number = ino;
|
||||
inode.mode = 0777 | V7FS_IFDIR;
|
||||
inode.uid = 0;
|
||||
inode.gid = 0;
|
||||
inode.nlink = 2; /* . + .. */
|
||||
inode.atime = inode.mtime = inode.ctime = time(0);
|
||||
|
||||
/* root dirent. */
|
||||
v7fs_datablock_expand(fs, &inode, sizeof(*dir) * 2);
|
||||
v7fs_daddr_t blk = inode.addr[0];
|
||||
void *buf;
|
||||
if (!(buf = scratch_read(fs, blk))) {
|
||||
v7fs_inode_deallocate(fs, ino);
|
||||
errno = error = EIO;
|
||||
warn("Can't read / dirent.");
|
||||
return error;
|
||||
}
|
||||
dir = (struct v7fs_dirent *)buf; /*disk endian */
|
||||
|
||||
strcpy(dir[0].name, ".");
|
||||
dir[0].inode_number = V7FS_VAL16(fs, ino);
|
||||
strcpy(dir[1].name, "..");
|
||||
dir[1].inode_number = V7FS_VAL16(fs, ino);
|
||||
if (!fs->io.write(fs->io.cookie, buf, blk)) {/*writeback */
|
||||
scratch_free(fs, buf);
|
||||
errno = error = EIO;
|
||||
warn("Can't write / dirent.");
|
||||
return error;
|
||||
}
|
||||
scratch_free(fs, buf);
|
||||
v7fs_inode_writeback(fs, &inode);
|
||||
if ((error = v7fs_superblock_writeback(fs))) {
|
||||
errno = error;
|
||||
warn("Can't write superblock.");
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static v7fs_daddr_t
|
||||
make_freeblocklist(struct v7fs_self *fs, v7fs_daddr_t listblk, uint8_t *buf)
|
||||
{
|
||||
uint32_t (*val32)(uint32_t) = fs->val.conv32;
|
||||
uint16_t (*val16)(uint16_t) = fs->val.conv16;
|
||||
struct v7fs_freeblock *fb = (struct v7fs_freeblock *)buf;
|
||||
int i, j, k;
|
||||
|
||||
memset(buf, 0, V7FS_BSIZE);
|
||||
|
||||
for (i = V7FS_MAX_FREEBLOCK - 1, j = listblk + 1, k = 0; i >= 0;
|
||||
i--, j++, k++) {
|
||||
progress(0);
|
||||
if (j == (int32_t)fs->superblock.volume_size)
|
||||
{
|
||||
VPRINTF("\nlast freeblock #%d\n",
|
||||
(*val32)(fb->freeblock[i + 1]));
|
||||
fb->nfreeblock = (*val16)(k);
|
||||
|
||||
memmove(fb->freeblock + 1, fb->freeblock + i + 1, k *
|
||||
sizeof(v7fs_daddr_t));
|
||||
fb->freeblock[0] = 0; /* Terminate link; */
|
||||
VPRINTF("last freeblock contains #%d\n",
|
||||
(*val16)(fb->nfreeblock));
|
||||
fs->io.write(fs->io.cookie, buf, listblk);
|
||||
return 0;
|
||||
}
|
||||
fb->freeblock[i] = (*val32)(j);
|
||||
}
|
||||
fb->nfreeblock = (*val16)(k);
|
||||
|
||||
if (!fs->io.write(fs->io.cookie, buf, listblk)) {
|
||||
errno = EIO;
|
||||
warn("blk=%ld", (long)listblk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return next link block */
|
||||
return (*val32)(fb->freeblock[0]);
|
||||
}
|
||||
|
||||
static int
|
||||
make_filesystem(struct v7fs_self *fs, v7fs_daddr_t volume_size,
|
||||
v7fs_daddr_t ilist_size)
|
||||
{
|
||||
struct v7fs_superblock *sb;
|
||||
v7fs_daddr_t blk;
|
||||
uint8_t buf[V7FS_BSIZE];
|
||||
int error = 0;
|
||||
int32_t i, j;
|
||||
|
||||
/* Setup ilist. (ilist must be zero filled. becuase of they are free) */
|
||||
VPRINTF("Zero clear ilist.\n");
|
||||
progress(&(struct progress_arg){ .label = "zero ilist", .tick =
|
||||
ilist_size / PROGRESS_BAR_GRANULE });
|
||||
memset(buf, 0, sizeof buf);
|
||||
for (i = V7FS_ILIST_SECTOR; i < (int32_t)ilist_size; i++) {
|
||||
fs->io.write(fs->io.cookie, buf, i);
|
||||
progress(0);
|
||||
}
|
||||
progress_done();
|
||||
VPRINTF("\n");
|
||||
|
||||
/* Construct superblock */
|
||||
sb = &fs->superblock;
|
||||
sb->volume_size = volume_size;
|
||||
sb->datablock_start_sector = ilist_size + V7FS_ILIST_SECTOR;
|
||||
sb->update_time = time(NULL);
|
||||
|
||||
/* fill free inode cache. */
|
||||
VPRINTF("Setup inode cache.\n");
|
||||
sb->nfreeinode = V7FS_MAX_FREEINODE;
|
||||
for (i = V7FS_MAX_FREEINODE - 1, j = V7FS_ROOT_INODE; i >= 0; i--, j++)
|
||||
sb->freeinode[i] = j;
|
||||
sb->total_freeinode = ilist_size * V7FS_INODE_PER_BLOCK - 1;
|
||||
|
||||
/* fill free block cache. */
|
||||
VPRINTF("Setup free block cache.\n");
|
||||
sb->nfreeblock = V7FS_MAX_FREEBLOCK;
|
||||
for (i = V7FS_MAX_FREEBLOCK - 1, j = sb->datablock_start_sector; i >= 0;
|
||||
i--, j++)
|
||||
sb->freeblock[i] = j;
|
||||
sb->total_freeblock = volume_size - sb->datablock_start_sector - 1;
|
||||
|
||||
/* Write superblock. */
|
||||
sb->modified = 1;
|
||||
if ((error = v7fs_superblock_writeback(fs))) {
|
||||
errno = error;
|
||||
warn("Can't write back superblock.");
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Construct freeblock list */
|
||||
VPRINTF("Setup whole freeblock list.\n");
|
||||
progress(&(struct progress_arg){ .label = "freeblock list", .tick =
|
||||
(volume_size - sb->datablock_start_sector) / PROGRESS_BAR_GRANULE});
|
||||
blk = sb->freeblock[0];
|
||||
while ((blk = make_freeblocklist(fs, blk, buf)))
|
||||
continue;
|
||||
progress_done();
|
||||
|
||||
VPRINTF("done.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_newfs(const struct v7fs_mount_device *mount, int32_t maxfile)
|
||||
{
|
||||
struct v7fs_self *fs;
|
||||
v7fs_daddr_t ilist_size;
|
||||
int error;
|
||||
v7fs_daddr_t volume_size = mount->sectors;
|
||||
|
||||
/* Check and determine ilistblock, datablock size. */
|
||||
if (volume_size > V7FS_DADDR_MAX + 1)
|
||||
return ENOSPC;
|
||||
|
||||
ilist_size = determine_ilist_size(volume_size, maxfile);
|
||||
|
||||
VPRINTF("volume size=%d, ilist size=%d, endian=%d, NAME_MAX=%d\n",
|
||||
volume_size, ilist_size, mount->endian, V7FS_NAME_MAX);
|
||||
|
||||
/* Setup I/O ops. */
|
||||
if ((error = v7fs_io_init(&fs, mount, V7FS_BSIZE))) {
|
||||
errno = error;
|
||||
warn("I/O setup failed.");
|
||||
return error;
|
||||
}
|
||||
fs->endian = mount->endian;
|
||||
v7fs_endian_init(fs);
|
||||
|
||||
/* Construct filesystem. */
|
||||
if ((error = make_filesystem(fs, volume_size, ilist_size))) {
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Setup root. */
|
||||
if ((error = make_root(fs))) {
|
||||
return error;
|
||||
}
|
||||
|
||||
v7fs_io_fini(fs);
|
||||
|
||||
return 0;
|
||||
}
|
117
sbin/newfs_v7fs/newfs_v7fs.8
Normal file
117
sbin/newfs_v7fs/newfs_v7fs.8
Normal file
@ -0,0 +1,117 @@
|
||||
.\" $NetBSD: newfs_v7fs.8,v 1.1 2011/06/27 11:52:58 uch Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||
.\" by UCHIYAMA Yasushi.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\" Copyright (c) 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)newlfs.8 8.1 (Berkeley) 6/19/93
|
||||
.\"
|
||||
.Dd April 29, 2011
|
||||
.Dt NEWFS_V7FS 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm newfs_v7fs
|
||||
.Nd construct a new 7th Edition(V7) File System
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl B Ar byte-order
|
||||
.Op Fl FZvP
|
||||
.Op Fl s Ar sectors
|
||||
.Op Fl n Ar inodes
|
||||
.Ar special
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
builds a 7th Edition(V7) file system on the specified special.
|
||||
If it is a device, the size information will be taken from the disk label and
|
||||
before running
|
||||
.Nm
|
||||
the disk must be labeled using
|
||||
.Xr disklabel 8 ;
|
||||
the proper fstype is
|
||||
.Dq Version 7 .
|
||||
Otherwise, the size must be specified on the command line.
|
||||
V7 filesystem's block size and sector size are 512byte.
|
||||
disk address limits are 24bit.
|
||||
.Pp
|
||||
The following arguments are supported:
|
||||
.Bl -tag -width Fl
|
||||
.It Fl P
|
||||
Display a progress meter for the file system construct.
|
||||
.It Fl v
|
||||
verbose.
|
||||
.It Fl F
|
||||
Create file system to a regular file.(needs -s option)
|
||||
.It Fl s Ar sectors
|
||||
Create file system with specified number of disk sectors.
|
||||
.It Fl Z
|
||||
Fill file with zeroes instead of creating a sparse file.
|
||||
.It Fl B Ar byte-order
|
||||
Specify the metadata byte order of the file system to be created.
|
||||
Valid byte orders are
|
||||
.Sq be
|
||||
and
|
||||
.Sq le
|
||||
and
|
||||
.Sq pdp .
|
||||
If no byte order is specified, the file system is created in host
|
||||
byte order.
|
||||
.It Fl n Ar inodes
|
||||
This specifies the number of inodes for the filesystem.
|
||||
If number of inodes exceeds 65536, contracted to 65536.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr disklabel 5 ,
|
||||
.Xr disktab 5 ,
|
||||
.\" .Xr fs 5 ,
|
||||
.Xr disklabel 8 ,
|
||||
.Xr diskpart 8
|
242
sbin/newfs_v7fs/newfs_v7fs.c
Normal file
242
sbin/newfs_v7fs/newfs_v7fs.c
Normal file
@ -0,0 +1,242 @@
|
||||
/* $NetBSD: newfs_v7fs.c,v 1.1 2011/06/27 11:52:58 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2004, 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: newfs_v7fs.c,v 1.1 2011/06/27 11:52:58 uch Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/disklabel.h>
|
||||
|
||||
#include <fs/v7fs/v7fs.h>
|
||||
#include "v7fs_impl.h"
|
||||
#include "progress.h"
|
||||
#include "newfs_v7fs.h"
|
||||
|
||||
static void usage(void) __dead;
|
||||
static bool progress_bar_enable = false;
|
||||
bool verbose = false;
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
const char *device;
|
||||
struct disklabel d;
|
||||
struct partition *p;
|
||||
struct stat st;
|
||||
uint32_t partsize;
|
||||
int Fflag, Zflag;
|
||||
int part;
|
||||
int fd, ch;
|
||||
int endian = _BYTE_ORDER;
|
||||
int32_t maxfile = 0;
|
||||
|
||||
if (argc < 2)
|
||||
usage();
|
||||
|
||||
Fflag = Zflag = partsize = 0;
|
||||
while ((ch = getopt(argc, argv, "Fs:Zs:n:B:vP")) != -1) {
|
||||
switch (ch) {
|
||||
case 'P':
|
||||
progress_bar_enable = true;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = true;
|
||||
break;
|
||||
case 'F':
|
||||
Fflag = 1;
|
||||
break;
|
||||
case 's':
|
||||
partsize = atoi(optarg);
|
||||
break;
|
||||
case 'n':
|
||||
maxfile = atoi(optarg);
|
||||
break;
|
||||
case 'Z':
|
||||
Zflag = 1;
|
||||
break;
|
||||
case 'B':
|
||||
switch (optarg[0]) {
|
||||
case 'l':
|
||||
endian = _LITTLE_ENDIAN;
|
||||
break;
|
||||
case 'b':
|
||||
endian = _BIG_ENDIAN;
|
||||
break;
|
||||
case 'p':
|
||||
endian = _PDP_ENDIAN;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 1)
|
||||
usage();
|
||||
device = argv[0];
|
||||
|
||||
if (progress_bar_enable) {
|
||||
progress_switch(progress_bar_enable);
|
||||
progress_init();
|
||||
progress(&(struct progress_arg){ .cdev = device });
|
||||
}
|
||||
|
||||
if (!Fflag) {
|
||||
if ((fd = open(device, O_RDWR)) == -1) {
|
||||
err(EXIT_FAILURE, "%s", device);
|
||||
}
|
||||
if (fstat(fd, &st) != 0) {
|
||||
goto err_exit;
|
||||
}
|
||||
if (!S_ISCHR(st.st_mode)) {
|
||||
warnx("not a raw device.\n");
|
||||
}
|
||||
|
||||
part = DISKPART(st.st_rdev);
|
||||
|
||||
if (ioctl(fd, DIOCGDINFO, &d) == -1) {
|
||||
goto err_exit;
|
||||
}
|
||||
p = &d.d_partitions[part];
|
||||
if (verbose) {
|
||||
printf("partition=%d size=%d offset=%d fstype=%d"
|
||||
" secsize=%d\n", part, p->p_size, p->p_offset,
|
||||
p->p_fstype, d.d_secsize);
|
||||
}
|
||||
if (p->p_fstype != FS_V7) {
|
||||
warnx("not a Version 7 partition.");
|
||||
goto err_exit;
|
||||
}
|
||||
partsize = p->p_size;
|
||||
} else {
|
||||
off_t filesize;
|
||||
uint8_t zbuf[8192] = {0, };
|
||||
|
||||
if (partsize == 0) {
|
||||
errx(EXIT_FAILURE, "-F requires -s");
|
||||
}
|
||||
|
||||
filesize = partsize << V7FS_BSHIFT;
|
||||
|
||||
fd = open(device, O_RDWR|O_CREAT|O_TRUNC, 0666);
|
||||
if (fd == -1) {
|
||||
err(EXIT_FAILURE, "%s", device);
|
||||
}
|
||||
|
||||
if (Zflag) {
|
||||
while (filesize > 0) {
|
||||
size_t writenow = MIN(filesize,
|
||||
(off_t)sizeof(zbuf));
|
||||
|
||||
if ((size_t)write(fd, zbuf, writenow) !=
|
||||
writenow) {
|
||||
err(EXIT_FAILURE, NULL);
|
||||
}
|
||||
filesize -= writenow;
|
||||
}
|
||||
} else {
|
||||
if (lseek(fd, filesize - 1, SEEK_SET) == -1) {
|
||||
goto err_exit;
|
||||
}
|
||||
if (write(fd, zbuf, 1) != 1) {
|
||||
goto err_exit;
|
||||
}
|
||||
if (lseek(fd, 0, SEEK_SET) == -1) {
|
||||
goto err_exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (v7fs_newfs(&(struct v7fs_mount_device)
|
||||
{ .device.fd = fd, .endian = endian, .sectors = partsize },
|
||||
maxfile) != 0)
|
||||
goto err_exit;
|
||||
|
||||
close(fd);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
err_exit:
|
||||
close(fd);
|
||||
err(EXIT_FAILURE, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
progress(const struct progress_arg *p)
|
||||
{
|
||||
static struct progress_arg Progress;
|
||||
static char cdev[32];
|
||||
static char label[32];
|
||||
|
||||
if (!progress_bar_enable)
|
||||
return;
|
||||
|
||||
if (p) {
|
||||
Progress = *p;
|
||||
if (p->cdev)
|
||||
strcpy(cdev, p->cdev);
|
||||
if (p->label)
|
||||
strcpy(label, p->label);
|
||||
}
|
||||
|
||||
if (!Progress.tick)
|
||||
return;
|
||||
if (++Progress.cnt > Progress.tick) {
|
||||
Progress.cnt = 0;
|
||||
Progress.total++;
|
||||
progress_bar(cdev, label, Progress.total, PROGRESS_BAR_GRANULE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
(void)fprintf(stderr, "usage: \n%s [-vP] [-n maxfile]"
|
||||
" [-B endian] special\n", getprogname());
|
||||
(void)fprintf(stderr, "%s -F -s partsize [-vPZ] [-n maxfile]"
|
||||
" [-B endian] file\n", getprogname());
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
48
sbin/newfs_v7fs/newfs_v7fs.h
Normal file
48
sbin/newfs_v7fs/newfs_v7fs.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* $NetBSD: newfs_v7fs.h,v 1.1 2011/06/27 11:52:58 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SBIN_NEWFS_V7FS_NEWFS_V7FS_H_
|
||||
#define _SBIN_NEWFS_V7FS_NEWFS_V7FS_H_
|
||||
|
||||
#define PROGRESS_BAR_GRANULE 100
|
||||
struct progress_arg {
|
||||
const char *cdev;
|
||||
const char *label;
|
||||
off_t tick;
|
||||
off_t cnt;
|
||||
off_t total;
|
||||
};
|
||||
__BEGIN_DECLS
|
||||
void progress(const struct progress_arg *);
|
||||
int v7fs_newfs(const struct v7fs_mount_device *, int32_t);
|
||||
extern bool verbose;
|
||||
__END_DECLS
|
||||
#endif /* !_SBIN_NEWFS_V7FS_NEWFS_V7FS_H_ */
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: files,v 1.1017 2011/06/23 23:42:43 matt Exp $
|
||||
# $NetBSD: files,v 1.1018 2011/06/27 11:52:24 uch Exp $
|
||||
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
|
||||
|
||||
version 20100430
|
||||
@ -1376,6 +1376,7 @@ include "fs/smbfs/files.smbfs"
|
||||
include "fs/sysvbfs/files.sysvbfs"
|
||||
include "fs/tmpfs/files.tmpfs"
|
||||
include "fs/union/files.union"
|
||||
include "fs/v7fs/files.v7fs"
|
||||
include "miscfs/fdesc/files.fdesc"
|
||||
include "miscfs/kernfs/files.kernfs"
|
||||
include "miscfs/nullfs/files.nullfs"
|
||||
|
@ -1,6 +1,6 @@
|
||||
# $NetBSD: Makefile,v 1.19 2010/06/14 14:40:47 pooka Exp $
|
||||
# $NetBSD: Makefile,v 1.20 2011/06/27 11:52:24 uch Exp $
|
||||
|
||||
SUBDIR= adosfs cd9660 efs filecorefs hfs msdosfs nilfs ntfs ptyfs \
|
||||
puffs smbfs sysvbfs tmpfs udf union
|
||||
puffs smbfs sysvbfs tmpfs udf union v7fs
|
||||
|
||||
.include <bsd.kinc.mk>
|
||||
|
7
sys/fs/v7fs/Makefile
Normal file
7
sys/fs/v7fs/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
# $NetBSD: Makefile,v 1.1 2011/06/27 11:52:24 uch Exp $
|
||||
|
||||
INCSDIR= /usr/include/fs/v7fs
|
||||
|
||||
INCS= v7fs.h v7fs_args.h
|
||||
|
||||
.include <bsd.kinc.mk>
|
22
sys/fs/v7fs/files.v7fs
Normal file
22
sys/fs/v7fs/files.v7fs
Normal file
@ -0,0 +1,22 @@
|
||||
# $NetBSD: files.v7fs,v 1.1 2011/06/27 11:52:24 uch Exp $
|
||||
|
||||
deffs V7FS
|
||||
defflag opt_v7fs.h V7FS_EI
|
||||
|
||||
# Core. OS independent. These files are used by userland program.(fsck,newfs)
|
||||
file fs/v7fs/v7fs_endian.c v7fs
|
||||
file fs/v7fs/v7fs_superblock.c v7fs
|
||||
file fs/v7fs/v7fs_inode.c v7fs
|
||||
file fs/v7fs/v7fs_dirent.c v7fs
|
||||
file fs/v7fs/v7fs_datablock.c v7fs
|
||||
file fs/v7fs/v7fs_file.c v7fs
|
||||
file fs/v7fs/v7fs_io.c v7fs
|
||||
# util.
|
||||
file fs/v7fs/v7fs_file_util.c v7fs
|
||||
file fs/v7fs/v7fs_inode_util.c v7fs
|
||||
file fs/v7fs/v7fs_superblock_util.c v7fs
|
||||
# OS glue
|
||||
file fs/v7fs/v7fs_io_kern.c v7fs
|
||||
file fs/v7fs/v7fs_extern.c v7fs
|
||||
file fs/v7fs/v7fs_vnops.c v7fs
|
||||
file fs/v7fs/v7fs_vfsops.c v7fs
|
180
sys/fs/v7fs/v7fs.h
Normal file
180
sys/fs/v7fs/v7fs.h
Normal file
@ -0,0 +1,180 @@
|
||||
/* $NetBSD: v7fs.h,v 1.1 2011/06/27 11:52:24 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _V7FS_H_
|
||||
/* 7th Edition of Unix(PDP-11) Filesystem definition. */
|
||||
#define _V7FS_H_
|
||||
#include <sys/types.h>
|
||||
#ifndef _KERNEL
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
/*
|
||||
* V7 File System
|
||||
*
|
||||
* +------------------
|
||||
* |Boot block (512byte) sector [0]
|
||||
* |
|
||||
* +------------------
|
||||
* |Super block (512byte) sector [1]
|
||||
* |
|
||||
* +------------------
|
||||
* |v7fs_inode(64byte sector [2]
|
||||
* .
|
||||
* .
|
||||
* |
|
||||
* +------------------
|
||||
* |data block sector [datablock_start_sector]
|
||||
* |
|
||||
* .
|
||||
* .
|
||||
* |
|
||||
* +------------------
|
||||
* <- [sector volume_size]
|
||||
*
|
||||
* |
|
||||
* +------------------ volume size.
|
||||
*
|
||||
* Max volume size is 8GB (24bit daddr_t)
|
||||
* Max file size is ~1GB
|
||||
*
|
||||
*/
|
||||
|
||||
/* V7 type. */
|
||||
typedef uint16_t v7fs_ino_t;
|
||||
typedef uint32_t v7fs_daddr_t;
|
||||
typedef int32_t v7fs_time_t;
|
||||
typedef uint32_t v7fs_off_t;
|
||||
typedef uint16_t v7fs_dev_t;
|
||||
typedef uint16_t v7fs_mode_t;
|
||||
#define V7FS_DADDR_MAX 0x00ffffff
|
||||
#define V7FS_INODE_MAX 0xffff
|
||||
|
||||
#define V7FS_BSIZE 512
|
||||
#define V7FS_BSHIFT 9
|
||||
#define V7FS_ROUND_BSIZE(x) \
|
||||
((((x) + (V7FS_BSIZE - 1)) & ~(V7FS_BSIZE - 1)))
|
||||
#define V7FS_TRUNC_BSIZE(x) ((x) & ~(V7FS_BSIZE - 1))
|
||||
|
||||
#define V7FS_RESIDUE_BSIZE(x) \
|
||||
((x) - ((((x) - 1) >> V7FS_BSHIFT) << V7FS_BSHIFT))
|
||||
|
||||
/* Disk location. */
|
||||
#define V7FS_BOOTBLOCK_SECTOR 0
|
||||
#define V7FS_SUPERBLOCK_SECTOR 1
|
||||
#define V7FS_ILIST_SECTOR 2
|
||||
|
||||
/* Superblock */
|
||||
/* cache. */
|
||||
#define V7FS_MAX_FREEBLOCK 50
|
||||
#define V7FS_MAX_FREEINODE 100
|
||||
struct v7fs_superblock {
|
||||
/* [3 ... (datablock_start_sector-1)]are ilist */
|
||||
uint16_t datablock_start_sector;
|
||||
v7fs_daddr_t volume_size;
|
||||
int16_t nfreeblock; /* # of freeblock in superblock cache. */
|
||||
v7fs_daddr_t freeblock[V7FS_MAX_FREEBLOCK]; /* cache. */
|
||||
int16_t nfreeinode; /* # of free inode in superblock cache. */
|
||||
v7fs_ino_t freeinode[V7FS_MAX_FREEINODE]; /* cache. */
|
||||
int8_t lock_freeblock;
|
||||
int8_t lock_freeinode;
|
||||
int8_t modified;
|
||||
int8_t readonly;
|
||||
v7fs_time_t update_time;
|
||||
v7fs_daddr_t total_freeblock;
|
||||
v7fs_ino_t total_freeinode;
|
||||
} __packed;
|
||||
|
||||
/* Datablock */
|
||||
#define V7FS_NADDR 13
|
||||
#define V7FS_NADDR_DIRECT 10
|
||||
#define V7FS_NADDR_INDEX1 10
|
||||
#define V7FS_NADDR_INDEX2 11
|
||||
#define V7FS_NADDR_INDEX3 12
|
||||
/* daddr index. */
|
||||
#define V7FS_DADDR_PER_BLOCK (V7FS_BSIZE / sizeof(v7fs_daddr_t))
|
||||
struct v7fs_freeblock {
|
||||
int16_t nfreeblock;
|
||||
v7fs_daddr_t freeblock[V7FS_MAX_FREEBLOCK];
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Dirent */
|
||||
#define V7FS_NAME_MAX 14
|
||||
#define V7FS_PATH_MAX PATH_MAX /* No V7 limit. */
|
||||
#define V7FS_LINK_MAX LINK_MAX /* No V7 limit. */
|
||||
struct v7fs_dirent {
|
||||
v7fs_ino_t inode_number;
|
||||
char name[V7FS_NAME_MAX];
|
||||
} __packed; /*16byte */
|
||||
|
||||
/* Inode */
|
||||
#define V7FS_BALBLK_INODE 1 /* monument */
|
||||
#define V7FS_ROOT_INODE 2
|
||||
#define V7FS_MAX_INODE(s) \
|
||||
(((s)->datablock_start_sector - V7FS_ILIST_SECTOR) * \
|
||||
V7FS_BSIZE / sizeof(struct v7fs_inode_diskimage))
|
||||
#define V7FS_INODE_PER_BLOCK \
|
||||
(V7FS_BSIZE / sizeof(struct v7fs_inode_diskimage))
|
||||
#define V7FS_ILISTBLK_MAX (V7FS_INODE_MAX / V7FS_INODE_PER_BLOCK)
|
||||
|
||||
struct v7fs_inode_diskimage {
|
||||
int16_t mode;
|
||||
int16_t nlink; /* [DIR] # of child directories. [REG] link count. */
|
||||
int16_t uid;
|
||||
int16_t gid;
|
||||
v7fs_off_t filesize; /* byte */
|
||||
#define V7FS_DINODE_ADDR_LEN 40
|
||||
/* 39 used; 13 addresses of 3 byte each. */
|
||||
uint8_t addr[V7FS_DINODE_ADDR_LEN];
|
||||
/*for device node: addr[0] is major << 8 | minor. */
|
||||
v7fs_time_t atime;
|
||||
v7fs_time_t mtime;
|
||||
v7fs_time_t ctime;
|
||||
} __packed; /*64byte */
|
||||
|
||||
/* File type */
|
||||
#define V7FS_IFMT 0170000 /* File type mask */
|
||||
#define V7FS_IFCHR 0020000 /* charcter device */
|
||||
#define V7FS_IFDIR 0040000 /* directory */
|
||||
#define V7FS_IFBLK 0060000 /* block device */
|
||||
#define V7FS_IFREG 0100000 /* file. */
|
||||
/* Obsoleted file type. */
|
||||
#define V7FS_IFMPC 0030000 /* multiplexed char special */
|
||||
#define V7FS_IFMPB 0070000 /* multiplexed block special */
|
||||
/* Don't apear original V7 filesystem. Found at 2.10BSD. */
|
||||
#define V7FSBSD_IFLNK 0120000 /* symbolic link */
|
||||
#define V7FSBSD_IFSOCK 0140000 /* socket */
|
||||
/* Don't apear original V7 filesystem. NetBSD. */
|
||||
#define V7FSBSD_IFFIFO 0010000 /* Named pipe. */
|
||||
|
||||
#define V7FSBSD_MAXSYMLINKS 8
|
||||
|
||||
#endif /*!_V7FS_H_ */
|
40
sys/fs/v7fs/v7fs_args.h
Normal file
40
sys/fs/v7fs/v7fs_args.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* $NetBSD: v7fs_args.h,v 1.1 2011/06/27 11:52:24 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2004, 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _FS_V7FS_V7FS_ARGS_H_
|
||||
#define _FS_V7FS_V7FS_ARGS_H_
|
||||
|
||||
struct v7fs_args {
|
||||
char *fspec; /* blocks special holding the fs to mount */
|
||||
int endian; /* target filesystem endian */
|
||||
};
|
||||
|
||||
#endif /* _FS_V7FS_V7FS_ARGS_H_ */
|
721
sys/fs/v7fs/v7fs_datablock.c
Normal file
721
sys/fs/v7fs/v7fs_datablock.c
Normal file
@ -0,0 +1,721 @@
|
||||
/* $NetBSD: v7fs_datablock.c,v 1.1 2011/06/27 11:52:24 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: v7fs_datablock.c,v 1.1 2011/06/27 11:52:24 uch Exp $");
|
||||
#if defined _KERNEL_OPT
|
||||
#include "opt_v7fs.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef _KERNEL
|
||||
#include <sys/systm.h>
|
||||
#include <sys/param.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include "v7fs.h"
|
||||
#include "v7fs_impl.h"
|
||||
#include "v7fs_endian.h"
|
||||
#include "v7fs_inode.h"
|
||||
#include "v7fs_datablock.h"
|
||||
#include "v7fs_superblock.h"
|
||||
|
||||
#ifdef V7FS_DATABLOCK_DEBUG
|
||||
#define DPRINTF(fmt, args...) printf("%s: " fmt, __func__, ##args)
|
||||
#else
|
||||
#define DPRINTF(fmt, args...) ((void)0)
|
||||
#endif
|
||||
|
||||
struct v7fs_daddr_map {
|
||||
int level; /* direct, index1, index2, index3 */
|
||||
v7fs_daddr_t index[3];
|
||||
};
|
||||
|
||||
static int v7fs_datablock_addr(size_t, struct v7fs_daddr_map *);
|
||||
static int v7fs_datablock_deallocate(struct v7fs_self *, v7fs_daddr_t);
|
||||
static int loop1(struct v7fs_self *, v7fs_daddr_t, size_t *,
|
||||
int (*)(struct v7fs_self *, void *, v7fs_daddr_t, size_t), void *);
|
||||
static int loop2(struct v7fs_self *, v7fs_daddr_t, size_t *,
|
||||
int (*)(struct v7fs_self *, void *, v7fs_daddr_t, size_t), void *);
|
||||
static v7fs_daddr_t link(struct v7fs_self *, v7fs_daddr_t, int);
|
||||
static v7fs_daddr_t add_leaf(struct v7fs_self *, v7fs_daddr_t, int);
|
||||
static v7fs_daddr_t unlink(struct v7fs_self *, v7fs_daddr_t, int);
|
||||
static v7fs_daddr_t remove_leaf(struct v7fs_self *, v7fs_daddr_t, int);
|
||||
static v7fs_daddr_t remove_self(struct v7fs_self *, v7fs_daddr_t);
|
||||
|
||||
#ifdef V7FS_DATABLOCK_DEBUG
|
||||
void daddr_map_dump(const struct v7fs_daddr_map *);
|
||||
#else
|
||||
#define daddr_map_dump(x) ((void)0)
|
||||
#endif
|
||||
|
||||
bool
|
||||
datablock_number_sanity(const struct v7fs_self *fs, v7fs_daddr_t blk)
|
||||
{
|
||||
const struct v7fs_superblock *sb = &fs->superblock;
|
||||
bool ok = (blk >= sb->datablock_start_sector) &&
|
||||
(blk < sb->volume_size);
|
||||
|
||||
#ifdef V7FS_DATABLOCK_DEBUG
|
||||
if (!ok) {
|
||||
DPRINTF("Bad data block #%d\n", blk);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_datablock_allocate(struct v7fs_self *fs, v7fs_daddr_t *block_number)
|
||||
{
|
||||
struct v7fs_superblock *sb = &fs->superblock;
|
||||
v7fs_daddr_t blk;
|
||||
int error = 0;
|
||||
|
||||
*block_number = 0;
|
||||
SUPERB_LOCK(fs);
|
||||
do {
|
||||
if (!sb->total_freeblock) {
|
||||
DPRINTF("free block exhausted!!!\n");
|
||||
SUPERB_UNLOCK(fs);
|
||||
return ENOSPC;
|
||||
}
|
||||
|
||||
/* Get free block from superblock cache. */
|
||||
blk = sb->freeblock[--sb->nfreeblock];
|
||||
sb->total_freeblock--;
|
||||
sb->modified = 1;
|
||||
|
||||
/* If nfreeblock is zero, it block is next freeblock link. */
|
||||
if (sb->nfreeblock == 0) {
|
||||
if ((error = v7fs_freeblock_update(fs, blk))) {
|
||||
DPRINTF("no freeblock!!!\n");
|
||||
SUPERB_UNLOCK(fs);
|
||||
return error;
|
||||
}
|
||||
/* This freeblock link is no longer required. */
|
||||
/* use as data block. */
|
||||
}
|
||||
} while (!datablock_number_sanity(fs, blk)); /* skip bogus block. */
|
||||
SUPERB_UNLOCK(fs);
|
||||
|
||||
DPRINTF("Get freeblock %d\n", blk);
|
||||
/* Zero clear datablock. */
|
||||
void *buf;
|
||||
if (!(buf = scratch_read(fs, blk)))
|
||||
return EIO;
|
||||
memset(buf, 0, V7FS_BSIZE);
|
||||
if (!fs->io.write(fs->io.cookie, buf, blk))
|
||||
error = EIO;
|
||||
scratch_free(fs, buf);
|
||||
|
||||
if (error == 0)
|
||||
*block_number = blk;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
v7fs_datablock_deallocate(struct v7fs_self *fs, v7fs_daddr_t blk)
|
||||
{
|
||||
struct v7fs_superblock *sb = &fs->superblock;
|
||||
void *buf;
|
||||
int error = 0;
|
||||
|
||||
if (!datablock_number_sanity(fs, blk))
|
||||
return EIO;
|
||||
|
||||
/* Add to in-core freelist. */
|
||||
SUPERB_LOCK(fs);
|
||||
if (sb->nfreeblock < V7FS_MAX_FREEBLOCK) {
|
||||
sb->freeblock[sb->nfreeblock++] = blk;
|
||||
sb->total_freeblock++;
|
||||
sb->modified = 1;
|
||||
DPRINTF("n_freeblock=%d\n", sb->total_freeblock);
|
||||
SUPERB_UNLOCK(fs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* No space to push. */
|
||||
/* Make this block to freeblock list.and current cache moved to this. */
|
||||
if (!(buf = scratch_read(fs, blk))) {
|
||||
SUPERB_UNLOCK(fs);
|
||||
return EIO; /* Fatal */
|
||||
}
|
||||
|
||||
struct v7fs_freeblock *fb = (struct v7fs_freeblock *)buf;
|
||||
fb->nfreeblock = V7FS_MAX_FREEBLOCK;
|
||||
int i;
|
||||
for (i = 0; i < V7FS_MAX_FREEBLOCK; i++)
|
||||
fb->freeblock[i] = V7FS_VAL32(fs, sb->freeblock[i]);
|
||||
|
||||
if (!fs->io.write(fs->io.cookie, (uint8_t *)fb, blk)) {
|
||||
error = EIO; /* Fatal */
|
||||
} else {
|
||||
/* Link. on next allocate, this block is used as datablock, */
|
||||
/* and swap outed freeblock list is restored. */
|
||||
sb->freeblock[0] = blk;
|
||||
sb->nfreeblock = 1;
|
||||
sb->total_freeblock++;
|
||||
sb->modified = 1;
|
||||
DPRINTF("n_freeblock=%d\n", sb->total_freeblock);
|
||||
}
|
||||
SUPERB_UNLOCK(fs);
|
||||
scratch_free(fs, buf);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
v7fs_datablock_addr(size_t sz, struct v7fs_daddr_map *map)
|
||||
{
|
||||
#define NIDX V7FS_DADDR_PER_BLOCK
|
||||
#define DIRECT_SZ (V7FS_NADDR_DIRECT * V7FS_BSIZE)
|
||||
#define IDX1_SZ (NIDX * V7FS_BSIZE)
|
||||
#define IDX2_SZ (NIDX * NIDX * V7FS_BSIZE)
|
||||
#define ROUND(x, a) ((((x) + ((a) - 1)) & ~((a) - 1)))
|
||||
if (!sz) {
|
||||
map->level = 0;
|
||||
map->index[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sz = V7FS_ROUND_BSIZE(sz);
|
||||
|
||||
/* Direct */
|
||||
if (sz <= DIRECT_SZ) {
|
||||
map->level = 0;
|
||||
map->index[0] = (sz >> V7FS_BSHIFT) - 1;
|
||||
return 0;
|
||||
}
|
||||
/* Index 1 */
|
||||
sz -= DIRECT_SZ;
|
||||
|
||||
if (sz <= IDX1_SZ) {
|
||||
map->level = 1;
|
||||
map->index[0] = (sz >> V7FS_BSHIFT) - 1;
|
||||
return 0;
|
||||
}
|
||||
sz -= IDX1_SZ;
|
||||
|
||||
/* Index 2 */
|
||||
if (sz <= IDX2_SZ) {
|
||||
map->level = 2;
|
||||
map->index[0] = ROUND(sz, IDX1_SZ) / IDX1_SZ - 1;
|
||||
map->index[1] = ((sz - (map->index[0] * IDX1_SZ)) >>
|
||||
V7FS_BSHIFT) - 1;
|
||||
return 0;
|
||||
}
|
||||
sz -= IDX2_SZ;
|
||||
|
||||
/* Index 3 */
|
||||
map->level = 3;
|
||||
map->index[0] = ROUND(sz, IDX2_SZ) / IDX2_SZ - 1;
|
||||
sz -= map->index[0] * IDX2_SZ;
|
||||
map->index[1] = ROUND(sz, IDX1_SZ) / IDX1_SZ - 1;
|
||||
sz -= map->index[1] * IDX1_SZ;
|
||||
map->index[2] = (sz >> V7FS_BSHIFT) - 1;
|
||||
|
||||
return map->index[2] >= NIDX ? ENOSPC : 0;
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_datablock_foreach(struct v7fs_self *fs, struct v7fs_inode *p,
|
||||
int (*func)(struct v7fs_self *, void *, v7fs_daddr_t, size_t), void *ctx)
|
||||
{
|
||||
size_t i;
|
||||
v7fs_daddr_t blk, blk2;
|
||||
size_t filesize;
|
||||
bool last;
|
||||
int ret;
|
||||
|
||||
if (!(filesize = v7fs_inode_filesize(p)))
|
||||
return 0;
|
||||
#ifdef V7FS_DATABLOCK_DEBUG
|
||||
size_t sz = filesize;
|
||||
#endif
|
||||
|
||||
/* Direct */
|
||||
for (i = 0; i < V7FS_NADDR_DIRECT; i++, filesize -= V7FS_BSIZE) {
|
||||
blk = p->addr[i];
|
||||
if (!datablock_number_sanity(fs, blk)) {
|
||||
DPRINTF("inode#%d direct=%zu filesize=%zu\n",
|
||||
p->inode_number, i, sz);
|
||||
return EIO;
|
||||
}
|
||||
|
||||
last = filesize <= V7FS_BSIZE;
|
||||
if ((ret = func(fs, ctx, blk, last ? filesize : V7FS_BSIZE)))
|
||||
return ret;
|
||||
if (last)
|
||||
return V7FS_ITERATOR_END;
|
||||
}
|
||||
|
||||
/* Index 1 */
|
||||
blk = p->addr[V7FS_NADDR_INDEX1];
|
||||
if (!datablock_number_sanity(fs, blk))
|
||||
return EIO;
|
||||
|
||||
if ((ret = loop1(fs, blk, &filesize, func, ctx)))
|
||||
return ret;
|
||||
|
||||
/* Index 2 */
|
||||
blk = p->addr[V7FS_NADDR_INDEX2];
|
||||
if (!datablock_number_sanity(fs, blk))
|
||||
return EIO;
|
||||
|
||||
if ((ret = loop2(fs, blk, &filesize, func, ctx)))
|
||||
return ret;
|
||||
|
||||
/* Index 3 */
|
||||
blk = p->addr[V7FS_NADDR_INDEX3];
|
||||
if (!datablock_number_sanity(fs, blk))
|
||||
return EIO;
|
||||
|
||||
for (i = 0; i < V7FS_DADDR_PER_BLOCK; i++) {
|
||||
blk2 = link(fs, blk, i);
|
||||
if (!datablock_number_sanity(fs, blk))
|
||||
return EIO;
|
||||
|
||||
if ((ret = loop2(fs, blk2, &filesize, func, ctx)))
|
||||
return ret;
|
||||
}
|
||||
|
||||
return EFBIG;
|
||||
}
|
||||
|
||||
static int
|
||||
loop2(struct v7fs_self *fs, v7fs_daddr_t listblk, size_t *filesize,
|
||||
int (*func)(struct v7fs_self *, void *, v7fs_daddr_t, size_t), void *ctx)
|
||||
{
|
||||
v7fs_daddr_t blk;
|
||||
int ret;
|
||||
size_t j;
|
||||
|
||||
for (j = 0; j < V7FS_DADDR_PER_BLOCK; j++) {
|
||||
blk = link(fs, listblk, j);
|
||||
if (!datablock_number_sanity(fs, blk))
|
||||
return EIO;
|
||||
if ((ret = loop1(fs, blk, filesize, func, ctx)))
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
loop1(struct v7fs_self *fs, v7fs_daddr_t listblk, size_t *filesize,
|
||||
int (*func)(struct v7fs_self *, void *, v7fs_daddr_t, size_t), void *ctx)
|
||||
{
|
||||
v7fs_daddr_t blk;
|
||||
bool last;
|
||||
int ret;
|
||||
size_t k;
|
||||
|
||||
for (k = 0; k < V7FS_DADDR_PER_BLOCK; k++, *filesize -= V7FS_BSIZE) {
|
||||
blk = link(fs, listblk, k);
|
||||
if (!datablock_number_sanity(fs, blk))
|
||||
return EIO;
|
||||
last = *filesize <= V7FS_BSIZE;
|
||||
if ((ret = func(fs, ctx, blk, last ? *filesize : V7FS_BSIZE)))
|
||||
return ret;
|
||||
if (last)
|
||||
return V7FS_ITERATOR_END;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
v7fs_daddr_t
|
||||
v7fs_datablock_last(struct v7fs_self *fs, struct v7fs_inode *inode,
|
||||
v7fs_off_t ofs)
|
||||
{
|
||||
struct v7fs_daddr_map map;
|
||||
v7fs_daddr_t blk = 0;
|
||||
v7fs_daddr_t *addr = inode->addr;
|
||||
|
||||
/* Inquire last data block location. */
|
||||
if (v7fs_datablock_addr(ofs, &map) != 0)
|
||||
return 0;
|
||||
|
||||
switch (map.level)
|
||||
{
|
||||
case 0: /*Direct */
|
||||
blk = inode->addr[map.index[0]];
|
||||
break;
|
||||
case 1: /*Index1 */
|
||||
blk = link(fs, addr[V7FS_NADDR_INDEX1], map.index[0]);
|
||||
break;
|
||||
case 2: /*Index2 */
|
||||
blk = link(fs, link(fs, addr[V7FS_NADDR_INDEX2], map.index[0]),
|
||||
map.index[1]);
|
||||
break;
|
||||
case 3: /*Index3 */
|
||||
blk = link(fs, link(fs, link(fs, addr[V7FS_NADDR_INDEX3],
|
||||
map.index[0]), map.index[1]), map.index[2]);
|
||||
break;
|
||||
}
|
||||
|
||||
return blk;
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_datablock_expand(struct v7fs_self *fs, struct v7fs_inode *inode, size_t sz)
|
||||
{
|
||||
size_t old_filesize = inode->filesize;
|
||||
size_t new_filesize = old_filesize + sz;
|
||||
struct v7fs_daddr_map oldmap, newmap;
|
||||
v7fs_daddr_t blk, idxblk;
|
||||
int error;
|
||||
v7fs_daddr_t old_nblk = V7FS_ROUND_BSIZE(old_filesize) >> V7FS_BSHIFT;
|
||||
v7fs_daddr_t new_nblk = V7FS_ROUND_BSIZE(new_filesize) >> V7FS_BSHIFT;
|
||||
|
||||
if (old_nblk == new_nblk) {
|
||||
inode->filesize += sz;
|
||||
v7fs_inode_writeback(fs, inode);
|
||||
return 0; /* no need to expand. */
|
||||
}
|
||||
struct v7fs_inode backup = *inode;
|
||||
v7fs_daddr_t required_blk = new_nblk - old_nblk;
|
||||
|
||||
DPRINTF("%zu->%zu, required block=%d\n", old_filesize, new_filesize,
|
||||
required_blk);
|
||||
|
||||
v7fs_datablock_addr(old_filesize, &oldmap);
|
||||
v7fs_daddr_t i;
|
||||
for (i = 0; i < required_blk; i++) {
|
||||
v7fs_datablock_addr(old_filesize + (i+1) * V7FS_BSIZE, &newmap);
|
||||
daddr_map_dump(&oldmap);
|
||||
daddr_map_dump(&newmap);
|
||||
|
||||
if (oldmap.level != newmap.level) {
|
||||
/* Allocate index area */
|
||||
if ((error = v7fs_datablock_allocate(fs, &idxblk)))
|
||||
return error;
|
||||
|
||||
switch (newmap.level) {
|
||||
case 1:
|
||||
DPRINTF("0->1\n");
|
||||
inode->addr[V7FS_NADDR_INDEX1] = idxblk;
|
||||
blk = add_leaf(fs, idxblk, 0);
|
||||
break;
|
||||
case 2:
|
||||
DPRINTF("1->2\n");
|
||||
inode->addr[V7FS_NADDR_INDEX2] = idxblk;
|
||||
blk = add_leaf(fs, add_leaf(fs, idxblk, 0), 0);
|
||||
break;
|
||||
case 3:
|
||||
DPRINTF("2->3\n");
|
||||
inode->addr[V7FS_NADDR_INDEX3] = idxblk;
|
||||
blk = add_leaf(fs, add_leaf(fs, add_leaf(fs,
|
||||
idxblk, 0), 0), 0);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (newmap.level) {
|
||||
case 0:
|
||||
if ((error = v7fs_datablock_allocate(fs, &blk)))
|
||||
return error;
|
||||
inode->addr[newmap.index[0]] = blk;
|
||||
DPRINTF("direct index %d = blk%d\n",
|
||||
newmap.index[0], blk);
|
||||
break;
|
||||
case 1:
|
||||
idxblk = inode->addr[V7FS_NADDR_INDEX1];
|
||||
blk = add_leaf(fs, idxblk, newmap.index[0]);
|
||||
break;
|
||||
case 2:
|
||||
idxblk = inode->addr[V7FS_NADDR_INDEX2];
|
||||
if (oldmap.index[0] != newmap.index[0])
|
||||
add_leaf(fs, idxblk, newmap.index[0]);
|
||||
blk = add_leaf(fs, link(fs,idxblk,
|
||||
newmap.index[0]), newmap.index[1]);
|
||||
break;
|
||||
case 3:
|
||||
idxblk = inode->addr[V7FS_NADDR_INDEX3];
|
||||
|
||||
if (oldmap.index[0] != newmap.index[0])
|
||||
add_leaf(fs, idxblk, newmap.index[0]);
|
||||
|
||||
if (oldmap.index[1] != newmap.index[1])
|
||||
add_leaf(fs, link(fs, idxblk,
|
||||
newmap.index[0]), newmap.index[1]);
|
||||
blk = add_leaf(fs, link(fs, link(fs, idxblk,
|
||||
newmap.index[0]), newmap.index[1]),
|
||||
newmap.index[2]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!blk) {
|
||||
*inode = backup; /* structure copy; */
|
||||
return ENOSPC;
|
||||
}
|
||||
oldmap = newmap;
|
||||
}
|
||||
inode->filesize += sz;
|
||||
v7fs_inode_writeback(fs, inode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static v7fs_daddr_t
|
||||
link(struct v7fs_self *fs, v7fs_daddr_t listblk, int n)
|
||||
{
|
||||
v7fs_daddr_t *list;
|
||||
v7fs_daddr_t blk;
|
||||
void *buf;
|
||||
|
||||
if (!datablock_number_sanity(fs, listblk))
|
||||
return 0;
|
||||
if (!(buf = scratch_read(fs, listblk)))
|
||||
return 0;
|
||||
list = (v7fs_daddr_t *)buf;
|
||||
blk = V7FS_VAL32(fs, list[n]);
|
||||
scratch_free(fs, buf);
|
||||
|
||||
if (!datablock_number_sanity(fs, blk))
|
||||
return 0;
|
||||
|
||||
return blk;
|
||||
}
|
||||
|
||||
static v7fs_daddr_t
|
||||
add_leaf(struct v7fs_self *fs, v7fs_daddr_t up, int idx)
|
||||
{
|
||||
v7fs_daddr_t newblk;
|
||||
v7fs_daddr_t *daddr_list;
|
||||
int error = 0;
|
||||
void *buf;
|
||||
|
||||
if (!up)
|
||||
return 0;
|
||||
if (!datablock_number_sanity(fs, up))
|
||||
return 0;
|
||||
|
||||
if ((error = v7fs_datablock_allocate(fs, &newblk)))
|
||||
return 0;
|
||||
if (!(buf = scratch_read(fs, up)))
|
||||
return 0;
|
||||
daddr_list = (v7fs_daddr_t *)buf;
|
||||
daddr_list[idx] = V7FS_VAL32(fs, newblk);
|
||||
if (!fs->io.write(fs->io.cookie, buf, up))
|
||||
newblk = 0;
|
||||
scratch_free(fs, buf);
|
||||
|
||||
return newblk;
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_datablock_contract(struct v7fs_self *fs, struct v7fs_inode *inode,
|
||||
size_t sz)
|
||||
{
|
||||
size_t old_filesize = inode->filesize;
|
||||
size_t new_filesize = old_filesize - sz;
|
||||
struct v7fs_daddr_map oldmap, newmap;
|
||||
v7fs_daddr_t blk, idxblk;
|
||||
int error = 0;
|
||||
v7fs_daddr_t old_nblk = V7FS_ROUND_BSIZE(old_filesize) >> V7FS_BSHIFT;
|
||||
v7fs_daddr_t new_nblk = V7FS_ROUND_BSIZE(new_filesize) >> V7FS_BSHIFT;
|
||||
|
||||
if (old_nblk == new_nblk) {
|
||||
inode->filesize -= sz;
|
||||
v7fs_inode_writeback(fs, inode);
|
||||
return 0; /* no need to contract; */
|
||||
}
|
||||
v7fs_daddr_t erase_blk = old_nblk - new_nblk;
|
||||
|
||||
DPRINTF("%zu->%zu # of erased block=%d\n", old_filesize, new_filesize,
|
||||
erase_blk);
|
||||
|
||||
v7fs_datablock_addr(old_filesize, &oldmap);
|
||||
v7fs_daddr_t i;
|
||||
for (i = 0; i < erase_blk; i++) {
|
||||
v7fs_datablock_addr(old_filesize - (i+1) * V7FS_BSIZE, &newmap);
|
||||
|
||||
if (oldmap.level != newmap.level) {
|
||||
switch (newmap.level) {
|
||||
case 0: /*1->0 */
|
||||
DPRINTF("1->0\n");
|
||||
idxblk = inode->addr[V7FS_NADDR_INDEX1];
|
||||
inode->addr[V7FS_NADDR_INDEX1] = 0;
|
||||
error = v7fs_datablock_deallocate(fs,
|
||||
remove_self(fs, idxblk));
|
||||
break;
|
||||
case 1: /*2->1 */
|
||||
DPRINTF("2->1\n");
|
||||
idxblk = inode->addr[V7FS_NADDR_INDEX2];
|
||||
inode->addr[V7FS_NADDR_INDEX2] = 0;
|
||||
error = v7fs_datablock_deallocate(fs,
|
||||
remove_self(fs, remove_self(fs, idxblk)));
|
||||
break;
|
||||
case 2:/*3->2 */
|
||||
DPRINTF("3->2\n");
|
||||
idxblk = inode->addr[V7FS_NADDR_INDEX3];
|
||||
inode->addr[V7FS_NADDR_INDEX3] = 0;
|
||||
error = v7fs_datablock_deallocate(fs,
|
||||
remove_self(fs, remove_self(fs,
|
||||
remove_self(fs, idxblk))));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (newmap.level) {
|
||||
case 0:
|
||||
DPRINTF("[0] %d\n", oldmap.index[0]);
|
||||
blk = inode->addr[oldmap.index[0]];
|
||||
error = v7fs_datablock_deallocate(fs, blk);
|
||||
break;
|
||||
case 1:
|
||||
DPRINTF("[1] %d\n", oldmap.index[0]);
|
||||
idxblk = inode->addr[V7FS_NADDR_INDEX1];
|
||||
remove_leaf(fs, idxblk, oldmap.index[0]);
|
||||
|
||||
break;
|
||||
case 2:
|
||||
DPRINTF("[2] %d %d\n", oldmap.index[0],
|
||||
oldmap.index[1]);
|
||||
idxblk = inode->addr[V7FS_NADDR_INDEX2];
|
||||
remove_leaf(fs, link(fs, idxblk,
|
||||
oldmap.index[0]), oldmap.index[1]);
|
||||
if (oldmap.index[0] != newmap.index[0]) {
|
||||
remove_leaf(fs, idxblk,
|
||||
oldmap.index[0]);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
DPRINTF("[2] %d %d %d\n", oldmap.index[0],
|
||||
oldmap.index[1], oldmap.index[2]);
|
||||
idxblk = inode->addr[V7FS_NADDR_INDEX3];
|
||||
remove_leaf(fs, link(fs, link(fs, idxblk,
|
||||
oldmap.index[0]), oldmap.index[1]),
|
||||
oldmap.index[2]);
|
||||
|
||||
if (oldmap.index[1] != newmap.index[1]) {
|
||||
remove_leaf(fs, link(fs, idxblk,
|
||||
oldmap.index[0]), oldmap.index[1]);
|
||||
}
|
||||
if (oldmap.index[0] != newmap.index[0]) {
|
||||
remove_leaf(fs, idxblk,
|
||||
oldmap.index[0]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
oldmap = newmap;
|
||||
}
|
||||
inode->filesize -= sz;
|
||||
v7fs_inode_writeback(fs, inode);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static v7fs_daddr_t
|
||||
unlink(struct v7fs_self *fs, v7fs_daddr_t idxblk, int n)
|
||||
{
|
||||
v7fs_daddr_t *daddr_list;
|
||||
v7fs_daddr_t blk;
|
||||
void *buf;
|
||||
|
||||
if (!(buf = scratch_read(fs, idxblk)))
|
||||
return 0;
|
||||
daddr_list = (v7fs_daddr_t *)buf;
|
||||
blk = V7FS_VAL32(fs, daddr_list[n]);
|
||||
daddr_list[n] = 0;
|
||||
fs->io.write(fs->io.cookie, buf, idxblk);
|
||||
scratch_free(fs, buf);
|
||||
|
||||
return blk; /* unlinked block. */
|
||||
}
|
||||
|
||||
static v7fs_daddr_t
|
||||
remove_self(struct v7fs_self *fs, v7fs_daddr_t up)
|
||||
{
|
||||
v7fs_daddr_t down;
|
||||
|
||||
if (!datablock_number_sanity(fs, up))
|
||||
return 0;
|
||||
|
||||
/* At 1st, remove from datablock list. */
|
||||
down = unlink(fs, up, 0);
|
||||
|
||||
/* link self to freelist. */
|
||||
v7fs_datablock_deallocate(fs, up);
|
||||
|
||||
return down;
|
||||
}
|
||||
|
||||
static v7fs_daddr_t
|
||||
remove_leaf(struct v7fs_self *fs, v7fs_daddr_t up, int n)
|
||||
{
|
||||
v7fs_daddr_t down;
|
||||
|
||||
if (!datablock_number_sanity(fs, up))
|
||||
return 0;
|
||||
|
||||
/* At 1st, remove from datablock list. */
|
||||
down = unlink(fs, up, n);
|
||||
|
||||
/* link leaf to freelist. */
|
||||
v7fs_datablock_deallocate(fs, down);
|
||||
|
||||
return down;
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_datablock_size_change(struct v7fs_self *fs, size_t newsz,
|
||||
struct v7fs_inode *inode)
|
||||
{
|
||||
ssize_t diff = newsz - v7fs_inode_filesize(inode);
|
||||
int error = 0;
|
||||
|
||||
if (diff > 0)
|
||||
error = v7fs_datablock_expand(fs, inode, diff);
|
||||
else if (diff < 0)
|
||||
error = v7fs_datablock_contract(fs, inode, -diff);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
#ifdef V7FS_DATABLOCK_DEBUG
|
||||
void
|
||||
daddr_map_dump(const struct v7fs_daddr_map *map)
|
||||
{
|
||||
|
||||
DPRINTF("level %d ", map->level);
|
||||
int m, n = !map->level ? 1 : map->level;
|
||||
for (m = 0; m < n; m++)
|
||||
printf("[%d]", map->index[m]);
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
46
sys/fs/v7fs/v7fs_datablock.h
Normal file
46
sys/fs/v7fs/v7fs_datablock.h
Normal file
@ -0,0 +1,46 @@
|
||||
/* $NetBSD: v7fs_datablock.h,v 1.1 2011/06/27 11:52:24 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _V7FS_DATABLOCK_H_
|
||||
#define _V7FS_DATABLOCK_H_
|
||||
|
||||
__BEGIN_DECLS
|
||||
bool datablock_number_sanity(const struct v7fs_self *, v7fs_daddr_t);
|
||||
int v7fs_datablock_allocate(struct v7fs_self *, v7fs_daddr_t *);
|
||||
int v7fs_datablock_foreach(struct v7fs_self *, struct v7fs_inode *,
|
||||
int (*)(struct v7fs_self *, void *, v7fs_daddr_t, size_t), void *);
|
||||
v7fs_daddr_t v7fs_datablock_last(struct v7fs_self *, struct v7fs_inode *,
|
||||
v7fs_off_t);
|
||||
int v7fs_datablock_expand(struct v7fs_self *, struct v7fs_inode *, size_t);
|
||||
int v7fs_datablock_contract(struct v7fs_self *, struct v7fs_inode *, size_t);
|
||||
int v7fs_datablock_size_change(struct v7fs_self *, size_t, struct v7fs_inode *);
|
||||
__END_DECLS
|
||||
#endif /*!_V7FS_INODE_H_ */
|
85
sys/fs/v7fs/v7fs_dirent.c
Normal file
85
sys/fs/v7fs/v7fs_dirent.c
Normal file
@ -0,0 +1,85 @@
|
||||
/* $NetBSD: v7fs_dirent.c,v 1.1 2011/06/27 11:52:24 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: v7fs_dirent.c,v 1.1 2011/06/27 11:52:24 uch Exp $");
|
||||
#if defined _KERNEL_OPT
|
||||
#include "opt_v7fs.h"
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <sys/systm.h>
|
||||
#include <sys/param.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "v7fs.h"
|
||||
#include "v7fs_impl.h"
|
||||
#include "v7fs_endian.h"
|
||||
#include "v7fs_inode.h"
|
||||
#include "v7fs_dirent.h"
|
||||
|
||||
#ifdef V7FS_DIRENT_DEBUG
|
||||
#define DPRINTF(fmt, args...) printf("%s: " fmt, __func__, ##args)
|
||||
#else
|
||||
#define DPRINTF(fmt, args...) ((void)0)
|
||||
#endif
|
||||
|
||||
bool
|
||||
v7fs_dirent_endian_convert(struct v7fs_self *fs, struct v7fs_dirent *dir, int n)
|
||||
{
|
||||
struct v7fs_superblock *sb = &fs->superblock;
|
||||
int i;
|
||||
v7fs_ino_t ino;
|
||||
bool ok = true;
|
||||
|
||||
for (i = 0; i < n; i++, dir++) {
|
||||
ino = V7FS_VAL16(fs, dir->inode_number);
|
||||
if (v7fs_inode_number_sanity(sb, ino)) {
|
||||
DPRINTF("Invalid inode# %d %s\n", ino, dir->name);
|
||||
ok = false;
|
||||
}
|
||||
dir->inode_number = ino;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
void
|
||||
v7fs_dirent_filename(char *dst/* size must be V7FS_NAME_MAX + 1 */,
|
||||
const char *src)
|
||||
{
|
||||
|
||||
strncpy(dst, src, V7FS_NAME_MAX);
|
||||
dst[V7FS_NAME_MAX] = '\0';
|
||||
}
|
38
sys/fs/v7fs/v7fs_dirent.h
Normal file
38
sys/fs/v7fs/v7fs_dirent.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* $NetBSD: v7fs_dirent.h,v 1.1 2011/06/27 11:52:24 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _V7FS_DIRENT_H_
|
||||
#define _V7FS_DIRENT_H_
|
||||
__BEGIN_DECLS
|
||||
bool v7fs_dirent_endian_convert(struct v7fs_self *, struct v7fs_dirent *, int);
|
||||
void v7fs_dirent_filename(char *, const char *);
|
||||
__END_DECLS
|
||||
#endif /*!_V7FS_DIRENT_H_ */
|
227
sys/fs/v7fs/v7fs_endian.c
Normal file
227
sys/fs/v7fs/v7fs_endian.c
Normal file
@ -0,0 +1,227 @@
|
||||
/* $NetBSD: v7fs_endian.c,v 1.1 2011/06/27 11:52:24 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: v7fs_endian.c,v 1.1 2011/06/27 11:52:24 uch Exp $");
|
||||
#if defined _KERNEL_OPT
|
||||
#include "opt_v7fs.h"
|
||||
#endif
|
||||
|
||||
#include "v7fs.h"
|
||||
#include "v7fs_endian.h"
|
||||
#include "v7fs_impl.h"
|
||||
|
||||
#ifndef BYTE_ORDER
|
||||
#error
|
||||
#endif
|
||||
|
||||
/* PDP to Little */
|
||||
#define bswap32pdp_le(x) \
|
||||
((uint32_t) \
|
||||
((((x) & 0xffff0000) >> 16) | \
|
||||
(((x) & 0x0000ffff) << 16)))
|
||||
/* PDP to Big */
|
||||
#define bswap32pdp_be(x) \
|
||||
((uint32_t) \
|
||||
((((x) & 0xff00ff00) >> 8) | \
|
||||
(((x) & 0x00ff00ff) << 8)))
|
||||
#ifdef V7FS_EI
|
||||
static uint32_t val32_normal_order(uint32_t);
|
||||
static uint32_t val32_reverse_order(uint32_t);
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
static uint32_t val32_pdp_to_little(uint32_t);
|
||||
#else
|
||||
static uint32_t val32_pdp_to_big(uint32_t);
|
||||
#endif
|
||||
static uint16_t val16_normal_order(uint16_t);
|
||||
static uint16_t val16_reverse_order(uint16_t);
|
||||
static v7fs_daddr_t val24_reverse_order_read(uint8_t *);
|
||||
static void val24_reverse_order_write(v7fs_daddr_t, uint8_t *);
|
||||
static v7fs_daddr_t val24_pdp_read(uint8_t *);
|
||||
static void val24_pdp_write(v7fs_daddr_t, uint8_t *);
|
||||
|
||||
static uint32_t
|
||||
val32_normal_order(uint32_t v)
|
||||
{
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
val32_reverse_order(uint32_t v)
|
||||
{
|
||||
|
||||
return bswap32(v);
|
||||
}
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
static uint32_t
|
||||
val32_pdp_to_little(uint32_t v)
|
||||
{
|
||||
|
||||
return bswap32pdp_le(v);
|
||||
}
|
||||
#else
|
||||
static uint32_t
|
||||
val32_pdp_to_big(uint32_t v)
|
||||
{
|
||||
|
||||
return bswap32pdp_be(v);
|
||||
}
|
||||
#endif
|
||||
static uint16_t
|
||||
val16_normal_order(uint16_t v)
|
||||
{
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
val16_reverse_order(uint16_t v)
|
||||
{
|
||||
|
||||
return bswap16(v);
|
||||
}
|
||||
|
||||
static v7fs_daddr_t
|
||||
val24_reverse_order_read(uint8_t *a)
|
||||
{
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
return (a[0] << 16) | (a[1] << 8) | a[2];
|
||||
#else
|
||||
return (a[2] << 16) | (a[1] << 8) | a[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
val24_reverse_order_write(v7fs_daddr_t addr, uint8_t *a)
|
||||
{
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
a[0] = (addr >> 16) & 0xff;
|
||||
a[1] = (addr >> 8) & 0xff;
|
||||
a[2] = addr & 0xff;
|
||||
#else
|
||||
a[0] = addr & 0xff;
|
||||
a[1] = (addr >> 8) & 0xff;
|
||||
a[2] = (addr >> 16) & 0xff;
|
||||
#endif
|
||||
}
|
||||
|
||||
static v7fs_daddr_t
|
||||
val24_pdp_read(uint8_t *a)
|
||||
{
|
||||
|
||||
return (a[0] << 16) | a[1] | (a[2] << 8);
|
||||
}
|
||||
|
||||
static void
|
||||
val24_pdp_write(v7fs_daddr_t addr, uint8_t *a)
|
||||
{
|
||||
|
||||
a[0] = (addr >> 16) & 0xff;
|
||||
a[1] = addr & 0xff;
|
||||
a[2] = (addr >> 8) & 0xff;
|
||||
}
|
||||
|
||||
void
|
||||
v7fs_endian_init(struct v7fs_self *fs)
|
||||
{
|
||||
struct endian_conversion_ops *ops = &fs->val;
|
||||
|
||||
switch (fs->endian)
|
||||
{
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
case LITTLE_ENDIAN:
|
||||
ops->conv32 = val32_normal_order;
|
||||
ops->conv16 = val16_normal_order;
|
||||
ops->conv24read = val24_normal_order_read;
|
||||
ops->conv24write = val24_normal_order_write;
|
||||
break;
|
||||
case BIG_ENDIAN:
|
||||
ops->conv32 = val32_reverse_order;
|
||||
ops->conv16 = val16_reverse_order;
|
||||
ops->conv24read = val24_reverse_order_read;
|
||||
ops->conv24write = val24_reverse_order_write;
|
||||
break;
|
||||
case PDP_ENDIAN:
|
||||
ops->conv32 = val32_pdp_to_little;
|
||||
ops->conv16 = val16_normal_order;
|
||||
ops->conv24read = val24_pdp_read;
|
||||
ops->conv24write = val24_pdp_write;
|
||||
break;
|
||||
#else /* BIG_ENDIAN */
|
||||
case LITTLE_ENDIAN:
|
||||
ops->conv32 = val32_reverse_order;
|
||||
ops->conv16 = val16_reverse_order;
|
||||
ops->conv24read = val24_reverse_order_read;
|
||||
ops->conv24write = val24_reverse_order_write;
|
||||
break;
|
||||
case BIG_ENDIAN:
|
||||
ops->conv32 = val32_normal_order;
|
||||
ops->conv16 = val16_normal_order;
|
||||
ops->conv24read = val24_normal_order_read;
|
||||
ops->conv24write = val24_normal_order_write;
|
||||
break;
|
||||
case PDP_ENDIAN:
|
||||
ops->conv32 = val32_pdp_to_big;
|
||||
ops->conv16 = val16_reverse_order;
|
||||
ops->conv24read = val24_pdp_read;
|
||||
ops->conv24write = val24_pdp_write;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif /* V7FS_EI */
|
||||
v7fs_daddr_t
|
||||
val24_normal_order_read(uint8_t *a)
|
||||
{
|
||||
/*(v7fs_daddr_t)cast is required for int 16bit system. */
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
return ((v7fs_daddr_t)a[2] << 16) | ((v7fs_daddr_t)a[1] << 8) |
|
||||
(v7fs_daddr_t)a[0];
|
||||
#else
|
||||
return ((v7fs_daddr_t)a[0] << 16) | ((v7fs_daddr_t)a[1] << 8) |
|
||||
(v7fs_daddr_t)a[2];
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
val24_normal_order_write(v7fs_daddr_t addr, uint8_t *a)
|
||||
{
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
a[0] = addr & 0xff;
|
||||
a[1] = (addr >> 8) & 0xff;
|
||||
a[2] = (addr >> 16) & 0xff;
|
||||
#else
|
||||
a[0] = (addr >> 16) & 0xff;
|
||||
a[1] = (addr >> 8) & 0xff;
|
||||
a[2] = addr & 0xff;
|
||||
#endif
|
||||
}
|
52
sys/fs/v7fs/v7fs_endian.h
Normal file
52
sys/fs/v7fs/v7fs_endian.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* $NetBSD: v7fs_endian.h,v 1.1 2011/06/27 11:52:24 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _V7FS_ENDIAN_H_
|
||||
#define _V7FS_ENDIAN_H_
|
||||
|
||||
struct v7fs_self;
|
||||
__BEGIN_DECLS;
|
||||
v7fs_daddr_t val24_normal_order_read(uint8_t *);
|
||||
void val24_normal_order_write(v7fs_daddr_t, uint8_t *);
|
||||
__END_DECLS
|
||||
#ifdef V7FS_EI
|
||||
#define V7FS_VAL32(x, v) ((*(x)->val.conv32)(v))
|
||||
#define V7FS_VAL16(x, v) ((*(x)->val.conv16)(v))
|
||||
#define V7FS_VAL24_READ(x, a) ((*(x)->val.conv24read)(a))
|
||||
#define V7FS_VAL24_WRITE(x, v, a) ((*(x)->val.conv24write)(v, a))
|
||||
void v7fs_endian_init(struct v7fs_self *);
|
||||
#else
|
||||
#define V7FS_VAL32(x, v) (v)
|
||||
#define V7FS_VAL16(x, v) (v)
|
||||
#define V7FS_VAL24_READ(x, a) (val24_normal_order_read(a))
|
||||
#define V7FS_VAL24_WRITE(x, v, a) (val24_normal_order_write(v, a))
|
||||
#endif /*V7FS_EI */
|
||||
#endif /*!_V7FS_ENDIAN_H_ */
|
262
sys/fs/v7fs/v7fs_extern.c
Normal file
262
sys/fs/v7fs/v7fs_extern.c
Normal file
@ -0,0 +1,262 @@
|
||||
/* $NetBSD: v7fs_extern.c,v 1.1 2011/06/27 11:52:24 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2004, 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: v7fs_extern.c,v 1.1 2011/06/27 11:52:24 uch Exp $");
|
||||
|
||||
#if defined _KERNEL_OPT
|
||||
#include "opt_v7fs.h"
|
||||
#endif
|
||||
#include <sys/resource.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
#include <miscfs/fifofs/fifo.h>
|
||||
#include <miscfs/genfs/genfs.h>
|
||||
#include <miscfs/genfs/genfs_node.h>
|
||||
|
||||
#include <fs/v7fs/v7fs_extern.h>
|
||||
|
||||
MODULE(MODULE_CLASS_VFS, v7fs, NULL);
|
||||
|
||||
/* External interfaces */
|
||||
|
||||
int (**v7fs_vnodeop_p)(void *); /* filled by getnewvnode (vnode.h) */
|
||||
|
||||
const struct vnodeopv_entry_desc v7fs_vnodeop_entries[] = {
|
||||
{ &vop_default_desc, vn_default_error },
|
||||
{ &vop_lookup_desc, v7fs_lookup }, /* lookup */
|
||||
{ &vop_create_desc, v7fs_create }, /* create */
|
||||
{ &vop_mknod_desc, v7fs_mknod }, /* mknod */
|
||||
{ &vop_open_desc, v7fs_open }, /* open */
|
||||
{ &vop_close_desc, v7fs_close }, /* close */
|
||||
{ &vop_access_desc, v7fs_access }, /* access */
|
||||
{ &vop_getattr_desc, v7fs_getattr }, /* getattr */
|
||||
{ &vop_setattr_desc, v7fs_setattr }, /* setattr */
|
||||
{ &vop_read_desc, v7fs_read }, /* read */
|
||||
{ &vop_write_desc, v7fs_write }, /* write */
|
||||
{ &vop_fcntl_desc, genfs_fcntl }, /* fcntl */
|
||||
{ &vop_ioctl_desc, genfs_enoioctl }, /* ioctl */
|
||||
{ &vop_poll_desc, genfs_poll }, /* poll */
|
||||
{ &vop_kqfilter_desc, genfs_kqfilter }, /* kqfilter */
|
||||
{ &vop_revoke_desc, genfs_revoke }, /* revoke */
|
||||
{ &vop_mmap_desc, genfs_mmap }, /* mmap */
|
||||
{ &vop_fsync_desc, v7fs_fsync }, /* fsync */
|
||||
{ &vop_seek_desc, genfs_seek }, /* seek */
|
||||
{ &vop_remove_desc, v7fs_remove }, /* remove */
|
||||
{ &vop_link_desc, v7fs_link }, /* link */
|
||||
{ &vop_rename_desc, v7fs_rename }, /* rename */
|
||||
{ &vop_mkdir_desc, v7fs_mkdir }, /* mkdir */
|
||||
{ &vop_rmdir_desc, v7fs_rmdir }, /* rmdir */
|
||||
{ &vop_symlink_desc, v7fs_symlink }, /* symlink */
|
||||
{ &vop_readdir_desc, v7fs_readdir }, /* readdir */
|
||||
{ &vop_readlink_desc, v7fs_readlink }, /* readlink */
|
||||
{ &vop_abortop_desc, genfs_abortop }, /* abortop */
|
||||
{ &vop_inactive_desc, v7fs_inactive }, /* inactive */
|
||||
{ &vop_reclaim_desc, v7fs_reclaim }, /* reclaim */
|
||||
{ &vop_lock_desc, genfs_lock }, /* lock */
|
||||
{ &vop_unlock_desc, genfs_unlock }, /* unlock */
|
||||
{ &vop_bmap_desc, v7fs_bmap }, /* bmap */
|
||||
{ &vop_strategy_desc, v7fs_strategy }, /* strategy */
|
||||
{ &vop_print_desc, v7fs_print }, /* print */
|
||||
{ &vop_islocked_desc, genfs_islocked }, /* islocked */
|
||||
{ &vop_pathconf_desc, v7fs_pathconf }, /* pathconf */
|
||||
{ &vop_advlock_desc, v7fs_advlock }, /* advlock */
|
||||
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */
|
||||
{ &vop_getpages_desc, genfs_getpages }, /* getpages */
|
||||
{ &vop_putpages_desc, genfs_putpages }, /* putpages */
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
int (**v7fs_specop_p)(void *);
|
||||
const struct vnodeopv_entry_desc v7fs_specop_entries[] = {
|
||||
{ &vop_default_desc, vn_default_error },
|
||||
{ &vop_lookup_desc, spec_lookup }, /* lookup */
|
||||
{ &vop_create_desc, spec_create }, /* create xxx*/
|
||||
{ &vop_mknod_desc, spec_mknod }, /* mknod xxx*/
|
||||
{ &vop_open_desc, spec_open }, /* open */
|
||||
{ &vop_close_desc, spec_close }, /* close */
|
||||
{ &vop_access_desc, v7fs_access }, /* access */
|
||||
{ &vop_getattr_desc, v7fs_getattr }, /* getattr */
|
||||
{ &vop_setattr_desc, v7fs_setattr }, /* setattr */
|
||||
{ &vop_read_desc, spec_read }, /* read */
|
||||
{ &vop_write_desc, spec_write }, /* write */
|
||||
{ &vop_ioctl_desc, spec_ioctl }, /* ioctl */
|
||||
{ &vop_fcntl_desc, genfs_fcntl }, /* fcntl */
|
||||
{ &vop_poll_desc, spec_poll }, /* poll */
|
||||
{ &vop_kqfilter_desc, spec_kqfilter }, /* kqfilter */
|
||||
{ &vop_revoke_desc, spec_revoke }, /* revoke */
|
||||
{ &vop_mmap_desc, spec_mmap }, /* mmap */
|
||||
{ &vop_fsync_desc, spec_fsync }, /* fsync */
|
||||
{ &vop_seek_desc, spec_seek }, /* seek */
|
||||
{ &vop_remove_desc, spec_remove }, /* remove */
|
||||
{ &vop_link_desc, spec_link }, /* link */
|
||||
{ &vop_rename_desc, spec_rename }, /* rename */
|
||||
{ &vop_mkdir_desc, spec_mkdir }, /* mkdir */
|
||||
{ &vop_rmdir_desc, spec_rmdir }, /* rmdir */
|
||||
{ &vop_symlink_desc, spec_symlink }, /* symlink */
|
||||
{ &vop_readdir_desc, spec_readdir }, /* readdir */
|
||||
{ &vop_readlink_desc, spec_readlink }, /* readlink */
|
||||
{ &vop_abortop_desc, spec_abortop }, /* abortop */
|
||||
{ &vop_inactive_desc, v7fs_inactive }, /* inactive */
|
||||
{ &vop_reclaim_desc, v7fs_reclaim }, /* reclaim */
|
||||
{ &vop_lock_desc, genfs_lock }, /* lock */
|
||||
{ &vop_unlock_desc, genfs_unlock }, /* unlock */
|
||||
{ &vop_bmap_desc, spec_bmap }, /* bmap */
|
||||
{ &vop_strategy_desc, spec_strategy }, /* strategy */
|
||||
{ &vop_print_desc, spec_print }, /* print */
|
||||
{ &vop_islocked_desc, genfs_islocked }, /* islocked */
|
||||
{ &vop_pathconf_desc, spec_pathconf }, /* pathconf */
|
||||
{ &vop_advlock_desc, spec_advlock }, /* advlock */
|
||||
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */
|
||||
{ &vop_getpages_desc, spec_getpages }, /* getpages */
|
||||
{ &vop_putpages_desc, spec_putpages }, /* putpages */
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
int (**v7fs_fifoop_p)(void *);
|
||||
const struct vnodeopv_entry_desc v7fs_fifoop_entries[] = {
|
||||
{ &vop_default_desc, vn_default_error },
|
||||
{ &vop_lookup_desc, vn_fifo_bypass }, /* lookup */
|
||||
{ &vop_create_desc, vn_fifo_bypass }, /* create */
|
||||
{ &vop_mknod_desc, vn_fifo_bypass }, /* mknod */
|
||||
{ &vop_open_desc, vn_fifo_bypass }, /* open */
|
||||
{ &vop_close_desc, vn_fifo_bypass }, /* close */
|
||||
{ &vop_access_desc, v7fs_access }, /* access */
|
||||
{ &vop_getattr_desc, v7fs_getattr }, /* getattr */
|
||||
{ &vop_setattr_desc, v7fs_setattr }, /* setattr */
|
||||
{ &vop_read_desc, vn_fifo_bypass }, /* read */
|
||||
{ &vop_write_desc, vn_fifo_bypass }, /* write */
|
||||
{ &vop_ioctl_desc, vn_fifo_bypass }, /* ioctl */
|
||||
{ &vop_fcntl_desc, genfs_fcntl }, /* fcntl */
|
||||
{ &vop_poll_desc, vn_fifo_bypass }, /* poll */
|
||||
{ &vop_kqfilter_desc, vn_fifo_bypass }, /* kqfilter */
|
||||
{ &vop_revoke_desc, vn_fifo_bypass }, /* revoke */
|
||||
{ &vop_mmap_desc, vn_fifo_bypass }, /* mmap */
|
||||
{ &vop_fsync_desc, vn_fifo_bypass }, /* fsync */
|
||||
{ &vop_seek_desc, vn_fifo_bypass }, /* seek */
|
||||
{ &vop_remove_desc, vn_fifo_bypass }, /* remove */
|
||||
{ &vop_link_desc, vn_fifo_bypass }, /* link */
|
||||
{ &vop_rename_desc, vn_fifo_bypass }, /* rename */
|
||||
{ &vop_mkdir_desc, vn_fifo_bypass }, /* mkdir */
|
||||
{ &vop_rmdir_desc, vn_fifo_bypass }, /* rmdir */
|
||||
{ &vop_symlink_desc, vn_fifo_bypass }, /* symlink */
|
||||
{ &vop_readdir_desc, vn_fifo_bypass }, /* readdir */
|
||||
{ &vop_readlink_desc, vn_fifo_bypass }, /* readlink */
|
||||
{ &vop_abortop_desc, vn_fifo_bypass }, /* abortop */
|
||||
{ &vop_inactive_desc, v7fs_inactive }, /* inactive */
|
||||
{ &vop_reclaim_desc, v7fs_reclaim }, /* reclaim */
|
||||
{ &vop_lock_desc, vn_fifo_bypass }, /* lock */
|
||||
{ &vop_unlock_desc, vn_fifo_bypass }, /* unlock */
|
||||
{ &vop_bmap_desc, vn_fifo_bypass }, /* bmap */
|
||||
{ &vop_strategy_desc, vn_fifo_bypass }, /* strategy */
|
||||
{ &vop_print_desc, vn_fifo_bypass }, /* print */
|
||||
{ &vop_islocked_desc, vn_fifo_bypass }, /* islocked */
|
||||
{ &vop_pathconf_desc, vn_fifo_bypass }, /* pathconf */
|
||||
{ &vop_advlock_desc, vn_fifo_bypass }, /* advlock */
|
||||
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */
|
||||
{ &vop_putpages_desc, vn_fifo_bypass }, /* putpages */
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
const struct vnodeopv_desc v7fs_fifoop_opv_desc = {
|
||||
&v7fs_fifoop_p,
|
||||
v7fs_fifoop_entries
|
||||
};
|
||||
|
||||
const struct vnodeopv_desc v7fs_vnodeop_opv_desc = {
|
||||
&v7fs_vnodeop_p,
|
||||
v7fs_vnodeop_entries
|
||||
};
|
||||
|
||||
const struct vnodeopv_desc v7fs_specop_opv_desc = {
|
||||
&v7fs_specop_p,
|
||||
v7fs_specop_entries
|
||||
};
|
||||
|
||||
const struct vnodeopv_desc *v7fs_vnodeopv_descs[] = {
|
||||
&v7fs_vnodeop_opv_desc,
|
||||
&v7fs_specop_opv_desc,
|
||||
&v7fs_fifoop_opv_desc,
|
||||
NULL,
|
||||
};
|
||||
|
||||
const struct genfs_ops v7fs_genfsops = {
|
||||
.gop_size = genfs_size,
|
||||
.gop_alloc = v7fs_gop_alloc,
|
||||
.gop_write = genfs_gop_write,
|
||||
};
|
||||
|
||||
struct vfsops v7fs_vfsops = {
|
||||
MOUNT_V7FS,
|
||||
sizeof(struct v7fs_args),
|
||||
v7fs_mount,
|
||||
v7fs_start,
|
||||
v7fs_unmount,
|
||||
v7fs_root,
|
||||
(void *)eopnotsupp, /* vfs_quotactl */
|
||||
v7fs_statvfs,
|
||||
v7fs_sync,
|
||||
v7fs_vget,
|
||||
v7fs_fhtovp,
|
||||
v7fs_vptofh,
|
||||
v7fs_init,
|
||||
v7fs_reinit,
|
||||
v7fs_done,
|
||||
v7fs_mountroot,
|
||||
(int (*)(struct mount *, struct vnode *, struct timespec *))
|
||||
eopnotsupp, /* snapshot */
|
||||
vfs_stdextattrctl,
|
||||
(void *)eopnotsupp, /* vfs_suspendctl */
|
||||
genfs_renamelock_enter,
|
||||
genfs_renamelock_exit,
|
||||
(void *)eopnotsupp,
|
||||
v7fs_vnodeopv_descs,
|
||||
0,
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static int
|
||||
v7fs_modcmd(modcmd_t cmd, void *arg)
|
||||
{
|
||||
|
||||
switch (cmd) {
|
||||
case MODULE_CMD_INIT:
|
||||
return vfs_attach(&v7fs_vfsops);
|
||||
case MODULE_CMD_FINI:
|
||||
return vfs_detach(&v7fs_vfsops);
|
||||
default:
|
||||
return ENOTTY;
|
||||
}
|
||||
}
|
116
sys/fs/v7fs/v7fs_extern.h
Normal file
116
sys/fs/v7fs/v7fs_extern.h
Normal file
@ -0,0 +1,116 @@
|
||||
/* $NetBSD: v7fs_extern.h,v 1.1 2011/06/27 11:52:24 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2004, 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _FS_V7FS_EXTERN_H_
|
||||
#define _FS_V7FS_EXTERN_H_
|
||||
|
||||
#include <fs/v7fs/v7fs_args.h>
|
||||
|
||||
#include <miscfs/genfs/genfs.h>
|
||||
#include <miscfs/genfs/genfs_node.h>
|
||||
#include <miscfs/specfs/specdev.h>
|
||||
|
||||
#include "v7fs.h"
|
||||
#include "v7fs_impl.h"
|
||||
#include "v7fs_inode.h"
|
||||
|
||||
struct v7fs_mount {
|
||||
struct mount *mountp;
|
||||
struct vnode *devvp; /* block device mounted vnode */
|
||||
struct v7fs_self *core; /* filesystem dependent implementation*/
|
||||
LIST_HEAD(, v7fs_node) v7fs_node_head;
|
||||
};
|
||||
|
||||
struct v7fs_node {
|
||||
struct genfs_node gnode;
|
||||
struct v7fs_inode inode; /* filesystem dependent implementation */
|
||||
struct vnode *vnode; /* back-link */
|
||||
struct v7fs_mount *v7fsmount; /* our filesystem */
|
||||
struct lockf *lockf; /* advlock */
|
||||
|
||||
int update_ctime;
|
||||
int update_atime;
|
||||
int update_mtime;
|
||||
|
||||
LIST_ENTRY(v7fs_node) link;
|
||||
};
|
||||
|
||||
#define VFSTOV7FS(mp) ((struct v7fs_mount *)((mp)->mnt_data))
|
||||
|
||||
__BEGIN_DECLS
|
||||
/* v-node ops. */
|
||||
int v7fs_lookup(void *);
|
||||
int v7fs_create(void *);
|
||||
int v7fs_open(void *);
|
||||
int v7fs_close(void *);
|
||||
int v7fs_access(void *);
|
||||
int v7fs_getattr(void *);
|
||||
int v7fs_setattr(void *);
|
||||
int v7fs_read(void *);
|
||||
int v7fs_write(void *);
|
||||
int v7fs_fsync(void *);
|
||||
int v7fs_remove(void *);
|
||||
int v7fs_rename(void *);
|
||||
int v7fs_readdir(void *);
|
||||
int v7fs_inactive(void *);
|
||||
int v7fs_reclaim(void *);
|
||||
int v7fs_bmap(void *);
|
||||
int v7fs_strategy(void *);
|
||||
int v7fs_print(void *);
|
||||
int v7fs_advlock(void *);
|
||||
int v7fs_pathconf(void *);
|
||||
|
||||
int v7fs_link(void *);
|
||||
int v7fs_symlink(void *);
|
||||
int v7fs_readlink(void *);
|
||||
|
||||
int v7fs_mkdir(void *);
|
||||
int v7fs_rmdir(void *);
|
||||
|
||||
int v7fs_mknod(void *);
|
||||
|
||||
/* vfs ops. */
|
||||
VFS_PROTOS(v7fs);
|
||||
|
||||
int v7fs_mountroot(void);
|
||||
extern int (**v7fs_vnodeop_p)(void *);
|
||||
extern int (**v7fs_specop_p)(void *);
|
||||
extern int (**v7fs_fifoop_p)(void *);
|
||||
|
||||
/* genfs ops */
|
||||
int v7fs_gop_alloc(struct vnode *, off_t, off_t, int, kauth_cred_t);
|
||||
extern const struct genfs_ops v7fs_genfsops;
|
||||
|
||||
/* internal service */
|
||||
int v7fs_update(struct vnode *, const struct timespec *,
|
||||
const struct timespec *, int);
|
||||
__END_DECLS
|
||||
#endif /* _FS_V7FS_EXTERN_H_ */
|
411
sys/fs/v7fs/v7fs_file.c
Normal file
411
sys/fs/v7fs/v7fs_file.c
Normal file
@ -0,0 +1,411 @@
|
||||
/* $NetBSD: v7fs_file.c,v 1.1 2011/06/27 11:52:24 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: v7fs_file.c,v 1.1 2011/06/27 11:52:24 uch Exp $");
|
||||
#if defined _KERNEL_OPT
|
||||
#include "opt_v7fs.h"
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <sys/systm.h>
|
||||
#include <sys/param.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#define MIN(a,b) ((/*CONSTCOND*/(a)<(b))?(a):(b))
|
||||
#endif
|
||||
|
||||
#include "v7fs.h"
|
||||
#include "v7fs_impl.h"
|
||||
#include "v7fs_endian.h"
|
||||
#include "v7fs_inode.h"
|
||||
#include "v7fs_dirent.h"
|
||||
#include "v7fs_file.h"
|
||||
#include "v7fs_datablock.h"
|
||||
|
||||
#ifdef V7FS_FILE_DEBUG
|
||||
#define DPRINTF(fmt, args...) printf("%s: " fmt, __func__, ##args)
|
||||
#else
|
||||
#define DPRINTF(fmt, args...) ((void)0)
|
||||
#endif
|
||||
|
||||
static int lookup_subr(struct v7fs_self *, void *, v7fs_daddr_t, size_t);
|
||||
static int remove_subr(struct v7fs_self *, void *, v7fs_daddr_t, size_t);
|
||||
|
||||
int
|
||||
v7fs_file_lookup_by_name(struct v7fs_self *fs, struct v7fs_inode *parent_dir,
|
||||
const char *name, v7fs_ino_t *ino)
|
||||
{
|
||||
char filename[V7FS_NAME_MAX + 1];
|
||||
char *q;
|
||||
int error;
|
||||
size_t len;
|
||||
|
||||
if ((q = strchr(name, '/'))) {
|
||||
/* Zap following path. */
|
||||
len = MIN(V7FS_NAME_MAX + 1, q - name);
|
||||
memcpy(filename, name, len);
|
||||
filename[len] = '\0'; /* '/' -> '\0' */
|
||||
} else {
|
||||
v7fs_dirent_filename(filename, name);
|
||||
}
|
||||
DPRINTF("%s(%s) dir=%d\n", filename, name, parent_dir->inode_number);
|
||||
|
||||
struct v7fs_lookup_arg lookup_arg = { .name = filename,
|
||||
.inode_number = 0 };
|
||||
if ((error = v7fs_datablock_foreach(fs, parent_dir, lookup_subr,
|
||||
&lookup_arg)) != V7FS_ITERATOR_BREAK) {
|
||||
DPRINTF("not found.\n");
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
*ino = lookup_arg.inode_number;
|
||||
DPRINTF("done. ino=%d\n", *ino);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
lookup_subr(struct v7fs_self *fs, void *ctx, v7fs_daddr_t blk, size_t sz)
|
||||
{
|
||||
struct v7fs_lookup_arg *p = (struct v7fs_lookup_arg *)ctx;
|
||||
struct v7fs_dirent *dir;
|
||||
const char *name = p->name;
|
||||
void *buf;
|
||||
size_t i, n;
|
||||
int ret = 0;
|
||||
|
||||
if (!(buf = scratch_read(fs, blk)))
|
||||
return EIO;
|
||||
|
||||
dir = (struct v7fs_dirent *)buf;
|
||||
n = sz / sizeof(*dir);
|
||||
v7fs_dirent_endian_convert(fs, dir, n);
|
||||
|
||||
for (i = 0; i < n; i++, dir++) {
|
||||
if (dir->inode_number < 1) {
|
||||
DPRINTF("*** bad inode #%d ***\n", dir->inode_number);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strncmp((const char *)dir->name, name, V7FS_NAME_MAX) == 0)
|
||||
{
|
||||
p->inode_number = dir->inode_number;
|
||||
ret = V7FS_ITERATOR_BREAK; /* found */
|
||||
break;
|
||||
}
|
||||
}
|
||||
scratch_free(fs, buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_file_allocate(struct v7fs_self *fs, struct v7fs_inode *parent_dir,
|
||||
const char *srcname, struct v7fs_fileattr *attr, v7fs_ino_t *ino)
|
||||
{
|
||||
struct v7fs_inode inode;
|
||||
char filename[V7FS_NAME_MAX + 1];
|
||||
struct v7fs_dirent *dir;
|
||||
int error;
|
||||
|
||||
/* Truncate filename. */
|
||||
v7fs_dirent_filename(filename, srcname);
|
||||
DPRINTF("%s(%s)\n", filename, srcname);
|
||||
|
||||
/* Check filename. */
|
||||
if (v7fs_file_lookup_by_name(fs, parent_dir, filename, ino) == 0) {
|
||||
DPRINTF("%s exists\n", filename);
|
||||
return EEXIST;
|
||||
}
|
||||
|
||||
/* Get new inode. */
|
||||
if ((error = v7fs_inode_allocate(fs, ino)))
|
||||
return error;
|
||||
|
||||
/* Set initial attribute. */
|
||||
memset(&inode, 0, sizeof(inode));
|
||||
inode.inode_number = *ino;
|
||||
inode.mode = attr->mode;
|
||||
inode.uid = attr->uid;
|
||||
inode.gid = attr->gid;
|
||||
if (attr->ctime)
|
||||
inode.ctime = attr->ctime;
|
||||
if (attr->mtime)
|
||||
inode.mtime = attr->mtime;
|
||||
if (attr->atime)
|
||||
inode.atime = attr->atime;
|
||||
|
||||
switch (inode.mode & V7FS_IFMT) {
|
||||
default:
|
||||
DPRINTF("Can't allocate %o type.\n", inode.mode);
|
||||
v7fs_inode_deallocate(fs, *ino);
|
||||
return EINVAL;
|
||||
case V7FS_IFCHR:
|
||||
/* FALLTHROUGH */
|
||||
case V7FS_IFBLK:
|
||||
inode.nlink = 1;
|
||||
inode.device = attr->device;
|
||||
inode.addr[0] = inode.device;
|
||||
break;
|
||||
case V7FSBSD_IFFIFO:
|
||||
/* FALLTHROUGH */
|
||||
case V7FSBSD_IFSOCK:
|
||||
/* FALLTHROUGH */
|
||||
case V7FSBSD_IFLNK:
|
||||
/* FALLTHROUGH */
|
||||
case V7FS_IFREG:
|
||||
inode.nlink = 1;
|
||||
break;
|
||||
case V7FS_IFDIR:
|
||||
inode.nlink = 2; /* . + .. */
|
||||
if ((error = v7fs_datablock_expand(fs, &inode, sizeof(*dir) * 2
|
||||
))) {
|
||||
v7fs_inode_deallocate(fs, *ino);
|
||||
return error;
|
||||
}
|
||||
v7fs_daddr_t blk = inode.addr[0];
|
||||
void *buf;
|
||||
if (!(buf = scratch_read(fs, blk))) {
|
||||
v7fs_inode_deallocate(fs, *ino);
|
||||
return EIO;
|
||||
}
|
||||
dir = (struct v7fs_dirent *)buf;
|
||||
strcpy(dir[0].name, ".");
|
||||
dir[0].inode_number = V7FS_VAL16(fs, *ino);
|
||||
strcpy(dir[1].name, "..");
|
||||
dir[1].inode_number = V7FS_VAL16(fs, parent_dir->inode_number);
|
||||
if (!fs->io.write(fs->io.cookie, buf, blk)) {
|
||||
scratch_free(fs, buf);
|
||||
return EIO;
|
||||
}
|
||||
scratch_free(fs, buf);
|
||||
break;
|
||||
}
|
||||
|
||||
v7fs_inode_writeback(fs, &inode);
|
||||
|
||||
/* Link this inode to parent directory. */
|
||||
if ((error = v7fs_directory_add_entry(fs, parent_dir, *ino, filename)))
|
||||
{
|
||||
DPRINTF("can't add dirent.\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_file_deallocate(struct v7fs_self *fs, struct v7fs_inode *parent_dir,
|
||||
const char *name)
|
||||
{
|
||||
v7fs_ino_t ino;
|
||||
struct v7fs_inode inode;
|
||||
int error;
|
||||
|
||||
DPRINTF("%s\n", name);
|
||||
if ((error = v7fs_file_lookup_by_name(fs, parent_dir, name, &ino))) {
|
||||
DPRINTF("no such a file: %s\n", name);
|
||||
return error;
|
||||
}
|
||||
DPRINTF("%s->#%d\n", name, ino);
|
||||
if ((error = v7fs_inode_load(fs, &inode, ino)))
|
||||
return error;
|
||||
|
||||
if (v7fs_inode_isdir(&inode)) {
|
||||
/* Check child directory exists. */
|
||||
if (v7fs_inode_filesize(&inode) !=
|
||||
sizeof(struct v7fs_dirent) * 2 /*"." + ".."*/) {
|
||||
DPRINTF("file exists.\n");
|
||||
return EEXIST;
|
||||
}
|
||||
inode.nlink = 0; /* remove this. */
|
||||
} else {
|
||||
/* Decrement reference count. */
|
||||
--inode.nlink; /* regular file. */
|
||||
}
|
||||
|
||||
|
||||
if ((error = v7fs_directory_remove_entry(fs, parent_dir, name)))
|
||||
return error;
|
||||
DPRINTF("remove dirent\n");
|
||||
|
||||
if (inode.nlink == 0) {
|
||||
v7fs_datablock_contract(fs, &inode, inode.filesize);
|
||||
DPRINTF("remove datablock\n");
|
||||
v7fs_inode_deallocate(fs, ino);
|
||||
DPRINTF("remove inode\n");
|
||||
} else {
|
||||
v7fs_inode_writeback(fs, &inode);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_directory_add_entry(struct v7fs_self *fs, struct v7fs_inode *parent_dir,
|
||||
v7fs_ino_t ino, const char *srcname)
|
||||
{
|
||||
struct v7fs_inode inode;
|
||||
struct v7fs_dirent *dir;
|
||||
int error = 0;
|
||||
v7fs_daddr_t blk;
|
||||
void *buf;
|
||||
char filename[V7FS_NAME_MAX + 1];
|
||||
|
||||
/* Truncate filename. */
|
||||
v7fs_dirent_filename(filename, srcname);
|
||||
DPRINTF("%s(%s) %d\n", filename, srcname, ino);
|
||||
|
||||
/* Target inode */
|
||||
if ((error = v7fs_inode_load(fs, &inode, ino)))
|
||||
return error;
|
||||
|
||||
/* Expand datablock. */
|
||||
if ((error = v7fs_datablock_expand(fs, parent_dir, sizeof(*dir))))
|
||||
return error;
|
||||
|
||||
/* Read last entry. */
|
||||
if (!(blk = v7fs_datablock_last(fs, parent_dir,
|
||||
v7fs_inode_filesize(parent_dir))))
|
||||
return EIO;
|
||||
|
||||
/* Load dirent block. This vnode(parent dir) is locked by VFS layer. */
|
||||
if (!(buf = scratch_read(fs, blk)))
|
||||
return EIO;
|
||||
|
||||
size_t sz = v7fs_inode_filesize(parent_dir);
|
||||
sz = V7FS_RESIDUE_BSIZE(sz); /* last block payload. */
|
||||
int n = sz / sizeof(*dir) - 1;
|
||||
/* Add dirent. */
|
||||
dir = (struct v7fs_dirent *)buf;
|
||||
dir[n].inode_number = V7FS_VAL16(fs, ino);
|
||||
memcpy((char *)dir[n].name, filename, V7FS_NAME_MAX);
|
||||
/* Write back datablock */
|
||||
if (!fs->io.write(fs->io.cookie, buf, blk))
|
||||
error = EIO;
|
||||
scratch_free(fs, buf);
|
||||
|
||||
if (v7fs_inode_isdir(&inode)) {
|
||||
parent_dir->nlink++;
|
||||
v7fs_inode_writeback(fs, parent_dir);
|
||||
}
|
||||
|
||||
DPRINTF("done. (dirent size=%dbyte)\n", parent_dir->filesize);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_directory_remove_entry(struct v7fs_self *fs, struct v7fs_inode *parent_dir,
|
||||
const char *name)
|
||||
{
|
||||
struct v7fs_inode inode;
|
||||
int error;
|
||||
struct v7fs_dirent lastdirent;
|
||||
v7fs_daddr_t lastblk;
|
||||
size_t sz, lastsz;
|
||||
v7fs_off_t pos;
|
||||
void *buf;
|
||||
|
||||
/* Setup replaced entry. */
|
||||
sz = parent_dir->filesize;
|
||||
lastblk = v7fs_datablock_last(fs, parent_dir,
|
||||
v7fs_inode_filesize(parent_dir));
|
||||
lastsz = V7FS_RESIDUE_BSIZE(sz);
|
||||
pos = lastsz - sizeof(lastdirent);
|
||||
|
||||
if (!(buf = scratch_read(fs, lastblk)))
|
||||
return EIO;
|
||||
lastdirent = *((struct v7fs_dirent *)((uint8_t *)buf + pos));
|
||||
scratch_free(fs, buf);
|
||||
DPRINTF("last dirent=%d %s pos=%d\n",
|
||||
V7FS_VAL16(fs, lastdirent.inode_number), lastdirent.name, pos);
|
||||
|
||||
struct v7fs_lookup_arg lookup_arg =
|
||||
{ .name = name, .replace = &lastdirent/*disk endian */ };
|
||||
/* Search entry that removed. replace it to last dirent. */
|
||||
if ((error = v7fs_datablock_foreach(fs, parent_dir, remove_subr,
|
||||
&lookup_arg)) != V7FS_ITERATOR_BREAK)
|
||||
return ENOENT;
|
||||
|
||||
/* Contract dirent entries. */
|
||||
v7fs_datablock_contract(fs, parent_dir, sizeof(lastdirent));
|
||||
DPRINTF("done. (dirent size=%dbyte)\n", parent_dir->filesize);
|
||||
|
||||
/* Target inode */
|
||||
if ((error = v7fs_inode_load(fs, &inode, lookup_arg.inode_number)))
|
||||
return error;
|
||||
|
||||
if (v7fs_inode_isdir(&inode)) {
|
||||
parent_dir->nlink--;
|
||||
v7fs_inode_writeback(fs, parent_dir);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
remove_subr(struct v7fs_self *fs, void *ctx, v7fs_daddr_t blk, size_t sz)
|
||||
{
|
||||
struct v7fs_lookup_arg *p = (struct v7fs_lookup_arg *)ctx;
|
||||
struct v7fs_dirent *dir;
|
||||
void *buf;
|
||||
size_t i;
|
||||
int ret = 0;
|
||||
|
||||
DPRINTF("match start blk=%x\n", blk);
|
||||
if (!(buf = scratch_read(fs, blk)))
|
||||
return EIO;
|
||||
|
||||
dir = (struct v7fs_dirent *)buf;
|
||||
|
||||
for (i = 0; i < sz / sizeof(*dir); i++, dir++) {
|
||||
DPRINTF("%d\n", V7FS_VAL16(fs, dir->inode_number));
|
||||
if (strncmp(p->name,
|
||||
(const char *)dir->name, V7FS_NAME_MAX) == 0) {
|
||||
p->inode_number = V7FS_VAL16(fs, dir->inode_number);
|
||||
/* Replace to last dirent. */
|
||||
*dir = *(p->replace); /* disk endian */
|
||||
/* Write back. */
|
||||
if (!fs->io.write(fs->io.cookie, buf, blk))
|
||||
ret = EIO;
|
||||
else
|
||||
ret = V7FS_ITERATOR_BREAK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
scratch_free(fs, buf);
|
||||
|
||||
return ret;
|
||||
}
|
64
sys/fs/v7fs/v7fs_file.h
Normal file
64
sys/fs/v7fs/v7fs_file.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* $NetBSD: v7fs_file.h,v 1.1 2011/06/27 11:52:24 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _V7FS_FILE_H_
|
||||
#define _V7FS_FILE_H_
|
||||
|
||||
struct v7fs_lookup_arg {
|
||||
const char *name;
|
||||
char *buf;
|
||||
v7fs_ino_t inode_number;
|
||||
struct v7fs_dirent *replace;
|
||||
};
|
||||
|
||||
__BEGIN_DECLS
|
||||
/* core */
|
||||
int v7fs_file_lookup_by_name(struct v7fs_self *, struct v7fs_inode *,
|
||||
const char*, v7fs_ino_t *);
|
||||
int v7fs_file_allocate(struct v7fs_self *, struct v7fs_inode *, const char *,
|
||||
struct v7fs_fileattr *, v7fs_ino_t *);
|
||||
int v7fs_file_deallocate(struct v7fs_self *, struct v7fs_inode *, const char *);
|
||||
int v7fs_directory_add_entry(struct v7fs_self *,struct v7fs_inode *, v7fs_ino_t,
|
||||
const char *);
|
||||
int v7fs_directory_remove_entry(struct v7fs_self *,struct v7fs_inode *,
|
||||
const char *);
|
||||
|
||||
/* util */
|
||||
int v7fs_file_rename(struct v7fs_self *, struct v7fs_inode *, const char *,
|
||||
struct v7fs_inode *, const char *);
|
||||
int v7fs_directory_replace_entry(struct v7fs_self *, struct v7fs_inode *,
|
||||
const char *, v7fs_ino_t);
|
||||
int v7fs_file_link(struct v7fs_self *, struct v7fs_inode *, struct v7fs_inode *,
|
||||
const char *);
|
||||
bool v7fs_file_lookup_by_number(struct v7fs_self *, struct v7fs_inode *,
|
||||
v7fs_ino_t, char *);
|
||||
__END_DECLS
|
||||
#endif /*!_V7FS_INODE_H_ */
|
223
sys/fs/v7fs/v7fs_file_util.c
Normal file
223
sys/fs/v7fs/v7fs_file_util.c
Normal file
@ -0,0 +1,223 @@
|
||||
/* $NetBSD: v7fs_file_util.c,v 1.1 2011/06/27 11:52:24 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: v7fs_file_util.c,v 1.1 2011/06/27 11:52:24 uch Exp $");
|
||||
#ifdef _KERNEL
|
||||
#include <sys/systm.h>
|
||||
#include <sys/param.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include "v7fs.h"
|
||||
#include "v7fs_impl.h"
|
||||
#include "v7fs_endian.h"
|
||||
#include "v7fs_inode.h"
|
||||
#include "v7fs_dirent.h"
|
||||
#include "v7fs_file.h"
|
||||
#include "v7fs_datablock.h"
|
||||
|
||||
#ifdef V7FS_FILE_DEBUG
|
||||
#define DPRINTF(fmt, args...) printf("%s: " fmt, __func__, ##args)
|
||||
#else
|
||||
#define DPRINTF(fmt, args...) ((void)0)
|
||||
#endif
|
||||
|
||||
static int replace_subr(struct v7fs_self *, void *, v7fs_daddr_t, size_t);
|
||||
static int lookup_by_number_subr(struct v7fs_self *, void *, v7fs_daddr_t,
|
||||
size_t);
|
||||
|
||||
int
|
||||
v7fs_file_link(struct v7fs_self *fs, struct v7fs_inode *parent_dir,
|
||||
struct v7fs_inode *p, const char *name)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
DPRINTF("%d %d %s\n", parent_dir->inode_number, p->inode_number, name);
|
||||
if ((error = v7fs_directory_add_entry(fs, parent_dir, p->inode_number,
|
||||
name))) {
|
||||
DPRINTF("can't add entry");
|
||||
return error;
|
||||
}
|
||||
p->nlink++;
|
||||
v7fs_inode_writeback(fs, p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_file_rename(struct v7fs_self *fs, struct v7fs_inode *parent_from,
|
||||
const char *from, struct v7fs_inode *parent_to, const char *to)
|
||||
{
|
||||
v7fs_ino_t from_ino, to_ino;
|
||||
int error;
|
||||
|
||||
if ((error = v7fs_file_lookup_by_name(fs, parent_from, from,
|
||||
&from_ino))) {
|
||||
DPRINTF("%s don't exists\n", from);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* If target file exists, remove. */
|
||||
error = v7fs_file_lookup_by_name(fs, parent_to, to, &to_ino);
|
||||
if (error == 0) {
|
||||
DPRINTF("%s already exists\n", to);
|
||||
if ((error = v7fs_file_deallocate(fs, parent_to, to))) {
|
||||
DPRINTF("%s can't remove\n", to);
|
||||
return error;
|
||||
}
|
||||
} else if (error != ENOENT) {
|
||||
DPRINTF("error=%d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
if ((error = v7fs_directory_add_entry(fs, parent_to, from_ino, to))) {
|
||||
DPRINTF("can't add entry");
|
||||
return error;
|
||||
}
|
||||
|
||||
if ((error = v7fs_directory_remove_entry(fs, parent_from, from))) {
|
||||
DPRINTF("can't remove entry");
|
||||
return error;
|
||||
}
|
||||
|
||||
if (parent_from != parent_to) {
|
||||
/* If directory move, update ".." */
|
||||
struct v7fs_inode inode;
|
||||
v7fs_inode_load(fs, &inode, from_ino);
|
||||
if (v7fs_inode_isdir(&inode)) {
|
||||
if ((error = v7fs_directory_replace_entry(fs, &inode,
|
||||
"..", parent_to->inode_number))) {
|
||||
DPRINTF("can't replace parent dir");
|
||||
return error;
|
||||
}
|
||||
v7fs_inode_writeback(fs, &inode);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
v7fs_directory_replace_entry(struct v7fs_self *fs, struct v7fs_inode *self_dir,
|
||||
const char *name, v7fs_ino_t ino)
|
||||
{
|
||||
int error;
|
||||
|
||||
/* Search entry that replaced. replace it to new inode number. */
|
||||
struct v7fs_lookup_arg lookup_arg = { .name = name,
|
||||
.inode_number = ino };
|
||||
if ((error = v7fs_datablock_foreach(fs, self_dir, replace_subr,
|
||||
&lookup_arg)) != V7FS_ITERATOR_BREAK)
|
||||
return ENOENT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
replace_subr(struct v7fs_self *fs, void *ctx, v7fs_daddr_t blk, size_t sz)
|
||||
{
|
||||
struct v7fs_lookup_arg *p = (struct v7fs_lookup_arg *)ctx;
|
||||
struct v7fs_dirent *dir;
|
||||
void *buf;
|
||||
size_t i, n;
|
||||
int ret = 0;
|
||||
|
||||
DPRINTF("match start blk=%x\n", blk);
|
||||
if (!(buf = scratch_read(fs, blk)))
|
||||
return EIO;
|
||||
|
||||
dir = (struct v7fs_dirent *)buf;
|
||||
n = sz / sizeof(*dir);
|
||||
|
||||
for (i = 0; i < n; i++, dir++) { /*disk endian */
|
||||
if (strncmp(p->name, (const char *)dir->name, V7FS_NAME_MAX)
|
||||
== 0) {
|
||||
/* Replace inode# */
|
||||
dir->inode_number = V7FS_VAL16(fs, p->inode_number);
|
||||
/* Write back. */
|
||||
if (!fs->io.write(fs->io.cookie, buf, blk))
|
||||
ret = EIO;
|
||||
else
|
||||
ret = V7FS_ITERATOR_BREAK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
scratch_free(fs, buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
v7fs_file_lookup_by_number(struct v7fs_self *fs, struct v7fs_inode *parent_dir,
|
||||
v7fs_ino_t ino, char *buf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = v7fs_datablock_foreach(fs, parent_dir, lookup_by_number_subr,
|
||||
&(struct v7fs_lookup_arg){ .inode_number = ino, .buf = buf });
|
||||
|
||||
return ret == V7FS_ITERATOR_BREAK;
|
||||
}
|
||||
|
||||
static int
|
||||
lookup_by_number_subr(struct v7fs_self *fs, void *ctx, v7fs_daddr_t blk,
|
||||
size_t sz)
|
||||
{
|
||||
struct v7fs_lookup_arg *p = (struct v7fs_lookup_arg *)ctx;
|
||||
struct v7fs_dirent *dir;
|
||||
void *buf;
|
||||
size_t i, n;
|
||||
int ret = 0;
|
||||
|
||||
if (!(buf = scratch_read(fs, blk)))
|
||||
return EIO;
|
||||
|
||||
dir = (struct v7fs_dirent *)buf;
|
||||
n = sz / sizeof(*dir);
|
||||
v7fs_dirent_endian_convert(fs, dir, n);
|
||||
|
||||
for (i = 0; i < n; i++, dir++) {
|
||||
if (dir->inode_number == p->inode_number) {
|
||||
if (p->buf)
|
||||
v7fs_dirent_filename(p->buf, dir->name);
|
||||
ret = V7FS_ITERATOR_BREAK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
scratch_free(fs, buf);
|
||||
|
||||
return ret;
|
||||
}
|
154
sys/fs/v7fs/v7fs_impl.h
Normal file
154
sys/fs/v7fs/v7fs_impl.h
Normal file
@ -0,0 +1,154 @@
|
||||
/* $NetBSD: v7fs_impl.h,v 1.1 2011/06/27 11:52:25 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* V7FS implementation. */
|
||||
#ifndef _V7FS_IMPL_H_
|
||||
#define _V7FS_IMPL_H_
|
||||
|
||||
#ifndef _KERNEL
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#define KDASSERT(x) assert(x)
|
||||
#endif
|
||||
|
||||
struct block_io_ops {
|
||||
void *cookie;
|
||||
bool (*drive)(void *, uint8_t);
|
||||
bool (*read)(void *, uint8_t *, daddr_t);
|
||||
bool (*read_n)(void *, uint8_t *, daddr_t, int);
|
||||
bool (*write)(void *, uint8_t *, daddr_t);
|
||||
bool (*write_n)(void *, uint8_t *, daddr_t, int);
|
||||
};
|
||||
|
||||
#ifdef V7FS_EI
|
||||
struct endian_conversion_ops {
|
||||
uint32_t (*conv32)(uint32_t);
|
||||
uint16_t (*conv16)(uint16_t);
|
||||
/* For daddr packing */
|
||||
v7fs_daddr_t (*conv24read)(uint8_t *);
|
||||
void (*conv24write)(v7fs_daddr_t, uint8_t *);
|
||||
};
|
||||
#endif
|
||||
#ifdef _KERNEL
|
||||
#define V7FS_LOCK
|
||||
#endif
|
||||
#ifdef V7FS_LOCK
|
||||
struct lock_ops {
|
||||
void *cookie;
|
||||
void (*lock)(void*);
|
||||
void (*unlock)(void *);
|
||||
};
|
||||
#define SUPERB_LOCK(x) ((x)->sb_lock.lock((x)->sb_lock.cookie))
|
||||
#define SUPERB_UNLOCK(x) ((x)->sb_lock.unlock((x)->sb_lock.cookie))
|
||||
#define ILIST_LOCK(x) ((x)->ilist_lock.lock((x)->ilist_lock.cookie))
|
||||
#define ILIST_UNLOCK(x) ((x)->ilist_lock.unlock((x)->ilist_lock.cookie))
|
||||
#define MEM_LOCK(x) ((x)->mem_lock.lock((x)->mem_lock.cookie))
|
||||
#define MEM_UNLOCK(x) ((x)->mem_lock.unlock((x)->mem_lock.cookie))
|
||||
#else /*V7FS_LOCK */
|
||||
#define SUPERB_LOCK(x) ((void)0)
|
||||
#define SUPERB_UNLOCK(x) ((void)0)
|
||||
#define ILIST_LOCK(x) ((void)0)
|
||||
#define ILIST_UNLOCK(x) ((void)0)
|
||||
#define MEM_LOCK(x) ((void)0)
|
||||
#define MEM_UNLOCK(x) ((void)0)
|
||||
#endif /*V7FS_LOCK */
|
||||
|
||||
struct v7fs_stat {
|
||||
int32_t total_blocks;
|
||||
int32_t free_blocks;
|
||||
int32_t total_inode;
|
||||
int32_t free_inode;
|
||||
int32_t total_files;
|
||||
};
|
||||
|
||||
struct v7fs_fileattr {
|
||||
int16_t uid;
|
||||
int16_t gid;
|
||||
v7fs_mode_t mode;
|
||||
v7fs_dev_t device;
|
||||
v7fs_time_t ctime;
|
||||
v7fs_time_t mtime;
|
||||
v7fs_time_t atime;
|
||||
};
|
||||
|
||||
struct v7fs_self {
|
||||
#define V7FS_SELF_NSCRATCH 3
|
||||
uint8_t scratch[V7FS_SELF_NSCRATCH][V7FS_BSIZE];
|
||||
int scratch_free; /* free block bitmap. */
|
||||
int scratch_remain; /* for statistic */
|
||||
struct block_io_ops io;
|
||||
#ifdef V7FS_EI
|
||||
struct endian_conversion_ops val;
|
||||
#endif
|
||||
#ifdef V7FS_LOCK
|
||||
/* in-core superblock access. (freeblock/freeinode) split? -uch */
|
||||
struct lock_ops sb_lock;
|
||||
struct lock_ops ilist_lock; /* disk ilist access. */
|
||||
struct lock_ops mem_lock; /* work memory allocation lock. */
|
||||
#endif
|
||||
struct v7fs_superblock superblock;
|
||||
struct v7fs_stat stat;
|
||||
int endian;
|
||||
};
|
||||
|
||||
struct v7fs_mount_device {
|
||||
union {
|
||||
void *vnode; /* NetBSD kernel */
|
||||
int fd; /* NetBSD newfs,fsck */
|
||||
const char *filename;/* misc test */
|
||||
} device;
|
||||
daddr_t sectors; /*total size in sector. */
|
||||
int endian;
|
||||
};
|
||||
|
||||
#define V7FS_ITERATOR_BREAK (-1)
|
||||
#define V7FS_ITERATOR_END (-2)
|
||||
#define V7FS_ITERATOR_ERROR (-3)
|
||||
__BEGIN_DECLS
|
||||
int v7fs_io_init(struct v7fs_self **, const struct v7fs_mount_device *, size_t);
|
||||
void v7fs_io_fini(struct v7fs_self *);
|
||||
void *scratch_read(struct v7fs_self *, daddr_t);
|
||||
void scratch_free(struct v7fs_self *, void *);
|
||||
int scratch_remain(const struct v7fs_self *);
|
||||
__END_DECLS
|
||||
|
||||
#if 0
|
||||
#define V7FS_IO_DEBUG
|
||||
#define V7FS_SUPERBLOCK_DEBUG
|
||||
#define V7FS_DATABLOCK_DEBUG
|
||||
#define V7FS_INODE_DEBUG
|
||||
#define V7FS_DIRENT_DEBUG
|
||||
#define V7FS_FILE_DEBUG
|
||||
#define V7FS_VFSOPS_DEBUG
|
||||
#define V7FS_VNOPS_DEBUG
|
||||
#endif
|
||||
|
||||
#endif /*!_V7FS_IMPL_H_ */
|
297
sys/fs/v7fs/v7fs_inode.c
Normal file
297
sys/fs/v7fs/v7fs_inode.c
Normal file
@ -0,0 +1,297 @@
|
||||
/* $NetBSD: v7fs_inode.c,v 1.1 2011/06/27 11:52:25 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: v7fs_inode.c,v 1.1 2011/06/27 11:52:25 uch Exp $");
|
||||
#if defined _KERNEL_OPT
|
||||
#include "opt_v7fs.h"
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <sys/systm.h>
|
||||
#include <sys/param.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#include "v7fs.h"
|
||||
#include "v7fs_impl.h"
|
||||
#include "v7fs_endian.h"
|
||||
#include "v7fs_inode.h"
|
||||
#include "v7fs_superblock.h"
|
||||
|
||||
#ifdef V7FS_INODE_DEBUG
|
||||
#define DPRINTF(fmt, args...) printf("%s: " fmt, __func__, ##args)
|
||||
#else
|
||||
#define DPRINTF(fmt, args...) ((void)0)
|
||||
#endif
|
||||
|
||||
static void v7fs_inode_setup_disk_image(const struct v7fs_self *,
|
||||
struct v7fs_inode *, struct v7fs_inode_diskimage *);
|
||||
static int v7fs_inode_inquire_disk_location(const struct v7fs_self *,
|
||||
v7fs_ino_t, v7fs_daddr_t *, v7fs_daddr_t *);
|
||||
#ifdef V7FS_INODE_DEBUG
|
||||
static int v7fs_inode_block_sanity(const struct v7fs_superblock *,
|
||||
v7fs_daddr_t);
|
||||
|
||||
static int
|
||||
v7fs_inode_block_sanity(const struct v7fs_superblock *sb, v7fs_daddr_t blk)
|
||||
{
|
||||
|
||||
if ((blk < V7FS_ILIST_SECTOR) || (blk >= sb->datablock_start_sector)) {
|
||||
DPRINTF("invalid inode block#%d (%d-%d)\n", blk,
|
||||
V7FS_ILIST_SECTOR, sb->datablock_start_sector);
|
||||
return ENOSPC;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* V7FS_INODE_DEBUG */
|
||||
|
||||
int
|
||||
v7fs_inode_number_sanity(const struct v7fs_superblock *sb, v7fs_ino_t ino)
|
||||
{
|
||||
|
||||
if (ino < V7FS_ROOT_INODE || ((size_t)ino >= V7FS_MAX_INODE(sb))) {
|
||||
DPRINTF("invalid inode#%d (%d-%zu)\n", ino,
|
||||
V7FS_ROOT_INODE, V7FS_MAX_INODE(sb));
|
||||
return ENOSPC;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_inode_allocate(struct v7fs_self *fs, v7fs_ino_t *ino)
|
||||
{
|
||||
struct v7fs_superblock *sb = &fs->superblock;
|
||||
v7fs_ino_t inode_number;
|
||||
int error = ENOSPC;
|
||||
*ino = 0;
|
||||
|
||||
SUPERB_LOCK(fs);
|
||||
if (sb->total_freeinode == 0) {
|
||||
DPRINTF("inode exhausted!(1)\n");
|
||||
goto errexit;
|
||||
}
|
||||
|
||||
/* If there is no free inode cache, update it. */
|
||||
if (sb->nfreeinode <= 0 && (error = v7fs_freeinode_update(fs))) {
|
||||
DPRINTF("inode exhausted!(2)\n");
|
||||
goto errexit;
|
||||
}
|
||||
/* Get inode from superblock cache. */
|
||||
KDASSERT(sb->nfreeinode <= V7FS_MAX_FREEINODE);
|
||||
inode_number = sb->freeinode[--sb->nfreeinode];
|
||||
sb->total_freeinode--;
|
||||
sb->modified = 1;
|
||||
|
||||
if ((error = v7fs_inode_number_sanity(sb, inode_number))) {
|
||||
DPRINTF("new inode#%d %d %d\n", inode_number, sb->nfreeinode,
|
||||
sb->total_freeinode);
|
||||
DPRINTF("free inode list corupt\n");
|
||||
goto errexit;
|
||||
}
|
||||
*ino = inode_number;
|
||||
|
||||
errexit:
|
||||
SUPERB_UNLOCK(fs);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void
|
||||
v7fs_inode_deallocate(struct v7fs_self *fs, v7fs_ino_t ino)
|
||||
{
|
||||
struct v7fs_superblock *sb = &fs->superblock;
|
||||
struct v7fs_inode inode;
|
||||
|
||||
memset(&inode, 0, sizeof(inode));
|
||||
inode.inode_number = ino;
|
||||
v7fs_inode_writeback(fs, &inode);
|
||||
|
||||
SUPERB_LOCK(fs);
|
||||
if (sb->nfreeinode < V7FS_MAX_FREEINODE) {
|
||||
/* link to freeinode list. */
|
||||
sb->freeinode[sb->nfreeinode++] = ino;
|
||||
}
|
||||
/* If superblock inode cache is full, this inode charged by
|
||||
v7fs_freeinode_update() later. */
|
||||
sb->total_freeinode++;
|
||||
sb->modified = true;
|
||||
SUPERB_UNLOCK(fs);
|
||||
}
|
||||
|
||||
void
|
||||
v7fs_inode_setup_memory_image(const struct v7fs_self *fs __unused,
|
||||
struct v7fs_inode *mem, struct v7fs_inode_diskimage *disk)
|
||||
{
|
||||
#define conv16(m) (mem->m = V7FS_VAL16(fs, (disk->m)))
|
||||
#define conv32(m) (mem->m = V7FS_VAL32(fs, (disk->m)))
|
||||
uint32_t addr;
|
||||
int i;
|
||||
|
||||
memset(mem, 0, sizeof(*mem));
|
||||
conv16(mode);
|
||||
conv16(nlink);
|
||||
conv16(uid);
|
||||
conv16(gid);
|
||||
conv32(filesize);
|
||||
conv32(atime);
|
||||
conv32(mtime);
|
||||
conv32(ctime);
|
||||
|
||||
for (i = 0; i < V7FS_NADDR; i++) {
|
||||
int j = i * 3; /* 3 byte each. (v7fs_daddr is 24bit) */
|
||||
/* expand to 4byte with endian conversion. */
|
||||
addr = V7FS_VAL24_READ(fs, &disk->addr[j]);
|
||||
mem->addr[i] = addr;
|
||||
}
|
||||
mem->device = 0;
|
||||
if (v7fs_inode_iscdev(mem) || v7fs_inode_isbdev(mem)) {
|
||||
mem->device = mem->addr[0];
|
||||
}
|
||||
|
||||
#undef conv16
|
||||
#undef conv32
|
||||
}
|
||||
|
||||
static void
|
||||
v7fs_inode_setup_disk_image(const struct v7fs_self *fs __unused,
|
||||
struct v7fs_inode *mem, struct v7fs_inode_diskimage *disk)
|
||||
{
|
||||
#define conv16(m) (disk->m = V7FS_VAL16(fs, (mem->m)))
|
||||
#define conv32(m) (disk->m = V7FS_VAL32(fs, (mem->m)))
|
||||
|
||||
conv16(mode);
|
||||
conv16(nlink);
|
||||
conv16(uid);
|
||||
conv16(gid);
|
||||
conv32(filesize);
|
||||
conv32(atime);
|
||||
conv32(mtime);
|
||||
conv32(ctime);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < V7FS_NADDR; i++) {
|
||||
int j = i * 3; /* 3 byte each. */
|
||||
V7FS_VAL24_WRITE(fs, mem->addr[i], disk->addr + j);
|
||||
}
|
||||
#undef conv16
|
||||
#undef conv32
|
||||
}
|
||||
|
||||
/* Load inode from disk. */
|
||||
int
|
||||
v7fs_inode_load(struct v7fs_self *fs, struct v7fs_inode *p, v7fs_ino_t n)
|
||||
{
|
||||
v7fs_daddr_t blk, ofs;
|
||||
struct v7fs_inode_diskimage *di;
|
||||
void *buf;
|
||||
|
||||
if (v7fs_inode_inquire_disk_location(fs, n, &blk, &ofs) != 0)
|
||||
return ENOENT;
|
||||
|
||||
ILIST_LOCK(fs);
|
||||
if (!(buf = scratch_read(fs, blk))) {
|
||||
ILIST_UNLOCK(fs);
|
||||
return EIO;
|
||||
}
|
||||
ILIST_UNLOCK(fs);
|
||||
di = (struct v7fs_inode_diskimage *)buf;
|
||||
|
||||
/* Decode disk address, convert endian. */
|
||||
v7fs_inode_setup_memory_image(fs, p, di + ofs);
|
||||
p->inode_number = n;
|
||||
|
||||
scratch_free(fs, buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Write back inode to disk. */
|
||||
int
|
||||
v7fs_inode_writeback(struct v7fs_self *fs, struct v7fs_inode *mem)
|
||||
{
|
||||
struct v7fs_inode_diskimage disk;
|
||||
v7fs_ino_t ino = mem->inode_number;
|
||||
v7fs_daddr_t blk;
|
||||
v7fs_daddr_t ofs;
|
||||
void *buf;
|
||||
int error = 0;
|
||||
|
||||
if (v7fs_inode_inquire_disk_location(fs, ino, &blk, &ofs) != 0)
|
||||
return ENOENT;
|
||||
|
||||
v7fs_inode_setup_disk_image(fs, mem, &disk);
|
||||
|
||||
ILIST_LOCK(fs);
|
||||
if (!(buf = scratch_read(fs, blk))) {
|
||||
ILIST_UNLOCK(fs);
|
||||
return EIO;
|
||||
}
|
||||
struct v7fs_inode_diskimage *di = (struct v7fs_inode_diskimage *)buf;
|
||||
di[ofs] = disk; /* structure copy; */
|
||||
if (!fs->io.write(fs->io.cookie, buf, blk))
|
||||
error = EIO;
|
||||
ILIST_UNLOCK(fs);
|
||||
|
||||
scratch_free(fs, buf);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
v7fs_inode_inquire_disk_location(const struct v7fs_self *fs
|
||||
__unused, v7fs_ino_t n, v7fs_daddr_t *block,
|
||||
v7fs_daddr_t *offset)
|
||||
{
|
||||
v7fs_daddr_t ofs, blk;
|
||||
#ifdef V7FS_INODE_DEBUG
|
||||
v7fs_inode_number_sanity(&fs->superblock, n);
|
||||
#endif
|
||||
ofs = (n - 1/*inode start from 1*/) *
|
||||
sizeof(struct v7fs_inode_diskimage);
|
||||
blk = ofs >> V7FS_BSHIFT;
|
||||
|
||||
*block = blk + V7FS_ILIST_SECTOR;
|
||||
*offset = (ofs - blk * V7FS_BSIZE) /
|
||||
sizeof(struct v7fs_inode_diskimage);
|
||||
#ifdef V7FS_INODE_DEBUG
|
||||
return v7fs_inode_block_sanity(&fs->superblock, *block);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
91
sys/fs/v7fs/v7fs_inode.h
Normal file
91
sys/fs/v7fs/v7fs_inode.h
Normal file
@ -0,0 +1,91 @@
|
||||
/* $NetBSD: v7fs_inode.h,v 1.1 2011/06/27 11:52:25 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _V7FS_INODE_H_
|
||||
#define _V7FS_INODE_H_
|
||||
|
||||
/* Software implementation of inode. (memory image) */
|
||||
struct v7fs_inode {
|
||||
v7fs_ino_t inode_number; /* inode location */
|
||||
/* attr */
|
||||
uint16_t mode;
|
||||
int16_t nlink;
|
||||
int16_t uid;
|
||||
int16_t gid;
|
||||
v7fs_time_t atime;
|
||||
v7fs_time_t mtime;
|
||||
v7fs_time_t ctime;
|
||||
/* open mode */
|
||||
bool append_mode;
|
||||
|
||||
v7fs_dev_t device; /* for special file.(cdev, bdev) */
|
||||
/* payload. */
|
||||
v7fs_off_t filesize; /* size of file (byte) */
|
||||
v7fs_daddr_t addr[V7FS_NADDR]; /* data block address list */
|
||||
};
|
||||
|
||||
#define v7fs_inode_filesize(i) ((i)->filesize)
|
||||
#define v7fs_inode_allocated(i) ((i)->mode)
|
||||
#define v7fs_inode_nlink(i) ((i)->nlink)
|
||||
/* V7 original */
|
||||
#define v7fs_inode_isdir(i) (((i)->mode & V7FS_IFMT) == V7FS_IFDIR)
|
||||
#define v7fs_inode_isfile(i) (((i)->mode & V7FS_IFMT) == V7FS_IFREG)
|
||||
#define v7fs_inode_iscdev(i) (((i)->mode & V7FS_IFMT) == V7FS_IFCHR)
|
||||
#define v7fs_inode_isbdev(i) (((i)->mode & V7FS_IFMT) == V7FS_IFBLK)
|
||||
/* 2BSD extension (implementation is different) */
|
||||
#define v7fs_inode_islnk(i) (((i)->mode & V7FS_IFMT) == V7FSBSD_IFLNK)
|
||||
#define v7fs_inode_issock(i) (((i)->mode & V7FS_IFMT) == V7FSBSD_IFSOCK)
|
||||
/* NetBSD Extension */
|
||||
#define v7fs_inode_isfifo(i) (((i)->mode & V7FS_IFMT) == V7FSBSD_IFFIFO)
|
||||
|
||||
__BEGIN_DECLS
|
||||
/* Free inode access ops. */
|
||||
int v7fs_inode_allocate(struct v7fs_self *, v7fs_ino_t *);
|
||||
void v7fs_inode_deallocate(struct v7fs_self *, v7fs_ino_t);
|
||||
|
||||
/* Disk I/O ops. */
|
||||
int v7fs_inode_load(struct v7fs_self *, struct v7fs_inode *, v7fs_ino_t);
|
||||
int v7fs_inode_writeback(struct v7fs_self *, struct v7fs_inode *);
|
||||
void v7fs_inode_setup_memory_image(const struct v7fs_self *,
|
||||
struct v7fs_inode *, struct v7fs_inode_diskimage *);
|
||||
|
||||
/* Check. */
|
||||
int v7fs_inode_number_sanity(const struct v7fs_superblock *, v7fs_ino_t);
|
||||
|
||||
/* Util. */
|
||||
void v7fs_inode_chmod(struct v7fs_inode *, v7fs_mode_t);
|
||||
void v7fs_inode_dump(const struct v7fs_inode *);
|
||||
|
||||
/* Loop over all inode in ilist. */
|
||||
int v7fs_ilist_foreach(struct v7fs_self *, int (*)(struct v7fs_self *, void *,
|
||||
struct v7fs_inode *, v7fs_ino_t), void *);
|
||||
__END_DECLS
|
||||
#endif /*!_V7FS_INODE_H_ */
|
124
sys/fs/v7fs/v7fs_inode_util.c
Normal file
124
sys/fs/v7fs/v7fs_inode_util.c
Normal file
@ -0,0 +1,124 @@
|
||||
/* $NetBSD: v7fs_inode_util.c,v 1.1 2011/06/27 11:52:25 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: v7fs_inode_util.c,v 1.1 2011/06/27 11:52:25 uch Exp $");
|
||||
#if defined _KERNEL_OPT
|
||||
#include "opt_v7fs.h"
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <sys/systm.h>
|
||||
#include <sys/param.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#include "v7fs.h"
|
||||
#include "v7fs_impl.h"
|
||||
#include "v7fs_inode.h"
|
||||
|
||||
#ifdef V7FS_INODE_DEBUG
|
||||
#define DPRINTF(fmt, args...) printf("%s: " fmt, __func__, ##args)
|
||||
#else
|
||||
#define DPRINTF(fmt, args...) ((void)0)
|
||||
#endif
|
||||
|
||||
void
|
||||
v7fs_inode_chmod(struct v7fs_inode *inode, v7fs_mode_t mode)
|
||||
{
|
||||
#define V7FS_MODE_MASK 0xfff
|
||||
DPRINTF("setattr %08o -> %08o\n", inode->mode, mode);
|
||||
|
||||
inode->mode &= ~V7FS_MODE_MASK;
|
||||
inode->mode |= (mode & V7FS_MODE_MASK);
|
||||
DPRINTF("setattr %08o -> %08o\n", inode->mode, mode);
|
||||
}
|
||||
|
||||
void
|
||||
v7fs_inode_dump(const struct v7fs_inode *p)
|
||||
{
|
||||
printf("nlink %d mode %06o %d/%d %d bytes\n",
|
||||
p->nlink, p->mode,
|
||||
p->uid, p->gid, p->filesize);
|
||||
|
||||
printf("atime %d mtime %d ctime %d\n",
|
||||
p->atime, p->mtime, p->ctime);
|
||||
#ifndef _KERNEL
|
||||
time_t at = p->atime;
|
||||
time_t mt = p->mtime;
|
||||
time_t ct = p->ctime;
|
||||
printf(" atime %s mtime %s ctime %s", ctime(&at), ctime(&mt),
|
||||
ctime(&ct));
|
||||
#endif
|
||||
if (v7fs_inode_iscdev(p) || v7fs_inode_isbdev(p)) {
|
||||
printf("device:%d/%d\n", (p->device >> 8), p->device & 0xff);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
v7fs_ilist_foreach
|
||||
(struct v7fs_self *fs,
|
||||
int (*func)(struct v7fs_self *, void *, struct v7fs_inode *, v7fs_ino_t),
|
||||
void *ctx)
|
||||
{
|
||||
struct v7fs_superblock *sb = &fs->superblock;
|
||||
size_t i, j, k;
|
||||
int ret;
|
||||
|
||||
/* Loop over ilist. */
|
||||
for (k = 1, i = V7FS_ILIST_SECTOR; i < sb->datablock_start_sector;
|
||||
i++) {
|
||||
struct v7fs_inode_diskimage *di;
|
||||
struct v7fs_inode inode;
|
||||
void *buf;
|
||||
|
||||
if (!(buf = scratch_read(fs, i))) {
|
||||
DPRINTF("block %zu I/O error.\n", i);
|
||||
k += V7FS_INODE_PER_BLOCK;
|
||||
continue;
|
||||
}
|
||||
di = (struct v7fs_inode_diskimage *)buf;
|
||||
for (j = 0; j < V7FS_INODE_PER_BLOCK; j++, k++) {
|
||||
v7fs_inode_setup_memory_image(fs, &inode, di + j);
|
||||
inode.inode_number = k;
|
||||
if ((ret = func(fs, ctx, &inode, k))) {
|
||||
scratch_free(fs, buf);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
scratch_free(fs, buf);
|
||||
}
|
||||
return 0;
|
||||
}
|
136
sys/fs/v7fs/v7fs_io.c
Normal file
136
sys/fs/v7fs/v7fs_io.c
Normal file
@ -0,0 +1,136 @@
|
||||
/* $NetBSD: v7fs_io.c,v 1.1 2011/06/27 11:52:25 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: v7fs_io.c,v 1.1 2011/06/27 11:52:25 uch Exp $");
|
||||
#if defined _KERNEL_OPT
|
||||
#include "opt_v7fs.h"
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <sys/param.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include "v7fs.h"
|
||||
#include "v7fs_impl.h"
|
||||
|
||||
#if defined _KERNEL
|
||||
#define STATIC_BUFFER
|
||||
#endif
|
||||
|
||||
#ifdef V7FS_IO_DEBUG
|
||||
#define DPRINTF(fmt, args...) printf("%s: " fmt, __func__, ##args)
|
||||
#else
|
||||
#define DPRINTF(fmt, args...) ((void)0)
|
||||
#endif
|
||||
|
||||
void *
|
||||
scratch_read(struct v7fs_self *fs, daddr_t blk)
|
||||
{
|
||||
#ifdef STATIC_BUFFER
|
||||
int i;
|
||||
MEM_LOCK(fs);
|
||||
for (i = 0; i < V7FS_SELF_NSCRATCH; i++) {
|
||||
if (fs->scratch_free & (1 << i)) {
|
||||
fs->scratch_free &= ~(1 << i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == V7FS_SELF_NSCRATCH) {
|
||||
DPRINTF("No scratch area. increase V7FS_SELF_NSCRATCH\n");
|
||||
assert(0);
|
||||
MEM_UNLOCK(fs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!fs->io.read(fs->io.cookie, fs->scratch[i], blk)) {
|
||||
DPRINTF("*** I/O error block %ld\n", (long)blk);
|
||||
fs->scratch_free |= (1 << i);
|
||||
MEM_UNLOCK(fs);
|
||||
return NULL;
|
||||
}
|
||||
MEM_UNLOCK(fs);
|
||||
/* Statistic */
|
||||
int n;
|
||||
if ((n = scratch_remain(fs)) < fs->scratch_remain)
|
||||
fs->scratch_remain = n;
|
||||
|
||||
return fs->scratch[i];
|
||||
#else
|
||||
uint8_t *buf = malloc(V7FS_BSIZE);
|
||||
if (!fs->io.read(fs->io.cookie, buf, blk)) {
|
||||
DPRINTF("*** I/O error block %ld\n",(long)blk);
|
||||
return NULL;
|
||||
}
|
||||
return buf;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
scratch_remain(const struct v7fs_self *fs)
|
||||
{
|
||||
#ifdef STATIC_BUFFER
|
||||
int nfree;
|
||||
int i;
|
||||
MEM_LOCK(fs);
|
||||
for (i = 0, nfree = 0; i < V7FS_SELF_NSCRATCH; i++) {
|
||||
if (fs->scratch_free & (1 << i)) {
|
||||
nfree++;
|
||||
}
|
||||
}
|
||||
MEM_UNLOCK(fs);
|
||||
return nfree;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
scratch_free(struct v7fs_self *fs __unused, void *p)
|
||||
{
|
||||
#ifdef STATIC_BUFFER
|
||||
int i;
|
||||
MEM_LOCK(fs);
|
||||
for (i = 0; i < V7FS_SELF_NSCRATCH; i++)
|
||||
if (fs->scratch[i] == p) {
|
||||
fs->scratch_free |= (1 << i);
|
||||
break;
|
||||
}
|
||||
MEM_UNLOCK(fs);
|
||||
assert(i != V7FS_SELF_NSCRATCH);
|
||||
#else
|
||||
free(p);
|
||||
#endif
|
||||
}
|
250
sys/fs/v7fs/v7fs_io_kern.c
Normal file
250
sys/fs/v7fs/v7fs_io_kern.c
Normal file
@ -0,0 +1,250 @@
|
||||
/* $NetBSD: v7fs_io_kern.c,v 1.1 2011/06/27 11:52:25 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2004, 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: v7fs_io_kern.c,v 1.1 2011/06/27 11:52:25 uch Exp $");
|
||||
#if defined _KERNEL_OPT
|
||||
#include "opt_v7fs.h"
|
||||
#endif
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__KERNEL_RCSID(0, "$NetBSD: v7fs_io_kern.c,v 1.1 2011/06/27 11:52:25 uch Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/kauth.h>
|
||||
#include <sys/mutex.h>
|
||||
|
||||
#include <fs/v7fs/v7fs.h>
|
||||
#include "v7fs_endian.h"
|
||||
#include "v7fs_impl.h"
|
||||
|
||||
#ifdef V7FS_IO_DEBUG
|
||||
#define DPRINTF(fmt, args...) printf("%s: " fmt, __func__, ##args)
|
||||
#else
|
||||
#define DPRINTF(fmt, args...) ((void)0)
|
||||
#endif
|
||||
|
||||
struct local_io {
|
||||
struct vnode *vp;
|
||||
kauth_cred_t cred;
|
||||
};
|
||||
|
||||
static bool v7fs_os_read_n(void *, uint8_t *, daddr_t, int);
|
||||
static bool v7fs_os_read(void *, uint8_t *, daddr_t);
|
||||
static bool v7fs_os_write_n(void *, uint8_t *, daddr_t, int);
|
||||
static bool v7fs_os_write(void *, uint8_t *, daddr_t);
|
||||
static void v7fs_os_lock(void *);
|
||||
static void v7fs_os_unlock(void *);
|
||||
static bool lock_init(struct lock_ops *);
|
||||
|
||||
MALLOC_JUSTDEFINE(M_V7FS, "v7fs core", "v7fs internal structures");
|
||||
|
||||
int
|
||||
v7fs_io_init(struct v7fs_self **fs,
|
||||
const struct v7fs_mount_device *mount_device, size_t block_size)
|
||||
{
|
||||
struct vnode *vp = mount_device->device.vnode;
|
||||
struct v7fs_self *p;
|
||||
struct local_io *local;
|
||||
int error = 0;
|
||||
|
||||
/* Allocate myself */
|
||||
if (!(p = (struct v7fs_self *)malloc(sizeof(*p), M_TEMP, M_WAITOK |
|
||||
M_ZERO)))
|
||||
return ENOMEM;
|
||||
memset(p, 0, sizeof(*p));
|
||||
|
||||
p->scratch_free = -1;
|
||||
p->scratch_remain = V7FS_SELF_NSCRATCH;
|
||||
|
||||
/* Endian */
|
||||
p->endian = mount_device->endian;
|
||||
#ifdef V7FS_EI
|
||||
v7fs_endian_init(p);
|
||||
#endif
|
||||
/* IO */
|
||||
if (!(local = (struct local_io *)malloc(sizeof(*local), M_TEMP,
|
||||
M_WAITOK | M_ZERO))) {
|
||||
error = ENOMEM;
|
||||
goto errexit;
|
||||
}
|
||||
p->io.read = v7fs_os_read;
|
||||
p->io.read_n = v7fs_os_read_n;
|
||||
p->io.write = v7fs_os_write;
|
||||
p->io.write_n = v7fs_os_write_n;
|
||||
p->scratch_free = -1; /* free all scratch buffer */
|
||||
|
||||
p->io.cookie = local;
|
||||
local->vp = vp;
|
||||
local->cred = NOCRED; /* upper layer check cred. */
|
||||
|
||||
/*LOCK */
|
||||
error = ENOMEM;
|
||||
if (!lock_init(&p->sb_lock))
|
||||
goto errexit;
|
||||
if (!lock_init(&p->ilist_lock))
|
||||
goto errexit;
|
||||
if (!lock_init(&p->mem_lock))
|
||||
goto errexit;
|
||||
error = 0;
|
||||
|
||||
*fs = p;
|
||||
return 0;
|
||||
|
||||
errexit:
|
||||
if (p->io.cookie)
|
||||
free(p->io.cookie, M_TEMP);
|
||||
if (p->sb_lock.cookie)
|
||||
free(p->sb_lock.cookie, M_TEMP);
|
||||
if (p->ilist_lock.cookie)
|
||||
free(p->ilist_lock.cookie, M_TEMP);
|
||||
if (p->mem_lock.cookie)
|
||||
free(p->mem_lock.cookie, M_TEMP);
|
||||
free(p, M_TEMP);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static bool
|
||||
lock_init(struct lock_ops *ops)
|
||||
{
|
||||
if (!(ops->cookie = (kmutex_t *)malloc(sizeof(kmutex_t), M_TEMP,
|
||||
M_WAITOK | M_ZERO))) {
|
||||
return false;
|
||||
}
|
||||
mutex_init(ops->cookie, MUTEX_DEFAULT, IPL_NONE);
|
||||
ops->lock = v7fs_os_lock;
|
||||
ops->unlock = v7fs_os_unlock;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
v7fs_io_fini(struct v7fs_self *fs)
|
||||
{
|
||||
mutex_destroy(fs->sb_lock.cookie);
|
||||
mutex_destroy(fs->ilist_lock.cookie);
|
||||
mutex_destroy(fs->mem_lock.cookie);
|
||||
|
||||
free(fs->io.cookie, M_TEMP);
|
||||
free(fs->sb_lock.cookie, M_TEMP);
|
||||
free(fs->ilist_lock.cookie, M_TEMP);
|
||||
free(fs, M_TEMP);
|
||||
}
|
||||
|
||||
static bool
|
||||
v7fs_os_read_n(void *self, uint8_t *buf, daddr_t block, int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (!v7fs_os_read(self, buf, block))
|
||||
return false;
|
||||
buf += DEV_BSIZE;
|
||||
block++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
v7fs_os_read(void *self, uint8_t *buf, daddr_t block)
|
||||
{
|
||||
struct local_io *bio = (struct local_io *)self;
|
||||
struct buf *bp = NULL;
|
||||
|
||||
if (bread(bio->vp, block, DEV_BSIZE, bio->cred, 0, &bp) != 0)
|
||||
goto error_exit;
|
||||
memcpy(buf, bp->b_data, DEV_BSIZE);
|
||||
brelse(bp, 0);
|
||||
|
||||
return true;
|
||||
error_exit:
|
||||
DPRINTF("block %ld read failed.\n", (long)block);
|
||||
|
||||
if (bp != NULL)
|
||||
brelse(bp, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
v7fs_os_write_n(void *self, uint8_t *buf, daddr_t block, int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (!v7fs_os_write(self, buf, block))
|
||||
return false;
|
||||
buf += DEV_BSIZE;
|
||||
block++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
v7fs_os_write(void *self, uint8_t *buf, daddr_t block)
|
||||
{
|
||||
struct local_io *bio = (struct local_io *)self;
|
||||
struct buf *bp;
|
||||
|
||||
if ((bp = getblk(bio->vp, block, DEV_BSIZE, 0, 0)) == 0) {
|
||||
DPRINTF("getblk failed. block=%ld\n", (long)block);
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(bp->b_data, buf, DEV_BSIZE);
|
||||
|
||||
if (bwrite(bp) != 0) {
|
||||
DPRINTF("bwrite failed. block=%ld\n", (long)block);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
v7fs_os_lock(void *self)
|
||||
{
|
||||
|
||||
mutex_enter((kmutex_t *)self);
|
||||
}
|
||||
|
||||
static void
|
||||
v7fs_os_unlock(void *self)
|
||||
{
|
||||
|
||||
mutex_exit((kmutex_t *)self);
|
||||
}
|
169
sys/fs/v7fs/v7fs_io_user.c
Normal file
169
sys/fs/v7fs/v7fs_io_user.c
Normal file
@ -0,0 +1,169 @@
|
||||
/* $NetBSD: v7fs_io_user.c,v 1.1 2011/06/27 11:52:25 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: v7fs_io_user.c,v 1.1 2011/06/27 11:52:25 uch Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <err.h>
|
||||
#include <sys/mman.h>
|
||||
#include "v7fs.h"
|
||||
#include "v7fs_endian.h"
|
||||
#include "v7fs_impl.h"
|
||||
|
||||
#ifdef V7FS_IO_DEBUG
|
||||
#define DPRINTF(fmt, args...) printf("%s: " fmt, __func__, ##args)
|
||||
#else
|
||||
#define DPRINTF(fmt, args...) ((void)0)
|
||||
#endif
|
||||
|
||||
struct local_io {
|
||||
int fd;
|
||||
size_t size;
|
||||
size_t blksz;
|
||||
uint8_t *addr;
|
||||
} local;
|
||||
|
||||
static bool read_sector(void *, uint8_t *, daddr_t);
|
||||
static bool write_sector(void *, uint8_t *, daddr_t);
|
||||
static bool read_mmap(void *, uint8_t *, daddr_t);
|
||||
static bool write_mmap(void *, uint8_t *, daddr_t);
|
||||
|
||||
int
|
||||
v7fs_io_init(struct v7fs_self **fs, const struct v7fs_mount_device *mount,
|
||||
size_t block_size)
|
||||
{
|
||||
struct v7fs_self *p;
|
||||
|
||||
if (!(p = (struct v7fs_self *)malloc(sizeof(*p))))
|
||||
return ENOMEM;
|
||||
memset(p, 0, sizeof(*p));
|
||||
|
||||
/* Endian */
|
||||
p->endian = mount->endian;
|
||||
#ifdef V7FS_EI
|
||||
v7fs_endian_init(p);
|
||||
#endif
|
||||
local.blksz = block_size;
|
||||
local.fd = mount->device.fd;
|
||||
local.size = mount->sectors * block_size;
|
||||
local.addr = mmap(NULL, local.size, PROT_READ | PROT_WRITE | PROT_NONE,
|
||||
MAP_FILE | MAP_SHARED/*writeback*/, local.fd, 0);
|
||||
if (local.addr == MAP_FAILED) {
|
||||
warn("mmap failed. use direct I/O.");
|
||||
local.addr = 0;
|
||||
p->io.read = read_sector;
|
||||
p->io.write = write_sector;
|
||||
} else {
|
||||
DPRINTF("mmaped addr=%p\n", local.addr);
|
||||
p->io.read = read_mmap;
|
||||
p->io.write = write_mmap;
|
||||
}
|
||||
|
||||
p->io.cookie = &local;
|
||||
*fs = p;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
v7fs_io_fini(struct v7fs_self *fs)
|
||||
{
|
||||
struct local_io *lio = (struct local_io *)fs->io.cookie;
|
||||
|
||||
if (lio->addr) {
|
||||
if (munmap(lio->addr, lio->size) != 0)
|
||||
warn(0);
|
||||
}
|
||||
fsync(lio->fd);
|
||||
|
||||
free(fs);
|
||||
}
|
||||
|
||||
static bool
|
||||
read_sector(void *ctx, uint8_t *buf, daddr_t sector)
|
||||
{
|
||||
struct local_io *lio = (struct local_io *)ctx;
|
||||
size_t blksz = lio->blksz;
|
||||
int fd = lio->fd;
|
||||
|
||||
if ((lseek(fd, sector * blksz, SEEK_SET) < 0) ||
|
||||
(read(fd, buf, blksz) < (ssize_t)blksz)) {
|
||||
warn("sector=%ld\n", (long)sector);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
write_sector(void *ctx, uint8_t *buf, daddr_t sector)
|
||||
{
|
||||
struct local_io *lio = (struct local_io *)ctx;
|
||||
size_t blksz = lio->blksz;
|
||||
int fd = lio->fd;
|
||||
|
||||
if ((lseek(fd, sector * blksz, SEEK_SET) < 0) ||
|
||||
(write(fd, buf, blksz) < (ssize_t)blksz)) {
|
||||
warn("sector=%ld\n", (long)sector);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
read_mmap(void *ctx, uint8_t *buf, daddr_t sector)
|
||||
{
|
||||
struct local_io *lio = (struct local_io *)ctx;
|
||||
size_t blksz = lio->blksz;
|
||||
|
||||
memcpy(buf, lio->addr + sector * blksz, blksz);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
write_mmap(void *ctx, uint8_t *buf, daddr_t sector)
|
||||
{
|
||||
struct local_io *lio = (struct local_io *)ctx;
|
||||
size_t blksz = lio->blksz;
|
||||
|
||||
memcpy(lio->addr + sector * blksz, buf, blksz);
|
||||
|
||||
return true;
|
||||
}
|
259
sys/fs/v7fs/v7fs_superblock.c
Normal file
259
sys/fs/v7fs/v7fs_superblock.c
Normal file
@ -0,0 +1,259 @@
|
||||
/* $NetBSD: v7fs_superblock.c,v 1.1 2011/06/27 11:52:25 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: v7fs_superblock.c,v 1.1 2011/06/27 11:52:25 uch Exp $");
|
||||
#if defined _KERNEL_OPT
|
||||
#include "opt_v7fs.h"
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <sys/systm.h>
|
||||
#include <sys/param.h> /* errno */
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include "v7fs.h"
|
||||
#include "v7fs_impl.h"
|
||||
#include "v7fs_endian.h"
|
||||
#include "v7fs_superblock.h"
|
||||
#include "v7fs_inode.h"
|
||||
#include "v7fs_datablock.h"
|
||||
|
||||
#ifdef V7FS_SUPERBLOCK_DEBUG
|
||||
#define DPRINTF(fmt, args...) printf("%s: " fmt, __func__, ##args)
|
||||
#define DPRINTF_(fmt, args...) printf(fmt, ##args)
|
||||
#else
|
||||
#define DPRINTF(fmt, args...) ((void)0)
|
||||
#define DPRINTF_(fmt, args...) ((void)0)
|
||||
#endif
|
||||
|
||||
static void v7fs_superblock_endian_convert(struct v7fs_self *,
|
||||
struct v7fs_superblock *, struct v7fs_superblock *);
|
||||
static int v7fs_superblock_sanity(struct v7fs_self *);
|
||||
|
||||
/* Load superblock from disk. */
|
||||
int
|
||||
v7fs_superblock_load(struct v7fs_self *fs)
|
||||
{
|
||||
struct v7fs_superblock *disksb;
|
||||
void *buf;
|
||||
int error;
|
||||
|
||||
if (!(buf = scratch_read(fs, V7FS_SUPERBLOCK_SECTOR)))
|
||||
return EIO;
|
||||
disksb = (struct v7fs_superblock *)buf;
|
||||
v7fs_superblock_endian_convert(fs, &fs->superblock, disksb);
|
||||
scratch_free(fs, buf);
|
||||
|
||||
if ((error = v7fs_superblock_sanity(fs)))
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Writeback superblock to disk. */
|
||||
int
|
||||
v7fs_superblock_writeback(struct v7fs_self *fs)
|
||||
{
|
||||
struct v7fs_superblock *memsb = &fs->superblock;
|
||||
struct v7fs_superblock *disksb;
|
||||
void *buf;
|
||||
int error = 0;
|
||||
|
||||
if (!memsb->modified)
|
||||
return 0;
|
||||
|
||||
if (!(buf = scratch_read(fs, V7FS_SUPERBLOCK_SECTOR)))
|
||||
return EIO;
|
||||
disksb = (struct v7fs_superblock *)buf;
|
||||
v7fs_superblock_endian_convert(fs, disksb, memsb);
|
||||
if (!fs->io.write(fs->io.cookie, buf, V7FS_SUPERBLOCK_SECTOR))
|
||||
error = EIO;
|
||||
scratch_free(fs, buf);
|
||||
|
||||
memsb->modified = 0;
|
||||
DPRINTF("done. %d\n", error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Check endian mismatch. */
|
||||
static int
|
||||
v7fs_superblock_sanity(struct v7fs_self *fs)
|
||||
{
|
||||
const struct v7fs_superblock *sb = &fs->superblock;
|
||||
void *buf = 0;
|
||||
|
||||
if ((sb->volume_size < 128) || /* smaller than 64KB. */
|
||||
(sb->datablock_start_sector > sb->volume_size) ||
|
||||
(sb->nfreeinode > V7FS_MAX_FREEINODE) ||
|
||||
(sb->nfreeblock > V7FS_MAX_FREEBLOCK) ||
|
||||
(sb->update_time < 0) ||
|
||||
(sb->total_freeblock > sb->volume_size) ||
|
||||
((sb->nfreeinode == 0) && (sb->nfreeblock == 0) &&
|
||||
(sb->total_freeblock == 0) && (sb->total_freeinode == 0)) ||
|
||||
(!(buf = scratch_read(fs, sb->volume_size - 1)))) {
|
||||
DPRINTF("invalid super block.\n");
|
||||
return EINVAL;
|
||||
}
|
||||
if (buf)
|
||||
scratch_free(fs, buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fill free block to superblock cache. */
|
||||
int
|
||||
v7fs_freeblock_update(struct v7fs_self *fs, v7fs_daddr_t blk)
|
||||
{
|
||||
/* Assume superblock is locked by caller. */
|
||||
struct v7fs_superblock *sb = &fs->superblock;
|
||||
struct v7fs_freeblock *fb;
|
||||
void *buf;
|
||||
int error;
|
||||
|
||||
/* Read next freeblock table from disk. */
|
||||
if (!datablock_number_sanity(fs, blk) || !(buf = scratch_read(fs, blk)))
|
||||
return EIO;
|
||||
|
||||
/* Update in-core superblock freelist. */
|
||||
fb = (struct v7fs_freeblock *)buf;
|
||||
if ((error = v7fs_freeblock_endian_convert(fs, fb))) {
|
||||
scratch_free(fs, buf);
|
||||
return error;
|
||||
}
|
||||
DPRINTF("freeblock table#%d, nfree=%d\n", blk, fb->nfreeblock);
|
||||
|
||||
memcpy(sb->freeblock, fb->freeblock, sizeof(blk) * fb->nfreeblock);
|
||||
sb->nfreeblock = fb->nfreeblock;
|
||||
sb->modified = true;
|
||||
scratch_free(fs, buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_freeblock_endian_convert(struct v7fs_self *fs __unused,
|
||||
struct v7fs_freeblock *fb __unused)
|
||||
{
|
||||
#ifdef V7FS_EI
|
||||
int i;
|
||||
int16_t nfree;
|
||||
|
||||
nfree = V7FS_VAL16(fs, fb->nfreeblock);
|
||||
if (nfree <= 0 || nfree > V7FS_MAX_FREEBLOCK) {
|
||||
DPRINTF("invalid freeblock list. %d (max=%d)\n", nfree,
|
||||
V7FS_MAX_FREEBLOCK);
|
||||
return ENOSPC;
|
||||
}
|
||||
fb->nfreeblock = nfree;
|
||||
|
||||
for (i = 0; i < nfree; i++) {
|
||||
fb->freeblock[i] = V7FS_VAL32(fs, fb->freeblock[i]);
|
||||
}
|
||||
#endif /* V7FS_EI */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fill free inode to superblock cache. */
|
||||
int
|
||||
v7fs_freeinode_update(struct v7fs_self *fs)
|
||||
{
|
||||
/* Assume superblock is locked by caller. */
|
||||
struct v7fs_superblock *sb = &fs->superblock;
|
||||
v7fs_ino_t *freeinode = sb->freeinode;
|
||||
size_t i, j, k;
|
||||
v7fs_ino_t ino;
|
||||
|
||||
/* Loop over all inode list. */
|
||||
for (i = V7FS_ILIST_SECTOR, ino = 1/* inode start from 1*/, k = 0;
|
||||
i < sb->datablock_start_sector; i++) {
|
||||
struct v7fs_inode_diskimage *di;
|
||||
void *buf;
|
||||
if (!(buf = scratch_read(fs, i))) {
|
||||
DPRINTF("block %zu I/O error.\n", i);
|
||||
ino += V7FS_INODE_PER_BLOCK;
|
||||
continue;
|
||||
}
|
||||
di = (struct v7fs_inode_diskimage *)buf;
|
||||
|
||||
for (j = 0;
|
||||
(j < V7FS_INODE_PER_BLOCK) && (k < V7FS_MAX_FREEINODE);
|
||||
j++, di++, ino++) {
|
||||
if (v7fs_inode_allocated(di))
|
||||
continue;
|
||||
DPRINTF("free inode%d\n", ino);
|
||||
freeinode[k++] = ino;
|
||||
}
|
||||
scratch_free(fs, buf);
|
||||
}
|
||||
sb->nfreeinode = k;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
v7fs_superblock_endian_convert(struct v7fs_self *fs __unused,
|
||||
struct v7fs_superblock *to, struct v7fs_superblock *from)
|
||||
{
|
||||
#ifdef V7FS_EI
|
||||
#define conv16(m) (to->m = V7FS_VAL16(fs, from->m))
|
||||
#define conv32(m) (to->m = V7FS_VAL32(fs, from->m))
|
||||
int i;
|
||||
|
||||
conv16(datablock_start_sector);
|
||||
conv32(volume_size);
|
||||
conv16(nfreeblock);
|
||||
v7fs_daddr_t *dfrom = from->freeblock;
|
||||
v7fs_daddr_t *dto = to->freeblock;
|
||||
for (i = 0; i < V7FS_MAX_FREEBLOCK; i++, dfrom++, dto++)
|
||||
*dto = V7FS_VAL32(fs, *dfrom);
|
||||
|
||||
conv16(nfreeinode);
|
||||
v7fs_ino_t *ifrom = from->freeinode;
|
||||
v7fs_ino_t *ito = to->freeinode;
|
||||
for (i = 0; i < V7FS_MAX_FREEINODE; i++, ifrom++, ito++)
|
||||
*ito = V7FS_VAL16(fs, *ifrom);
|
||||
|
||||
conv32(update_time);
|
||||
conv32(total_freeblock);
|
||||
conv16(total_freeinode);
|
||||
#undef conv16
|
||||
#undef conv32
|
||||
#else /* V7FS_EI */
|
||||
memcpy(to, from , sizeof(*to));
|
||||
#endif /* V7FS_EI */
|
||||
}
|
48
sys/fs/v7fs/v7fs_superblock.h
Normal file
48
sys/fs/v7fs/v7fs_superblock.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* $NetBSD: v7fs_superblock.h,v 1.1 2011/06/27 11:52:25 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _V7FS_SUPERBLOCK_H_
|
||||
#define _V7FS_SUPERBLOCK_H_
|
||||
struct v7fs_self;
|
||||
|
||||
__BEGIN_DECLS
|
||||
/* core */
|
||||
int v7fs_superblock_load(struct v7fs_self *);
|
||||
int v7fs_superblock_writeback(struct v7fs_self *);
|
||||
int v7fs_freeblock_update(struct v7fs_self *, v7fs_daddr_t);
|
||||
int v7fs_freeblock_endian_convert(struct v7fs_self *, struct v7fs_freeblock *);
|
||||
int v7fs_freeinode_update(struct v7fs_self *);
|
||||
|
||||
/* util. */
|
||||
void v7fs_superblock_status(struct v7fs_self *);
|
||||
void v7fs_superblock_dump(const struct v7fs_self *);
|
||||
__END_DECLS
|
||||
#endif /*!_V7FS_SUPERBLOCK_H_ */
|
97
sys/fs/v7fs/v7fs_superblock_util.c
Normal file
97
sys/fs/v7fs/v7fs_superblock_util.c
Normal file
@ -0,0 +1,97 @@
|
||||
/* $NetBSD: v7fs_superblock_util.c,v 1.1 2011/06/27 11:52:25 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: v7fs_superblock_util.c,v 1.1 2011/06/27 11:52:25 uch Exp $");
|
||||
#if defined _KERNEL_OPT
|
||||
#include "opt_v7fs.h"
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <sys/systm.h>
|
||||
#include <sys/param.h> /* errno */
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#include "v7fs.h"
|
||||
#include "v7fs_impl.h"
|
||||
#include "v7fs_superblock.h"
|
||||
#include "v7fs_inode.h"
|
||||
|
||||
#ifdef V7FS_SUPERBLOCK_DEBUG
|
||||
#define DPRINTF(fmt, args...) printf("%s: " fmt, __func__, ##args)
|
||||
#define DPRINTF_(fmt, args...) printf(fmt, ##args)
|
||||
#else
|
||||
#define DPRINTF(fmt, args...) ((void)0)
|
||||
#define DPRINTF_(fmt, args...) ((void)0)
|
||||
#endif
|
||||
|
||||
void
|
||||
v7fs_superblock_status(struct v7fs_self *fs)
|
||||
{
|
||||
struct v7fs_superblock *sb = &fs->superblock;
|
||||
struct v7fs_stat *stat = &fs->stat;
|
||||
|
||||
stat->total_blocks = sb->volume_size - sb->datablock_start_sector;
|
||||
stat->total_inode = V7FS_MAX_INODE(sb);
|
||||
stat->free_inode = sb->total_freeinode;
|
||||
stat->free_blocks = sb->total_freeblock;
|
||||
stat->total_files = stat->total_inode - sb->total_freeinode - 1;
|
||||
|
||||
DPRINTF("block %d/%d, inode %d/%d\n", stat->free_blocks,
|
||||
stat->total_blocks, stat->free_inode, stat->total_inode);
|
||||
}
|
||||
|
||||
void
|
||||
v7fs_superblock_dump(const struct v7fs_self *fs)
|
||||
{
|
||||
const struct v7fs_superblock *sb = &fs->superblock;
|
||||
|
||||
#define print(x) printf("%s: %d\n", #x, sb->x)
|
||||
print(datablock_start_sector);
|
||||
print(volume_size);
|
||||
print(nfreeblock);
|
||||
print(nfreeinode);
|
||||
print(update_time);
|
||||
print(lock_freeblock);
|
||||
print(lock_freeinode);
|
||||
print(modified);
|
||||
print(readonly);
|
||||
#if !defined _KERNEL
|
||||
time_t t = sb->update_time;
|
||||
printf("%s", ctime(&t));
|
||||
#endif
|
||||
print(total_freeblock);
|
||||
print(total_freeinode);
|
||||
#undef print
|
||||
}
|
602
sys/fs/v7fs/v7fs_vfsops.c
Normal file
602
sys/fs/v7fs/v7fs_vfsops.c
Normal file
@ -0,0 +1,602 @@
|
||||
/* $NetBSD: v7fs_vfsops.c,v 1.1 2011/06/27 11:52:25 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2004, 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by UCHIYAMA Yasushi.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: v7fs_vfsops.c,v 1.1 2011/06/27 11:52:25 uch Exp $");
|
||||
#if defined _KERNEL_OPT
|
||||
#include "opt_v7fs.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/pool.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ucred.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/kauth.h>
|
||||
#include <sys/proc.h>
|
||||
|
||||
/* v-node */
|
||||
#include <sys/namei.h>
|
||||
#include <sys/vnode.h>
|
||||
/* devsw */
|
||||
#include <sys/conf.h>
|
||||
|
||||
#include "v7fs_extern.h"
|
||||
#include "v7fs.h"
|
||||
#include "v7fs_impl.h"
|
||||
#include "v7fs_inode.h"
|
||||
#include "v7fs_superblock.h"
|
||||
|
||||
#ifdef V7FS_VFSOPS_DEBUG
|
||||
#define DPRINTF(fmt, args...) printf("%s: " fmt, __func__, ##args)
|
||||
#else
|
||||
#define DPRINTF(arg...) ((void)0)
|
||||
#endif
|
||||
|
||||
MALLOC_JUSTDEFINE(M_V7FS_VFS, "v7fs vfs", "v7fs vfs structures");
|
||||
|
||||
struct pool v7fs_node_pool;
|
||||
|
||||
static int v7fs_mountfs(struct vnode *, struct mount *, int);
|
||||
static int v7fs_openfs(struct vnode *, struct mount *, struct lwp *);
|
||||
static void v7fs_closefs(struct vnode *, struct mount *);
|
||||
static bool is_v7fs_partition(struct vnode *);
|
||||
static enum vtype v7fs_mode_to_vtype(v7fs_mode_t mode);
|
||||
|
||||
int
|
||||
v7fs_mount(struct mount *mp, const char *path, void *data, size_t *data_len)
|
||||
{
|
||||
struct lwp *l = curlwp;
|
||||
struct v7fs_args *args = data;
|
||||
struct v7fs_mount *v7fsmount = (void *)mp->mnt_data;
|
||||
struct vnode *devvp = NULL;
|
||||
int error;
|
||||
bool update = mp->mnt_flag & MNT_UPDATE;
|
||||
|
||||
DPRINTF("mnt_flag=%x %s\n", mp->mnt_flag, update ? "update" : "");
|
||||
|
||||
if (*data_len < sizeof(*args))
|
||||
return EINVAL;
|
||||
|
||||
if (mp->mnt_flag & MNT_GETARGS) {
|
||||
if (!v7fsmount)
|
||||
return EIO;
|
||||
args->fspec = NULL;
|
||||
args->endian = v7fsmount->core->endian;
|
||||
*data_len = sizeof(*args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DPRINTF("args->fspec=%s endian=%d\n", args->fspec, args->endian);
|
||||
if (args->fspec == NULL) {
|
||||
/* nothing to do. */
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (args->fspec != NULL) {
|
||||
/* Look up the name and verify that it's sane. */
|
||||
error = namei_simple_user(args->fspec,
|
||||
NSM_FOLLOW_NOEMULROOT, &devvp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
DPRINTF("mount device=%lx\n", (long)devvp->v_rdev);
|
||||
|
||||
if (!update) {
|
||||
/*
|
||||
* Be sure this is a valid block device
|
||||
*/
|
||||
if (devvp->v_type != VBLK)
|
||||
error = ENOTBLK;
|
||||
else if (bdevsw_lookup(devvp->v_rdev) == NULL)
|
||||
error = ENXIO;
|
||||
} else {
|
||||
KDASSERT(v7fsmount);
|
||||
/*
|
||||
* Be sure we're still naming the same device
|
||||
* used for our initial mount
|
||||
*/
|
||||
if (devvp != v7fsmount->devvp) {
|
||||
DPRINTF("devvp %p != %p rootvp=%p\n", devvp,
|
||||
v7fsmount->devvp, rootvp);
|
||||
if (rootvp == v7fsmount->devvp) {
|
||||
vrele(devvp);
|
||||
devvp = rootvp;
|
||||
vref(devvp);
|
||||
} else {
|
||||
error = EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If mount by non-root, then verify that user has necessary
|
||||
* permissions on the device.
|
||||
*
|
||||
* Permission to update a mount is checked higher, so here we presume
|
||||
* updating the mount is okay (for example, as far as securelevel goes)
|
||||
* which leaves us with the normal check.
|
||||
*/
|
||||
if (error == 0) {
|
||||
int accessmode = VREAD;
|
||||
if (update ?
|
||||
(mp->mnt_iflag & IMNT_WANTRDWR) != 0 :
|
||||
(mp->mnt_flag & MNT_RDONLY) == 0)
|
||||
accessmode |= VWRITE;
|
||||
error = genfs_can_mount(devvp, accessmode, l->l_cred);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
vrele(devvp);
|
||||
return error;
|
||||
}
|
||||
|
||||
if (!update) {
|
||||
if ((error = v7fs_openfs(devvp, mp, l))) {
|
||||
vrele(devvp);
|
||||
return error;
|
||||
}
|
||||
|
||||
if ((error = v7fs_mountfs(devvp, mp, args->endian))) {
|
||||
v7fs_closefs(devvp, mp);
|
||||
VOP_UNLOCK(devvp);
|
||||
vrele(devvp);
|
||||
return error;
|
||||
}
|
||||
VOP_UNLOCK(devvp);
|
||||
} else if (mp->mnt_flag & MNT_RDONLY) {
|
||||
/* XXX: r/w -> read only */
|
||||
}
|
||||
|
||||
return set_statvfs_info(path, UIO_USERSPACE, args->fspec, UIO_USERSPACE,
|
||||
mp->mnt_op->vfs_name, mp, l);
|
||||
}
|
||||
|
||||
static bool
|
||||
is_v7fs_partition(struct vnode *devvp)
|
||||
{
|
||||
struct partinfo dpart;
|
||||
int error;
|
||||
|
||||
if ((error = VOP_IOCTL(devvp, DIOCGPART, &dpart, FREAD, NOCRED)) != 0) {
|
||||
DPRINTF("VOP_IOCTL=%d\n", error);
|
||||
return false;
|
||||
}
|
||||
DPRINTF("fstype=%d dtype=%d bsize=%d\n", dpart.part->p_fstype,
|
||||
dpart.disklab->d_type, dpart.disklab->d_secsize);
|
||||
|
||||
return dpart.part->p_fstype == FS_V7;
|
||||
}
|
||||
|
||||
static int
|
||||
v7fs_openfs(struct vnode *devvp, struct mount *mp, struct lwp *l)
|
||||
{
|
||||
kauth_cred_t cred = l->l_cred;
|
||||
int oflags;
|
||||
int error;
|
||||
|
||||
/* Flush buffer */
|
||||
vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
|
||||
if ((error = vinvalbuf(devvp, V_SAVE, cred, l, 0, 0)))
|
||||
goto unlock_exit;
|
||||
|
||||
/* Open block device */
|
||||
oflags = FREAD;
|
||||
if ((mp->mnt_flag & MNT_RDONLY) == 0)
|
||||
oflags |= FWRITE;
|
||||
|
||||
if ((error = VOP_OPEN(devvp, oflags, NOCRED)) != 0) {
|
||||
DPRINTF("VOP_OPEN=%d\n", error);
|
||||
goto unlock_exit;
|
||||
}
|
||||
|
||||
/* Get partition information */
|
||||
if (!is_v7fs_partition(devvp))
|
||||
goto close_exit;
|
||||
|
||||
return 0; /* lock held */
|
||||
|
||||
close_exit:
|
||||
VOP_CLOSE(devvp, oflags, NOCRED);
|
||||
unlock_exit:
|
||||
VOP_UNLOCK(devvp);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static void
|
||||
v7fs_closefs(struct vnode *devvp, struct mount *mp)
|
||||
{
|
||||
int oflags = FREAD;
|
||||
|
||||
if ((mp->mnt_flag & MNT_RDONLY) == 0)
|
||||
oflags |= FWRITE;
|
||||
|
||||
VOP_CLOSE(devvp, oflags, NOCRED);
|
||||
}
|
||||
|
||||
static int
|
||||
v7fs_mountfs(struct vnode *devvp, struct mount *mp, int endian)
|
||||
{
|
||||
struct v7fs_mount *v7fsmount;
|
||||
int error;
|
||||
struct v7fs_mount_device mount;
|
||||
|
||||
DPRINTF("%d\n",endian);
|
||||
|
||||
v7fsmount = malloc(sizeof(*v7fsmount), M_V7FS_VFS, M_WAITOK);
|
||||
if (v7fsmount == NULL) {
|
||||
return ENOMEM;
|
||||
}
|
||||
v7fsmount->devvp = devvp;
|
||||
v7fsmount->mountp = mp;
|
||||
|
||||
mount.device.vnode = devvp;
|
||||
mount.endian = endian;
|
||||
|
||||
if ((error = v7fs_io_init(&v7fsmount->core, &mount, V7FS_BSIZE))) {
|
||||
goto err_exit;
|
||||
}
|
||||
struct v7fs_self *fs = v7fsmount->core;
|
||||
|
||||
if ((error = v7fs_superblock_load(fs))) {
|
||||
v7fs_io_fini(fs);
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
LIST_INIT(&v7fsmount->v7fs_node_head);
|
||||
|
||||
mp->mnt_data = v7fsmount;
|
||||
mp->mnt_stat.f_fsidx.__fsid_val[0] = (long)devvp->v_rdev;
|
||||
mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_V7FS);
|
||||
mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
|
||||
mp->mnt_stat.f_namemax = V7FS_NAME_MAX;
|
||||
mp->mnt_flag |= MNT_LOCAL;
|
||||
mp->mnt_dev_bshift = V7FS_BSHIFT;
|
||||
mp->mnt_fs_bshift = V7FS_BSHIFT;
|
||||
|
||||
return 0;
|
||||
|
||||
err_exit:
|
||||
free(v7fsmount, M_V7FS_VFS);
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_start(struct mount *mp, int flags)
|
||||
{
|
||||
|
||||
DPRINTF("\n");
|
||||
/* Nothing to do. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_unmount(struct mount *mp, int mntflags)
|
||||
{
|
||||
struct v7fs_mount *v7fsmount = (void *)mp->mnt_data;
|
||||
int error;
|
||||
|
||||
DPRINTF("%p\n", v7fsmount);
|
||||
|
||||
if ((error = vflush(mp, NULLVP,
|
||||
mntflags & MNT_FORCE ? FORCECLOSE : 0)) != 0)
|
||||
return error;
|
||||
|
||||
vn_lock(v7fsmount->devvp, LK_EXCLUSIVE | LK_RETRY);
|
||||
error = VOP_CLOSE(v7fsmount->devvp, FREAD, NOCRED);
|
||||
vput(v7fsmount->devvp);
|
||||
|
||||
v7fs_io_fini(v7fsmount->core);
|
||||
|
||||
free(v7fsmount, M_V7FS_VFS);
|
||||
mp->mnt_data = NULL;
|
||||
mp->mnt_flag &= ~MNT_LOCAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_root(struct mount *mp, struct vnode **vpp)
|
||||
{
|
||||
struct vnode *vp;
|
||||
int error;
|
||||
|
||||
DPRINTF("\n");
|
||||
if ((error = VFS_VGET(mp, V7FS_ROOT_INODE, &vp)) != 0) {
|
||||
DPRINTF("error=%d\n", error);
|
||||
return error;
|
||||
}
|
||||
*vpp = vp;
|
||||
DPRINTF("done.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_statvfs(struct mount *mp, struct statvfs *f)
|
||||
{
|
||||
struct v7fs_mount *v7fsmount = mp->mnt_data;
|
||||
struct v7fs_self *fs = v7fsmount->core;
|
||||
|
||||
DPRINTF("scratch remain=%d\n", fs->scratch_remain);
|
||||
|
||||
v7fs_superblock_status(fs);
|
||||
|
||||
f->f_bsize = V7FS_BSIZE;
|
||||
f->f_frsize = V7FS_BSIZE;
|
||||
f->f_iosize = V7FS_BSIZE;
|
||||
f->f_blocks = fs->stat.total_blocks;
|
||||
f->f_bfree = fs->stat.free_blocks;
|
||||
f->f_bavail = fs->stat.free_blocks;
|
||||
f->f_bresvd = 0;
|
||||
f->f_files = fs->stat.total_files;
|
||||
f->f_ffree = fs->stat.free_inode;
|
||||
f->f_favail = f->f_ffree;
|
||||
f->f_fresvd = 0;
|
||||
copy_statvfs_info(f, mp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_sync(struct mount *mp, int waitfor, kauth_cred_t cred)
|
||||
{
|
||||
struct v7fs_mount *v7fsmount = mp->mnt_data;
|
||||
struct v7fs_self *fs = v7fsmount->core;
|
||||
struct v7fs_node *v7fs_node;
|
||||
struct v7fs_inode *inode;
|
||||
struct vnode *v;
|
||||
int err, error;
|
||||
int retry_cnt;
|
||||
|
||||
DPRINTF("\n");
|
||||
|
||||
v7fs_superblock_writeback(fs);
|
||||
for (retry_cnt = 0; retry_cnt < 2; retry_cnt++) {
|
||||
error = 0;
|
||||
|
||||
mutex_enter(&mntvnode_lock);
|
||||
for (v7fs_node = LIST_FIRST(&v7fsmount->v7fs_node_head);
|
||||
v7fs_node != NULL; v7fs_node = LIST_NEXT(v7fs_node, link)) {
|
||||
inode = &v7fs_node->inode;
|
||||
if (!v7fs_inode_allocated(inode)) {
|
||||
continue;
|
||||
}
|
||||
v = v7fs_node->vnode;
|
||||
mutex_enter(v->v_interlock);
|
||||
mutex_exit(&mntvnode_lock);
|
||||
err = vget(v, LK_EXCLUSIVE | LK_NOWAIT);
|
||||
if (err == 0) {
|
||||
err = VOP_FSYNC(v, cred, FSYNC_WAIT, 0, 0);
|
||||
vput(v);
|
||||
}
|
||||
if (err != 0)
|
||||
error = err;
|
||||
mutex_enter(&mntvnode_lock);
|
||||
}
|
||||
mutex_exit(&mntvnode_lock);
|
||||
|
||||
if (error == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static enum vtype
|
||||
v7fs_mode_to_vtype (v7fs_mode_t mode)
|
||||
{
|
||||
enum vtype table[] = { VCHR, VDIR, VBLK, VREG, VLNK, VSOCK };
|
||||
|
||||
if ((mode & V7FS_IFMT) == V7FSBSD_IFFIFO)
|
||||
return VFIFO;
|
||||
|
||||
return table[((mode >> 13) & 7) - 1];
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
|
||||
{
|
||||
struct v7fs_mount *v7fsmount = mp->mnt_data;
|
||||
struct v7fs_self *fs = v7fsmount->core;
|
||||
struct vnode *vp;
|
||||
struct v7fs_node *v7fs_node;
|
||||
struct v7fs_inode inode;
|
||||
int error;
|
||||
|
||||
/* Lookup requested i-node */
|
||||
if ((error = v7fs_inode_load(fs, &inode, ino))) {
|
||||
DPRINTF("v7fs_inode_load failed.\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
retry:
|
||||
mutex_enter(&mntvnode_lock);
|
||||
for (v7fs_node = LIST_FIRST(&v7fsmount->v7fs_node_head);
|
||||
v7fs_node != NULL; v7fs_node = LIST_NEXT(v7fs_node, link)) {
|
||||
if (v7fs_node->inode.inode_number == ino) {
|
||||
vp = v7fs_node->vnode;
|
||||
mutex_enter(vp->v_interlock);
|
||||
mutex_exit(&mntvnode_lock);
|
||||
if (vget(vp, LK_EXCLUSIVE) == 0) {
|
||||
*vpp = vp;
|
||||
return 0;
|
||||
} else {
|
||||
DPRINTF("retry!\n");
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
}
|
||||
mutex_exit(&mntvnode_lock);
|
||||
|
||||
/* Allocate v-node. */
|
||||
if ((error = getnewvnode(VT_V7FS, mp, v7fs_vnodeop_p, NULL, &vp))) {
|
||||
DPRINTF("getnewvnode error.\n");
|
||||
return error;
|
||||
}
|
||||
/* Lock vnode here */
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
||||
|
||||
/* Allocate i-node */
|
||||
vp->v_data = pool_get(&v7fs_node_pool, PR_WAITOK);
|
||||
memset(vp->v_data, 0, sizeof(*v7fs_node));
|
||||
v7fs_node = vp->v_data;
|
||||
mutex_enter(&mntvnode_lock);
|
||||
LIST_INSERT_HEAD(&v7fsmount->v7fs_node_head, v7fs_node, link);
|
||||
mutex_exit(&mntvnode_lock);
|
||||
v7fs_node->vnode = vp;
|
||||
v7fs_node->v7fsmount = v7fsmount;
|
||||
v7fs_node->inode = inode;/*structure copy */
|
||||
v7fs_node->lockf = NULL; /* advlock */
|
||||
|
||||
genfs_node_init(vp, &v7fs_genfsops);
|
||||
uvm_vnp_setsize(vp, v7fs_inode_filesize(&inode));
|
||||
|
||||
if (ino == V7FS_ROOT_INODE) {
|
||||
vp->v_type = VDIR;
|
||||
vp->v_vflag |= VV_ROOT;
|
||||
} else {
|
||||
vp->v_type = v7fs_mode_to_vtype(inode.mode);
|
||||
|
||||
if (vp->v_type == VBLK || vp->v_type == VCHR) {
|
||||
dev_t rdev = inode.device;
|
||||
vp->v_op = v7fs_specop_p;
|
||||
spec_node_init(vp, rdev);
|
||||
} else if (vp->v_type == VFIFO) {
|
||||
vp->v_op = v7fs_fifoop_p;
|
||||
}
|
||||
}
|
||||
|
||||
*vpp = vp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
v7fs_fhtovp(struct mount *mp, struct fid *fid, struct vnode **vpp)
|
||||
{
|
||||
|
||||
DPRINTF("\n");
|
||||
/* notyet */
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_vptofh(struct vnode *vpp, struct fid *fid, size_t *fh_size)
|
||||
{
|
||||
|
||||
DPRINTF("\n");
|
||||
/* notyet */
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
|
||||
MALLOC_DECLARE(M_V7FS);
|
||||
MALLOC_DECLARE(M_V7FS_VNODE);
|
||||
|
||||
void
|
||||
v7fs_init(void)
|
||||
{
|
||||
|
||||
DPRINTF("\n");
|
||||
malloc_type_attach(M_V7FS_VFS);
|
||||
malloc_type_attach(M_V7FS);
|
||||
malloc_type_attach(M_V7FS_VNODE);
|
||||
pool_init(&v7fs_node_pool, sizeof(struct v7fs_node), 0, 0, 0,
|
||||
"v7fs_node_pool", &pool_allocator_nointr, IPL_NONE);
|
||||
}
|
||||
|
||||
void
|
||||
v7fs_reinit(void)
|
||||
{
|
||||
|
||||
/* Nothing to do. */
|
||||
DPRINTF("\n");
|
||||
}
|
||||
|
||||
void
|
||||
v7fs_done(void)
|
||||
{
|
||||
|
||||
DPRINTF("\n");
|
||||
pool_destroy(&v7fs_node_pool);
|
||||
malloc_type_detach(M_V7FS);
|
||||
malloc_type_detach(M_V7FS_VFS);
|
||||
malloc_type_detach(M_V7FS_VNODE);
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_gop_alloc(struct vnode *vp, off_t off, off_t len, int flags,
|
||||
kauth_cred_t cred)
|
||||
{
|
||||
|
||||
DPRINTF("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
v7fs_mountroot(void)
|
||||
{
|
||||
struct mount *mp;
|
||||
int error;
|
||||
|
||||
DPRINTF("");
|
||||
/* On mountroot, devvp (rootdev) is opened by vfs_mountroot */
|
||||
if (!is_v7fs_partition (rootvp))
|
||||
return EINVAL;
|
||||
|
||||
if ((error = vfs_rootmountalloc(MOUNT_V7FS, "root_device", &mp))) {
|
||||
DPRINTF("mountalloc error=%d\n", error);
|
||||
vrele(rootvp);
|
||||
return error;
|
||||
}
|
||||
|
||||
if ((error = v7fs_mountfs(rootvp, mp, _BYTE_ORDER))) {
|
||||
DPRINTF("mountfs error=%d\n", error);
|
||||
vfs_unbusy(mp, false, NULL);
|
||||
vfs_destroy(mp);
|
||||
return error;
|
||||
}
|
||||
|
||||
mutex_enter(&mountlist_lock);
|
||||
CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
|
||||
mutex_exit(&mountlist_lock);
|
||||
|
||||
vfs_unbusy(mp, false, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
1281
sys/fs/v7fs/v7fs_vnops.c
Normal file
1281
sys/fs/v7fs/v7fs_vnops.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: disklabel.h,v 1.108 2011/01/18 19:52:24 matt Exp $ */
|
||||
/* $NetBSD: disklabel.h,v 1.109 2011/06/27 11:52:24 uch Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1987, 1988, 1993
|
||||
@ -328,7 +328,7 @@ static const char *const dktypenames[] = { DKTYPE_DEFN(DKTYPE_NAMES) NULL };
|
||||
x(UNUSED, 0, "unused", NULL, NULL) /* unused */ \
|
||||
x(SWAP, 1, "swap", NULL, NULL) /* swap */ \
|
||||
x(V6, 2, "Version 6", NULL, NULL) /* Sixth Edition */ \
|
||||
x(V7, 3, "Version 7", NULL, NULL) /* Seventh Edition */ \
|
||||
x(V7, 3, "Version 7", "v7fs", "v7fs") /* Seventh Edition */ \
|
||||
x(SYSV, 4, "System V", NULL, NULL) /* System V */ \
|
||||
x(V71K, 5, "4.1BSD", NULL, NULL) /* V7, 1K blocks (4.1, 2.9) */ \
|
||||
x(V8, 6, "Eighth Edition",NULL, NULL) /* Eighth Edition, 4K blocks */ \
|
||||
@ -355,6 +355,7 @@ x(SYSVBFS, 25, "SysVBFS", NULL, "sysvbfs")/* System V boot file system */ \
|
||||
x(EFS, 26, "EFS", NULL, "efs") /* SGI's Extent Filesystem */ \
|
||||
x(NILFS, 27, "NiLFS", NULL, "nilfs") /* NTT's NiLFS(2) */
|
||||
|
||||
|
||||
#ifndef _LOCORE
|
||||
#define FS_TYPENUMS(tag, number, name, fsck, mount) __CONCAT(FS_,tag=number),
|
||||
enum { FSTYPE_DEFN(FS_TYPENUMS) FSMAXTYPES };
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: mount.h,v 1.199 2011/04/02 04:57:35 rmind Exp $ */
|
||||
/* $NetBSD: mount.h,v 1.200 2011/06/27 11:52:24 uch Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1991, 1993
|
||||
@ -94,6 +94,7 @@
|
||||
#define MOUNT_ZFS "zfs" /* Sun ZFS */
|
||||
#define MOUNT_NILFS "nilfs" /* NTT's NiLFS(2) logging file system */
|
||||
#define MOUNT_RUMPFS "rumpfs" /* rump virtual file system */
|
||||
#define MOUNT_V7FS "v7fs" /* 7th Edition of Unix Filesystem */
|
||||
|
||||
#ifndef _STANDALONE
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vnode.h,v 1.232 2011/06/21 17:28:11 riz Exp $ */
|
||||
/* $NetBSD: vnode.h,v 1.233 2011/06/27 11:52:24 uch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008 The NetBSD Foundation, Inc.
|
||||
@ -105,7 +105,7 @@ enum vtagtype {
|
||||
VT_AFS, VT_ISOFS, VT_UNION, VT_ADOSFS, VT_EXT2FS, VT_CODA,
|
||||
VT_FILECORE, VT_NTFS, VT_VFS, VT_OVERLAY, VT_SMBFS, VT_PTYFS,
|
||||
VT_TMPFS, VT_UDF, VT_SYSVBFS, VT_PUFFS, VT_HFS, VT_EFS, VT_ZFS,
|
||||
VT_RUMP, VT_NILFS
|
||||
VT_RUMP, VT_NILFS, VT_V7FS
|
||||
};
|
||||
|
||||
#define VNODE_TAGS \
|
||||
@ -114,7 +114,7 @@ enum vtagtype {
|
||||
"VT_AFS", "VT_ISOFS", "VT_UNION", "VT_ADOSFS", "VT_EXT2FS", "VT_CODA", \
|
||||
"VT_FILECORE", "VT_NTFS", "VT_VFS", "VT_OVERLAY", "VT_SMBFS", "VT_PTYFS", \
|
||||
"VT_TMPFS", "VT_UDF", "VT_SYSVBFS", "VT_PUFFS", "VT_HFS", "VT_EFS", \
|
||||
"VT_ZFS", "VT_RUMP", "VT_NILFS"
|
||||
"VT_ZFS", "VT_RUMP", "VT_NILFS", "VT_V7FS"
|
||||
|
||||
struct vnode;
|
||||
struct buf;
|
||||
|
Loading…
Reference in New Issue
Block a user