aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2/inode.c')
-rw-r--r--fs/gfs2/inode.c50
1 files changed, 31 insertions, 19 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}