diff options
author | Mark Fasheh <mark.fasheh@oracle.com> | 2007-01-02 20:59:40 -0500 |
---|---|---|
committer | Mark Fasheh <mark.fasheh@oracle.com> | 2007-01-21 19:18:49 -0500 |
commit | 592282cf2eaa33409c6511ddd3f3ecaa57daeaaa (patch) | |
tree | fea7fe8403d6b2a96848372a69976b0123a4cf1d /fs/ocfs2/namei.c | |
parent | 72bce5078d124a8b13fb167aea028b6e8d91873e (diff) |
ocfs2: Directory c/mtime update fixes
ocfs2 wasn't updating c/mtime on directories during dirent
creation/deletion. Fix ocfs2_unlink(), ocfs2_rename() and
__ocfs2_add_entry() by adding the proper code to update the struct inode and
push the change out to disk.
This helps rename/unlink on nfs exported file systems in particular as those
clients compare directory time values to avoid a full re-reading a directory
which hasn't changed.
ocfs2_rename() loses some superfluous error handling as a result of this
patch.
Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
Diffstat (limited to 'fs/ocfs2/namei.c')
-rw-r--r-- | fs/ocfs2/namei.c | 69 |
1 files changed, 37 insertions, 32 deletions
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 9637039c2633..f3d7803b4b46 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -932,14 +932,15 @@ static int ocfs2_unlink(struct inode *dir, | |||
932 | goto leave; | 932 | goto leave; |
933 | } | 933 | } |
934 | 934 | ||
935 | if (S_ISDIR(inode->i_mode)) { | 935 | dir->i_ctime = dir->i_mtime = CURRENT_TIME; |
936 | if (S_ISDIR(inode->i_mode)) | ||
936 | drop_nlink(dir); | 937 | drop_nlink(dir); |
937 | status = ocfs2_mark_inode_dirty(handle, dir, | 938 | |
938 | parent_node_bh); | 939 | status = ocfs2_mark_inode_dirty(handle, dir, parent_node_bh); |
939 | if (status < 0) { | 940 | if (status < 0) { |
940 | mlog_errno(status); | 941 | mlog_errno(status); |
942 | if (S_ISDIR(inode->i_mode)) | ||
941 | inc_nlink(dir); | 943 | inc_nlink(dir); |
942 | } | ||
943 | } | 944 | } |
944 | 945 | ||
945 | leave: | 946 | leave: |
@@ -1068,6 +1069,7 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1068 | char orphan_name[OCFS2_ORPHAN_NAMELEN + 1]; | 1069 | char orphan_name[OCFS2_ORPHAN_NAMELEN + 1]; |
1069 | struct buffer_head *orphan_entry_bh = NULL; | 1070 | struct buffer_head *orphan_entry_bh = NULL; |
1070 | struct buffer_head *newfe_bh = NULL; | 1071 | struct buffer_head *newfe_bh = NULL; |
1072 | struct buffer_head *old_inode_bh = NULL; | ||
1071 | struct buffer_head *insert_entry_bh = NULL; | 1073 | struct buffer_head *insert_entry_bh = NULL; |
1072 | struct ocfs2_super *osb = NULL; | 1074 | struct ocfs2_super *osb = NULL; |
1073 | u64 newfe_blkno; | 1075 | u64 newfe_blkno; |
@@ -1079,7 +1081,7 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1079 | struct buffer_head *new_de_bh = NULL, *old_de_bh = NULL; // bhs for above | 1081 | struct buffer_head *new_de_bh = NULL, *old_de_bh = NULL; // bhs for above |
1080 | struct buffer_head *old_inode_de_bh = NULL; // if old_dentry is a dir, | 1082 | struct buffer_head *old_inode_de_bh = NULL; // if old_dentry is a dir, |
1081 | // this is the 1st dirent bh | 1083 | // this is the 1st dirent bh |
1082 | nlink_t old_dir_nlink = old_dir->i_nlink, new_dir_nlink = new_dir->i_nlink; | 1084 | nlink_t old_dir_nlink = old_dir->i_nlink; |
1083 | 1085 | ||
1084 | /* At some point it might be nice to break this function up a | 1086 | /* At some point it might be nice to break this function up a |
1085 | * bit. */ | 1087 | * bit. */ |
@@ -1139,12 +1141,11 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1139 | } | 1141 | } |
1140 | 1142 | ||
1141 | /* | 1143 | /* |
1142 | * Though we don't require an inode meta data update if | 1144 | * Aside from allowing a meta data update, the locking here |
1143 | * old_inode is not a directory, we lock anyway here to ensure | 1145 | * also ensures that the vote thread on other nodes won't have |
1144 | * the vote thread on other nodes won't have to concurrently | 1146 | * to concurrently downconvert the inode and the dentry locks. |
1145 | * downconvert the inode and the dentry locks. | ||
1146 | */ | 1147 | */ |
1147 | status = ocfs2_meta_lock(old_inode, NULL, 1); | 1148 | status = ocfs2_meta_lock(old_inode, &old_inode_bh, 1); |
1148 | if (status < 0) { | 1149 | if (status < 0) { |
1149 | if (status != -ENOENT) | 1150 | if (status != -ENOENT) |
1150 | mlog_errno(status); | 1151 | mlog_errno(status); |
@@ -1355,6 +1356,7 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1355 | 1356 | ||
1356 | old_inode->i_ctime = CURRENT_TIME; | 1357 | old_inode->i_ctime = CURRENT_TIME; |
1357 | mark_inode_dirty(old_inode); | 1358 | mark_inode_dirty(old_inode); |
1359 | ocfs2_mark_inode_dirty(handle, old_inode, old_inode_bh); | ||
1358 | 1360 | ||
1359 | /* now that the name has been added to new_dir, remove the old name */ | 1361 | /* now that the name has been added to new_dir, remove the old name */ |
1360 | status = ocfs2_delete_entry(handle, old_dir, old_de, old_de_bh); | 1362 | status = ocfs2_delete_entry(handle, old_dir, old_de, old_de_bh); |
@@ -1384,27 +1386,22 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1384 | } | 1386 | } |
1385 | } | 1387 | } |
1386 | mark_inode_dirty(old_dir); | 1388 | mark_inode_dirty(old_dir); |
1387 | if (new_inode) | 1389 | ocfs2_mark_inode_dirty(handle, old_dir, old_dir_bh); |
1390 | if (new_inode) { | ||
1388 | mark_inode_dirty(new_inode); | 1391 | mark_inode_dirty(new_inode); |
1392 | ocfs2_mark_inode_dirty(handle, new_inode, newfe_bh); | ||
1393 | } | ||
1389 | 1394 | ||
1390 | if (old_dir != new_dir) | 1395 | if (old_dir != new_dir) { |
1391 | if (new_dir_nlink != new_dir->i_nlink) { | 1396 | /* Keep the same times on both directories.*/ |
1392 | if (!new_dir_bh) { | 1397 | new_dir->i_ctime = new_dir->i_mtime = old_dir->i_ctime; |
1393 | mlog(ML_ERROR, "need to change nlink for new " | 1398 | |
1394 | "dir %llu from %d to %d but bh is NULL\n", | 1399 | /* |
1395 | (unsigned long long)OCFS2_I(new_dir)->ip_blkno, | 1400 | * This will also pick up the i_nlink change from the |
1396 | (int)new_dir_nlink, new_dir->i_nlink); | 1401 | * block above. |
1397 | } else { | 1402 | */ |
1398 | struct ocfs2_dinode *fe; | 1403 | ocfs2_mark_inode_dirty(handle, new_dir, new_dir_bh); |
1399 | status = ocfs2_journal_access(handle, | 1404 | } |
1400 | new_dir, | ||
1401 | new_dir_bh, | ||
1402 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
1403 | fe = (struct ocfs2_dinode *) new_dir_bh->b_data; | ||
1404 | fe->i_links_count = cpu_to_le16(new_dir->i_nlink); | ||
1405 | status = ocfs2_journal_dirty(handle, new_dir_bh); | ||
1406 | } | ||
1407 | } | ||
1408 | 1405 | ||
1409 | if (old_dir_nlink != old_dir->i_nlink) { | 1406 | if (old_dir_nlink != old_dir->i_nlink) { |
1410 | if (!old_dir_bh) { | 1407 | if (!old_dir_bh) { |
@@ -1455,6 +1452,8 @@ bail: | |||
1455 | iput(new_inode); | 1452 | iput(new_inode); |
1456 | if (newfe_bh) | 1453 | if (newfe_bh) |
1457 | brelse(newfe_bh); | 1454 | brelse(newfe_bh); |
1455 | if (old_inode_bh) | ||
1456 | brelse(old_inode_bh); | ||
1458 | if (old_dir_bh) | 1457 | if (old_dir_bh) |
1459 | brelse(old_dir_bh); | 1458 | brelse(old_dir_bh); |
1460 | if (new_dir_bh) | 1459 | if (new_dir_bh) |
@@ -1826,6 +1825,13 @@ static int __ocfs2_add_entry(handle_t *handle, | |||
1826 | (le16_to_cpu(de->rec_len) >= rec_len)) || | 1825 | (le16_to_cpu(de->rec_len) >= rec_len)) || |
1827 | (le16_to_cpu(de->rec_len) >= | 1826 | (le16_to_cpu(de->rec_len) >= |
1828 | (OCFS2_DIR_REC_LEN(de->name_len) + rec_len))) { | 1827 | (OCFS2_DIR_REC_LEN(de->name_len) + rec_len))) { |
1828 | dir->i_mtime = dir->i_ctime = CURRENT_TIME; | ||
1829 | retval = ocfs2_mark_inode_dirty(handle, dir, parent_fe_bh); | ||
1830 | if (retval < 0) { | ||
1831 | mlog_errno(retval); | ||
1832 | goto bail; | ||
1833 | } | ||
1834 | |||
1829 | status = ocfs2_journal_access(handle, dir, insert_bh, | 1835 | status = ocfs2_journal_access(handle, dir, insert_bh, |
1830 | OCFS2_JOURNAL_ACCESS_WRITE); | 1836 | OCFS2_JOURNAL_ACCESS_WRITE); |
1831 | /* By now the buffer is marked for journaling */ | 1837 | /* By now the buffer is marked for journaling */ |
@@ -1848,7 +1854,6 @@ static int __ocfs2_add_entry(handle_t *handle, | |||
1848 | de->name_len = namelen; | 1854 | de->name_len = namelen; |
1849 | memcpy(de->name, name, namelen); | 1855 | memcpy(de->name, name, namelen); |
1850 | 1856 | ||
1851 | dir->i_mtime = dir->i_ctime = CURRENT_TIME; | ||
1852 | dir->i_version++; | 1857 | dir->i_version++; |
1853 | status = ocfs2_journal_dirty(handle, insert_bh); | 1858 | status = ocfs2_journal_dirty(handle, insert_bh); |
1854 | retval = 0; | 1859 | retval = 0; |