aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/namei.c60
-rw-r--r--include/linux/ext4_fs.h4
2 files changed, 49 insertions, 15 deletions
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 40106b7ea4b8..da224974af78 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -1629,6 +1629,35 @@ static int ext4_delete_entry (handle_t *handle,
1629 return -ENOENT; 1629 return -ENOENT;
1630} 1630}
1631 1631
1632/*
1633 * DIR_NLINK feature is set if 1) nlinks > EXT4_LINK_MAX or 2) nlinks == 2,
1634 * since this indicates that nlinks count was previously 1.
1635 */
1636static void ext4_inc_count(handle_t *handle, struct inode *inode)
1637{
1638 inc_nlink(inode);
1639 if (is_dx(inode) && inode->i_nlink > 1) {
1640 /* limit is 16-bit i_links_count */
1641 if (inode->i_nlink >= EXT4_LINK_MAX || inode->i_nlink == 2) {
1642 inode->i_nlink = 1;
1643 EXT4_SET_RO_COMPAT_FEATURE(inode->i_sb,
1644 EXT4_FEATURE_RO_COMPAT_DIR_NLINK);
1645 }
1646 }
1647}
1648
1649/*
1650 * If a directory had nlink == 1, then we should let it be 1. This indicates
1651 * directory has >EXT4_LINK_MAX subdirs.
1652 */
1653static void ext4_dec_count(handle_t *handle, struct inode *inode)
1654{
1655 drop_nlink(inode);
1656 if (S_ISDIR(inode->i_mode) && inode->i_nlink == 0)
1657 inc_nlink(inode);
1658}
1659
1660
1632static int ext4_add_nondir(handle_t *handle, 1661static int ext4_add_nondir(handle_t *handle,
1633 struct dentry *dentry, struct inode *inode) 1662 struct dentry *dentry, struct inode *inode)
1634{ 1663{
@@ -1725,7 +1754,7 @@ static int ext4_mkdir(struct inode * dir, struct dentry * dentry, int mode)
1725 struct ext4_dir_entry_2 * de; 1754 struct ext4_dir_entry_2 * de;
1726 int err, retries = 0; 1755 int err, retries = 0;
1727 1756
1728 if (dir->i_nlink >= EXT4_LINK_MAX) 1757 if (EXT4_DIR_LINK_MAX(dir))
1729 return -EMLINK; 1758 return -EMLINK;
1730 1759
1731retry: 1760retry:
@@ -1748,7 +1777,7 @@ retry:
1748 inode->i_size = EXT4_I(inode)->i_disksize = inode->i_sb->s_blocksize; 1777 inode->i_size = EXT4_I(inode)->i_disksize = inode->i_sb->s_blocksize;
1749 dir_block = ext4_bread (handle, inode, 0, 1, &err); 1778 dir_block = ext4_bread (handle, inode, 0, 1, &err);
1750 if (!dir_block) { 1779 if (!dir_block) {
1751 drop_nlink(inode); /* is this nlink == 0? */ 1780 ext4_dec_count(handle, inode); /* is this nlink == 0? */
1752 ext4_mark_inode_dirty(handle, inode); 1781 ext4_mark_inode_dirty(handle, inode);
1753 iput (inode); 1782 iput (inode);
1754 goto out_stop; 1783 goto out_stop;
@@ -1780,7 +1809,7 @@ retry:
1780 iput (inode); 1809 iput (inode);
1781 goto out_stop; 1810 goto out_stop;
1782 } 1811 }
1783 inc_nlink(dir); 1812 ext4_inc_count(handle, dir);
1784 ext4_update_dx_flag(dir); 1813 ext4_update_dx_flag(dir);
1785 ext4_mark_inode_dirty(handle, dir); 1814 ext4_mark_inode_dirty(handle, dir);
1786 d_instantiate(dentry, inode); 1815 d_instantiate(dentry, inode);
@@ -2045,9 +2074,9 @@ static int ext4_rmdir (struct inode * dir, struct dentry *dentry)
2045 retval = ext4_delete_entry(handle, dir, de, bh); 2074 retval = ext4_delete_entry(handle, dir, de, bh);
2046 if (retval) 2075 if (retval)
2047 goto end_rmdir; 2076 goto end_rmdir;
2048 if (inode->i_nlink != 2) 2077 if (!EXT4_DIR_LINK_EMPTY(inode))
2049 ext4_warning (inode->i_sb, "ext4_rmdir", 2078 ext4_warning (inode->i_sb, "ext4_rmdir",
2050 "empty directory has nlink!=2 (%d)", 2079 "empty directory has too many links (%d)",
2051 inode->i_nlink); 2080 inode->i_nlink);
2052 inode->i_version++; 2081 inode->i_version++;
2053 clear_nlink(inode); 2082 clear_nlink(inode);
@@ -2058,7 +2087,7 @@ static int ext4_rmdir (struct inode * dir, struct dentry *dentry)
2058 ext4_orphan_add(handle, inode); 2087 ext4_orphan_add(handle, inode);
2059 inode->i_ctime = dir->i_ctime = dir->i_mtime = ext4_current_time(inode); 2088 inode->i_ctime = dir->i_ctime = dir->i_mtime = ext4_current_time(inode);
2060 ext4_mark_inode_dirty(handle, inode); 2089 ext4_mark_inode_dirty(handle, inode);
2061 drop_nlink(dir); 2090 ext4_dec_count(handle, dir);
2062 ext4_update_dx_flag(dir); 2091 ext4_update_dx_flag(dir);
2063 ext4_mark_inode_dirty(handle, dir); 2092 ext4_mark_inode_dirty(handle, dir);
2064 2093
@@ -2109,7 +2138,7 @@ static int ext4_unlink(struct inode * dir, struct dentry *dentry)
2109 dir->i_ctime = dir->i_mtime = ext4_current_time(dir); 2138 dir->i_ctime = dir->i_mtime = ext4_current_time(dir);
2110 ext4_update_dx_flag(dir); 2139 ext4_update_dx_flag(dir);
2111 ext4_mark_inode_dirty(handle, dir); 2140 ext4_mark_inode_dirty(handle, dir);
2112 drop_nlink(inode); 2141 ext4_dec_count(handle, inode);
2113 if (!inode->i_nlink) 2142 if (!inode->i_nlink)
2114 ext4_orphan_add(handle, inode); 2143 ext4_orphan_add(handle, inode);
2115 inode->i_ctime = ext4_current_time(inode); 2144 inode->i_ctime = ext4_current_time(inode);
@@ -2159,7 +2188,7 @@ retry:
2159 err = __page_symlink(inode, symname, l, 2188 err = __page_symlink(inode, symname, l,
2160 mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); 2189 mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
2161 if (err) { 2190 if (err) {
2162 drop_nlink(inode); 2191 ext4_dec_count(handle, inode);
2163 ext4_mark_inode_dirty(handle, inode); 2192 ext4_mark_inode_dirty(handle, inode);
2164 iput (inode); 2193 iput (inode);
2165 goto out_stop; 2194 goto out_stop;
@@ -2185,8 +2214,9 @@ static int ext4_link (struct dentry * old_dentry,
2185 struct inode *inode = old_dentry->d_inode; 2214 struct inode *inode = old_dentry->d_inode;
2186 int err, retries = 0; 2215 int err, retries = 0;
2187 2216
2188 if (inode->i_nlink >= EXT4_LINK_MAX) 2217 if (EXT4_DIR_LINK_MAX(inode))
2189 return -EMLINK; 2218 return -EMLINK;
2219
2190 /* 2220 /*
2191 * Return -ENOENT if we've raced with unlink and i_nlink is 0. Doing 2221 * Return -ENOENT if we've raced with unlink and i_nlink is 0. Doing
2192 * otherwise has the potential to corrupt the orphan inode list. 2222 * otherwise has the potential to corrupt the orphan inode list.
@@ -2204,7 +2234,7 @@ retry:
2204 handle->h_sync = 1; 2234 handle->h_sync = 1;
2205 2235
2206 inode->i_ctime = ext4_current_time(inode); 2236 inode->i_ctime = ext4_current_time(inode);
2207 inc_nlink(inode); 2237 ext4_inc_count(handle, inode);
2208 atomic_inc(&inode->i_count); 2238 atomic_inc(&inode->i_count);
2209 2239
2210 err = ext4_add_nondir(handle, dentry, inode); 2240 err = ext4_add_nondir(handle, dentry, inode);
@@ -2337,7 +2367,7 @@ static int ext4_rename (struct inode * old_dir, struct dentry *old_dentry,
2337 } 2367 }
2338 2368
2339 if (new_inode) { 2369 if (new_inode) {
2340 drop_nlink(new_inode); 2370 ext4_dec_count(handle, new_inode);
2341 new_inode->i_ctime = ext4_current_time(new_inode); 2371 new_inode->i_ctime = ext4_current_time(new_inode);
2342 } 2372 }
2343 old_dir->i_ctime = old_dir->i_mtime = ext4_current_time(old_dir); 2373 old_dir->i_ctime = old_dir->i_mtime = ext4_current_time(old_dir);
@@ -2348,11 +2378,13 @@ static int ext4_rename (struct inode * old_dir, struct dentry *old_dentry,
2348 PARENT_INO(dir_bh->b_data) = cpu_to_le32(new_dir->i_ino); 2378 PARENT_INO(dir_bh->b_data) = cpu_to_le32(new_dir->i_ino);
2349 BUFFER_TRACE(dir_bh, "call ext4_journal_dirty_metadata"); 2379 BUFFER_TRACE(dir_bh, "call ext4_journal_dirty_metadata");
2350 ext4_journal_dirty_metadata(handle, dir_bh); 2380 ext4_journal_dirty_metadata(handle, dir_bh);
2351 drop_nlink(old_dir); 2381 ext4_dec_count(handle, old_dir);
2352 if (new_inode) { 2382 if (new_inode) {
2353 drop_nlink(new_inode); 2383 /* checked empty_dir above, can't have another parent,
2384 * ext3_dec_count() won't work for many-linked dirs */
2385 new_inode->i_nlink = 0;
2354 } else { 2386 } else {
2355 inc_nlink(new_dir); 2387 ext4_inc_count(handle, new_dir);
2356 ext4_update_dx_flag(new_dir); 2388 ext4_update_dx_flag(new_dir);
2357 ext4_mark_inode_dirty(handle, new_dir); 2389 ext4_mark_inode_dirty(handle, new_dir);
2358 } 2390 }
diff --git a/include/linux/ext4_fs.h b/include/linux/ext4_fs.h
index 52dcc24dd986..cdee7aaa57aa 100644
--- a/include/linux/ext4_fs.h
+++ b/include/linux/ext4_fs.h
@@ -71,7 +71,7 @@
71/* 71/*
72 * Maximal count of links to a file 72 * Maximal count of links to a file
73 */ 73 */
74#define EXT4_LINK_MAX 32000 74#define EXT4_LINK_MAX 65000
75 75
76/* 76/*
77 * Macro-instructions used to manage several block sizes 77 * Macro-instructions used to manage several block sizes
@@ -692,6 +692,7 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
692#define EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 692#define EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
693#define EXT4_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 693#define EXT4_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
694#define EXT4_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 694#define EXT4_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
695#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020
695#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040 696#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040
696 697
697#define EXT4_FEATURE_INCOMPAT_COMPRESSION 0x0001 698#define EXT4_FEATURE_INCOMPAT_COMPRESSION 0x0001
@@ -710,6 +711,7 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
710 EXT4_FEATURE_INCOMPAT_64BIT) 711 EXT4_FEATURE_INCOMPAT_64BIT)
711#define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \ 712#define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \
712 EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \ 713 EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \
714 EXT4_FEATURE_RO_COMPAT_DIR_NLINK | \
713 EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE | \ 715 EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE | \
714 EXT4_FEATURE_RO_COMPAT_BTREE_DIR) 716 EXT4_FEATURE_RO_COMPAT_BTREE_DIR)
715 717