aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ocfs2/namei.c')
-rw-r--r--fs/ocfs2/namei.c66
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
114static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, 114static 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
127static int ocfs2_create_symlink_data(struct ocfs2_super *osb, 128static 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
2087static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, 2104static 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
2127leave: 2149leave:
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
2211leave: 2226leave:
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