All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andreas Dilger <adilger@sun.com>
To: "Theodore Ts'o" <tytso@mit.edu>, linux-ext4@vger.kernel.org
Subject: Re: [PATCH][6/28] e2fsprogs-nlinks.patch
Date: Sat, 02 Feb 2008 01:25:03 -0700	[thread overview]
Message-ID: <20080202082503.GF31694@webber.adilger.int> (raw)
In-Reply-To: <20080202075943.GB23836@webber.adilger.int>


Add support for the DIR_NLINK feature.

This patch includes the changes required to e2fsck to understand the 
nlink count changes made in the kernel. In pass2, while counting the 
links for a directory, if the link count exceeds 65000, its permanently 
set to EXT2_LINK_MAX + 10. In pass4, when the counted and actual nlink
counts are compared, e2fsck does not flag an error if counted links =
EXT2_NLINK_MAX + 10 and existing link count is 1. 

It also handles the case when a directory had more than 65000 subdirs 
and they were later deleted. The nlink count of such a directory remains 
1. In pass4 if counted links are 2 and if existing nlink count = 1, 
e2fsck corrects the nlink count without displaying any errors. 

The file hard link count is also increased to 65000, but this cannot be
exceeded.

Signed-off-by: Andreas Dilger <adilger@clusterfs.com>
Signed-off-by: Kalpak Shah <kalpak@clusterfs.com>

Index: e2fsprogs-1.40.1/e2fsck/pass2.c
===================================================================
--- e2fsprogs-1.40.1.orig/e2fsck/pass2.c
+++ e2fsprogs-1.40.1/e2fsck/pass2.c
@@ -717,7 +717,7 @@ static int check_dir_block(ext2_filsys f
 	blk_t			block_nr = db->blk;
 	ext2_ino_t 		ino = db->ino;
 	ext2_ino_t 		subdir_parent;
-	__u16			links;
+	__u32			links;
 	struct check_dir_struct	*cd;
 	char 			*buf;
 	e2fsck_t		ctx;
@@ -1024,9 +1024,11 @@ static int check_dir_block(ext2_filsys f
 			dups_found++;
 		} else
 			dict_alloc_insert(&de_dict, dirent, dirent);
-		
-		ext2fs_icount_increment(ctx->inode_count, dirent->inode,
-					&links);
+
+		ext2fs_icount_inc32(ctx->inode_count, dirent->inode, &links,
+				    ext2fs_test_inode_bitmap(ctx->inode_dir_map,
+							     dirent->inode) ?
+				    EXT2_LINK_MAX : (__u32)~0U);
 		if (links > 1)
 			ctx->fs_links_count++;
 		ctx->fs_total_count++;
Index: e2fsprogs-1.40.1/e2fsck/pass4.c
===================================================================
--- e2fsprogs-1.40.1.orig/e2fsck/pass4.c
+++ e2fsprogs-1.40.1/e2fsck/pass4.c
@@ -99,7 +99,8 @@ void e2fsck_pass4(e2fsck_t ctx)
 	struct resource_track	rtrack;
 #endif
 	struct problem_context	pctx;
-	__u16	link_count, link_counted;
+	__u16	link_count;
+	__u32	link_counted;
 	char	*buf = 0;
 	int	group, maxgroup;
 	
@@ -145,7 +146,7 @@ void e2fsck_pass4(e2fsck_t ctx)
 		     ext2fs_test_inode_bitmap(ctx->inode_bb_map, i)))
 			continue;
 		ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
-		ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
+		ext2fs_icount_fetch32(ctx->inode_count, i, &link_counted);
 		if (link_counted == 0) {
 			if (!buf)
 				buf = e2fsck_allocate_memory(ctx,
@@ -156,10 +157,12 @@ void e2fsck_pass4(e2fsck_t ctx)
 				continue;
 			ext2fs_icount_fetch(ctx->inode_link_info, i,
 					    &link_count);
-			ext2fs_icount_fetch(ctx->inode_count, i,
-					    &link_counted);
+			ext2fs_icount_fetch32(ctx->inode_count, i,
+					      &link_counted);
 		}
-		if (link_counted != link_count) {
+		if (link_counted != link_count &&
+		    !(ext2fs_test_inode_bitmap(ctx->inode_dir_map, i) &&
+		      link_count == 1 && link_counted > EXT2_LINK_MAX)) {
 			e2fsck_read_inode(ctx, i, inode, "pass4");
 			pctx.ino = i;
 			pctx.inode = inode;
@@ -169,7 +172,12 @@ void e2fsck_pass4(e2fsck_t ctx)
 					    PR_4_INCONSISTENT_COUNT, &pctx);
 			}
 			pctx.num = link_counted;
-			if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
+			/* i_link_count was previously exceeded, but no longer
+			 * is, fix this but don't consider it an error */
+			if ((LINUX_S_ISDIR(inode->i_mode) && link_counted > 1 &&
+			     (inode->i_flags & EXT2_INDEX_FL) &&
+			     link_count == 1 && !(ctx->options & E2F_OPT_NO)) ||
+			     (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx))) {
 				inode->i_links_count = link_counted;
 				e2fsck_write_inode(ctx, i, inode, "pass4");
 			}
Index: e2fsprogs-1.40.1/lib/ext2fs/ext2_fs.h
===================================================================
--- e2fsprogs-1.40.1.orig/lib/ext2fs/ext2_fs.h
+++ e2fsprogs-1.40.1/lib/ext2fs/ext2_fs.h
@@ -646,6 +646,7 @@ struct ext2_super_block {
 #define EXT2_FEATURE_INCOMPAT_SUPP	(EXT2_FEATURE_INCOMPAT_FILETYPE)
 #define EXT2_FEATURE_RO_COMPAT_SUPP	(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
 					 EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
+					 EXT4_FEATURE_RO_COMPAT_DIR_NLINK| \
 					 EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
 
 /*
Index: e2fsprogs-1.40.1/lib/ext2fs/ext2fs.h
===================================================================
--- e2fsprogs-1.40.1.orig/lib/ext2fs/ext2fs.h
+++ e2fsprogs-1.40.1/lib/ext2fs/ext2fs.h
@@ -462,7 +462,8 @@ typedef struct ext2_icount *ext2_icount_
 					 EXT3_FEATURE_INCOMPAT_RECOVER)
 #endif
 #define EXT2_LIB_FEATURE_RO_COMPAT_SUPP	(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
-					 EXT2_FEATURE_RO_COMPAT_LARGE_FILE)
+					 EXT2_FEATURE_RO_COMPAT_LARGE_FILE|\
+					 EXT4_FEATURE_RO_COMPAT_DIR_NLINK)
 
 /*
  * These features are only allowed if EXT2_FLAG_SOFTSUPP_FEATURES is passed
@@ -471,7 +472,6 @@ typedef struct ext2_icount *ext2_icount_
 #define EXT2_LIB_SOFTSUPP_INCOMPAT	(EXT3_FEATURE_INCOMPAT_EXTENTS)
 #define EXT2_LIB_SOFTSUPP_RO_COMPAT	(EXT4_FEATURE_RO_COMPAT_HUGE_FILE|\
 					 EXT4_FEATURE_RO_COMPAT_GDT_CSUM|\
-					 EXT4_FEATURE_RO_COMPAT_DIR_NLINK|\
 					 EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE)
 
 /*
@@ -795,12 +795,20 @@ extern errcode_t ext2fs_create_icount2(e
 extern errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, 
 				      unsigned int size,
 				      ext2_icount_t *ret);
+extern errcode_t ext2fs_icount_fetch32(ext2_icount_t icount, ext2_ino_t ino,
+				       __u32 *ret);
 extern errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino,
 				     __u16 *ret);
+extern errcode_t ext2fs_icount_inc32(ext2_icount_t icount, ext2_ino_t ino,
+				     __u32 *ret, __u32 overflow);
 extern errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino,
 					 __u16 *ret);
+extern errcode_t ext2fs_icount_dec32(ext2_icount_t icount, ext2_ino_t ino,
+				     __u32 *ret);
 extern errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
 					 __u16 *ret);
+extern errcode_t ext2fs_icount_store32(ext2_icount_t icount, ext2_ino_t ino,
+				       __u32 count);
 extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
 				     __u16 count);
 extern ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount);
Index: e2fsprogs-1.40.1/lib/ext2fs/icount.c
===================================================================
--- e2fsprogs-1.40.1.orig/lib/ext2fs/icount.c
+++ e2fsprogs-1.40.1/lib/ext2fs/icount.c
@@ -43,7 +43,7 @@
 
 struct ext2_icount_el {
 	ext2_ino_t	ino;
-	__u16	count;
+	__u32	count;
 };
 
 struct ext2_icount {
@@ -397,16 +397,16 @@ static struct ext2_icount_el *get_icount
 }
 
 static errcode_t set_inode_count(ext2_icount_t icount, ext2_ino_t ino,
-				 __u16 count)
+				 __u32 count)
 {
-	struct ext2_icount_el 	*el;
+	struct ext2_icount_el	*el;
 	TDB_DATA key, data;
 
 	if (icount->tdb) {
 		key.dptr = (unsigned char *) &ino;
 		key.dsize = sizeof(ext2_ino_t);
 		data.dptr = (unsigned char *) &count;
-		data.dsize = sizeof(__u16);
+		data.dsize = sizeof(__u32);
 		if (count) {
 			if (tdb_store(icount->tdb, key, data, TDB_REPLACE))
 				return tdb_error(icount->tdb) +
@@ -428,9 +428,9 @@ static errcode_t set_inode_count(ext2_ic
 }
 
 static errcode_t get_inode_count(ext2_icount_t icount, ext2_ino_t ino,
-				 __u16 *count)
+				 __u32 *count)
 {
-	struct ext2_icount_el 	*el;
+	struct ext2_icount_el	*el;
 	TDB_DATA key, data;
 
 	if (icount->tdb) {
@@ -443,7 +443,7 @@ static errcode_t get_inode_count(ext2_ic
 			return tdb_error(icount->tdb) + EXT2_ET_TDB_SUCCESS;
 		}
 
-		*count = *((__u16 *) data.dptr);
+		*count = *((__u32 *) data.dptr);
 		free(data.dptr);
 		return 0;
 	}
@@ -480,7 +480,7 @@ errcode_t ext2fs_icount_validate(ext2_ic
 	return ret;
 }
 
-errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, __u16 *ret)
+errcode_t ext2fs_icount_fetch32(ext2_icount_t icount, ext2_ino_t ino, __u32 *ret)
 {
 	EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
 
@@ -500,10 +500,21 @@ errcode_t ext2fs_icount_fetch(ext2_icoun
 	return 0;
 }
 
-errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino,
-				  __u16 *ret)
+errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, __u16 *ret)
 {
-	__u16			curr_value;
+	__u32 ret32 = ret ? *ret : 0;
+	errcode_t err;
+
+	err = ext2fs_icount_fetch32(icount, ino, &ret32);
+	*ret = (__u16)ret32;
+
+	return err;
+}
+
+errcode_t ext2fs_icount_inc32(ext2_icount_t icount, ext2_ino_t ino,
+			      __u32 *ret, __u32 overflow)
+{
+	__u32			curr_value;
 
 	EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
 
@@ -528,6 +539,8 @@ errcode_t ext2fs_icount_increment(ext2_i
 		if (ext2fs_test_inode_bitmap(icount->multiple, ino)) {
 			get_inode_count(icount, ino, &curr_value);
 			curr_value++;
+			if (curr_value >= overflow)
+				curr_value = overflow + 10;
 			if (set_inode_count(icount, ino, curr_value))
 				return EXT2_ET_NO_MEMORY;
 		} else {
@@ -547,6 +560,8 @@ errcode_t ext2fs_icount_increment(ext2_i
 		 */
 		get_inode_count(icount, ino, &curr_value);
 		curr_value++;
+		if (curr_value >= overflow)
+			curr_value = overflow + 10;
 		if (set_inode_count(icount, ino, curr_value))
 			return EXT2_ET_NO_MEMORY;
 	}
@@ -557,10 +572,23 @@ errcode_t ext2fs_icount_increment(ext2_i
 	return 0;
 }
 
-errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
+errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino,
 				  __u16 *ret)
 {
-	__u16			curr_value;
+	__u32 ret32 = ret ? *ret : 0;
+	errcode_t err;
+
+	err = ext2fs_icount_inc32(icount, ino, &ret32, (__u16)~0U);
+	if (ret)
+		*ret = ret32;
+
+	return err;
+}
+
+errcode_t ext2fs_icount_dec32(ext2_icount_t icount, ext2_ino_t ino,
+			      __u32 *ret)
+{
+	__u32			curr_value;
 
 	if (!ino || (ino > icount->num_inodes))
 		return EXT2_ET_INVALID_ARGUMENT;
@@ -600,8 +628,21 @@ errcode_t ext2fs_icount_decrement(ext2_i
 	return 0;
 }
 
-errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
-			      __u16 count)
+errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
+				  __u16 *ret)
+{
+	__u32 ret32 = ret ? *ret : 0;
+	errcode_t err;
+
+	err = ext2fs_icount_dec32(icount, ino, &ret32);
+	if (ret)
+		*ret = ret32;
+
+	return err;
+}
+
+errcode_t ext2fs_icount_store32(ext2_icount_t icount, ext2_ino_t ino,
+				__u32 count)
 {
 	if (!ino || (ino > icount->num_inodes))
 		return EXT2_ET_INVALID_ARGUMENT;
@@ -635,6 +676,12 @@ errcode_t ext2fs_icount_store(ext2_icoun
 	return 0;
 }
 
+errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
+			      __u16 count)
+{
+	return ext2fs_icount_store32(icount, ino, count);
+}
+
 ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount)
 {
 	if (!icount || icount->magic != EXT2_ET_MAGIC_ICOUNT)
Index: e2fsprogs-1.40.1/e2fsck/pass3.c
===================================================================
--- e2fsprogs-1.40.1.orig/e2fsck/pass3.c
+++ e2fsprogs-1.40.1/e2fsck/pass3.c
@@ -581,19 +581,22 @@ errcode_t e2fsck_adjust_inode_count(e2fs
 #endif
 
 	if (adj == 1) {
-		ext2fs_icount_increment(ctx->inode_count, ino, 0);
+		ext2fs_icount_inc32(ctx->inode_count, ino, 0,
+				    ext2fs_test_inode_bitmap(ctx->inode_dir_map,
+							     ino) ?
+				    EXT2_LINK_MAX : ~0U);
 		if (inode.i_links_count == (__u16) ~0)
 			return 0;
 		ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
 		inode.i_links_count++;
 	} else if (adj == -1) {
-		ext2fs_icount_decrement(ctx->inode_count, ino, 0);
+		ext2fs_icount_dec32(ctx->inode_count, ino, 0);
 		if (inode.i_links_count == 0)
 			return 0;
 		ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
 		inode.i_links_count--;
 	}
-	
+
 	retval = ext2fs_write_inode(fs, ino, &inode);
 	if (retval)
 		return retval;

Cheers, Andreas
--
Andreas Dilger
Sr. Staff Engineer, Lustre Group
Sun Microsystems of Canada, Inc.

  parent reply	other threads:[~2008-02-02  8:25 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-02-02  7:59 [PATCH][0/28] Lustre e2fsprogs patch series Andreas Dilger
2008-02-02  8:14 ` [PATCH][1/28] e2fsprogs-specdotin.patch Andreas Dilger
2008-02-02  8:16 ` [PATCH] [2/28] e2fsprogs-eacheck.patch Andreas Dilger
2008-02-02  8:17 ` [PATCH][3/28] e2fsprogs-extended_ops.patch Andreas Dilger
2008-02-02  8:20 ` [PATCH][4/28] e2fsprogs-tests-f_unsorted_EAs.patch Andreas Dilger
2008-02-02  8:22 ` [PATCH][5/28] e2fsprogs-tests-f_ea_checks.patch Andreas Dilger
2008-02-02  8:25 ` Andreas Dilger [this message]
2008-02-02  8:25 ` [PATCH][0/28] e2fsprogs-extents.patch Andreas Dilger
2008-02-02  8:27   ` [PATCH][7/28] e2fsprogs-extents.patch Andreas Dilger
2008-02-18 17:56     ` Eric Sandeen
2008-02-18 18:12       ` Eric Sandeen
2008-02-18 19:53       ` Theodore Tso
2008-02-18 20:48         ` Eric Sandeen
2008-02-18 22:09           ` Theodore Tso
2008-02-19  4:35       ` Andreas Dilger
2008-02-02  8:29 ` [PATCH][8/28] e2fsprogs-config-before-cmdline.patch Andreas Dilger
2008-02-02  8:30 ` [PATCH][9/28] e2fsprogs-SLES10--m-support.patch Andreas Dilger
2008-02-02  8:34 ` [PATCH][10/28] e2fsprogs-uninit.patch Andreas Dilger
2008-03-15 19:41   ` Theodore Tso
2008-03-16  0:34     ` Andreas Dilger
2008-03-17 12:33   ` Theodore Tso
2008-02-02  8:36 ` [PATCH][11/28] e2fsprogs-nlinks-flag.patch Andreas Dilger
2008-02-02  8:36 ` [PATCH][12/28] e2fsprogs-expand-extra-isize.patch Andreas Dilger
2008-02-02  8:40 ` [PATCH][14/28] e2fsprogs-tests-f_expisize_ea_del.patch Andreas Dilger
2008-02-02  8:41 ` [PATCH][15/28] e2fsprogs-ibadness-counter.patch Andreas Dilger
2008-02-02  8:43 ` [PATCH][16/28] e2fsprogs-tests-f_ibadness.patch Andreas Dilger
2008-02-02  8:46 ` [PATCH][18/28] e2fsprogs-tests-f_random_corruption.patch Andreas Dilger
2008-02-02  8:47 ` [PATCH][19/28] e2fsprogs-stride_option.patch Andreas Dilger
2008-02-02  8:48 ` [PATCH][20/28] e2fsprogs-mmp.patch Andreas Dilger
2008-02-02  8:49 ` [PATCH][21/28] e2fsprogs-journal_chksum.patch Andreas Dilger
2008-02-02  8:54 ` [PATCH][25/28] e2fsprogs-i_size-corruption.patch Andreas Dilger
2008-02-02  8:54 ` [PATCH][26/28] e2fsprogs-fiemap.patch Andreas Dilger
2008-02-02  8:56 ` [PATCH][27/28] e2fsprogs-debugfs-supported_features.patch Andreas Dilger
2008-02-02  8:57 ` [PATCH][28/28] e2fsprogs-lts-make_rpms.patch Andreas Dilger
2008-02-11  4:19 ` [PATCH][0/28] Lustre e2fsprogs patch series Theodore Tso
2008-02-11 10:22   ` Aneesh Kumar K.V
2008-02-11 20:09   ` Andreas Dilger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080202082503.GF31694@webber.adilger.int \
    --to=adilger@sun.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=tytso@mit.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.