7th Edition(V7) File System support. and NetBSD symbolic-link, socket, FIFO extension. see newfs_v7fs(8).

This commit is contained in:
uch 2011-06-27 11:52:22 +00:00
parent 846092f009
commit 9255b46fb4
54 changed files with 8987 additions and 13 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
View 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
View 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
View 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;
}

View 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
View 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);
}

View 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
View 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
View 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
View 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
View 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>

View 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.

View 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);
}

View 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
View 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
View 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;
}

View 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

View 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);
}

View 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_ */

View File

@ -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"

View File

@ -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
View 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
View 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
View 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
View 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_ */

View 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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_ */

View 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
View 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
View 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
View 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_ */

View 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
View 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
View 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
View 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;
}

View 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 */
}

View 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_ */

View 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
View 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

File diff suppressed because it is too large Load Diff

View File

@ -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 };

View File

@ -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

View File

@ -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;