diff options
Diffstat (limited to 'fs/ocfs2/namei.c')
-rw-r--r-- | fs/ocfs2/namei.c | 66 |
1 files changed, 39 insertions, 27 deletions
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 79f513001a6d..dc2e89a0c4af 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -112,7 +112,7 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, | |||
112 | struct inode *inode2); | 112 | struct inode *inode2); |
113 | 113 | ||
114 | static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, | 114 | static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, |
115 | struct ocfs2_journal_handle *handle, | 115 | struct inode **ret_orphan_dir, |
116 | struct inode *inode, | 116 | struct inode *inode, |
117 | char *name, | 117 | char *name, |
118 | struct buffer_head **de_bh); | 118 | struct buffer_head **de_bh); |
@@ -122,7 +122,8 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, | |||
122 | struct inode *inode, | 122 | struct inode *inode, |
123 | struct ocfs2_dinode *fe, | 123 | struct ocfs2_dinode *fe, |
124 | char *name, | 124 | char *name, |
125 | struct buffer_head *de_bh); | 125 | struct buffer_head *de_bh, |
126 | struct inode *orphan_dir_inode); | ||
126 | 127 | ||
127 | static int ocfs2_create_symlink_data(struct ocfs2_super *osb, | 128 | static int ocfs2_create_symlink_data(struct ocfs2_super *osb, |
128 | struct ocfs2_journal_handle *handle, | 129 | struct ocfs2_journal_handle *handle, |
@@ -813,6 +814,7 @@ static int ocfs2_unlink(struct inode *dir, | |||
813 | { | 814 | { |
814 | int status; | 815 | int status; |
815 | struct inode *inode = dentry->d_inode; | 816 | struct inode *inode = dentry->d_inode; |
817 | struct inode *orphan_dir = NULL; | ||
816 | struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); | 818 | struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); |
817 | u64 blkno; | 819 | u64 blkno; |
818 | struct ocfs2_dinode *fe = NULL; | 820 | struct ocfs2_dinode *fe = NULL; |
@@ -895,7 +897,7 @@ static int ocfs2_unlink(struct inode *dir, | |||
895 | } | 897 | } |
896 | 898 | ||
897 | if (inode_is_unlinkable(inode)) { | 899 | if (inode_is_unlinkable(inode)) { |
898 | status = ocfs2_prepare_orphan_dir(osb, handle, inode, | 900 | status = ocfs2_prepare_orphan_dir(osb, &orphan_dir, inode, |
899 | orphan_name, | 901 | orphan_name, |
900 | &orphan_entry_bh); | 902 | &orphan_entry_bh); |
901 | if (status < 0) { | 903 | if (status < 0) { |
@@ -923,7 +925,7 @@ static int ocfs2_unlink(struct inode *dir, | |||
923 | 925 | ||
924 | if (inode_is_unlinkable(inode)) { | 926 | if (inode_is_unlinkable(inode)) { |
925 | status = ocfs2_orphan_add(osb, handle, inode, fe, orphan_name, | 927 | status = ocfs2_orphan_add(osb, handle, inode, fe, orphan_name, |
926 | orphan_entry_bh); | 928 | orphan_entry_bh, orphan_dir); |
927 | if (status < 0) { | 929 | if (status < 0) { |
928 | mlog_errno(status); | 930 | mlog_errno(status); |
929 | goto leave; | 931 | goto leave; |
@@ -962,6 +964,13 @@ leave: | |||
962 | if (handle) | 964 | if (handle) |
963 | ocfs2_commit_trans(handle); | 965 | ocfs2_commit_trans(handle); |
964 | 966 | ||
967 | if (orphan_dir) { | ||
968 | /* This was locked for us in ocfs2_prepare_orphan_dir() */ | ||
969 | ocfs2_meta_unlock(orphan_dir, 1); | ||
970 | mutex_unlock(&orphan_dir->i_mutex); | ||
971 | iput(orphan_dir); | ||
972 | } | ||
973 | |||
965 | if (fe_bh) | 974 | if (fe_bh) |
966 | brelse(fe_bh); | 975 | brelse(fe_bh); |
967 | 976 | ||
@@ -1053,6 +1062,7 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1053 | int status = 0, rename_lock = 0; | 1062 | int status = 0, rename_lock = 0; |
1054 | struct inode *old_inode = old_dentry->d_inode; | 1063 | struct inode *old_inode = old_dentry->d_inode; |
1055 | struct inode *new_inode = new_dentry->d_inode; | 1064 | struct inode *new_inode = new_dentry->d_inode; |
1065 | struct inode *orphan_dir = NULL; | ||
1056 | struct ocfs2_dinode *newfe = NULL; | 1066 | struct ocfs2_dinode *newfe = NULL; |
1057 | char orphan_name[OCFS2_ORPHAN_NAMELEN + 1]; | 1067 | char orphan_name[OCFS2_ORPHAN_NAMELEN + 1]; |
1058 | struct buffer_head *orphan_entry_bh = NULL; | 1068 | struct buffer_head *orphan_entry_bh = NULL; |
@@ -1252,7 +1262,7 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1252 | (unsigned long long)newfe_bh->b_blocknr : 0ULL); | 1262 | (unsigned long long)newfe_bh->b_blocknr : 0ULL); |
1253 | 1263 | ||
1254 | if (S_ISDIR(new_inode->i_mode) || (new_inode->i_nlink == 1)) { | 1264 | if (S_ISDIR(new_inode->i_mode) || (new_inode->i_nlink == 1)) { |
1255 | status = ocfs2_prepare_orphan_dir(osb, handle, | 1265 | status = ocfs2_prepare_orphan_dir(osb, &orphan_dir, |
1256 | new_inode, | 1266 | new_inode, |
1257 | orphan_name, | 1267 | orphan_name, |
1258 | &orphan_entry_bh); | 1268 | &orphan_entry_bh); |
@@ -1307,7 +1317,7 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1307 | (newfe->i_links_count == cpu_to_le16(1))){ | 1317 | (newfe->i_links_count == cpu_to_le16(1))){ |
1308 | status = ocfs2_orphan_add(osb, handle, new_inode, | 1318 | status = ocfs2_orphan_add(osb, handle, new_inode, |
1309 | newfe, orphan_name, | 1319 | newfe, orphan_name, |
1310 | orphan_entry_bh); | 1320 | orphan_entry_bh, orphan_dir); |
1311 | if (status < 0) { | 1321 | if (status < 0) { |
1312 | mlog_errno(status); | 1322 | mlog_errno(status); |
1313 | goto bail; | 1323 | goto bail; |
@@ -1426,6 +1436,13 @@ bail: | |||
1426 | if (handle) | 1436 | if (handle) |
1427 | ocfs2_commit_trans(handle); | 1437 | ocfs2_commit_trans(handle); |
1428 | 1438 | ||
1439 | if (orphan_dir) { | ||
1440 | /* This was locked for us in ocfs2_prepare_orphan_dir() */ | ||
1441 | ocfs2_meta_unlock(orphan_dir, 1); | ||
1442 | mutex_unlock(&orphan_dir->i_mutex); | ||
1443 | iput(orphan_dir); | ||
1444 | } | ||
1445 | |||
1429 | if (new_inode) | 1446 | if (new_inode) |
1430 | sync_mapping_buffers(old_inode->i_mapping); | 1447 | sync_mapping_buffers(old_inode->i_mapping); |
1431 | 1448 | ||
@@ -2085,19 +2102,19 @@ bail: | |||
2085 | } | 2102 | } |
2086 | 2103 | ||
2087 | static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, | 2104 | static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, |
2088 | struct ocfs2_journal_handle *handle, | 2105 | struct inode **ret_orphan_dir, |
2089 | struct inode *inode, | 2106 | struct inode *inode, |
2090 | char *name, | 2107 | char *name, |
2091 | struct buffer_head **de_bh) | 2108 | struct buffer_head **de_bh) |
2092 | { | 2109 | { |
2093 | struct inode *orphan_dir_inode = NULL; | 2110 | struct inode *orphan_dir_inode; |
2094 | struct buffer_head *orphan_dir_bh = NULL; | 2111 | struct buffer_head *orphan_dir_bh = NULL; |
2095 | int status = 0; | 2112 | int status = 0; |
2096 | 2113 | ||
2097 | status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, name); | 2114 | status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, name); |
2098 | if (status < 0) { | 2115 | if (status < 0) { |
2099 | mlog_errno(status); | 2116 | mlog_errno(status); |
2100 | goto leave; | 2117 | return status; |
2101 | } | 2118 | } |
2102 | 2119 | ||
2103 | orphan_dir_inode = ocfs2_get_system_file_inode(osb, | 2120 | orphan_dir_inode = ocfs2_get_system_file_inode(osb, |
@@ -2106,11 +2123,12 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, | |||
2106 | if (!orphan_dir_inode) { | 2123 | if (!orphan_dir_inode) { |
2107 | status = -ENOENT; | 2124 | status = -ENOENT; |
2108 | mlog_errno(status); | 2125 | mlog_errno(status); |
2109 | goto leave; | 2126 | return status; |
2110 | } | 2127 | } |
2111 | 2128 | ||
2112 | ocfs2_handle_add_inode(handle, orphan_dir_inode); | 2129 | mutex_lock(&orphan_dir_inode->i_mutex); |
2113 | status = ocfs2_meta_lock(orphan_dir_inode, handle, &orphan_dir_bh, 1); | 2130 | |
2131 | status = ocfs2_meta_lock(orphan_dir_inode, NULL, &orphan_dir_bh, 1); | ||
2114 | if (status < 0) { | 2132 | if (status < 0) { |
2115 | mlog_errno(status); | 2133 | mlog_errno(status); |
2116 | goto leave; | 2134 | goto leave; |
@@ -2120,13 +2138,19 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, | |||
2120 | orphan_dir_bh, name, | 2138 | orphan_dir_bh, name, |
2121 | OCFS2_ORPHAN_NAMELEN, de_bh); | 2139 | OCFS2_ORPHAN_NAMELEN, de_bh); |
2122 | if (status < 0) { | 2140 | if (status < 0) { |
2141 | ocfs2_meta_unlock(orphan_dir_inode, 1); | ||
2142 | |||
2123 | mlog_errno(status); | 2143 | mlog_errno(status); |
2124 | goto leave; | 2144 | goto leave; |
2125 | } | 2145 | } |
2126 | 2146 | ||
2147 | *ret_orphan_dir = orphan_dir_inode; | ||
2148 | |||
2127 | leave: | 2149 | leave: |
2128 | if (orphan_dir_inode) | 2150 | if (status) { |
2151 | mutex_unlock(&orphan_dir_inode->i_mutex); | ||
2129 | iput(orphan_dir_inode); | 2152 | iput(orphan_dir_inode); |
2153 | } | ||
2130 | 2154 | ||
2131 | if (orphan_dir_bh) | 2155 | if (orphan_dir_bh) |
2132 | brelse(orphan_dir_bh); | 2156 | brelse(orphan_dir_bh); |
@@ -2140,24 +2164,15 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, | |||
2140 | struct inode *inode, | 2164 | struct inode *inode, |
2141 | struct ocfs2_dinode *fe, | 2165 | struct ocfs2_dinode *fe, |
2142 | char *name, | 2166 | char *name, |
2143 | struct buffer_head *de_bh) | 2167 | struct buffer_head *de_bh, |
2168 | struct inode *orphan_dir_inode) | ||
2144 | { | 2169 | { |
2145 | struct inode *orphan_dir_inode = NULL; | ||
2146 | struct buffer_head *orphan_dir_bh = NULL; | 2170 | struct buffer_head *orphan_dir_bh = NULL; |
2147 | int status = 0; | 2171 | int status = 0; |
2148 | struct ocfs2_dinode *orphan_fe; | 2172 | struct ocfs2_dinode *orphan_fe; |
2149 | 2173 | ||
2150 | mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino); | 2174 | mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino); |
2151 | 2175 | ||
2152 | orphan_dir_inode = ocfs2_get_system_file_inode(osb, | ||
2153 | ORPHAN_DIR_SYSTEM_INODE, | ||
2154 | osb->slot_num); | ||
2155 | if (!orphan_dir_inode) { | ||
2156 | status = -ENOENT; | ||
2157 | mlog_errno(status); | ||
2158 | goto leave; | ||
2159 | } | ||
2160 | |||
2161 | status = ocfs2_read_block(osb, | 2176 | status = ocfs2_read_block(osb, |
2162 | OCFS2_I(orphan_dir_inode)->ip_blkno, | 2177 | OCFS2_I(orphan_dir_inode)->ip_blkno, |
2163 | &orphan_dir_bh, OCFS2_BH_CACHED, | 2178 | &orphan_dir_bh, OCFS2_BH_CACHED, |
@@ -2209,9 +2224,6 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, | |||
2209 | (unsigned long long)OCFS2_I(inode)->ip_blkno, osb->slot_num); | 2224 | (unsigned long long)OCFS2_I(inode)->ip_blkno, osb->slot_num); |
2210 | 2225 | ||
2211 | leave: | 2226 | leave: |
2212 | if (orphan_dir_inode) | ||
2213 | iput(orphan_dir_inode); | ||
2214 | |||
2215 | if (orphan_dir_bh) | 2227 | if (orphan_dir_bh) |
2216 | brelse(orphan_dir_bh); | 2228 | brelse(orphan_dir_bh); |
2217 | 2229 | ||