summaryrefslogtreecommitdiffstats
path: root/fs/ext4/namei.c
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2013-02-09 16:27:09 -0500
committerTheodore Ts'o <tytso@mit.edu>2013-02-09 16:27:09 -0500
commit1139575a927010390c6b38e4215a6d741b056074 (patch)
tree0fb06dbe63ed7aaa2e14ce4c03587fd9c4f87b63 /fs/ext4/namei.c
parent95eaefbdececae5e781d76d03fe7472a857c8c7a (diff)
ext4: start handle at the last possible moment when creating inodes
In ext4_{create,mknod,mkdir,symlink}(), don't start the journal handle until the inode has been succesfully allocated. In order to do this, we need to start the handle in the ext4_new_inode(). So create a new variant of this function, ext4_new_inode_start_handle(), so the handle can be created at the last possible minute, before we need to modify the inode allocation bitmap block. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/namei.c')
-rw-r--r--fs/ext4/namei.c94
1 files changed, 44 insertions, 50 deletions
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 5f3d2b569c63..3e1529c39808 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -2257,30 +2257,28 @@ static int ext4_create(struct inode *dir, struct dentry *dentry, umode_t mode,
2257{ 2257{
2258 handle_t *handle; 2258 handle_t *handle;
2259 struct inode *inode; 2259 struct inode *inode;
2260 int err, retries = 0; 2260 int err, credits, retries = 0;
2261 2261
2262 dquot_initialize(dir); 2262 dquot_initialize(dir);
2263 2263
2264 credits = (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
2265 EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
2266 EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
2264retry: 2267retry:
2265 handle = ext4_journal_start(dir, EXT4_HT_DIR, 2268 inode = ext4_new_inode_start_handle(dir, mode, &dentry->d_name, 0,
2266 (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + 2269 NULL, EXT4_HT_DIR, credits);
2267 EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 + 2270 handle = ext4_journal_current_handle();
2268 EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb)));
2269 if (IS_ERR(handle))
2270 return PTR_ERR(handle);
2271
2272 if (IS_DIRSYNC(dir))
2273 ext4_handle_sync(handle);
2274
2275 inode = ext4_new_inode(handle, dir, mode, &dentry->d_name, 0, NULL);
2276 err = PTR_ERR(inode); 2271 err = PTR_ERR(inode);
2277 if (!IS_ERR(inode)) { 2272 if (!IS_ERR(inode)) {
2278 inode->i_op = &ext4_file_inode_operations; 2273 inode->i_op = &ext4_file_inode_operations;
2279 inode->i_fop = &ext4_file_operations; 2274 inode->i_fop = &ext4_file_operations;
2280 ext4_set_aops(inode); 2275 ext4_set_aops(inode);
2281 err = ext4_add_nondir(handle, dentry, inode); 2276 err = ext4_add_nondir(handle, dentry, inode);
2277 if (!err && IS_DIRSYNC(dir))
2278 ext4_handle_sync(handle);
2282 } 2279 }
2283 ext4_journal_stop(handle); 2280 if (handle)
2281 ext4_journal_stop(handle);
2284 if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) 2282 if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
2285 goto retry; 2283 goto retry;
2286 return err; 2284 return err;
@@ -2291,32 +2289,30 @@ static int ext4_mknod(struct inode *dir, struct dentry *dentry,
2291{ 2289{
2292 handle_t *handle; 2290 handle_t *handle;
2293 struct inode *inode; 2291 struct inode *inode;
2294 int err, retries = 0; 2292 int err, credits, retries = 0;
2295 2293
2296 if (!new_valid_dev(rdev)) 2294 if (!new_valid_dev(rdev))
2297 return -EINVAL; 2295 return -EINVAL;
2298 2296
2299 dquot_initialize(dir); 2297 dquot_initialize(dir);
2300 2298
2299 credits = (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
2300 EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
2301 EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
2301retry: 2302retry:
2302 handle = ext4_journal_start(dir, EXT4_HT_DIR, 2303 inode = ext4_new_inode_start_handle(dir, mode, &dentry->d_name, 0,
2303 (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + 2304 NULL, EXT4_HT_DIR, credits);
2304 EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 + 2305 handle = ext4_journal_current_handle();
2305 EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb)));
2306 if (IS_ERR(handle))
2307 return PTR_ERR(handle);
2308
2309 if (IS_DIRSYNC(dir))
2310 ext4_handle_sync(handle);
2311
2312 inode = ext4_new_inode(handle, dir, mode, &dentry->d_name, 0, NULL);
2313 err = PTR_ERR(inode); 2306 err = PTR_ERR(inode);
2314 if (!IS_ERR(inode)) { 2307 if (!IS_ERR(inode)) {
2315 init_special_inode(inode, inode->i_mode, rdev); 2308 init_special_inode(inode, inode->i_mode, rdev);
2316 inode->i_op = &ext4_special_inode_operations; 2309 inode->i_op = &ext4_special_inode_operations;
2317 err = ext4_add_nondir(handle, dentry, inode); 2310 err = ext4_add_nondir(handle, dentry, inode);
2311 if (!err && IS_DIRSYNC(dir))
2312 ext4_handle_sync(handle);
2318 } 2313 }
2319 ext4_journal_stop(handle); 2314 if (handle)
2315 ext4_journal_stop(handle);
2320 if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) 2316 if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
2321 goto retry; 2317 goto retry;
2322 return err; 2318 return err;
@@ -2408,26 +2404,21 @@ static int ext4_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
2408{ 2404{
2409 handle_t *handle; 2405 handle_t *handle;
2410 struct inode *inode; 2406 struct inode *inode;
2411 int err, retries = 0; 2407 int err, credits, retries = 0;
2412 2408
2413 if (EXT4_DIR_LINK_MAX(dir)) 2409 if (EXT4_DIR_LINK_MAX(dir))
2414 return -EMLINK; 2410 return -EMLINK;
2415 2411
2416 dquot_initialize(dir); 2412 dquot_initialize(dir);
2417 2413
2414 credits = (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
2415 EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
2416 EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
2418retry: 2417retry:
2419 handle = ext4_journal_start(dir, EXT4_HT_DIR, 2418 inode = ext4_new_inode_start_handle(dir, S_IFDIR | mode,
2420 (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + 2419 &dentry->d_name,
2421 EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 + 2420 0, NULL, EXT4_HT_DIR, credits);
2422 EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb))); 2421 handle = ext4_journal_current_handle();
2423 if (IS_ERR(handle))
2424 return PTR_ERR(handle);
2425
2426 if (IS_DIRSYNC(dir))
2427 ext4_handle_sync(handle);
2428
2429 inode = ext4_new_inode(handle, dir, S_IFDIR | mode,
2430 &dentry->d_name, 0, NULL);
2431 err = PTR_ERR(inode); 2422 err = PTR_ERR(inode);
2432 if (IS_ERR(inode)) 2423 if (IS_ERR(inode))
2433 goto out_stop; 2424 goto out_stop;
@@ -2455,8 +2446,12 @@ out_clear_inode:
2455 goto out_clear_inode; 2446 goto out_clear_inode;
2456 unlock_new_inode(inode); 2447 unlock_new_inode(inode);
2457 d_instantiate(dentry, inode); 2448 d_instantiate(dentry, inode);
2449 if (IS_DIRSYNC(dir))
2450 ext4_handle_sync(handle);
2451
2458out_stop: 2452out_stop:
2459 ext4_journal_stop(handle); 2453 if (handle)
2454 ext4_journal_stop(handle);
2460 if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) 2455 if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
2461 goto retry; 2456 goto retry;
2462 return err; 2457 return err;
@@ -2883,15 +2878,10 @@ static int ext4_symlink(struct inode *dir,
2883 EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb); 2878 EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb);
2884 } 2879 }
2885retry: 2880retry:
2886 handle = ext4_journal_start(dir, EXT4_HT_DIR, credits); 2881 inode = ext4_new_inode_start_handle(dir, S_IFLNK|S_IRWXUGO,
2887 if (IS_ERR(handle)) 2882 &dentry->d_name, 0, NULL,
2888 return PTR_ERR(handle); 2883 EXT4_HT_DIR, credits);
2889 2884 handle = ext4_journal_current_handle();
2890 if (IS_DIRSYNC(dir))
2891 ext4_handle_sync(handle);
2892
2893 inode = ext4_new_inode(handle, dir, S_IFLNK|S_IRWXUGO,
2894 &dentry->d_name, 0, NULL);
2895 err = PTR_ERR(inode); 2885 err = PTR_ERR(inode);
2896 if (IS_ERR(inode)) 2886 if (IS_ERR(inode))
2897 goto out_stop; 2887 goto out_stop;
@@ -2944,8 +2934,12 @@ retry:
2944 } 2934 }
2945 EXT4_I(inode)->i_disksize = inode->i_size; 2935 EXT4_I(inode)->i_disksize = inode->i_size;
2946 err = ext4_add_nondir(handle, dentry, inode); 2936 err = ext4_add_nondir(handle, dentry, inode);
2937 if (!err && IS_DIRSYNC(dir))
2938 ext4_handle_sync(handle);
2939
2947out_stop: 2940out_stop:
2948 ext4_journal_stop(handle); 2941 if (handle)
2942 ext4_journal_stop(handle);
2949 if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) 2943 if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
2950 goto retry; 2944 goto retry;
2951 return err; 2945 return err;