Commit c8cdf479 authored by Steven Whitehouse's avatar Steven Whitehouse
Browse files

[GFS2] Recovery for lost unlinked inodes



Under certain circumstances its possible (though rather unlikely) that
inodes which were unlinked by one node while still open on another might
get "lost" in the sense that they don't get deallocated if the node
which held the inode open crashed before it was unlinked.

This patch adds the recovery code which allows automatic deallocation of
the inode if its found during block allocation (the sensible time to
look for such inodes since we are scanning the rgrp's bitmaps anyway at
this time, so it adds no overhead to do this).

Since the inode will have had its i_nlink set to zero, all we need to
trigger recovery is a lookup and an iput(), and the normal deallocation
code takes care of the rest.
Signed-off-by: default avatarSteven Whitehouse <swhiteho@redhat.com>
parent b35997d4
...@@ -95,6 +95,8 @@ struct gfs2_rgrpd { ...@@ -95,6 +95,8 @@ struct gfs2_rgrpd {
u32 rd_last_alloc_data; u32 rd_last_alloc_data;
u32 rd_last_alloc_meta; u32 rd_last_alloc_meta;
struct gfs2_sbd *rd_sbd; struct gfs2_sbd *rd_sbd;
unsigned long rd_flags;
#define GFS2_RDF_CHECK 0x0001 /* Need to check for unlinked inodes */
}; };
enum gfs2_state_bits { enum gfs2_state_bits {
......
...@@ -98,22 +98,8 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, u64 no_addr, unsigned in ...@@ -98,22 +98,8 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, u64 no_addr, unsigned in
if (inode->i_state & I_NEW) { if (inode->i_state & I_NEW) {
struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_sbd *sdp = GFS2_SB(inode);
umode_t mode = DT2IF(type); umode_t mode;
inode->i_private = ip; inode->i_private = ip;
inode->i_mode = mode;
if (S_ISREG(mode)) {
inode->i_op = &gfs2_file_iops;
inode->i_fop = &gfs2_file_fops;
inode->i_mapping->a_ops = &gfs2_file_aops;
} else if (S_ISDIR(mode)) {
inode->i_op = &gfs2_dir_iops;
inode->i_fop = &gfs2_dir_fops;
} else if (S_ISLNK(mode)) {
inode->i_op = &gfs2_symlink_iops;
} else {
inode->i_op = &gfs2_dev_iops;
}
error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl); error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
if (unlikely(error)) if (unlikely(error))
...@@ -130,10 +116,44 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, u64 no_addr, unsigned in ...@@ -130,10 +116,44 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, u64 no_addr, unsigned in
goto fail_iopen; goto fail_iopen;
gfs2_glock_put(io_gl); gfs2_glock_put(io_gl);
/*
* We must read the inode in order to work out its type in
* this case. Note that this doesn't happen often as we normally
* know the type beforehand. This code path only occurs during
* unlinked inode recovery (where it is safe to do this glock,
* which is not true in the general case).
*/
inode->i_mode = mode = DT2IF(type);
if (type == DT_UNKNOWN) {
struct gfs2_holder gh;
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
if (unlikely(error))
goto fail_glock;
/* Inode is now uptodate */
mode = inode->i_mode;
gfs2_glock_dq_uninit(&gh);
}
if (S_ISREG(mode)) {
inode->i_op = &gfs2_file_iops;
inode->i_fop = &gfs2_file_fops;
inode->i_mapping->a_ops = &gfs2_file_aops;
} else if (S_ISDIR(mode)) {
inode->i_op = &gfs2_dir_iops;
inode->i_fop = &gfs2_dir_fops;
} else if (S_ISLNK(mode)) {
inode->i_op = &gfs2_symlink_iops;
} else {
inode->i_op = &gfs2_dev_iops;
}
unlock_new_inode(inode); unlock_new_inode(inode);
} }
return inode; return inode;
fail_glock:
gfs2_glock_dq(&ip->i_iopen_gh);
fail_iopen: fail_iopen:
gfs2_glock_put(io_gl); gfs2_glock_put(io_gl);
fail_put: fail_put:
......
No preview for this file type
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment