svn commit: r234479 - in projects/nand: lib/libnandfs sbin/nandfs
sbin/newfs_nandfs sys/fs/nandfs
Grzegorz Bernacki
gber at FreeBSD.org
Fri Apr 20 03:02:08 UTC 2012
Author: gber
Date: Fri Apr 20 03:02:07 2012
New Revision: 234479
URL: http://svn.freebsd.org/changeset/base/234479
Log:
nandfs: Fixes.
- replace error numbers with proper macros
- get rid of some unused fields in fsdata and super block
- when erasing segment invalidate gc buffers that still point to it
- flag segments that are going to be erased (this flag should never hit
storage - it is only so that cleaner does not try to clear one segment
twice)
- place some asserts
- add veryfing FS revision at mount time
- rmdir without this operation left invalid data in inode
- file created right after deleted directory appeared as directory
- reduce inode size of removed directory to 0 (similar to ext2fs, msdosfs)
- check if inode has any links during lookup (similar to ufs)
- protect write entry points by very same lock used to protect segment
construction - this servers as our own version of vfs_write_suspend
- ignore MNT_LAZY syncs - this is a hack used to ignore periodic syncs
from mnt_syncer
Obtained from: Semihalf
Supported by: FreeBSD Foundation, Juniper Networks
Modified:
projects/nand/lib/libnandfs/Makefile
projects/nand/sbin/nandfs/nandfs.c
projects/nand/sbin/newfs_nandfs/newfs_nandfs.c
projects/nand/sys/fs/nandfs/nandfs.h
projects/nand/sys/fs/nandfs/nandfs_alloc.c
projects/nand/sys/fs/nandfs/nandfs_cleaner.c
projects/nand/sys/fs/nandfs/nandfs_fs.h
projects/nand/sys/fs/nandfs/nandfs_segment.c
projects/nand/sys/fs/nandfs/nandfs_subr.c
projects/nand/sys/fs/nandfs/nandfs_subr.h
projects/nand/sys/fs/nandfs/nandfs_sufile.c
projects/nand/sys/fs/nandfs/nandfs_vfsops.c
projects/nand/sys/fs/nandfs/nandfs_vnops.c
Modified: projects/nand/lib/libnandfs/Makefile
==============================================================================
--- projects/nand/lib/libnandfs/Makefile Fri Apr 20 02:47:35 2012 (r234478)
+++ projects/nand/lib/libnandfs/Makefile Fri Apr 20 03:02:07 2012 (r234479)
@@ -1,3 +1,5 @@
+# $FreeBSD$
+
LIB= nandfs
SRCS+= nandfs.c
INCS= libnandfs.h
Modified: projects/nand/sbin/nandfs/nandfs.c
==============================================================================
--- projects/nand/sbin/nandfs/nandfs.c Fri Apr 20 02:47:35 2012 (r234478)
+++ projects/nand/sbin/nandfs/nandfs.c Fri Apr 20 03:02:07 2012 (r234479)
@@ -45,7 +45,7 @@ usage(void)
fprintf(stderr, "usage: nandfs [lssnap | mksnap <snap> | rmsnap] "
"node\n");
- exit(EX_USAGE);
+ exit(1);
}
int
Modified: projects/nand/sbin/newfs_nandfs/newfs_nandfs.c
==============================================================================
--- projects/nand/sbin/newfs_nandfs/newfs_nandfs.c Fri Apr 20 02:47:35 2012 (r234478)
+++ projects/nand/sbin/newfs_nandfs/newfs_nandfs.c Fri Apr 20 03:02:07 2012 (r234479)
@@ -517,13 +517,9 @@ create_fsdata(void)
fsdata.f_rev_level = NANDFS_CURRENT_REV;
fsdata.f_sbbytes = NANDFS_SB_BYTES;
fsdata.f_bytes = NANDFS_FSDATA_CRC_BYTES;
- fsdata.f_dev_size = mediasize;
fsdata.f_ctime = nandfs_time;
fsdata.f_log_block_size = nandfs_log2(blocksize) - 10;
fsdata.f_errors = 1;
- fsdata.f_lastcheck = nandfs_time;
- fsdata.f_checkinterval = 60*60*24*180;
- fsdata.f_first_ino = NANDFS_USER_INO;
fsdata.f_inode_size = sizeof(struct nandfs_inode);
fsdata.f_dat_entry_size = sizeof(struct nandfs_dat_entry);
fsdata.f_checkpoint_size = sizeof(struct nandfs_checkpoint);
@@ -559,8 +555,6 @@ create_super_block(void)
(nsegments - bad_segments_count) * blocks_per_segment;
super_block.s_mtime = 0;
super_block.s_wtime = nandfs_time;
- super_block.s_mnt_count = 0;
- super_block.s_max_mnt_count = NANDFS_DFL_MAX_MNT_COUNT;
super_block.s_state = NANDFS_VALID_FS;
super_block.s_sum = crc32_le(crc_seed, (const uint8_t *)&super_block,
Modified: projects/nand/sys/fs/nandfs/nandfs.h
==============================================================================
--- projects/nand/sys/fs/nandfs/nandfs.h Fri Apr 20 02:47:35 2012 (r234478)
+++ projects/nand/sys/fs/nandfs/nandfs.h Fri Apr 20 03:02:07 2012 (r234479)
@@ -233,6 +233,11 @@ extern SLIST_HEAD(_nandfs_devices, nandf
#define SYNCER_FSYNC 0x4
#define SYNCER_ROUPD 0x5
+#define NANDFS_WRITELOCK(vp, fsdev) nandfs_writelock(vp, fsdev)
+#define NANDFS_WRITEUNLOCK(fsdev) nandfs_writeunlock(fsdev)
+
+#define NANDFS_WRITEASSERT(fsdev) nandfs_writeassert(fsdev)
+
/* Specific mountpoint; head or a checkpoint/snapshot */
struct nandfsmount {
STAILQ_ENTRY(nandfsmount) nm_next_mount;
Modified: projects/nand/sys/fs/nandfs/nandfs_alloc.c
==============================================================================
--- projects/nand/sys/fs/nandfs/nandfs_alloc.c Fri Apr 20 02:47:35 2012 (r234478)
+++ projects/nand/sys/fs/nandfs/nandfs_alloc.c Fri Apr 20 03:02:07 2012 (r234479)
@@ -260,6 +260,7 @@ nandfs_free_entry(struct nandfs_mdt* mdt
/* Set bit to indicate that entry is taken */
mask = (uint32_t *)req->bp_bitmap->b_data;
maskrw = mask[bitmap_idx];
+ KASSERT(maskrw & (1 << bitmap_off), ("freeing unallocated vblock"));
maskrw &= ~(1 << bitmap_off);
mask[bitmap_idx] = maskrw;
Modified: projects/nand/sys/fs/nandfs/nandfs_cleaner.c
==============================================================================
--- projects/nand/sys/fs/nandfs/nandfs_cleaner.c Fri Apr 20 02:47:35 2012 (r234478)
+++ projects/nand/sys/fs/nandfs/nandfs_cleaner.c Fri Apr 20 03:02:07 2012 (r234479)
@@ -256,8 +256,8 @@ nandfs_cleaner_iterate_segment(struct na
binfo = (union nandfs_binfo *)(bp->b_data + segsum->ss_bytes);
if (!nandfs_segsum_valid(segsum)) {
- nandfs_error("nandfs: invalid summary of segment %jx\n", segno);
brelse(bp);
+ nandfs_error("nandfs: invalid summary of segment %jx\n", segno);
return (error);
}
@@ -293,7 +293,8 @@ nandfs_cleaner_choose_segment(struct nan
error = nandfs_get_segment_info_filter(fsdev, suinfo, nsegs, *rseg,
&ssegs, NANDFS_SEGMENT_USAGE_DIRTY,
- NANDFS_SEGMENT_USAGE_ACTIVE | NANDFS_SEGMENT_USAGE_ERROR);
+ NANDFS_SEGMENT_USAGE_ACTIVE | NANDFS_SEGMENT_USAGE_ERROR |
+ NANDFS_SEGMENT_USAGE_GC);
if (error) {
nandfs_error("%s:%d", __FILE__, __LINE__);
goto out;
@@ -306,7 +307,7 @@ nandfs_cleaner_choose_segment(struct nan
(*segpp)++;
}
- *rseg = suinfo[i - 1].nsi_num;
+ *rseg = suinfo[i - 1].nsi_num + 1;
out:
free(suinfo, M_NANDFSTEMP);
@@ -351,13 +352,21 @@ nandfs_cleaner_body(struct nandfs_device
error = nandfs_cleaner_iterate_segment(fsdev, segnums[i], &vip,
&bdp, &select);
if (error) {
- nandfs_error("%s:%d", __FILE__, __LINE__);
+ /*
+ * XXX deselect (see below)?
+ */
goto out;
}
if (!select)
segnums[i] = NANDFS_NOSEGMENT;
- else
+ else {
+ error = nandfs_markgc_segment(fsdev, segnums[i]);
+ if (error) {
+ nandfs_error("%s:%d\n", __FILE__, __LINE__);
+ goto out;
+ }
selected++;
+ }
}
if (selected == 0) {
@@ -379,14 +388,16 @@ nandfs_cleaner_body(struct nandfs_device
cpinfo, cpstat.ncp_nss, NULL);
if (error) {
nandfs_error("%s:%d\n", __FILE__, __LINE__);
- goto out;
+ goto out_locked;
}
}
+ lockmgr(&fsdev->nd_seg_const, LK_EXCLUSIVE, NULL);
+
error = nandfs_get_dat_vinfo(fsdev, vinfo, vip - vinfo);
if (error) {
nandfs_error("%s:%d\n", __FILE__, __LINE__);
- goto out;
+ goto out_locked;
}
nandfs_cleaner_vinfo_mark_alive(fsdev, vinfo, vip - vinfo, cpinfo,
@@ -395,7 +406,7 @@ nandfs_cleaner_body(struct nandfs_device
error = nandfs_get_dat_bdescs(fsdev, bdesc, bdp - bdesc);
if (error) {
nandfs_error("%s:%d\n", __FILE__, __LINE__);
- goto out;
+ goto out_locked;
}
nandfs_cleaner_bdesc_mark_alive(fsdev, bdesc, bdp - bdesc);
@@ -407,8 +418,9 @@ nandfs_cleaner_body(struct nandfs_device
vipi->nvi_start, vipi->nvi_end, vipi->nvi_alive));
}
for (bdpi = bdesc; bdpi < bdp; bdpi++) {
- DPRINTF(CLEAN, ("b oblocknr %jx blocknr %jx offset %jx\n",
- bdpi->bd_oblocknr, bdpi->bd_blocknr, bdpi->bd_offset));
+ DPRINTF(CLEAN, ("b oblocknr %jx blocknr %jx offset %jx "
+ "alive %d\n", bdpi->bd_oblocknr, bdpi->bd_blocknr,
+ bdpi->bd_offset, bdpi->bd_alive));
}
DPRINTF(CLEAN, ("end list\n"));
@@ -417,6 +429,8 @@ nandfs_cleaner_body(struct nandfs_device
if (error)
nandfs_error("%s:%d\n", __FILE__, __LINE__);
+out_locked:
+ lockmgr(&fsdev->nd_seg_const, LK_RELEASE, NULL);
out:
free(cpinfo, M_NANDFSTEMP);
free(segnums, M_NANDFSTEMP);
@@ -464,7 +478,6 @@ nandfs_cleaner_clean_segments(struct nan
gc = nffsdev->nd_gc_node;
- lockmgr(&nffsdev->nd_seg_const, LK_EXCLUSIVE, NULL);
DPRINTF(CLEAN, ("%s: enter\n", __func__));
@@ -535,7 +548,6 @@ nandfs_cleaner_clean_segments(struct nan
}
out:
- lockmgr(&nffsdev->nd_seg_const, LK_RELEASE, NULL);
DPRINTF(CLEAN, ("%s: exit error %d\n", __func__, error));
Modified: projects/nand/sys/fs/nandfs/nandfs_fs.h
==============================================================================
--- projects/nand/sys/fs/nandfs/nandfs_fs.h Fri Apr 20 02:47:35 2012 (r234478)
+++ projects/nand/sys/fs/nandfs/nandfs_fs.h Fri Apr 20 03:02:07 2012 (r234479)
@@ -146,7 +146,6 @@ struct nandfs_fsdata {
uint32_t f_sum; /* checksum of fsdata */
uint32_t f_rev_level; /* major disk format revision */
- uint64_t f_dev_size; /* block device size in bytes */
uint64_t f_ctime; /* creation time (execution time
of newfs) */
/* Block size represented as: blocksize = 1 << (f_log_block_size + 10) */
@@ -162,7 +161,6 @@ struct nandfs_fsdata {
is excluded! */
uint16_t f_errors; /* behaviour on detecting errors */
- uint64_t f_lastcheck; /* time of last checked */
uint32_t f_erasesize;
uint64_t f_nsegments; /* number of segm. in filesystem */
@@ -170,24 +168,17 @@ struct nandfs_fsdata {
uint32_t f_blocks_per_segment; /* number of blocks per segment */
uint32_t f_r_segments_percentage; /* reserved segments percentage */
- uint32_t f_checkinterval; /* max. time between checks */
- uint16_t f_def_resuid; /* default uid for reserv. blocks */
- uint16_t f_def_resgid; /* default gid for reserv. blocks */
- uint32_t f_first_ino; /* first non-reserved inode */
-
uint32_t f_crc_seed; /* seed value of CRC calculation */
struct uuid f_uuid; /* 128-bit uuid for volume */
char f_volume_name[16]; /* volume name */
- uint32_t f_pad[96];
+ uint32_t f_pad[103];
} __packed;
#ifdef _KERNEL
CTASSERT(sizeof(struct nandfs_fsdata) == 512);
#endif
-#define NANDFS_DFL_MAX_MNT_COUNT 50 /* default 50 mounts before fsck */
-
struct nandfs_super_block {
uint16_t s_magic; /* magic value for identification */
@@ -200,8 +191,6 @@ struct nandfs_super_block {
uint64_t s_mtime; /* mount time */
uint64_t s_wtime; /* write time */
- uint16_t s_mnt_count; /* mount count */
- uint16_t s_max_mnt_count; /* maximal mount count */
uint16_t s_state; /* file system state */
char s_last_mounted[64]; /* directory where last mounted */
@@ -209,7 +198,7 @@ struct nandfs_super_block {
uint32_t s_c_interval; /* commit interval of segment */
uint32_t s_c_block_max; /* threshold of data amount for
the segment construction */
- uint32_t s_reserved[31]; /* padding to end of the block */
+ uint32_t s_reserved[32]; /* padding to end of the block */
} __packed;
#ifdef _KERNEL
@@ -442,6 +431,7 @@ struct nandfs_segment_usage {
#define NANDFS_SEGMENT_USAGE_ACTIVE 1
#define NANDFS_SEGMENT_USAGE_DIRTY 2
#define NANDFS_SEGMENT_USAGE_ERROR 4
+#define NANDFS_SEGMENT_USAGE_GC 8
#define NANDFS_SEGMENT_USAGE_BITS "\20\1ACTIVE\2DIRTY\3ERROR"
/* Header of the segment usage file */
Modified: projects/nand/sys/fs/nandfs/nandfs_segment.c
==============================================================================
--- projects/nand/sys/fs/nandfs/nandfs_segment.c Fri Apr 20 02:47:35 2012 (r234478)
+++ projects/nand/sys/fs/nandfs/nandfs_segment.c Fri Apr 20 03:02:07 2012 (r234479)
@@ -110,7 +110,7 @@ create_segment(struct nandfs_seginfo *se
}
start_block = fsdev->nd_last_pseg + (uint64_t)nblocks;
/*
- * XXX hack
+ * XXX Hack
*/
if (blks_per_seg - (start_block % blks_per_seg) - 1 == 0)
start_block++;
@@ -123,6 +123,10 @@ create_segment(struct nandfs_seginfo *se
__func__);
return (error);
}
+ /*
+ * XXX Hack
+ */
+ nandfs_get_segment_range(fsdev, fsdev->nd_seg_num, &start_block, NULL);
}
} else {
nandfs_get_segment_range(fsdev, fsdev->nd_next_seg_num,
@@ -503,6 +507,12 @@ nandfs_iterate_dirty_vnodes(struct mount
continue;
}
+ if (vp->v_iflag & VI_DOOMED) {
+ vput(vp);
+ MNT_ILOCK(mp);
+ continue;
+ }
+
nandfs_node = VTON(vp);
if (nandfs_node->nn_flags & IN_MODIFIED) {
nandfs_node->nn_flags &= ~(IN_MODIFIED);
@@ -921,6 +931,36 @@ out:
return (error);
}
+static void
+nandfs_invalidate_bufs(struct nandfs_device *fsdev, uint64_t segno)
+{
+ uint64_t start, end;
+ struct buf *bp, *tbd;
+ struct bufobj *bo;
+
+ nandfs_get_segment_range(fsdev, segno, &start, &end);
+
+ bo = &NTOV(fsdev->nd_gc_node)->v_bufobj;
+
+ BO_LOCK(bo);
+restart_locked_gc:
+ TAILQ_FOREACH_SAFE(bp, &bo->bo_clean.bv_hd, b_bobufs, tbd) {
+ if (!(bp->b_lblkno >= start || bp->b_lblkno <= end))
+ continue;
+
+ if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL))
+ goto restart_locked_gc;
+
+ bremfree(bp);
+ bp->b_flags |= (B_INVAL | B_RELBUF);
+ bp->b_flags &= ~(B_ASYNC | B_MANAGED);
+ BO_UNLOCK(bo);
+ brelse(bp);
+ BO_LOCK(bo);
+ }
+ BO_UNLOCK(bo);
+}
+
/* Process segments marks to free by cleaner */
static void
nandfs_process_segments(struct nandfs_device *fsdev)
@@ -940,6 +980,7 @@ nandfs_process_segments(struct nandfs_de
saved_segment = nandfs_get_segnum_of_block(
fsdev, fsdev->nd_super.s_last_pseg);
}
+ nandfs_invalidate_bufs(fsdev, fsdev->nd_free_base[i]);
nandfs_clear_segment(fsdev, fsdev->nd_free_base[i]);
}
Modified: projects/nand/sys/fs/nandfs/nandfs_subr.c
==============================================================================
--- projects/nand/sys/fs/nandfs/nandfs_subr.c Fri Apr 20 02:47:35 2012 (r234478)
+++ projects/nand/sys/fs/nandfs/nandfs_subr.c Fri Apr 20 03:02:07 2012 (r234479)
@@ -274,6 +274,8 @@ nandfs_bdestroy(struct nandfs_node *node
{
int error;
+ NANDFS_WRITEASSERT(node->nn_nandfsdev);
+
error = nandfs_vblock_end(node->nn_nandfsdev, vblk);
if (error) {
nandfs_error("%s: ending vblk: %jx failed\n",
@@ -292,6 +294,7 @@ nandfs_bcreate(struct nandfs_node *node,
int error;
ASSERT_VOP_LOCKED(NTOV(node), __func__);
+ NANDFS_WRITEASSERT(node->nn_nandfsdev);
DPRINTF(BLOCK, ("%s: vp:%p lbn:%#jx\n", __func__, NTOV(node),
blocknr));
@@ -329,6 +332,7 @@ nandfs_bcreate_meta(struct nandfs_node *
int error;
ASSERT_VOP_LOCKED(NTOV(node), __func__);
+ NANDFS_WRITEASSERT(node->nn_nandfsdev);
DPRINTF(BLOCK, ("%s: vp:%p lbn:%#jx\n", __func__, NTOV(node),
blocknr));
@@ -431,7 +435,7 @@ nandfs_mdt_trans_blk(struct nandfs_mdt *
static int
nandfs_vtop(struct nandfs_device *nandfsdev, nandfs_daddr_t vblocknr,
- uint64_t *pblocknr)
+ nandfs_daddr_t *pblocknr)
{
struct nandfs_node *dat_node;
struct nandfs_dat_entry *entry;
@@ -468,13 +472,16 @@ nandfs_vtop(struct nandfs_device *nandfs
brelse(bp);
if (!locked)
VOP_UNLOCK(NTOV(dat_node), 0);
+
+ MPASS(*pblocknr >= 0);
+
return (0);
}
int
nandfs_nvtop(struct nandfs_node *node, uint64_t blks, nandfs_daddr_t *l2vmap,
- uint64_t *v2pmap)
+ nandfs_daddr_t *v2pmap)
{
nandfs_daddr_t vblocknr;
uint64_t *pblocknr;
@@ -1200,3 +1207,34 @@ nandfs_block_to_dblock(struct nandfs_dev
return (btodb(block * fsdev->nd_blocksize));
}
+
+void
+nandfs_writelock(struct vnode *vp, struct nandfs_device *fsdev)
+{
+ int lock;
+
+ if (lockmgr(&fsdev->nd_seg_const, LK_NOWAIT | LK_SHARED, NULL)) {
+ vref(vp);
+ lock = VOP_ISLOCKED(vp);
+ VOP_UNLOCK(vp, 0);
+ DPRINTF(WRITE, ("%s: waiting for write lock, vp %p\n",
+ __func__, vp));
+ lockmgr(&fsdev->nd_seg_const, LK_SHARED, NULL);
+ VOP_LOCK(vp, lock | LK_RETRY);
+ vunref(vp);
+ }
+}
+
+void
+nandfs_writeunlock(struct nandfs_device *fsdev)
+{
+
+ lockmgr(&fsdev->nd_seg_const, LK_RELEASE, NULL);
+}
+
+void
+nandfs_writeassert(struct nandfs_device *fsdev)
+{
+
+ lockmgr_assert(&fsdev->nd_seg_const, KA_LOCKED);
+}
Modified: projects/nand/sys/fs/nandfs/nandfs_subr.h
==============================================================================
--- projects/nand/sys/fs/nandfs/nandfs_subr.h Fri Apr 20 02:47:35 2012 (r234478)
+++ projects/nand/sys/fs/nandfs/nandfs_subr.h Fri Apr 20 03:02:07 2012 (r234479)
@@ -75,7 +75,7 @@ int nandfs_bmap_nlookup(struct nandfs_no
uint64_t *);
/* vtop operations */
-int nandfs_nvtop(struct nandfs_node *, uint64_t, nandfs_daddr_t *, uint64_t *);
+int nandfs_nvtop(struct nandfs_node *, uint64_t, nandfs_daddr_t *, nandfs_daddr_t *);
/* Node action implementators */
int nandfs_vinit(struct vnode *, uint64_t);
@@ -147,6 +147,7 @@ int nandfs_update_segment(struct nandfs_
int nandfs_free_segment(struct nandfs_device *, uint64_t);
int nandfs_clear_segment(struct nandfs_device *, uint64_t);
int nandfs_touch_segment(struct nandfs_device *, uint64_t);
+int nandfs_markgc_segment(struct nandfs_device *, uint64_t);
int nandfs_bmap_insert_block(struct nandfs_node *, nandfs_lbn_t, struct buf *);
int nandfs_bmap_update_block(struct nandfs_node *, struct buf *, nandfs_lbn_t);
@@ -226,6 +227,10 @@ int nandfs_vop_islocked(struct vnode *vp
nandfs_daddr_t nandfs_block_to_dblock(struct nandfs_device *, nandfs_lbn_t);
+void nandfs_writelock(struct vnode *, struct nandfs_device *);
+void nandfs_writeunlock(struct nandfs_device *);
+void nandfs_writeassert(struct nandfs_device *);
+
#define DEBUG_MODE
#if defined(DEBUG_MODE)
#define nandfs_error panic
Modified: projects/nand/sys/fs/nandfs/nandfs_sufile.c
==============================================================================
--- projects/nand/sys/fs/nandfs/nandfs_sufile.c Fri Apr 20 02:47:35 2012 (r234478)
+++ projects/nand/sys/fs/nandfs/nandfs_sufile.c Fri Apr 20 03:02:07 2012 (r234479)
@@ -367,6 +367,40 @@ nandfs_bad_segment(struct nandfs_device
}
int
+nandfs_markgc_segment(struct nandfs_device *fsdev, uint64_t seg)
+{
+ struct nandfs_node *su_node;
+ struct nandfs_segment_usage *su_usage;
+ struct buf *bp;
+ uint64_t blk, offset;
+ int error;
+
+ su_node = fsdev->nd_su_node;
+
+ VOP_LOCK(NTOV(su_node), LK_EXCLUSIVE);
+
+ nandfs_seg_usage_blk_offset(fsdev, seg, &blk, &offset);
+
+ error = nandfs_bread(su_node, blk, NOCRED, 0, &bp);
+ if (error) {
+ brelse(bp);
+ VOP_UNLOCK(NTOV(su_node), 0);
+ return (error);
+ }
+
+ su_usage = SU_USAGE_OFF(bp, offset);
+ MPASS((su_usage->su_flags & NANDFS_SEGMENT_USAGE_GC) == 0);
+ su_usage->su_flags |= NANDFS_SEGMENT_USAGE_GC;
+
+ brelse(bp);
+ VOP_UNLOCK(NTOV(su_node), 0);
+
+ DPRINTF(SEG, ("%s: seg:%#jx\n", __func__, (uintmax_t)seg));
+
+ return (0);
+}
+
+int
nandfs_clear_segment(struct nandfs_device *fsdev, uint64_t seg)
{
uint64_t offset, segsize;
Modified: projects/nand/sys/fs/nandfs/nandfs_vfsops.c
==============================================================================
--- projects/nand/sys/fs/nandfs/nandfs_vfsops.c Fri Apr 20 02:47:35 2012 (r234478)
+++ projects/nand/sys/fs/nandfs/nandfs_vfsops.c Fri Apr 20 03:02:07 2012 (r234479)
@@ -664,6 +664,13 @@ nandfs_mount_base(struct nandfs_device *
return (error);
}
+ if (nandfsdev->nd_fsdata.f_rev_level != NANDFS_CURRENT_REV) {
+ printf("nandfs: unsupported file system revision: %d "
+ "(supported is %d).\n", nandfsdev->nd_fsdata.f_rev_level,
+ NANDFS_CURRENT_REV);
+ return (EINVAL);
+ }
+
if (nandfsdev->nd_fsdata.f_erasesize != nandfsdev->nd_erasesize) {
printf("nandfs: erasesize mismatch (device %#x, fs %#x)\n",
nandfsdev->nd_erasesize, nandfsdev->nd_fsdata.f_erasesize);
@@ -892,11 +899,7 @@ nandfs_mount_device(struct vnode *devvp,
if (error) {
DPRINTF(VOLUMES, ("couldn't get erasesize: %d\n", error));
- /*
- * FIXME translate this to some normal error codes, also make
- * sure that we cannot get this error with NAND devices
- */
- if (error == -3 || error == 45) {
+ if (error == ENOIOCTL || error == EOPNOTSUPP) {
/*
* We conclude that this is not NAND storage
*/
@@ -1116,12 +1119,10 @@ nandfs_procbody(struct nandfsmount *nmp)
flags = (nmp->nm_flags & (NANDFS_FORCE_SYNCER|NANDFS_UMOUNT));
- vfs_write_suspend(mp);
error = nandfs_segment_constructor(nmp, flags);
if (error)
nandfs_error("%s: error:%d when creating segments\n",
__func__, error);
- vfs_write_resume(mp);
nmp->nm_flags &= ~flags;
@@ -1173,9 +1174,7 @@ stop_syncer(struct nandfsmount *nmp)
MPASS(nmp->nm_nandfsdev->nd_syncer != NULL);
- vn_finished_write(nmp->nm_vfs_mountp);
nandfs_wakeup_wait_sync(nmp->nm_nandfsdev, SYNCER_UMOUNT);
- vn_start_write(NULL, &nmp->nm_vfs_mountp, V_WAIT);
DPRINTF(SYNC, ("%s: stop syncer\n", __func__));
return (0);
@@ -1453,12 +1452,7 @@ nandfs_unmount(struct mount *mp, int mnt
/* Umount already stopped writing */
if (!(nmp->nm_ronly)) {
nmp->nm_flags |= NANDFS_UMOUNT;
- /*
- * XXX This is a hack soon to be removed
- */
- vn_finished_write(mp);
nandfs_wakeup_wait_sync(nmp->nm_nandfsdev, SYNCER_VFS_SYNC);
- vn_start_write(NULL, &mp, V_WAIT);
}
error = vflush(mp, 0, flags | SKIPSYSTEM, curthread);
if (error)
@@ -1578,11 +1572,16 @@ nandfs_sync(struct mount *mp, int waitfo
{
struct nandfsmount *nmp = VFSTONANDFS(mp);
+ DPRINTF(SYNC, ("%s: mp %p waitfor %d\n", __func__, mp, waitfor));
+
+ /*
+ * XXX: A hack to be removed soon
+ */
+ if (waitfor == MNT_LAZY)
+ return (0);
if (waitfor == MNT_SUSPEND)
return (0);
- vn_finished_write(mp);
nandfs_wakeup_wait_sync(nmp->nm_nandfsdev, SYNCER_VFS_SYNC);
- vn_start_write(NULL, &mp, V_WAIT);
return (0);
}
Modified: projects/nand/sys/fs/nandfs/nandfs_vnops.c
==============================================================================
--- projects/nand/sys/fs/nandfs/nandfs_vnops.c Fri Apr 20 02:47:35 2012 (r234478)
+++ projects/nand/sys/fs/nandfs/nandfs_vnops.c Fri Apr 20 03:02:07 2012 (r234479)
@@ -124,8 +124,8 @@ static int
nandfs_read(struct vop_read_args *ap)
{
register struct vnode *vp = ap->a_vp;
- register struct nandfs_node *nandfs_node = VTON(vp);
- struct nandfs_device *nandfsdev = nandfs_node->nn_nandfsdev;
+ register struct nandfs_node *node = VTON(vp);
+ struct nandfs_device *nandfsdev = node->nn_nandfsdev;
struct uio *uio = ap->a_uio;
struct buf *bp;
uint64_t size;
@@ -139,10 +139,12 @@ nandfs_read(struct vop_read_args *ap)
if (uio->uio_resid == 0)
return (0);
- size = nandfs_node->nn_inode.i_size;
+ size = node->nn_inode.i_size;
if (uio->uio_offset >= size)
return (0);
+ NANDFS_WRITELOCK(vp, node->nn_nandfsdev);
+
blocksize = nandfsdev->nd_blocksize;
bytesinfile = size - uio->uio_offset;
@@ -157,7 +159,7 @@ nandfs_read(struct vop_read_args *ap)
DPRINTF(READ, ("nandfs_read bn: 0x%jx toread: 0x%zx (0x%x)\n",
(uintmax_t)lbn, toread, blocksize));
- error = nandfs_bread(nandfs_node, lbn, NOCRED, 0, &bp);
+ error = nandfs_bread(node, lbn, NOCRED, 0, &bp);
if (error) {
brelse(bp);
break;
@@ -173,6 +175,8 @@ nandfs_read(struct vop_read_args *ap)
resid -= toread;
}
+ NANDFS_WRITEUNLOCK(node->nn_nandfsdev);
+
return (error);
}
@@ -208,6 +212,8 @@ nandfs_write(struct vop_write_args *ap)
if (uio->uio_resid == 0)
return (0);
+ NANDFS_WRITELOCK(vp, node->nn_nandfsdev);
+
blocksize = fsdev->nd_blocksize;
file_size = node->nn_inode.i_size;
@@ -217,6 +223,7 @@ nandfs_write(struct vop_write_args *ap)
uio->uio_offset = file_size;
break;
case VDIR:
+ NANDFS_WRITEUNLOCK(node->nn_nandfsdev);
return (EISDIR);
case VLNK:
break;
@@ -288,6 +295,8 @@ nandfs_write(struct vop_write_args *ap)
}
}
+ NANDFS_WRITEUNLOCK(node->nn_nandfsdev);
+
DPRINTF(WRITE, ("%s: return:%d\n", __func__, error));
return (error);
@@ -332,6 +341,9 @@ nandfs_lookup(struct vop_cachedlookup_ar
if (islastcn && mounted_ro && (nameiop == DELETE || nameiop == RENAME))
return (EROFS);
+ if (dir_node->nn_inode.i_links_count == 0)
+ return (ENOENT);
+
/*
* Obviously, the file is not (anymore) in the namecache, we have to
* search for it. There are three basic cases: '.', '..' and others.
@@ -579,9 +591,12 @@ nandfs_truncate(struct vnode *vp, uint64
/* Calculate end of file */
size = inode->i_size;
+ NANDFS_WRITELOCK(vp, node->nn_nandfsdev);
+
if (newsize == size) {
node->nn_flags |= IN_CHANGE | IN_UPDATE;
nandfs_itimes(vp);
+ NANDFS_WRITEUNLOCK(node->nn_nandfsdev);
return (0);
}
@@ -590,6 +605,7 @@ nandfs_truncate(struct vnode *vp, uint64
vnode_pager_setsize(vp, newsize);
node->nn_flags |= IN_CHANGE | IN_UPDATE;
nandfs_itimes(vp);
+ NANDFS_WRITEUNLOCK(node->nn_nandfsdev);
return (0);
}
@@ -599,8 +615,10 @@ nandfs_truncate(struct vnode *vp, uint64
if (rest) {
error = nandfs_bmap_nlookup(node, nblks - 1, 1, &vblk);
- if (error)
+ if (error) {
+ NANDFS_WRITEUNLOCK(node->nn_nandfsdev);
return (error);
+ }
if (vblk != 0)
error = nandfs_bread(node, nblks - 1, NOCRED, 0, &bp);
@@ -610,14 +628,17 @@ nandfs_truncate(struct vnode *vp, uint64
if (error) {
if (bp)
brelse(bp);
+ NANDFS_WRITEUNLOCK(node->nn_nandfsdev);
return (error);
}
bzero((char *)bp->b_data + rest,
(u_int)(nffsdev->nd_blocksize - rest));
error = nandfs_dirty_buf(bp, 0);
- if (error)
+ if (error) {
+ NANDFS_WRITEUNLOCK(node->nn_nandfsdev);
return (error);
+ }
}
DPRINTF(VNCALL, ("%s: vp %p oblks %jx nblks %jx\n", __func__, vp, oblks,
@@ -627,6 +648,7 @@ nandfs_truncate(struct vnode *vp, uint64
if (error) {
if (bp)
nandfs_undirty_buf(bp);
+ NANDFS_WRITEUNLOCK(node->nn_nandfsdev);
return (error);
}
@@ -634,6 +656,7 @@ nandfs_truncate(struct vnode *vp, uint64
if (error) {
if (bp)
nandfs_undirty_buf(bp);
+ NANDFS_WRITEUNLOCK(node->nn_nandfsdev);
return (error);
}
@@ -642,6 +665,8 @@ nandfs_truncate(struct vnode *vp, uint64
node->nn_flags |= IN_CHANGE | IN_UPDATE;
nandfs_itimes(vp);
+ NANDFS_WRITEUNLOCK(node->nn_nandfsdev);
+
return (error);
}
@@ -1068,7 +1093,7 @@ nandfs_read_filebuf(struct nandfs_node *
struct nandfs_device *nandfsdev = node->nn_nandfsdev;
struct buf *nbp;
nandfs_daddr_t *l2vmap;
- uint64_t *v2pmap;
+ nandfs_daddr_t *v2pmap;
nandfs_lbn_t from;
uint64_t blks;
uint32_t blocksize;
@@ -1375,6 +1400,8 @@ nandfs_link(struct vop_link_args *ap)
/* Update link count */
inode->i_links_count++;
+ NANDFS_WRITELOCK(vp, node->nn_nandfsdev);
+
/* Add dir entry */
error = nandfs_add_dirent(tdvp, node->nn_ino, cnp->cn_nameptr,
cnp->cn_namelen, IFTODT(inode->i_mode));
@@ -1387,6 +1414,8 @@ nandfs_link(struct vop_link_args *ap)
DPRINTF(VNCALL, ("%s: tdvp %p vp %p cnp %p\n",
__func__, tdvp, vp, cnp));
+ NANDFS_WRITEUNLOCK(node->nn_nandfsdev);
+
return (0);
}
@@ -1407,6 +1436,8 @@ nandfs_create(struct vop_create_args *ap
if (nandfs_fs_full(dir_node->nn_nandfsdev))
return (ENOSPC);
+ NANDFS_WRITELOCK(dvp, nmp->nm_nandfsdev);
+
/* Create new vnode/inode */
error = nandfs_node_create(nmp, &node, mode);
if (error)
@@ -1422,10 +1453,13 @@ nandfs_create(struct vop_create_args *ap
nandfs_error("%s: error destroying node %p\n",
__func__, node);
}
+ NANDFS_WRITEUNLOCK(nmp->nm_nandfsdev);
return (error);
}
*vpp = NTOV(node);
+ NANDFS_WRITEUNLOCK(nmp->nm_nandfsdev);
+
DPRINTF(VNCALL, ("created file vp %p nandnode %p ino %jx\n", *vpp, node,
(uintmax_t)node->nn_ino));
return (0);
@@ -1452,10 +1486,14 @@ nandfs_remove(struct vop_remove_args *ap
(dnode->nn_inode.i_flags & APPEND))
return (EPERM);
+ NANDFS_WRITELOCK(vp, node->nn_nandfsdev);
+
nandfs_remove_dirent(dvp, node, cnp);
node->nn_inode.i_links_count--;
node->nn_flags |= IN_CHANGE;
+ NANDFS_WRITEUNLOCK(node->nn_nandfsdev);
+
return (0);
}
@@ -1543,6 +1581,9 @@ nandfs_rename(struct vop_rename_args *ap
DPRINTF(VNCALL, ("%s: fdvp:%p fvp:%p tdvp:%p tdp:%p\n", __func__, fdvp,
fvp, tdvp, tvp));
+
+ NANDFS_WRITELOCK(tdvp, tdnode->nn_nandfsdev);
+
/*
* Check for cross-device rename.
*/
@@ -1558,6 +1599,7 @@ abortit:
vput(tvp);
vrele(fdvp);
vrele(fvp);
+ NANDFS_WRITEUNLOCK(tdnode->nn_nandfsdev);
return (error);
}
@@ -1763,6 +1805,7 @@ abortit:
if (doingdirectory)
panic("nandfs_rename: lost dir entry");
vrele(ap->a_fvp);
+ NANDFS_WRITEUNLOCK(tdnode->nn_nandfsdev);
return (0);
}
@@ -1810,6 +1853,7 @@ abortit:
if (fnode)
vput(fvp);
vrele(ap->a_fvp);
+ NANDFS_WRITEUNLOCK(tdnode->nn_nandfsdev);
return (error);
bad:
@@ -1827,6 +1871,7 @@ out:
vput(fvp);
} else
vrele(fvp);
+ NANDFS_WRITEUNLOCK(tdnode->nn_nandfsdev);
return (error);
}
@@ -1851,9 +1896,14 @@ nandfs_mkdir(struct vop_mkdir_args *ap)
if (dir_inode->i_links_count >= LINK_MAX)
return (EMLINK);
+ NANDFS_WRITELOCK(dvp, nmp->nm_nandfsdev);
+
error = nandfs_node_create(nmp, &node, mode);
- if (error)
+ if (error) {
+ NANDFS_WRITEUNLOCK(nmp->nm_nandfsdev);
return (error);
+ }
+
node->nn_inode.i_gid = dir_node->nn_inode.i_gid;
node->nn_inode.i_uid = cnp->cn_cred->cr_uid;
@@ -1863,6 +1913,7 @@ nandfs_mkdir(struct vop_mkdir_args *ap)
cnp->cn_namelen, IFTODT(mode));
if (error) {
vput(*vpp);
+ NANDFS_WRITEUNLOCK(nmp->nm_nandfsdev);
return (error);
}
@@ -1872,9 +1923,12 @@ nandfs_mkdir(struct vop_mkdir_args *ap)
error = nandfs_init_dir(NTOV(node), node->nn_ino, dir_node->nn_ino);
if (error) {
vput(NTOV(node));
+ NANDFS_WRITEUNLOCK(nmp->nm_nandfsdev);
return (error);
}
+ NANDFS_WRITEUNLOCK(nmp->nm_nandfsdev);
+
DPRINTF(VNCALL, ("created dir vp %p nandnode %p ino %jx\n", *vpp, node,
(uintmax_t)node->nn_ino));
return (0);
@@ -1896,9 +1950,13 @@ nandfs_mknod(struct vop_mknod_args *ap)
if (nandfs_fs_full(dir_node->nn_nandfsdev))
return (ENOSPC);
+ NANDFS_WRITELOCK(dvp, nmp->nm_nandfsdev);
+
error = nandfs_node_create(nmp, &node, mode);
- if (error)
+ if (error) {
+ NANDFS_WRITEUNLOCK(nmp->nm_nandfsdev);
return (error);
+ }
node->nn_inode.i_gid = dir_node->nn_inode.i_gid;
node->nn_inode.i_uid = cnp->cn_cred->cr_uid;
if (vap->va_rdev != VNOVAL)
@@ -1909,11 +1967,14 @@ nandfs_mknod(struct vop_mknod_args *ap)
if (nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr,
cnp->cn_namelen, IFTODT(mode))) {
vput(*vpp);
+ NANDFS_WRITEUNLOCK(nmp->nm_nandfsdev);
return (ENOTDIR);
}
node->nn_flags |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
+ NANDFS_WRITEUNLOCK(nmp->nm_nandfsdev);
+
return (0);
}
@@ -1932,9 +1993,13 @@ nandfs_symlink(struct vop_symlink_args *
if (nandfs_fs_full(dir_node->nn_nandfsdev))
return (ENOSPC);
+ NANDFS_WRITELOCK(dvp, nmp->nm_nandfsdev);
+
error = nandfs_node_create(nmp, &node, S_IFLNK | mode);
- if (error)
+ if (error) {
+ NANDFS_WRITEUNLOCK(nmp->nm_nandfsdev);
return (error);
+ }
node->nn_inode.i_gid = dir_node->nn_inode.i_gid;
node->nn_inode.i_uid = cnp->cn_cred->cr_uid;
@@ -1943,6 +2008,7 @@ nandfs_symlink(struct vop_symlink_args *
if (nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr,
cnp->cn_namelen, IFTODT(mode))) {
vput(*vpp);
+ NANDFS_WRITEUNLOCK(nmp->nm_nandfsdev);
return (ENOTDIR);
}
@@ -1954,6 +2020,8 @@ nandfs_symlink(struct vop_symlink_args *
if (error)
vput(*vpp);
+ NANDFS_WRITEUNLOCK(nmp->nm_nandfsdev);
+
return (error);
}
@@ -1973,6 +2041,7 @@ nandfs_rmdir(struct vop_rmdir_args *ap)
struct componentname *cnp = ap->a_cnp;
struct nandfs_node *node, *dnode;
uint32_t dflag, flag;
+ int error = 0;
node = VTON(vp);
dnode = VTON(dvp);
@@ -2002,16 +2071,26 @@ nandfs_rmdir(struct vop_rmdir_args *ap)
if (vp->v_mountedhere != 0)
return (EINVAL);
+ NANDFS_WRITELOCK(vp, node->nn_nandfsdev);
+
nandfs_remove_dirent(dvp, node, cnp);
dnode->nn_inode.i_links_count -= 1;
dnode->nn_flags |= IN_CHANGE;
cache_purge(dvp);
+ error = nandfs_truncate(vp, (uint64_t)0);
+ if (error)
+ return (error);
+
node->nn_inode.i_links_count -= 2;
node->nn_flags |= IN_CHANGE;
- return (0);
+ NANDFS_WRITEUNLOCK(node->nn_nandfsdev);
+
+ cache_purge(vp);
+
+ return (error);
}
static int
@@ -2032,9 +2111,7 @@ nandfs_fsync(struct vop_fsync_args *ap)
vp->v_bufobj.bo_dirty.bv_cnt) {
locked = VOP_ISLOCKED(vp);
VOP_UNLOCK(vp, 0);
- vn_finished_write(nmp->nm_vfs_mountp);
nandfs_wakeup_wait_sync(nmp->nm_nandfsdev, SYNCER_FSYNC);
- vn_start_write(NULL, &nmp->nm_vfs_mountp, V_WAIT);
VOP_LOCK(vp, locked);
}
@@ -2047,7 +2124,7 @@ nandfs_bmap(struct vop_bmap_args *ap)
struct vnode *vp = ap->a_vp;
struct nandfs_node *nnode = VTON(vp);
struct nandfs_device *nandfsdev = nnode->nn_nandfsdev;
- uint64_t l2vmap, v2pmap;
+ nandfs_daddr_t l2vmap, v2pmap;
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-projects
mailing list