Module Name:    src
Committed By:   jdolecek
Date:           Mon Aug 15 18:38:10 UTC 2016

Modified Files:
        src/sys/ufs/ext2fs: ext2fs.h ext2fs_rename.c ext2fs_vnops.c

Log Message:
bump link limit to 65000 for files, and add support for 
EXT2F_ROCOMPAT_DIR_NLINK to make link count unlimited for directories


To generate a diff of this commit:
cvs rdiff -u -r1.45 -r1.46 src/sys/ufs/ext2fs/ext2fs.h
cvs rdiff -u -r1.10 -r1.11 src/sys/ufs/ext2fs/ext2fs_rename.c
cvs rdiff -u -r1.124 -r1.125 src/sys/ufs/ext2fs/ext2fs_vnops.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/ufs/ext2fs/ext2fs.h
diff -u src/sys/ufs/ext2fs/ext2fs.h:1.45 src/sys/ufs/ext2fs/ext2fs.h:1.46
--- src/sys/ufs/ext2fs/ext2fs.h:1.45	Sun Aug 14 11:42:50 2016
+++ src/sys/ufs/ext2fs/ext2fs.h	Mon Aug 15 18:38:10 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: ext2fs.h,v 1.45 2016/08/14 11:42:50 jdolecek Exp $	*/
+/*	$NetBSD: ext2fs.h,v 1.46 2016/08/15 18:38:10 jdolecek Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1993
@@ -128,6 +128,13 @@
 #define MINFREE		5
 
 /*
+ * This is maximum amount of links allowed for files. For directories,
+ * going over this means setting DIR_NLINK feature.
+ */
+#define EXT2FS_LINK_MAX		65000
+#define EXT2FS_LINK_INF		1		/* link count unknown */
+
+/*
  * Super block for an ext2fs file system.
  */
 struct ext2fs {
@@ -358,7 +365,8 @@ struct m_ext2fs {
 #define EXT2F_ROCOMPAT_SUPP		(EXT2F_ROCOMPAT_SPARSESUPER \
 					 | EXT2F_ROCOMPAT_LARGEFILE \
 					 | EXT2F_ROCOMPAT_HUGE_FILE \
-					 | EXT2F_ROCOMPAT_EXTRA_ISIZE)
+					 | EXT2F_ROCOMPAT_EXTRA_ISIZE \
+					 | EXT2F_ROCOMPAT_DIR_NLINK)
 #define EXT2F_INCOMPAT_SUPP		(EXT2F_INCOMPAT_FTYPE \
 					 | EXT2F_INCOMPAT_EXTENTS)
 

Index: src/sys/ufs/ext2fs/ext2fs_rename.c
diff -u src/sys/ufs/ext2fs/ext2fs_rename.c:1.10 src/sys/ufs/ext2fs/ext2fs_rename.c:1.11
--- src/sys/ufs/ext2fs/ext2fs_rename.c:1.10	Sat Aug 13 07:40:10 2016
+++ src/sys/ufs/ext2fs/ext2fs_rename.c	Mon Aug 15 18:38:10 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: ext2fs_rename.c,v 1.10 2016/08/13 07:40:10 christos Exp $	*/
+/*	$NetBSD: ext2fs_rename.c,v 1.11 2016/08/15 18:38:10 jdolecek Exp $	*/
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_rename.c,v 1.10 2016/08/13 07:40:10 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_rename.c,v 1.11 2016/08/15 18:38:10 jdolecek Exp $");
 
 #include <sys/param.h>
 #include <sys/buf.h>
@@ -307,7 +307,7 @@ ext2fs_gro_rename(struct mount *mp, kaut
 	 * We shall need to temporarily bump the link count, so make
 	 * sure there is room to do so.
 	 */
-	if ((nlink_t)VTOI(fvp)->i_e2fs_nlink >= LINK_MAX)
+	if ((nlink_t)VTOI(fvp)->i_e2fs_nlink >= EXT2FS_LINK_MAX)
 		return EMLINK;
 
 	directory_p = (fvp->v_type == VDIR);
@@ -330,7 +330,7 @@ ext2fs_gro_rename(struct mount *mp, kaut
 	 *    may be wrong, but correctable.
 	 */
 
-	KASSERT((nlink_t)VTOI(fvp)->i_e2fs_nlink < LINK_MAX);
+	KASSERT((nlink_t)VTOI(fvp)->i_e2fs_nlink < EXT2FS_LINK_MAX);
 	VTOI(fvp)->i_e2fs_nlink++;
 	VTOI(fvp)->i_flag |= IN_CHANGE;
 	error = ext2fs_update(fvp, NULL, NULL, UPDATE_WAIT);
@@ -352,11 +352,11 @@ ext2fs_gro_rename(struct mount *mp, kaut
 		 * parent we don't fool with the link count.
 		 */
 		if (directory_p && reparent_p) {
-			if ((nlink_t)VTOI(tdvp)->i_e2fs_nlink >= LINK_MAX) {
+			if ((nlink_t)VTOI(tdvp)->i_e2fs_nlink >= EXT2FS_LINK_MAX) {
 				error = EMLINK;
 				goto whymustithurtsomuch;
 			}
-			KASSERT((nlink_t)VTOI(tdvp)->i_e2fs_nlink < LINK_MAX);
+			KASSERT((nlink_t)VTOI(tdvp)->i_e2fs_nlink < EXT2FS_LINK_MAX);
 			VTOI(tdvp)->i_e2fs_nlink++;
 			VTOI(tdvp)->i_flag |= IN_CHANGE;
 			error = ext2fs_update(tdvp, NULL, NULL, UPDATE_WAIT);

Index: src/sys/ufs/ext2fs/ext2fs_vnops.c
diff -u src/sys/ufs/ext2fs/ext2fs_vnops.c:1.124 src/sys/ufs/ext2fs/ext2fs_vnops.c:1.125
--- src/sys/ufs/ext2fs/ext2fs_vnops.c:1.124	Mon Aug 15 18:29:34 2016
+++ src/sys/ufs/ext2fs/ext2fs_vnops.c	Mon Aug 15 18:38:10 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: ext2fs_vnops.c,v 1.124 2016/08/15 18:29:34 jdolecek Exp $	*/
+/*	$NetBSD: ext2fs_vnops.c,v 1.125 2016/08/15 18:38:10 jdolecek Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -65,7 +65,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.124 2016/08/15 18:29:34 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.125 2016/08/15 18:38:10 jdolecek Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -626,7 +626,7 @@ ext2fs_link(void *v)
 		goto out2;
 	}
 	ip = VTOI(vp);
-	if ((nlink_t)ip->i_e2fs_nlink >= LINK_MAX) {
+	if ((nlink_t)ip->i_e2fs_nlink >= EXT2FS_LINK_MAX) {
 		VOP_ABORTOP(dvp, cnp);
 		error = EMLINK;
 		goto out1;
@@ -677,11 +677,6 @@ ext2fs_mkdir(void *v)
 	ulr = &VTOI(dvp)->i_crap;
 	UFS_CHECK_CRAPCOUNTER(VTOI(dvp));
 
-	if ((nlink_t)dp->i_e2fs_nlink >= LINK_MAX) {
-		error = EMLINK;
-		goto out;
-	}
-
 	/*
 	 * Acquire the inode, but don't sync/direnter it just yet
 	 */
@@ -700,7 +695,24 @@ ext2fs_mkdir(void *v)
 	 * be done before reference is created
 	 * so reparation is possible if we crash.
 	 */
-	dp->i_e2fs_nlink++;
+	if (dp->i_e2fs_nlink != EXT2FS_LINK_INF)
+		dp->i_e2fs_nlink++;
+
+	/*
+	 * If we hit the link limit, for directories just set the nlink
+	 * to special value 1, which means the link count is bigger
+	 * than EXT2FS_LINK_MAX.
+	 */
+	if ((nlink_t)dp->i_e2fs_nlink >= EXT2FS_LINK_MAX) {
+		dp->i_e2fs_nlink = EXT2FS_LINK_INF;
+
+		/* set the feature flag DIR_NLINK if not set already */
+		if (!EXT2F_HAS_ROCOMPAT_FEATURE(dp->i_e2fs, EXT2F_ROCOMPAT_DIR_NLINK)) {
+                	dp->i_e2fs->e2fs.e2fs_features_rocompat |= EXT2F_ROCOMPAT_DIR_NLINK;
+                	dp->i_e2fs->e2fs_fmod = 1;
+		}
+	}
+
 	dp->i_flag |= IN_CHANGE;
 	if ((error = ext2fs_update(dvp, NULL, NULL, UPDATE_DIROP)) != 0)
 		goto bad;
@@ -725,7 +737,8 @@ ext2fs_mkdir(void *v)
 	    sizeof (dirtemplate), (off_t)0, IO_NODELOCKED|IO_SYNC,
 	    cnp->cn_cred, (size_t *)0, NULL);
 	if (error) {
-		dp->i_e2fs_nlink--;
+		if (dp->i_e2fs_nlink != EXT2FS_LINK_INF)
+			dp->i_e2fs_nlink--;
 		dp->i_flag |= IN_CHANGE;
 		goto bad;
 	}
@@ -734,7 +747,8 @@ ext2fs_mkdir(void *v)
 	else {
 		error = ext2fs_setsize(ip, VTOI(dvp)->i_e2fs->e2fs_bsize);
 		if (error) {
-			dp->i_e2fs_nlink--;
+			if (dp->i_e2fs_nlink != EXT2FS_LINK_INF)
+				dp->i_e2fs_nlink--;
 			dp->i_flag |= IN_CHANGE;
 			goto bad;
 		}
@@ -745,7 +759,8 @@ ext2fs_mkdir(void *v)
 	/* Directory set up, now install its entry in the parent directory. */
 	error = ext2fs_direnter(ip, dvp, ulr, cnp);
 	if (error != 0) {
-		dp->i_e2fs_nlink--;
+		if (dp->i_e2fs_nlink != EXT2FS_LINK_INF)
+			dp->i_e2fs_nlink--;
 		dp->i_flag |= IN_CHANGE;
 	}
 bad:
@@ -807,7 +822,7 @@ ext2fs_rmdir(void *v)
 	 *  non-empty.)
 	 */
 	error = 0;
-	if (ip->i_e2fs_nlink != 2 ||
+	if ((ip->i_e2fs_nlink != 2 && ip->i_e2fs_nlink != EXT2FS_LINK_INF) ||
 	    !ext2fs_dirempty(ip, dp->i_number, cnp->cn_cred)) {
 		error = ENOTEMPTY;
 		goto out;
@@ -825,7 +840,8 @@ ext2fs_rmdir(void *v)
 	error = ext2fs_dirremove(dvp, ulr, cnp);
 	if (error != 0)
 		goto out;
-	dp->i_e2fs_nlink--;
+	if (dp->i_e2fs_nlink != EXT2FS_LINK_INF)
+		dp->i_e2fs_nlink--;
 	dp->i_flag |= IN_CHANGE;
 	VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
 	cache_purge(dvp);

Reply via email to