Whamcloud - gitweb
land b1_5 onto HEAD
[fs/lustre-release.git] / lustre / kernel_patches / patches / ext3-nlinks-2.6.9.patch
diff --git a/lustre/kernel_patches/patches/ext3-nlinks-2.6.9.patch b/lustre/kernel_patches/patches/ext3-nlinks-2.6.9.patch
new file mode 100644 (file)
index 0000000..37cca81
--- /dev/null
@@ -0,0 +1,142 @@
+diff -Nur orig/fs/ext3/namei.c patch/fs/ext3/namei.c
+--- orig/fs/ext3/namei.c       2005-10-12 13:58:19.000000000 -0700
++++ patch/fs/ext3/namei.c      2005-10-12 14:00:33.000000000 -0700
+@@ -1603,11 +1603,17 @@
+ static inline void ext3_inc_count(handle_t *handle, struct inode *inode)
+ {
+       inode->i_nlink++;
++      if (is_dx(inode) && inode->i_nlink > 1) {
++              /* limit is 16-bit i_links_count */
++              if (inode->i_nlink >= EXT3_LINK_MAX || inode->i_nlink == 2)
++                      inode->i_nlink = 1;
++      }
+ }
+ static inline void ext3_dec_count(handle_t *handle, struct inode *inode)
+ {
+-      inode->i_nlink--;
++      if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2)
++              inode->i_nlink--;
+ }
+ static int ext3_add_nondir(handle_t *handle,
+@@ -1706,7 +1712,7 @@ static int ext3_add_nondir(handle_t
+       struct ext3_dir_entry_2 * de;
+       int err, retries = 0;
+-      if (dir->i_nlink >= EXT3_LINK_MAX)
++      if (EXT3_DIR_LINK_MAX(dir))
+               return -EMLINK;
+ retry:
+@@ -1729,7 +1735,7 @@ static int ext3_mkdir(struct inode
+       inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
+       dir_block = ext3_bread (handle, inode, 0, 1, &err);
+       if (!dir_block) {
+-              inode->i_nlink--; /* is this nlink == 0? */
++              ext3_dec_count(handle, inode); /* is this nlink == 0? */
+               ext3_mark_inode_dirty(handle, inode);
+               iput (inode);
+               goto out_stop;
+@@ -1761,7 +1767,7 @@ static int ext3_mkdir(struct inode
+               iput (inode);
+               goto out_stop;
+       }
+-      dir->i_nlink++;
++      ext3_inc_count(handle, dir);
+       ext3_update_dx_flag(dir);
+       ext3_mark_inode_dirty(handle, dir);
+       d_instantiate(dentry, inode);
+@@ -2026,10 +2032,10 @@ static int ext3_rmdir (struct inode
+       retval = ext3_delete_entry(handle, dir, de, bh);
+       if (retval)
+               goto end_rmdir;
+-      if (inode->i_nlink != 2)
+-              ext3_warning (inode->i_sb, "ext3_rmdir",
+-                            "empty directory has nlink!=2 (%d)",
+-                            inode->i_nlink);
++      if (!EXT3_DIR_LINK_EMPTY(inode))
++              ext3_warning(inode->i_sb, "ext3_rmdir",
++                           "empty directory has too many links (%d)",
++                           inode->i_nlink);
+       inode->i_version++;
+       inode->i_nlink = 0;
+       /* There's no need to set i_disksize: the fact that i_nlink is
+@@ -2039,7 +2045,7 @@ static int ext3_rmdir (struct inode
+       ext3_orphan_add(handle, inode);
+       inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
+       ext3_mark_inode_dirty(handle, inode);
+-      dir->i_nlink--;
++      ext3_dec_count(handle, dir);
+       ext3_update_dx_flag(dir);
+       ext3_mark_inode_dirty(handle, dir);
+@@ -2090,7 +2096,7 @@ static int ext3_unlink(struct inode
+       dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
+       ext3_update_dx_flag(dir);
+       ext3_mark_inode_dirty(handle, dir);
+-      inode->i_nlink--;
++      ext3_dec_count(handle, inode);
+       if (!inode->i_nlink)
+               ext3_orphan_add(handle, inode);
+       inode->i_ctime = dir->i_ctime;
+@@ -2165,7 +2171,7 @@ static int ext3_link (struct dentry
+       struct inode *inode = old_dentry->d_inode;
+       int err, retries = 0;
+-      if (inode->i_nlink >= EXT3_LINK_MAX)
++      if (EXT3_DIR_LINK_MAX(inode))
+               return -EMLINK;
+ retry:
+@@ -2252,8 +2258,8 @@ static int ext3_rename (struct inode
+               if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino)
+                       goto end_rename;
+               retval = -EMLINK;
+-              if (!new_inode && new_dir!=old_dir &&
+-                              new_dir->i_nlink >= EXT3_LINK_MAX)
++              if (!new_inode && new_dir != old_dir &&
++                  EXT3_DIR_LINK_MAX(new_dir))
+                       goto end_rename;
+       }
+       if (!new_bh) {
+@@ -2310,7 +2316,7 @@ static int ext3_rename (struct inode
+       }
+       if (new_inode) {
+-              new_inode->i_nlink--;
++              ext3_dec_count(handle, new_inode);
+               new_inode->i_ctime = CURRENT_TIME_SEC;
+       }
+       old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
+@@ -2321,11 +2327,13 @@ static int ext3_rename (struct inode
+               PARENT_INO(dir_bh->b_data) = cpu_to_le32(new_dir->i_ino);
+               BUFFER_TRACE(dir_bh, "call ext3_journal_dirty_metadata");
+               ext3_journal_dirty_metadata(handle, dir_bh);
+-              old_dir->i_nlink--;
++              ext3_dec_count(handle, old_dir);
+               if (new_inode) {
+-                      new_inode->i_nlink--;
++                      /* checked empty_dir above, can't have another parent,
++                       * ext3_dec_count() won't work for many-linked dirs */
++                      new_inode->i_nlink = 0;
+               } else {
+-                      new_dir->i_nlink++;
++                      ext3_inc_count(handle, new_dir);
+                       ext3_update_dx_flag(new_dir);
+                       ext3_mark_inode_dirty(handle, new_dir);
+               }
+
+Index: linux-2.6.7/include/linux/ext3_fs.h
+===================================================================
+--- linux-2.6.7.orig/include/linux/ext3_fs.h   2004-06-15 23:19:36.000000000 -0600
++++ linux-2.6.7/include/linux/ext3_fs.h        2004-08-20 17:41:27.000000000 -0600
+@@ -79,7 +81,7 @@
+ /*
+  * Maximal count of links to a file
+  */
+-#define EXT3_LINK_MAX         32000
++#define EXT3_LINK_MAX         65000
+ /*
+  * Macro-instructions used to manage several block sizes