aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/ops_inode.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2008-08-26 04:38:26 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2008-08-27 08:33:10 -0400
commit0188d6c5807b65e2e20dcb75a668efbe5418b27e (patch)
tree419ee0e74cded399d2e4b9adf4dacf9f9dd31a3e /fs/gfs2/ops_inode.c
parent72dbf4790fc6736f9cb54424245114acf0b0038c (diff)
GFS2: Fix & clean up GFS2 rename
This patch fixes a locking issue in the rename code by ensuring that we hold the per sb rename lock over both directory and "other" renames which involve different parent directories. At the same time, this moved the (only called from one place) function gfs2_ok_to_move into the file that its called from, so we can mark it static. This should make a code a bit easier to follow. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com> Cc: Peter Staubach <staubach@redhat.com>
Diffstat (limited to 'fs/gfs2/ops_inode.c')
-rw-r--r--fs/gfs2/ops_inode.c71
1 files changed, 60 insertions, 11 deletions
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index 35f6f032a026..534e1e2c65ca 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -589,6 +589,54 @@ static int gfs2_mknod(struct inode *dir, struct dentry *dentry, int mode,
589 return 0; 589 return 0;
590} 590}
591 591
592/*
593 * gfs2_ok_to_move - check if it's ok to move a directory to another directory
594 * @this: move this
595 * @to: to here
596 *
597 * Follow @to back to the root and make sure we don't encounter @this
598 * Assumes we already hold the rename lock.
599 *
600 * Returns: errno
601 */
602
603static int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
604{
605 struct inode *dir = &to->i_inode;
606 struct super_block *sb = dir->i_sb;
607 struct inode *tmp;
608 struct qstr dotdot;
609 int error = 0;
610
611 gfs2_str2qstr(&dotdot, "..");
612
613 igrab(dir);
614
615 for (;;) {
616 if (dir == &this->i_inode) {
617 error = -EINVAL;
618 break;
619 }
620 if (dir == sb->s_root->d_inode) {
621 error = 0;
622 break;
623 }
624
625 tmp = gfs2_lookupi(dir, &dotdot, 1);
626 if (IS_ERR(tmp)) {
627 error = PTR_ERR(tmp);
628 break;
629 }
630
631 iput(dir);
632 dir = tmp;
633 }
634
635 iput(dir);
636
637 return error;
638}
639
592/** 640/**
593 * gfs2_rename - Rename a file 641 * gfs2_rename - Rename a file
594 * @odir: Parent directory of old file name 642 * @odir: Parent directory of old file name
@@ -607,7 +655,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
607 struct gfs2_inode *ip = GFS2_I(odentry->d_inode); 655 struct gfs2_inode *ip = GFS2_I(odentry->d_inode);
608 struct gfs2_inode *nip = NULL; 656 struct gfs2_inode *nip = NULL;
609 struct gfs2_sbd *sdp = GFS2_SB(odir); 657 struct gfs2_sbd *sdp = GFS2_SB(odir);
610 struct gfs2_holder ghs[5], r_gh; 658 struct gfs2_holder ghs[5], r_gh = { .gh_gl = NULL, };
611 struct gfs2_rgrpd *nrgd; 659 struct gfs2_rgrpd *nrgd;
612 unsigned int num_gh; 660 unsigned int num_gh;
613 int dir_rename = 0; 661 int dir_rename = 0;
@@ -621,19 +669,20 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
621 return 0; 669 return 0;
622 } 670 }
623 671
624 /* Make sure we aren't trying to move a dirctory into it's subdir */
625 672
626 if (S_ISDIR(ip->i_inode.i_mode) && odip != ndip) { 673 if (odip != ndip) {
627 dir_rename = 1; 674 error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE,
628 675 0, &r_gh);
629 error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE, 0,
630 &r_gh);
631 if (error) 676 if (error)
632 goto out; 677 goto out;
633 678
634 error = gfs2_ok_to_move(ip, ndip); 679 if (S_ISDIR(ip->i_inode.i_mode)) {
635 if (error) 680 dir_rename = 1;
636 goto out_gunlock_r; 681 /* don't move a dirctory into it's subdir */
682 error = gfs2_ok_to_move(ip, ndip);
683 if (error)
684 goto out_gunlock_r;
685 }
637 } 686 }
638 687
639 num_gh = 1; 688 num_gh = 1;
@@ -829,7 +878,7 @@ out_gunlock:
829 gfs2_holder_uninit(ghs + x); 878 gfs2_holder_uninit(ghs + x);
830 } 879 }
831out_gunlock_r: 880out_gunlock_r:
832 if (dir_rename) 881 if (r_gh.gh_gl)
833 gfs2_glock_dq_uninit(&r_gh); 882 gfs2_glock_dq_uninit(&r_gh);
834out: 883out:
835 return error; 884 return error;