diff options
-rw-r--r-- | fs/gfs2/inode.c | 50 | ||||
-rw-r--r-- | fs/gfs2/inode.h | 2 | ||||
-rw-r--r-- | fs/gfs2/ops_inode.c | 25 |
3 files changed, 35 insertions, 42 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index bab338f6b610..58c2ce785fed 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -281,13 +281,13 @@ out: | |||
281 | } | 281 | } |
282 | 282 | ||
283 | /** | 283 | /** |
284 | * gfs2_change_nlink_i - Change nlink count on inode | 284 | * gfs2_change_nlink - Change nlink count on inode |
285 | * @ip: The GFS2 inode | 285 | * @ip: The GFS2 inode |
286 | * @diff: The change in the nlink count required | 286 | * @diff: The change in the nlink count required |
287 | * | 287 | * |
288 | * Returns: errno | 288 | * Returns: errno |
289 | */ | 289 | */ |
290 | int gfs2_change_nlink_i(struct gfs2_inode *ip, int diff) | 290 | int gfs2_change_nlink(struct gfs2_inode *ip, int diff) |
291 | { | 291 | { |
292 | struct buffer_head *dibh; | 292 | struct buffer_head *dibh; |
293 | u32 nlink; | 293 | u32 nlink; |
@@ -320,40 +320,52 @@ int gfs2_change_nlink_i(struct gfs2_inode *ip, int diff) | |||
320 | brelse(dibh); | 320 | brelse(dibh); |
321 | mark_inode_dirty(&ip->i_inode); | 321 | mark_inode_dirty(&ip->i_inode); |
322 | 322 | ||
323 | if (ip->i_inode.i_nlink == 0) | ||
324 | error = gfs2_change_nlink_i(ip); | ||
325 | |||
323 | return error; | 326 | return error; |
324 | } | 327 | } |
325 | 328 | ||
326 | int gfs2_change_nlink(struct gfs2_inode *ip, int diff) | 329 | int gfs2_change_nlink_i(struct gfs2_inode *ip) |
327 | { | 330 | { |
328 | struct gfs2_sbd *sdp = ip->i_inode.i_sb->s_fs_info; | 331 | struct gfs2_sbd *sdp = ip->i_inode.i_sb->s_fs_info; |
329 | int error; | 332 | struct gfs2_inode *rindex = GFS2_I(sdp->sd_rindex); |
330 | 333 | struct gfs2_glock *ri_gl = rindex->i_gl; | |
331 | /* update the nlink */ | 334 | struct gfs2_rgrpd *rgd; |
332 | error = gfs2_change_nlink_i(ip, diff); | 335 | struct gfs2_holder ri_gh, rg_gh; |
333 | if (error) | 336 | int existing, error; |
334 | return error; | ||
335 | |||
336 | /* return meta data block back to rg */ | ||
337 | if (ip->i_inode.i_nlink == 0) { | ||
338 | struct gfs2_rgrpd *rgd; | ||
339 | struct gfs2_holder ri_gh, rg_gh; | ||
340 | 337 | ||
338 | /* if we come from rename path, we could have the lock already */ | ||
339 | existing = gfs2_glock_is_locked_by_me(ri_gl); | ||
340 | if (!existing) { | ||
341 | error = gfs2_rindex_hold(sdp, &ri_gh); | 341 | error = gfs2_rindex_hold(sdp, &ri_gh); |
342 | if (error) | 342 | if (error) |
343 | goto out; | 343 | goto out; |
344 | error = -EIO; | 344 | } |
345 | rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr); | 345 | |
346 | if (!rgd) | 346 | /* find the matching rgd */ |
347 | goto out_norgrp; | 347 | error = -EIO; |
348 | rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr); | ||
349 | if (!rgd) | ||
350 | goto out_norgrp; | ||
351 | |||
352 | /* | ||
353 | * Eventually we may want to move rgd(s) to a linked list | ||
354 | * and piggyback the free logic into one of gfs2 daemons | ||
355 | * to gain some performance. | ||
356 | */ | ||
357 | if (!rgd->rd_gl || !gfs2_glock_is_locked_by_me(rgd->rd_gl)) { | ||
348 | error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, &rg_gh); | 358 | error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, &rg_gh); |
349 | if (error) | 359 | if (error) |
350 | goto out_norgrp; | 360 | goto out_norgrp; |
351 | 361 | ||
352 | gfs2_unlink_di(&ip->i_inode); /* mark inode unlinked */ | 362 | gfs2_unlink_di(&ip->i_inode); /* mark inode unlinked */ |
353 | gfs2_glock_dq_uninit(&rg_gh); | 363 | gfs2_glock_dq_uninit(&rg_gh); |
364 | } | ||
365 | |||
354 | out_norgrp: | 366 | out_norgrp: |
367 | if (!existing) | ||
355 | gfs2_glock_dq_uninit(&ri_gh); | 368 | gfs2_glock_dq_uninit(&ri_gh); |
356 | } | ||
357 | out: | 369 | out: |
358 | return error; | 370 | return error; |
359 | } | 371 | } |
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index 85c67cb568d1..cee281b5326b 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h | |||
@@ -40,7 +40,7 @@ int gfs2_inode_refresh(struct gfs2_inode *ip); | |||
40 | 40 | ||
41 | int gfs2_dinode_dealloc(struct gfs2_inode *inode); | 41 | int gfs2_dinode_dealloc(struct gfs2_inode *inode); |
42 | int gfs2_change_nlink(struct gfs2_inode *ip, int diff); | 42 | int gfs2_change_nlink(struct gfs2_inode *ip, int diff); |
43 | int gfs2_change_nlink_i(struct gfs2_inode *ip, int diff); | 43 | int gfs2_change_nlink_i(struct gfs2_inode *ip); |
44 | struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, | 44 | struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, |
45 | int is_root, struct nameidata *nd); | 45 | int is_root, struct nameidata *nd); |
46 | struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, | 46 | struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, |
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index 919e8947e710..b2a12f44f59d 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c | |||
@@ -553,7 +553,6 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
553 | int alloc_required; | 553 | int alloc_required; |
554 | unsigned int x; | 554 | unsigned int x; |
555 | int error; | 555 | int error; |
556 | struct gfs2_rgrpd *rgd; | ||
557 | 556 | ||
558 | if (ndentry->d_inode) { | 557 | if (ndentry->d_inode) { |
559 | nip = GFS2_I(ndentry->d_inode); | 558 | nip = GFS2_I(ndentry->d_inode); |
@@ -685,12 +684,12 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
685 | error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + | 684 | error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + |
686 | al->al_rgd->rd_ri.ri_length + | 685 | al->al_rgd->rd_ri.ri_length + |
687 | 4 * RES_DINODE + 4 * RES_LEAF + | 686 | 4 * RES_DINODE + 4 * RES_LEAF + |
688 | RES_STATFS + RES_QUOTA + 1, 0); | 687 | RES_STATFS + RES_QUOTA + 4, 0); |
689 | if (error) | 688 | if (error) |
690 | goto out_ipreserv; | 689 | goto out_ipreserv; |
691 | } else { | 690 | } else { |
692 | error = gfs2_trans_begin(sdp, 4 * RES_DINODE + | 691 | error = gfs2_trans_begin(sdp, 4 * RES_DINODE + |
693 | 5 * RES_LEAF + 1, 0); | 692 | 5 * RES_LEAF + 4, 0); |
694 | if (error) | 693 | if (error) |
695 | goto out_gunlock; | 694 | goto out_gunlock; |
696 | } | 695 | } |
@@ -704,25 +703,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
704 | error = gfs2_dir_del(ndip, &ndentry->d_name); | 703 | error = gfs2_dir_del(ndip, &ndentry->d_name); |
705 | if (error) | 704 | if (error) |
706 | goto out_end_trans; | 705 | goto out_end_trans; |
707 | error = gfs2_change_nlink_i(nip, -1); | 706 | error = gfs2_change_nlink(nip, -1); |
708 | if ((!error) && (nip->i_inode.i_nlink == 0)) { | ||
709 | error = -EIO; | ||
710 | rgd = gfs2_blk2rgrpd(sdp, nip->i_num.no_addr); | ||
711 | if (rgd) { | ||
712 | struct gfs2_holder nlink_rg_gh; | ||
713 | if (rgd != nip->i_alloc.al_rgd) | ||
714 | error = gfs2_glock_nq_init( | ||
715 | rgd->rd_gl, LM_ST_EXCLUSIVE, | ||
716 | 0, &nlink_rg_gh); | ||
717 | else | ||
718 | error = 0; | ||
719 | if (!error) { | ||
720 | gfs2_unlink_di(&nip->i_inode); | ||
721 | if (rgd != nip->i_alloc.al_rgd) | ||
722 | gfs2_glock_dq_uninit(&nlink_rg_gh); | ||
723 | } | ||
724 | } | ||
725 | } | ||
726 | } | 707 | } |
727 | if (error) | 708 | if (error) |
728 | goto out_end_trans; | 709 | goto out_end_trans; |