diff options
Diffstat (limited to 'fs/gfs2/ops_inode.c')
-rw-r--r-- | fs/gfs2/ops_inode.c | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index 5591f8905cf7..f40a84807d75 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c | |||
@@ -264,13 +264,23 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry) | |||
264 | struct gfs2_inode *dip = GFS2_I(dir); | 264 | struct gfs2_inode *dip = GFS2_I(dir); |
265 | struct gfs2_sbd *sdp = GFS2_SB(dir); | 265 | struct gfs2_sbd *sdp = GFS2_SB(dir); |
266 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); | 266 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); |
267 | struct gfs2_holder ghs[2]; | 267 | struct gfs2_holder ghs[3]; |
268 | struct gfs2_rgrpd *rgd; | ||
269 | struct gfs2_holder ri_gh; | ||
268 | int error; | 270 | int error; |
269 | 271 | ||
272 | error = gfs2_rindex_hold(sdp, &ri_gh); | ||
273 | if (error) | ||
274 | return error; | ||
275 | |||
270 | gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); | 276 | gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); |
271 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); | 277 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); |
272 | 278 | ||
273 | error = gfs2_glock_nq_m(2, ghs); | 279 | rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr); |
280 | gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2); | ||
281 | |||
282 | |||
283 | error = gfs2_glock_nq_m(3, ghs); | ||
274 | if (error) | 284 | if (error) |
275 | goto out; | 285 | goto out; |
276 | 286 | ||
@@ -291,10 +301,12 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry) | |||
291 | out_end_trans: | 301 | out_end_trans: |
292 | gfs2_trans_end(sdp); | 302 | gfs2_trans_end(sdp); |
293 | out_gunlock: | 303 | out_gunlock: |
294 | gfs2_glock_dq_m(2, ghs); | 304 | gfs2_glock_dq_m(3, ghs); |
295 | out: | 305 | out: |
296 | gfs2_holder_uninit(ghs); | 306 | gfs2_holder_uninit(ghs); |
297 | gfs2_holder_uninit(ghs + 1); | 307 | gfs2_holder_uninit(ghs + 1); |
308 | gfs2_holder_uninit(ghs + 2); | ||
309 | gfs2_glock_dq_uninit(&ri_gh); | ||
298 | return error; | 310 | return error; |
299 | } | 311 | } |
300 | 312 | ||
@@ -449,13 +461,22 @@ static int gfs2_rmdir(struct inode *dir, struct dentry *dentry) | |||
449 | struct gfs2_inode *dip = GFS2_I(dir); | 461 | struct gfs2_inode *dip = GFS2_I(dir); |
450 | struct gfs2_sbd *sdp = GFS2_SB(dir); | 462 | struct gfs2_sbd *sdp = GFS2_SB(dir); |
451 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); | 463 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); |
452 | struct gfs2_holder ghs[2]; | 464 | struct gfs2_holder ghs[3]; |
465 | struct gfs2_rgrpd *rgd; | ||
466 | struct gfs2_holder ri_gh; | ||
453 | int error; | 467 | int error; |
454 | 468 | ||
469 | |||
470 | error = gfs2_rindex_hold(sdp, &ri_gh); | ||
471 | if (error) | ||
472 | return error; | ||
455 | gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); | 473 | gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); |
456 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); | 474 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); |
457 | 475 | ||
458 | error = gfs2_glock_nq_m(2, ghs); | 476 | rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr); |
477 | gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2); | ||
478 | |||
479 | error = gfs2_glock_nq_m(3, ghs); | ||
459 | if (error) | 480 | if (error) |
460 | goto out; | 481 | goto out; |
461 | 482 | ||
@@ -483,10 +504,12 @@ static int gfs2_rmdir(struct inode *dir, struct dentry *dentry) | |||
483 | gfs2_trans_end(sdp); | 504 | gfs2_trans_end(sdp); |
484 | 505 | ||
485 | out_gunlock: | 506 | out_gunlock: |
486 | gfs2_glock_dq_m(2, ghs); | 507 | gfs2_glock_dq_m(3, ghs); |
487 | out: | 508 | out: |
488 | gfs2_holder_uninit(ghs); | 509 | gfs2_holder_uninit(ghs); |
489 | gfs2_holder_uninit(ghs + 1); | 510 | gfs2_holder_uninit(ghs + 1); |
511 | gfs2_holder_uninit(ghs + 2); | ||
512 | gfs2_glock_dq_uninit(&ri_gh); | ||
490 | return error; | 513 | return error; |
491 | } | 514 | } |
492 | 515 | ||
@@ -547,7 +570,8 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
547 | struct gfs2_inode *ip = GFS2_I(odentry->d_inode); | 570 | struct gfs2_inode *ip = GFS2_I(odentry->d_inode); |
548 | struct gfs2_inode *nip = NULL; | 571 | struct gfs2_inode *nip = NULL; |
549 | struct gfs2_sbd *sdp = GFS2_SB(odir); | 572 | struct gfs2_sbd *sdp = GFS2_SB(odir); |
550 | struct gfs2_holder ghs[4], r_gh; | 573 | struct gfs2_holder ghs[5], r_gh; |
574 | struct gfs2_rgrpd *nrgd; | ||
551 | unsigned int num_gh; | 575 | unsigned int num_gh; |
552 | int dir_rename = 0; | 576 | int dir_rename = 0; |
553 | int alloc_required; | 577 | int alloc_required; |
@@ -587,6 +611,13 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
587 | if (nip) { | 611 | if (nip) { |
588 | gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh); | 612 | gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh); |
589 | num_gh++; | 613 | num_gh++; |
614 | /* grab the resource lock for unlink flag twiddling | ||
615 | * this is the case of the target file already existing | ||
616 | * so we unlink before doing the rename | ||
617 | */ | ||
618 | nrgd = gfs2_blk2rgrpd(sdp, nip->i_num.no_addr); | ||
619 | if (nrgd) | ||
620 | gfs2_holder_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh++); | ||
590 | } | 621 | } |
591 | 622 | ||
592 | error = gfs2_glock_nq_m(num_gh, ghs); | 623 | error = gfs2_glock_nq_m(num_gh, ghs); |