aboutsummaryrefslogtreecommitdiffstats
path: root/fs
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
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')
-rw-r--r--fs/ext4/ext4.h17
-rw-r--r--fs/ext4/ialloc.c15
-rw-r--r--fs/ext4/namei.c94
3 files changed, 71 insertions, 55 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 61ecf059f70c..fc1c0375c9f2 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2004,9 +2004,20 @@ extern int ext4fs_dirhash(const char *name, int len, struct
2004 dx_hash_info *hinfo); 2004 dx_hash_info *hinfo);
2005 2005
2006/* ialloc.c */ 2006/* ialloc.c */
2007extern struct inode *ext4_new_inode(handle_t *, struct inode *, umode_t, 2007extern struct inode *__ext4_new_inode(handle_t *, struct inode *, umode_t,
2008 const struct qstr *qstr, __u32 goal, 2008 const struct qstr *qstr, __u32 goal,
2009 uid_t *owner); 2009 uid_t *owner, int handle_type,
2010 unsigned int line_no, int nblocks);
2011
2012#define ext4_new_inode(handle, dir, mode, qstr, goal, owner) \
2013 __ext4_new_inode((handle), (dir), (mode), (qstr), (goal), (owner), \
2014 0, 0, 0)
2015#define ext4_new_inode_start_handle(dir, mode, qstr, goal, owner, \
2016 type, nblocks) \
2017 __ext4_new_inode(NULL, (dir), (mode), (qstr), (goal), (owner), \
2018 (type), __LINE__, (nblocks))
2019
2020
2010extern void ext4_free_inode(handle_t *, struct inode *); 2021extern void ext4_free_inode(handle_t *, struct inode *);
2011extern struct inode * ext4_orphan_get(struct super_block *, unsigned long); 2022extern struct inode * ext4_orphan_get(struct super_block *, unsigned long);
2012extern unsigned long ext4_count_free_inodes(struct super_block *); 2023extern unsigned long ext4_count_free_inodes(struct super_block *);
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 10bd6fecc9ff..91d8fe3aced3 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -634,8 +634,10 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
634 * For other inodes, search forward from the parent directory's block 634 * For other inodes, search forward from the parent directory's block
635 * group to find a free inode. 635 * group to find a free inode.
636 */ 636 */
637struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, 637struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
638 const struct qstr *qstr, __u32 goal, uid_t *owner) 638 umode_t mode, const struct qstr *qstr,
639 __u32 goal, uid_t *owner, int handle_type,
640 unsigned int line_no, int nblocks)
639{ 641{
640 struct super_block *sb; 642 struct super_block *sb;
641 struct buffer_head *inode_bitmap_bh = NULL; 643 struct buffer_head *inode_bitmap_bh = NULL;
@@ -725,6 +727,15 @@ repeat_in_this_group:
725 "inode=%lu", ino + 1); 727 "inode=%lu", ino + 1);
726 continue; 728 continue;
727 } 729 }
730 if (!handle) {
731 BUG_ON(nblocks <= 0);
732 handle = __ext4_journal_start_sb(dir->i_sb, line_no,
733 handle_type, nblocks);
734 if (IS_ERR(handle)) {
735 err = PTR_ERR(handle);
736 goto fail;
737 }
738 }
728 BUFFER_TRACE(inode_bitmap_bh, "get_write_access"); 739 BUFFER_TRACE(inode_bitmap_bh, "get_write_access");
729 err = ext4_journal_get_write_access(handle, inode_bitmap_bh); 740 err = ext4_journal_get_write_access(handle, inode_bitmap_bh);
730 if (err) 741 if (err)
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;