diff options
author | Bob Peterson <rpeterso@redhat.com> | 2019-08-30 12:31:00 -0500 |
---|---|---|
committer | Andreas Gruenbacher <agruenba@redhat.com> | 2019-09-04 20:22:17 +0200 |
commit | bc74aaefdd538bb2756d74518c177378e6bd589f (patch) | |
tree | 7012c74dc336c12fa40c4569013f3f9afc74bde6 /fs/gfs2/inode.c | |
parent | bccaef90738581038ee609e946f36812bd6fb1b3 (diff) | |
download | linux-bc74aaefdd538bb2756d74518c177378e6bd589f.tar.bz2 |
gfs2: separate holder for rgrps in gfs2_rename
Before this patch, gfs2_rename added a holder for the rgrp glock to
its array of holders, ghs. There's nothing wrong with that, but this
patch separates it into a separate holder. This is done to ensure
it's always locked last as per the proper glock lock ordering,
and also to pave the way for a future patch in which we will
lock the non-rgrp glocks asynchronously.
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Diffstat (limited to 'fs/gfs2/inode.c')
-rw-r--r-- | fs/gfs2/inode.c | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 2e2a8a2fb51d..50eeb15c6f4f 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -1348,7 +1348,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, struct gfs2_inode *ip = GFS2_I(d_inode(odentry)); struct gfs2_inode *nip = NULL; struct gfs2_sbd *sdp = GFS2_SB(odir); - struct gfs2_holder ghs[5], r_gh; + struct gfs2_holder ghs[4], r_gh, rd_gh; struct gfs2_rgrpd *nrgd; unsigned int num_gh; int dir_rename = 0; @@ -1357,6 +1357,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, int error; gfs2_holder_mark_uninitialized(&r_gh); + gfs2_holder_mark_uninitialized(&rd_gh); if (d_really_is_positive(ndentry)) { nip = GFS2_I(d_inode(ndentry)); if (ip == nip) @@ -1398,13 +1399,6 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, if (nip) { gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh); num_gh++; - /* grab the resource lock for unlink flag twiddling - * this is the case of the target file already existing - * so we unlink before doing the rename - */ - nrgd = gfs2_blk2rgrpd(sdp, nip->i_no_addr, 1); - if (nrgd) - gfs2_holder_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh++); } for (x = 0; x < num_gh; x++) { @@ -1413,6 +1407,22 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, goto out_gunlock; } + if (nip) { + /* Grab the resource group glock for unlink flag twiddling. + * This is the case where the target dinode already exists + * so we unlink before doing the rename. + */ + nrgd = gfs2_blk2rgrpd(sdp, nip->i_no_addr, 1); + if (!nrgd) { + error = -ENOENT; + goto out_gunlock; + } + error = gfs2_glock_nq_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0, + &rd_gh); + if (error) + goto out_gunlock; + } + error = -ENOENT; if (ip->i_inode.i_nlink == 0) goto out_gunlock; @@ -1541,6 +1551,9 @@ out_gunlock_q: gfs2_quota_unlock(ndip); out_gunlock: gfs2_dir_no_add(&da); + if (gfs2_holder_initialized(&rd_gh)) + gfs2_glock_dq_uninit(&rd_gh); + while (x--) { gfs2_glock_dq(ghs + x); gfs2_holder_uninit(ghs + x); |