diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2012-10-31 06:30:22 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2012-11-07 08:32:42 -0500 |
commit | c9aecf73717f55e41ac11682a50bef8594547025 (patch) | |
tree | edcf950235d2c1c35c0c5431f011ab14d09cb532 /fs | |
parent | bcd97c06308cbfa8b46e11762ea116300cdce772 (diff) |
GFS2: Use proper allocation context for new inodes
Rather than using the parent directory's allocation context, this
patch allocated the new inode earlier in the process and then uses
it to contain all the information required. As a result, we can now
use the new inode's own allocation context to allocate it rather
than having to use the parent directory's context. This give us a
lot more flexibility in where the inode is placed on disk.
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/gfs2/inode.c | 171 |
1 files changed, 92 insertions, 79 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 381893ceefa4..749b05a960ef 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -364,34 +364,34 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name, | |||
364 | return 0; | 364 | return 0; |
365 | } | 365 | } |
366 | 366 | ||
367 | static void munge_mode_uid_gid(struct gfs2_inode *dip, umode_t *mode, | 367 | static void munge_mode_uid_gid(const struct gfs2_inode *dip, |
368 | unsigned int *uid, unsigned int *gid) | 368 | struct inode *inode) |
369 | { | 369 | { |
370 | if (GFS2_SB(&dip->i_inode)->sd_args.ar_suiddir && | 370 | if (GFS2_SB(&dip->i_inode)->sd_args.ar_suiddir && |
371 | (dip->i_inode.i_mode & S_ISUID) && dip->i_inode.i_uid) { | 371 | (dip->i_inode.i_mode & S_ISUID) && dip->i_inode.i_uid) { |
372 | if (S_ISDIR(*mode)) | 372 | if (S_ISDIR(inode->i_mode)) |
373 | *mode |= S_ISUID; | 373 | inode->i_mode |= S_ISUID; |
374 | else if (dip->i_inode.i_uid != current_fsuid()) | 374 | else if (dip->i_inode.i_uid != current_fsuid()) |
375 | *mode &= ~07111; | 375 | inode->i_mode &= ~07111; |
376 | *uid = dip->i_inode.i_uid; | 376 | inode->i_uid = dip->i_inode.i_uid; |
377 | } else | 377 | } else |
378 | *uid = current_fsuid(); | 378 | inode->i_uid = current_fsuid(); |
379 | 379 | ||
380 | if (dip->i_inode.i_mode & S_ISGID) { | 380 | if (dip->i_inode.i_mode & S_ISGID) { |
381 | if (S_ISDIR(*mode)) | 381 | if (S_ISDIR(inode->i_mode)) |
382 | *mode |= S_ISGID; | 382 | inode->i_mode |= S_ISGID; |
383 | *gid = dip->i_inode.i_gid; | 383 | inode->i_gid = dip->i_inode.i_gid; |
384 | } else | 384 | } else |
385 | *gid = current_fsgid(); | 385 | inode->i_gid = current_fsgid(); |
386 | } | 386 | } |
387 | 387 | ||
388 | static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation) | 388 | static int alloc_dinode(struct gfs2_inode *ip) |
389 | { | 389 | { |
390 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | 390 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
391 | int error; | 391 | int error; |
392 | int dblocks = 1; | 392 | int dblocks = 1; |
393 | 393 | ||
394 | error = gfs2_inplace_reserve(dip, RES_DINODE); | 394 | error = gfs2_inplace_reserve(ip, RES_DINODE); |
395 | if (error) | 395 | if (error) |
396 | goto out; | 396 | goto out; |
397 | 397 | ||
@@ -399,12 +399,15 @@ static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation) | |||
399 | if (error) | 399 | if (error) |
400 | goto out_ipreserv; | 400 | goto out_ipreserv; |
401 | 401 | ||
402 | error = gfs2_alloc_blocks(dip, no_addr, &dblocks, 1, generation); | 402 | error = gfs2_alloc_blocks(ip, &ip->i_no_addr, &dblocks, 1, &ip->i_generation); |
403 | ip->i_no_formal_ino = ip->i_generation; | ||
404 | ip->i_inode.i_ino = ip->i_no_addr; | ||
405 | ip->i_goal = ip->i_no_addr; | ||
403 | 406 | ||
404 | gfs2_trans_end(sdp); | 407 | gfs2_trans_end(sdp); |
405 | 408 | ||
406 | out_ipreserv: | 409 | out_ipreserv: |
407 | gfs2_inplace_release(dip); | 410 | gfs2_inplace_release(ip); |
408 | out: | 411 | out: |
409 | return error; | 412 | return error; |
410 | } | 413 | } |
@@ -429,52 +432,42 @@ static void gfs2_init_dir(struct buffer_head *dibh, | |||
429 | /** | 432 | /** |
430 | * init_dinode - Fill in a new dinode structure | 433 | * init_dinode - Fill in a new dinode structure |
431 | * @dip: The directory this inode is being created in | 434 | * @dip: The directory this inode is being created in |
432 | * @gl: The glock covering the new inode | 435 | * @ip: The inode |
433 | * @inum: The inode number | ||
434 | * @mode: The file permissions | ||
435 | * @uid: The uid of the new inode | ||
436 | * @gid: The gid of the new inode | ||
437 | * @generation: The generation number of the new inode | ||
438 | * @dev: The device number (if a device node) | ||
439 | * @symname: The symlink destination (if a symlink) | 436 | * @symname: The symlink destination (if a symlink) |
440 | * @size: The inode size (ignored for directories) | ||
441 | * @bhp: The buffer head (returned to caller) | 437 | * @bhp: The buffer head (returned to caller) |
442 | * | 438 | * |
443 | */ | 439 | */ |
444 | 440 | ||
445 | static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, | 441 | static void init_dinode(struct gfs2_inode *dip, struct gfs2_inode *ip, |
446 | const struct gfs2_inum_host *inum, umode_t mode, | 442 | const char *symname, struct buffer_head **bhp) |
447 | unsigned int uid, unsigned int gid, | ||
448 | const u64 *generation, dev_t dev, const char *symname, | ||
449 | unsigned size, struct buffer_head **bhp) | ||
450 | { | 443 | { |
451 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | 444 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); |
452 | struct gfs2_dinode *di; | 445 | struct gfs2_dinode *di; |
453 | struct buffer_head *dibh; | 446 | struct buffer_head *dibh; |
454 | struct timespec tv = CURRENT_TIME; | 447 | struct timespec tv = CURRENT_TIME; |
455 | 448 | ||
456 | dibh = gfs2_meta_new(gl, inum->no_addr); | 449 | dibh = gfs2_meta_new(ip->i_gl, ip->i_no_addr); |
457 | gfs2_trans_add_bh(gl, dibh, 1); | 450 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
458 | gfs2_metatype_set(dibh, GFS2_METATYPE_DI, GFS2_FORMAT_DI); | 451 | gfs2_metatype_set(dibh, GFS2_METATYPE_DI, GFS2_FORMAT_DI); |
459 | gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); | 452 | gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); |
460 | di = (struct gfs2_dinode *)dibh->b_data; | 453 | di = (struct gfs2_dinode *)dibh->b_data; |
461 | 454 | ||
462 | di->di_num.no_formal_ino = cpu_to_be64(inum->no_formal_ino); | 455 | di->di_num.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino); |
463 | di->di_num.no_addr = cpu_to_be64(inum->no_addr); | 456 | di->di_num.no_addr = cpu_to_be64(ip->i_no_addr); |
464 | di->di_mode = cpu_to_be32(mode); | 457 | di->di_mode = cpu_to_be32(ip->i_inode.i_mode); |
465 | di->di_uid = cpu_to_be32(uid); | 458 | di->di_uid = cpu_to_be32(ip->i_inode.i_uid); |
466 | di->di_gid = cpu_to_be32(gid); | 459 | di->di_gid = cpu_to_be32(ip->i_inode.i_gid); |
467 | di->di_nlink = 0; | 460 | di->di_nlink = 0; |
468 | di->di_size = cpu_to_be64(size); | 461 | di->di_size = cpu_to_be64(ip->i_inode.i_size); |
469 | di->di_blocks = cpu_to_be64(1); | 462 | di->di_blocks = cpu_to_be64(1); |
470 | di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(tv.tv_sec); | 463 | di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(tv.tv_sec); |
471 | di->di_major = cpu_to_be32(MAJOR(dev)); | 464 | di->di_major = cpu_to_be32(MAJOR(ip->i_inode.i_rdev)); |
472 | di->di_minor = cpu_to_be32(MINOR(dev)); | 465 | di->di_minor = cpu_to_be32(MINOR(ip->i_inode.i_rdev)); |
473 | di->di_goal_meta = di->di_goal_data = cpu_to_be64(inum->no_addr); | 466 | di->di_goal_meta = di->di_goal_data = cpu_to_be64(ip->i_no_addr); |
474 | di->di_generation = cpu_to_be64(*generation); | 467 | di->di_generation = cpu_to_be64(ip->i_generation); |
475 | di->di_flags = 0; | 468 | di->di_flags = 0; |
476 | di->__pad1 = 0; | 469 | di->__pad1 = 0; |
477 | di->di_payload_format = cpu_to_be32(S_ISDIR(mode) ? GFS2_FORMAT_DE : 0); | 470 | di->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) ? GFS2_FORMAT_DE : 0); |
478 | di->di_height = 0; | 471 | di->di_height = 0; |
479 | di->__pad2 = 0; | 472 | di->__pad2 = 0; |
480 | di->__pad3 = 0; | 473 | di->__pad3 = 0; |
@@ -487,7 +480,7 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, | |||
487 | di->di_ctime_nsec = cpu_to_be32(tv.tv_nsec); | 480 | di->di_ctime_nsec = cpu_to_be32(tv.tv_nsec); |
488 | memset(&di->di_reserved, 0, sizeof(di->di_reserved)); | 481 | memset(&di->di_reserved, 0, sizeof(di->di_reserved)); |
489 | 482 | ||
490 | switch(mode & S_IFMT) { | 483 | switch(ip->i_inode.i_mode & S_IFMT) { |
491 | case S_IFREG: | 484 | case S_IFREG: |
492 | if ((dip->i_diskflags & GFS2_DIF_INHERIT_JDATA) || | 485 | if ((dip->i_diskflags & GFS2_DIF_INHERIT_JDATA) || |
493 | gfs2_tune_get(sdp, gt_new_files_jdata)) | 486 | gfs2_tune_get(sdp, gt_new_files_jdata)) |
@@ -502,7 +495,7 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, | |||
502 | gfs2_init_dir(dibh, dip); | 495 | gfs2_init_dir(dibh, dip); |
503 | break; | 496 | break; |
504 | case S_IFLNK: | 497 | case S_IFLNK: |
505 | memcpy(dibh->b_data + sizeof(struct gfs2_dinode), symname, size); | 498 | memcpy(dibh->b_data + sizeof(struct gfs2_dinode), symname, ip->i_inode.i_size); |
506 | break; | 499 | break; |
507 | } | 500 | } |
508 | 501 | ||
@@ -511,25 +504,22 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, | |||
511 | *bhp = dibh; | 504 | *bhp = dibh; |
512 | } | 505 | } |
513 | 506 | ||
514 | static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, | 507 | static int make_dinode(struct gfs2_inode *dip, struct gfs2_inode *ip, |
515 | umode_t mode, const struct gfs2_inum_host *inum, | 508 | const char *symname, struct buffer_head **bhp) |
516 | const u64 *generation, dev_t dev, const char *symname, | ||
517 | unsigned int size, struct buffer_head **bhp) | ||
518 | { | 509 | { |
510 | struct inode *inode = &ip->i_inode; | ||
519 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | 511 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); |
520 | unsigned int uid, gid; | ||
521 | int error; | 512 | int error; |
522 | 513 | ||
523 | munge_mode_uid_gid(dip, &mode, &uid, &gid); | ||
524 | error = gfs2_rindex_update(sdp); | 514 | error = gfs2_rindex_update(sdp); |
525 | if (error) | 515 | if (error) |
526 | return error; | 516 | return error; |
527 | 517 | ||
528 | error = gfs2_quota_lock(dip, uid, gid); | 518 | error = gfs2_quota_lock(dip, inode->i_uid, inode->i_gid); |
529 | if (error) | 519 | if (error) |
530 | return error; | 520 | return error; |
531 | 521 | ||
532 | error = gfs2_quota_check(dip, uid, gid); | 522 | error = gfs2_quota_check(dip, inode->i_uid, inode->i_gid); |
533 | if (error) | 523 | if (error) |
534 | goto out_quota; | 524 | goto out_quota; |
535 | 525 | ||
@@ -537,8 +527,8 @@ static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, | |||
537 | if (error) | 527 | if (error) |
538 | goto out_quota; | 528 | goto out_quota; |
539 | 529 | ||
540 | init_dinode(dip, gl, inum, mode, uid, gid, generation, dev, symname, size, bhp); | 530 | init_dinode(dip, ip, symname, bhp); |
541 | gfs2_quota_change(dip, +1, uid, gid); | 531 | gfs2_quota_change(dip, +1, inode->i_uid, inode->i_gid); |
542 | gfs2_trans_end(sdp); | 532 | gfs2_trans_end(sdp); |
543 | 533 | ||
544 | out_quota: | 534 | out_quota: |
@@ -657,19 +647,13 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, | |||
657 | struct inode *inode = NULL; | 647 | struct inode *inode = NULL; |
658 | struct gfs2_inode *dip = GFS2_I(dir), *ip; | 648 | struct gfs2_inode *dip = GFS2_I(dir), *ip; |
659 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | 649 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); |
660 | struct gfs2_inum_host inum = { .no_addr = 0, .no_formal_ino = 0 }; | 650 | struct gfs2_glock *io_gl; |
661 | int error; | 651 | int error; |
662 | u64 generation; | ||
663 | struct buffer_head *bh = NULL; | 652 | struct buffer_head *bh = NULL; |
664 | 653 | ||
665 | if (!name->len || name->len > GFS2_FNAMESIZE) | 654 | if (!name->len || name->len > GFS2_FNAMESIZE) |
666 | return -ENAMETOOLONG; | 655 | return -ENAMETOOLONG; |
667 | 656 | ||
668 | /* We need a reservation to allocate the new dinode block. The | ||
669 | directory ip temporarily points to the reservation, but this is | ||
670 | being done to get a set of contiguous blocks for the new dinode. | ||
671 | Since this is a create, we don't have a sizehint yet, so it will | ||
672 | have to use the minimum reservation size. */ | ||
673 | error = gfs2_rs_alloc(dip); | 657 | error = gfs2_rs_alloc(dip); |
674 | if (error) | 658 | if (error) |
675 | return error; | 659 | return error; |
@@ -688,45 +672,63 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, | |||
688 | if (error) | 672 | if (error) |
689 | goto fail_gunlock; | 673 | goto fail_gunlock; |
690 | 674 | ||
691 | error = alloc_dinode(dip, &inum.no_addr, &generation); | 675 | inode = new_inode(sdp->sd_vfs); |
676 | ip = GFS2_I(inode); | ||
677 | error = gfs2_rs_alloc(ip); | ||
692 | if (error) | 678 | if (error) |
693 | goto fail_gunlock; | 679 | goto fail_free_inode; |
694 | inum.no_formal_ino = generation; | 680 | |
681 | set_bit(GIF_INVALID, &ip->i_flags); | ||
682 | inode->i_mode = mode; | ||
683 | inode->i_rdev = dev; | ||
684 | inode->i_size = size; | ||
685 | munge_mode_uid_gid(dip, inode); | ||
686 | ip->i_goal = dip->i_goal; | ||
695 | 687 | ||
696 | error = gfs2_glock_nq_num(sdp, inum.no_addr, &gfs2_inode_glops, | 688 | error = alloc_dinode(ip); |
697 | LM_ST_EXCLUSIVE, GL_SKIP, ghs + 1); | ||
698 | if (error) | 689 | if (error) |
699 | goto fail_gunlock; | 690 | goto fail_free_inode; |
700 | 691 | ||
701 | error = make_dinode(dip, ghs[1].gh_gl, mode, &inum, &generation, dev, symname, size, &bh); | 692 | error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl); |
702 | if (error) | 693 | if (error) |
703 | goto fail_gunlock2; | 694 | goto fail_free_inode; |
704 | 695 | ||
705 | inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode), inum.no_addr, | 696 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, ghs + 1); |
706 | inum.no_formal_ino, 0); | 697 | if (error) |
707 | if (IS_ERR(inode)) | 698 | goto fail_free_inode; |
699 | |||
700 | error = make_dinode(dip, ip, symname, &bh); | ||
701 | if (error) | ||
708 | goto fail_gunlock2; | 702 | goto fail_gunlock2; |
709 | 703 | ||
710 | ip = GFS2_I(inode); | 704 | error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_iopen_glops, CREATE, &io_gl); |
711 | error = gfs2_inode_refresh(ip); | ||
712 | if (error) | 705 | if (error) |
713 | goto fail_gunlock2; | 706 | goto fail_gunlock2; |
714 | 707 | ||
715 | error = gfs2_rs_alloc(ip); | 708 | error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh); |
716 | if (error) | 709 | if (error) |
717 | goto fail_gunlock2; | 710 | goto fail_gunlock2; |
718 | 711 | ||
712 | ip->i_iopen_gh.gh_gl->gl_object = ip; | ||
713 | gfs2_glock_put(io_gl); | ||
714 | gfs2_set_iop(inode); | ||
715 | insert_inode_hash(inode); | ||
716 | |||
717 | error = gfs2_inode_refresh(ip); | ||
718 | if (error) | ||
719 | goto fail_gunlock3; | ||
720 | |||
719 | error = gfs2_acl_create(dip, inode); | 721 | error = gfs2_acl_create(dip, inode); |
720 | if (error) | 722 | if (error) |
721 | goto fail_gunlock2; | 723 | goto fail_gunlock3; |
722 | 724 | ||
723 | error = gfs2_security_init(dip, ip, name); | 725 | error = gfs2_security_init(dip, ip, name); |
724 | if (error) | 726 | if (error) |
725 | goto fail_gunlock2; | 727 | goto fail_gunlock3; |
726 | 728 | ||
727 | error = link_dinode(dip, name, ip); | 729 | error = link_dinode(dip, name, ip); |
728 | if (error) | 730 | if (error) |
729 | goto fail_gunlock2; | 731 | goto fail_gunlock3; |
730 | 732 | ||
731 | if (bh) | 733 | if (bh) |
732 | brelse(bh); | 734 | brelse(bh); |
@@ -739,8 +741,20 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, | |||
739 | d_instantiate(dentry, inode); | 741 | d_instantiate(dentry, inode); |
740 | return 0; | 742 | return 0; |
741 | 743 | ||
744 | fail_gunlock3: | ||
745 | gfs2_glock_dq_uninit(ghs + 1); | ||
746 | if (ip->i_gl) | ||
747 | gfs2_glock_put(ip->i_gl); | ||
748 | goto fail_gunlock; | ||
749 | |||
742 | fail_gunlock2: | 750 | fail_gunlock2: |
743 | gfs2_glock_dq_uninit(ghs + 1); | 751 | gfs2_glock_dq_uninit(ghs + 1); |
752 | fail_free_inode: | ||
753 | if (ip->i_gl) | ||
754 | gfs2_glock_put(ip->i_gl); | ||
755 | gfs2_rs_delete(ip); | ||
756 | free_inode_nonrcu(inode); | ||
757 | inode = NULL; | ||
744 | fail_gunlock: | 758 | fail_gunlock: |
745 | gfs2_glock_dq_uninit(ghs); | 759 | gfs2_glock_dq_uninit(ghs); |
746 | if (inode && !IS_ERR(inode)) { | 760 | if (inode && !IS_ERR(inode)) { |
@@ -748,7 +762,6 @@ fail_gunlock: | |||
748 | iput(inode); | 762 | iput(inode); |
749 | } | 763 | } |
750 | fail: | 764 | fail: |
751 | gfs2_rs_delete(dip); | ||
752 | if (bh) | 765 | if (bh) |
753 | brelse(bh); | 766 | brelse(bh); |
754 | return error; | 767 | return error; |