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