aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ocfs2/namei.c127
1 files changed, 107 insertions, 20 deletions
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 54c629855357..a00dda2e4f16 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -2128,6 +2128,99 @@ leave:
2128 return status; 2128 return status;
2129} 2129}
2130 2130
2131/**
2132 * ocfs2_prep_new_orphaned_file() - Prepare the orphan dir to recieve a newly
2133 * allocated file. This is different from the typical 'add to orphan dir'
2134 * operation in that the inode does not yet exist. This is a problem because
2135 * the orphan dir stringifies the inode block number to come up with it's
2136 * dirent. Obviously if the inode does not yet exist we have a chicken and egg
2137 * problem. This function works around it by calling deeper into the orphan
2138 * and suballoc code than other callers. Use this only by necessity.
2139 * @dir: The directory which this inode will ultimately wind up under - not the
2140 * orphan dir!
2141 * @dir_bh: buffer_head the @dir inode block
2142 * @orphan_name: string of length (CFS2_ORPHAN_NAMELEN + 1). Will be filled
2143 * with the string to be used for orphan dirent. Pass back to the orphan dir
2144 * code.
2145 * @ret_orphan_dir: orphan dir inode returned to be passed back into orphan
2146 * dir code.
2147 * @ret_di_blkno: block number where the new inode will be allocated.
2148 * @orphan_insert: Dir insert context to be passed back into orphan dir code.
2149 * @ret_inode_ac: Inode alloc context to be passed back to the allocator.
2150 *
2151 * Returns zero on success and the ret_orphan_dir, name and lookup
2152 * fields will be populated.
2153 *
2154 * Returns non-zero on failure.
2155 */
2156static int ocfs2_prep_new_orphaned_file(struct inode *dir,
2157 struct buffer_head *dir_bh,
2158 char *orphan_name,
2159 struct inode **ret_orphan_dir,
2160 u64 *ret_di_blkno,
2161 struct ocfs2_dir_lookup_result *orphan_insert,
2162 struct ocfs2_alloc_context **ret_inode_ac)
2163{
2164 int ret;
2165 u64 di_blkno;
2166 struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
2167 struct inode *orphan_dir = NULL;
2168 struct buffer_head *orphan_dir_bh = NULL;
2169 struct ocfs2_alloc_context *inode_ac = NULL;
2170
2171 ret = ocfs2_lookup_lock_orphan_dir(osb, &orphan_dir, &orphan_dir_bh);
2172 if (ret < 0) {
2173 mlog_errno(ret);
2174 return ret;
2175 }
2176
2177 /* reserve an inode spot */
2178 ret = ocfs2_reserve_new_inode(osb, &inode_ac);
2179 if (ret < 0) {
2180 if (ret != -ENOSPC)
2181 mlog_errno(ret);
2182 goto out;
2183 }
2184
2185 ret = ocfs2_find_new_inode_loc(dir, dir_bh, inode_ac,
2186 &di_blkno);
2187 if (ret) {
2188 mlog_errno(ret);
2189 goto out;
2190 }
2191
2192 ret = __ocfs2_prepare_orphan_dir(orphan_dir, orphan_dir_bh,
2193 di_blkno, orphan_name, orphan_insert);
2194 if (ret < 0) {
2195 mlog_errno(ret);
2196 goto out;
2197 }
2198
2199out:
2200 if (ret == 0) {
2201 *ret_orphan_dir = orphan_dir;
2202 *ret_di_blkno = di_blkno;
2203 *ret_inode_ac = inode_ac;
2204 /*
2205 * orphan_name and orphan_insert are already up to
2206 * date via prepare_orphan_dir
2207 */
2208 } else {
2209 /* Unroll reserve_new_inode* */
2210 if (inode_ac)
2211 ocfs2_free_alloc_context(inode_ac);
2212
2213 /* Unroll orphan dir locking */
2214 mutex_unlock(&orphan_dir->i_mutex);
2215 ocfs2_inode_unlock(orphan_dir, 1);
2216 iput(orphan_dir);
2217 }
2218
2219 brelse(orphan_dir_bh);
2220
2221 return 0;
2222}
2223
2131int ocfs2_create_inode_in_orphan(struct inode *dir, 2224int ocfs2_create_inode_in_orphan(struct inode *dir,
2132 int mode, 2225 int mode,
2133 struct inode **new_inode) 2226 struct inode **new_inode)
@@ -2143,6 +2236,8 @@ int ocfs2_create_inode_in_orphan(struct inode *dir,
2143 struct buffer_head *new_di_bh = NULL; 2236 struct buffer_head *new_di_bh = NULL;
2144 struct ocfs2_alloc_context *inode_ac = NULL; 2237 struct ocfs2_alloc_context *inode_ac = NULL;
2145 struct ocfs2_dir_lookup_result orphan_insert = { NULL, }; 2238 struct ocfs2_dir_lookup_result orphan_insert = { NULL, };
2239 u64 uninitialized_var(di_blkno), suballoc_loc;
2240 u16 suballoc_bit;
2146 2241
2147 status = ocfs2_inode_lock(dir, &parent_di_bh, 1); 2242 status = ocfs2_inode_lock(dir, &parent_di_bh, 1);
2148 if (status < 0) { 2243 if (status < 0) {
@@ -2151,20 +2246,9 @@ int ocfs2_create_inode_in_orphan(struct inode *dir,
2151 return status; 2246 return status;
2152 } 2247 }
2153 2248
2154 /* 2249 status = ocfs2_prep_new_orphaned_file(dir, parent_di_bh,
2155 * We give the orphan dir the root blkno to fake an orphan name, 2250 orphan_name, &orphan_dir,
2156 * and allocate enough space for our insertion. 2251 &di_blkno, &orphan_insert, &inode_ac);
2157 */
2158 status = ocfs2_prepare_orphan_dir(osb, &orphan_dir,
2159 osb->root_blkno,
2160 orphan_name, &orphan_insert);
2161 if (status < 0) {
2162 mlog_errno(status);
2163 goto leave;
2164 }
2165
2166 /* reserve an inode spot */
2167 status = ocfs2_reserve_new_inode(osb, &inode_ac);
2168 if (status < 0) { 2252 if (status < 0) {
2169 if (status != -ENOSPC) 2253 if (status != -ENOSPC)
2170 mlog_errno(status); 2254 mlog_errno(status);
@@ -2191,17 +2275,20 @@ int ocfs2_create_inode_in_orphan(struct inode *dir,
2191 goto leave; 2275 goto leave;
2192 did_quota_inode = 1; 2276 did_quota_inode = 1;
2193 2277
2194 inode->i_nlink = 0; 2278 status = ocfs2_claim_new_inode_at_loc(handle, dir, inode_ac,
2195 /* do the real work now. */ 2279 &suballoc_loc,
2196 status = ocfs2_mknod_locked(osb, dir, inode, 2280 &suballoc_bit, di_blkno);
2197 0, &new_di_bh, parent_di_bh, handle,
2198 inode_ac);
2199 if (status < 0) { 2281 if (status < 0) {
2200 mlog_errno(status); 2282 mlog_errno(status);
2201 goto leave; 2283 goto leave;
2202 } 2284 }
2203 2285
2204 status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, orphan_name); 2286 inode->i_nlink = 0;
2287 /* do the real work now. */
2288 status = __ocfs2_mknod_locked(dir, inode,
2289 0, &new_di_bh, parent_di_bh, handle,
2290 inode_ac, di_blkno, suballoc_loc,
2291 suballoc_bit);
2205 if (status < 0) { 2292 if (status < 0) {
2206 mlog_errno(status); 2293 mlog_errno(status);
2207 goto leave; 2294 goto leave;