diff options
Diffstat (limited to 'fs/gfs2/ops_super.c')
-rw-r--r-- | fs/gfs2/ops_super.c | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index b89999d3a767..485ce3d49923 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c | |||
@@ -284,6 +284,31 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data) | |||
284 | } | 284 | } |
285 | 285 | ||
286 | /** | 286 | /** |
287 | * gfs2_drop_inode - Drop an inode (test for remote unlink) | ||
288 | * @inode: The inode to drop | ||
289 | * | ||
290 | * If we've received a callback on an iopen lock then its because a | ||
291 | * remote node tried to deallocate the inode but failed due to this node | ||
292 | * still having the inode open. Here we mark the link count zero | ||
293 | * since we know that it must have reached zero if the GLF_DEMOTE flag | ||
294 | * is set on the iopen glock. If we didn't do a disk read since the | ||
295 | * remote node removed the final link then we might otherwise miss | ||
296 | * this event. This check ensures that this node will deallocate the | ||
297 | * inode's blocks, or alternatively pass the baton on to another | ||
298 | * node for later deallocation. | ||
299 | */ | ||
300 | static void gfs2_drop_inode(struct inode *inode) | ||
301 | { | ||
302 | if (inode->i_private && inode->i_nlink) { | ||
303 | struct gfs2_inode *ip = GFS2_I(inode); | ||
304 | struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl; | ||
305 | if (gl && test_bit(GLF_DEMOTE, &gl->gl_flags)) | ||
306 | clear_nlink(inode); | ||
307 | } | ||
308 | generic_drop_inode(inode); | ||
309 | } | ||
310 | |||
311 | /** | ||
287 | * gfs2_clear_inode - Deallocate an inode when VFS is done with it | 312 | * gfs2_clear_inode - Deallocate an inode when VFS is done with it |
288 | * @inode: The VFS inode | 313 | * @inode: The VFS inode |
289 | * | 314 | * |
@@ -441,7 +466,7 @@ out_unlock: | |||
441 | out_uninit: | 466 | out_uninit: |
442 | gfs2_holder_uninit(&ip->i_iopen_gh); | 467 | gfs2_holder_uninit(&ip->i_iopen_gh); |
443 | gfs2_glock_dq_uninit(&gh); | 468 | gfs2_glock_dq_uninit(&gh); |
444 | if (error) | 469 | if (error && error != GLR_TRYFAILED) |
445 | fs_warn(sdp, "gfs2_delete_inode: %d\n", error); | 470 | fs_warn(sdp, "gfs2_delete_inode: %d\n", error); |
446 | out: | 471 | out: |
447 | truncate_inode_pages(&inode->i_data, 0); | 472 | truncate_inode_pages(&inode->i_data, 0); |
@@ -481,6 +506,7 @@ const struct super_operations gfs2_super_ops = { | |||
481 | .statfs = gfs2_statfs, | 506 | .statfs = gfs2_statfs, |
482 | .remount_fs = gfs2_remount_fs, | 507 | .remount_fs = gfs2_remount_fs, |
483 | .clear_inode = gfs2_clear_inode, | 508 | .clear_inode = gfs2_clear_inode, |
509 | .drop_inode = gfs2_drop_inode, | ||
484 | .show_options = gfs2_show_options, | 510 | .show_options = gfs2_show_options, |
485 | }; | 511 | }; |
486 | 512 | ||