diff options
author | Tiger Yang <tiger.yang@oracle.com> | 2008-11-13 22:15:44 -0500 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2009-01-05 11:34:19 -0500 |
commit | f5d362022a947e84b0a3dd656d09c6b2322e234f (patch) | |
tree | eb9772da46c5e2566618414eba11845ed13482dc | |
parent | fecc01126d7a244b7e9b563c80663ffdca35343b (diff) |
ocfs2: move new inode allocation out of the transaction
Move out inode allocation from ocfs2_mknod_locked() because
vfs_dq_init() must be called outside of a transaction.
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Tiger Yang <tiger.yang@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
-rw-r--r-- | fs/ocfs2/namei.c | 108 |
1 files changed, 64 insertions, 44 deletions
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 2545e7402efe..e8ff0bae179d 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -66,12 +66,12 @@ | |||
66 | 66 | ||
67 | static int ocfs2_mknod_locked(struct ocfs2_super *osb, | 67 | static int ocfs2_mknod_locked(struct ocfs2_super *osb, |
68 | struct inode *dir, | 68 | struct inode *dir, |
69 | struct dentry *dentry, int mode, | 69 | struct inode *inode, |
70 | struct dentry *dentry, | ||
70 | dev_t dev, | 71 | dev_t dev, |
71 | struct buffer_head **new_fe_bh, | 72 | struct buffer_head **new_fe_bh, |
72 | struct buffer_head *parent_fe_bh, | 73 | struct buffer_head *parent_fe_bh, |
73 | handle_t *handle, | 74 | handle_t *handle, |
74 | struct inode **ret_inode, | ||
75 | struct ocfs2_alloc_context *inode_ac); | 75 | struct ocfs2_alloc_context *inode_ac); |
76 | 76 | ||
77 | static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, | 77 | static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, |
@@ -186,6 +186,34 @@ bail: | |||
186 | return ret; | 186 | return ret; |
187 | } | 187 | } |
188 | 188 | ||
189 | static struct inode *ocfs2_get_init_inode(struct inode *dir, int mode) | ||
190 | { | ||
191 | struct inode *inode; | ||
192 | |||
193 | inode = new_inode(dir->i_sb); | ||
194 | if (!inode) { | ||
195 | mlog(ML_ERROR, "new_inode failed!\n"); | ||
196 | return NULL; | ||
197 | } | ||
198 | |||
199 | /* populate as many fields early on as possible - many of | ||
200 | * these are used by the support functions here and in | ||
201 | * callers. */ | ||
202 | if (S_ISDIR(mode)) | ||
203 | inode->i_nlink = 2; | ||
204 | else | ||
205 | inode->i_nlink = 1; | ||
206 | inode->i_uid = current_fsuid(); | ||
207 | if (dir->i_mode & S_ISGID) { | ||
208 | inode->i_gid = dir->i_gid; | ||
209 | if (S_ISDIR(mode)) | ||
210 | mode |= S_ISGID; | ||
211 | } else | ||
212 | inode->i_gid = current_fsgid(); | ||
213 | inode->i_mode = mode; | ||
214 | return inode; | ||
215 | } | ||
216 | |||
189 | static int ocfs2_mknod(struct inode *dir, | 217 | static int ocfs2_mknod(struct inode *dir, |
190 | struct dentry *dentry, | 218 | struct dentry *dentry, |
191 | int mode, | 219 | int mode, |
@@ -250,6 +278,13 @@ static int ocfs2_mknod(struct inode *dir, | |||
250 | goto leave; | 278 | goto leave; |
251 | } | 279 | } |
252 | 280 | ||
281 | inode = ocfs2_get_init_inode(dir, mode); | ||
282 | if (!inode) { | ||
283 | status = -ENOMEM; | ||
284 | mlog_errno(status); | ||
285 | goto leave; | ||
286 | } | ||
287 | |||
253 | /* Reserve a cluster if creating an extent based directory. */ | 288 | /* Reserve a cluster if creating an extent based directory. */ |
254 | if (S_ISDIR(mode) && !ocfs2_supports_inline_data(osb)) { | 289 | if (S_ISDIR(mode) && !ocfs2_supports_inline_data(osb)) { |
255 | status = ocfs2_reserve_clusters(osb, 1, &data_ac); | 290 | status = ocfs2_reserve_clusters(osb, 1, &data_ac); |
@@ -269,9 +304,9 @@ static int ocfs2_mknod(struct inode *dir, | |||
269 | } | 304 | } |
270 | 305 | ||
271 | /* do the real work now. */ | 306 | /* do the real work now. */ |
272 | status = ocfs2_mknod_locked(osb, dir, dentry, mode, dev, | 307 | status = ocfs2_mknod_locked(osb, dir, inode, dentry, dev, |
273 | &new_fe_bh, parent_fe_bh, handle, | 308 | &new_fe_bh, parent_fe_bh, handle, |
274 | &inode, inode_ac); | 309 | inode_ac); |
275 | if (status < 0) { | 310 | if (status < 0) { |
276 | mlog_errno(status); | 311 | mlog_errno(status); |
277 | goto leave; | 312 | goto leave; |
@@ -332,8 +367,10 @@ leave: | |||
332 | brelse(de_bh); | 367 | brelse(de_bh); |
333 | brelse(parent_fe_bh); | 368 | brelse(parent_fe_bh); |
334 | 369 | ||
335 | if ((status < 0) && inode) | 370 | if ((status < 0) && inode) { |
371 | clear_nlink(inode); | ||
336 | iput(inode); | 372 | iput(inode); |
373 | } | ||
337 | 374 | ||
338 | if (inode_ac) | 375 | if (inode_ac) |
339 | ocfs2_free_alloc_context(inode_ac); | 376 | ocfs2_free_alloc_context(inode_ac); |
@@ -348,12 +385,12 @@ leave: | |||
348 | 385 | ||
349 | static int ocfs2_mknod_locked(struct ocfs2_super *osb, | 386 | static int ocfs2_mknod_locked(struct ocfs2_super *osb, |
350 | struct inode *dir, | 387 | struct inode *dir, |
351 | struct dentry *dentry, int mode, | 388 | struct inode *inode, |
389 | struct dentry *dentry, | ||
352 | dev_t dev, | 390 | dev_t dev, |
353 | struct buffer_head **new_fe_bh, | 391 | struct buffer_head **new_fe_bh, |
354 | struct buffer_head *parent_fe_bh, | 392 | struct buffer_head *parent_fe_bh, |
355 | handle_t *handle, | 393 | handle_t *handle, |
356 | struct inode **ret_inode, | ||
357 | struct ocfs2_alloc_context *inode_ac) | 394 | struct ocfs2_alloc_context *inode_ac) |
358 | { | 395 | { |
359 | int status = 0; | 396 | int status = 0; |
@@ -361,14 +398,12 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, | |||
361 | struct ocfs2_extent_list *fel; | 398 | struct ocfs2_extent_list *fel; |
362 | u64 fe_blkno = 0; | 399 | u64 fe_blkno = 0; |
363 | u16 suballoc_bit; | 400 | u16 suballoc_bit; |
364 | struct inode *inode = NULL; | ||
365 | 401 | ||
366 | mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode, | 402 | mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, |
367 | (unsigned long)dev, dentry->d_name.len, | 403 | inode->i_mode, (unsigned long)dev, dentry->d_name.len, |
368 | dentry->d_name.name); | 404 | dentry->d_name.name); |
369 | 405 | ||
370 | *new_fe_bh = NULL; | 406 | *new_fe_bh = NULL; |
371 | *ret_inode = NULL; | ||
372 | 407 | ||
373 | status = ocfs2_claim_new_inode(osb, handle, inode_ac, &suballoc_bit, | 408 | status = ocfs2_claim_new_inode(osb, handle, inode_ac, &suballoc_bit, |
374 | &fe_blkno); | 409 | &fe_blkno); |
@@ -377,23 +412,11 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, | |||
377 | goto leave; | 412 | goto leave; |
378 | } | 413 | } |
379 | 414 | ||
380 | inode = new_inode(dir->i_sb); | ||
381 | if (!inode) { | ||
382 | status = -ENOMEM; | ||
383 | mlog(ML_ERROR, "new_inode failed!\n"); | ||
384 | goto leave; | ||
385 | } | ||
386 | |||
387 | /* populate as many fields early on as possible - many of | 415 | /* populate as many fields early on as possible - many of |
388 | * these are used by the support functions here and in | 416 | * these are used by the support functions here and in |
389 | * callers. */ | 417 | * callers. */ |
390 | inode->i_ino = ino_from_blkno(osb->sb, fe_blkno); | 418 | inode->i_ino = ino_from_blkno(osb->sb, fe_blkno); |
391 | OCFS2_I(inode)->ip_blkno = fe_blkno; | 419 | OCFS2_I(inode)->ip_blkno = fe_blkno; |
392 | if (S_ISDIR(mode)) | ||
393 | inode->i_nlink = 2; | ||
394 | else | ||
395 | inode->i_nlink = 1; | ||
396 | inode->i_mode = mode; | ||
397 | spin_lock(&osb->osb_lock); | 420 | spin_lock(&osb->osb_lock); |
398 | inode->i_generation = osb->s_next_generation++; | 421 | inode->i_generation = osb->s_next_generation++; |
399 | spin_unlock(&osb->osb_lock); | 422 | spin_unlock(&osb->osb_lock); |
@@ -421,17 +444,11 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, | |||
421 | fe->i_blkno = cpu_to_le64(fe_blkno); | 444 | fe->i_blkno = cpu_to_le64(fe_blkno); |
422 | fe->i_suballoc_bit = cpu_to_le16(suballoc_bit); | 445 | fe->i_suballoc_bit = cpu_to_le16(suballoc_bit); |
423 | fe->i_suballoc_slot = cpu_to_le16(inode_ac->ac_alloc_slot); | 446 | fe->i_suballoc_slot = cpu_to_le16(inode_ac->ac_alloc_slot); |
424 | fe->i_uid = cpu_to_le32(current_fsuid()); | 447 | fe->i_uid = cpu_to_le32(inode->i_uid); |
425 | if (dir->i_mode & S_ISGID) { | 448 | fe->i_gid = cpu_to_le32(inode->i_gid); |
426 | fe->i_gid = cpu_to_le32(dir->i_gid); | 449 | fe->i_mode = cpu_to_le16(inode->i_mode); |
427 | if (S_ISDIR(mode)) | 450 | if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) |
428 | mode |= S_ISGID; | ||
429 | } else | ||
430 | fe->i_gid = cpu_to_le32(current_fsgid()); | ||
431 | fe->i_mode = cpu_to_le16(mode); | ||
432 | if (S_ISCHR(mode) || S_ISBLK(mode)) | ||
433 | fe->id1.dev1.i_rdev = cpu_to_le64(huge_encode_dev(dev)); | 451 | fe->id1.dev1.i_rdev = cpu_to_le64(huge_encode_dev(dev)); |
434 | |||
435 | fe->i_links_count = cpu_to_le16(inode->i_nlink); | 452 | fe->i_links_count = cpu_to_le16(inode->i_nlink); |
436 | 453 | ||
437 | fe->i_last_eb_blk = 0; | 454 | fe->i_last_eb_blk = 0; |
@@ -446,7 +463,7 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, | |||
446 | /* | 463 | /* |
447 | * If supported, directories start with inline data. | 464 | * If supported, directories start with inline data. |
448 | */ | 465 | */ |
449 | if (S_ISDIR(mode) && ocfs2_supports_inline_data(osb)) { | 466 | if (S_ISDIR(inode->i_mode) && ocfs2_supports_inline_data(osb)) { |
450 | u16 feat = le16_to_cpu(fe->i_dyn_features); | 467 | u16 feat = le16_to_cpu(fe->i_dyn_features); |
451 | 468 | ||
452 | fe->i_dyn_features = cpu_to_le16(feat | OCFS2_INLINE_DATA_FL); | 469 | fe->i_dyn_features = cpu_to_le16(feat | OCFS2_INLINE_DATA_FL); |
@@ -484,17 +501,12 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, | |||
484 | status = 0; /* error in ocfs2_create_new_inode_locks is not | 501 | status = 0; /* error in ocfs2_create_new_inode_locks is not |
485 | * critical */ | 502 | * critical */ |
486 | 503 | ||
487 | *ret_inode = inode; | ||
488 | leave: | 504 | leave: |
489 | if (status < 0) { | 505 | if (status < 0) { |
490 | if (*new_fe_bh) { | 506 | if (*new_fe_bh) { |
491 | brelse(*new_fe_bh); | 507 | brelse(*new_fe_bh); |
492 | *new_fe_bh = NULL; | 508 | *new_fe_bh = NULL; |
493 | } | 509 | } |
494 | if (inode) { | ||
495 | clear_nlink(inode); | ||
496 | iput(inode); | ||
497 | } | ||
498 | } | 510 | } |
499 | 511 | ||
500 | mlog_exit(status); | 512 | mlog_exit(status); |
@@ -1542,6 +1554,13 @@ static int ocfs2_symlink(struct inode *dir, | |||
1542 | goto bail; | 1554 | goto bail; |
1543 | } | 1555 | } |
1544 | 1556 | ||
1557 | inode = ocfs2_get_init_inode(dir, S_IFLNK | S_IRWXUGO); | ||
1558 | if (!inode) { | ||
1559 | status = -ENOMEM; | ||
1560 | mlog_errno(status); | ||
1561 | goto bail; | ||
1562 | } | ||
1563 | |||
1545 | /* don't reserve bitmap space for fast symlinks. */ | 1564 | /* don't reserve bitmap space for fast symlinks. */ |
1546 | if (l > ocfs2_fast_symlink_chars(sb)) { | 1565 | if (l > ocfs2_fast_symlink_chars(sb)) { |
1547 | status = ocfs2_reserve_clusters(osb, 1, &data_ac); | 1566 | status = ocfs2_reserve_clusters(osb, 1, &data_ac); |
@@ -1560,10 +1579,9 @@ static int ocfs2_symlink(struct inode *dir, | |||
1560 | goto bail; | 1579 | goto bail; |
1561 | } | 1580 | } |
1562 | 1581 | ||
1563 | status = ocfs2_mknod_locked(osb, dir, dentry, | 1582 | status = ocfs2_mknod_locked(osb, dir, inode, dentry, |
1564 | S_IFLNK | S_IRWXUGO, 0, | 1583 | 0, &new_fe_bh, parent_fe_bh, handle, |
1565 | &new_fe_bh, parent_fe_bh, handle, | 1584 | inode_ac); |
1566 | &inode, inode_ac); | ||
1567 | if (status < 0) { | 1585 | if (status < 0) { |
1568 | mlog_errno(status); | 1586 | mlog_errno(status); |
1569 | goto bail; | 1587 | goto bail; |
@@ -1644,8 +1662,10 @@ bail: | |||
1644 | ocfs2_free_alloc_context(inode_ac); | 1662 | ocfs2_free_alloc_context(inode_ac); |
1645 | if (data_ac) | 1663 | if (data_ac) |
1646 | ocfs2_free_alloc_context(data_ac); | 1664 | ocfs2_free_alloc_context(data_ac); |
1647 | if ((status < 0) && inode) | 1665 | if ((status < 0) && inode) { |
1666 | clear_nlink(inode); | ||
1648 | iput(inode); | 1667 | iput(inode); |
1668 | } | ||
1649 | 1669 | ||
1650 | mlog_exit(status); | 1670 | mlog_exit(status); |
1651 | 1671 | ||