aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/gfs2/inode.c50
-rw-r--r--fs/gfs2/inode.h2
-rw-r--r--fs/gfs2/ops_inode.c25
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 */
290int gfs2_change_nlink_i(struct gfs2_inode *ip, int diff) 290int 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
326int gfs2_change_nlink(struct gfs2_inode *ip, int diff) 329int 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
354out_norgrp: 366out_norgrp:
367 if (!existing)
355 gfs2_glock_dq_uninit(&ri_gh); 368 gfs2_glock_dq_uninit(&ri_gh);
356 }
357out: 369out:
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
41int gfs2_dinode_dealloc(struct gfs2_inode *inode); 41int gfs2_dinode_dealloc(struct gfs2_inode *inode);
42int gfs2_change_nlink(struct gfs2_inode *ip, int diff); 42int gfs2_change_nlink(struct gfs2_inode *ip, int diff);
43int gfs2_change_nlink_i(struct gfs2_inode *ip, int diff); 43int gfs2_change_nlink_i(struct gfs2_inode *ip);
44struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, 44struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
45 int is_root, struct nameidata *nd); 45 int is_root, struct nameidata *nd);
46struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, 46struct 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;