aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/inode.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2007-06-08 05:05:33 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2007-07-09 03:23:26 -0400
commitc8cdf479377462315d6b4f56379f8ac989b0ef29 (patch)
tree3eee98ca4af8bba92a6df096f6fd2de615a71fa5 /fs/gfs2/inode.c
parentb35997d4482ed24b43a5951c5b021d224b24293c (diff)
[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: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/inode.c')
-rw-r--r--fs/gfs2/inode.c50
1 files changed, 35 insertions, 15 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 87505f7eb745..cacdb0dfe577 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -98,22 +98,8 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, u64 no_addr, unsigned in
98 98
99 if (inode->i_state & I_NEW) { 99 if (inode->i_state & I_NEW) {
100 struct gfs2_sbd *sdp = GFS2_SB(inode); 100 struct gfs2_sbd *sdp = GFS2_SB(inode);
101 umode_t mode = DT2IF(type); 101 umode_t mode;
102 inode->i_private = ip; 102 inode->i_private = ip;
103 inode->i_mode = mode;
104
105 if (S_ISREG(mode)) {
106 inode->i_op = &gfs2_file_iops;
107 inode->i_fop = &gfs2_file_fops;
108 inode->i_mapping->a_ops = &gfs2_file_aops;
109 } else if (S_ISDIR(mode)) {
110 inode->i_op = &gfs2_dir_iops;
111 inode->i_fop = &gfs2_dir_fops;
112 } else if (S_ISLNK(mode)) {
113 inode->i_op = &gfs2_symlink_iops;
114 } else {
115 inode->i_op = &gfs2_dev_iops;
116 }
117 103
118 error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl); 104 error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
119 if (unlikely(error)) 105 if (unlikely(error))
@@ -130,10 +116,44 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, u64 no_addr, unsigned in
130 goto fail_iopen; 116 goto fail_iopen;
131 117
132 gfs2_glock_put(io_gl); 118 gfs2_glock_put(io_gl);
119
120 /*
121 * We must read the inode in order to work out its type in
122 * this case. Note that this doesn't happen often as we normally
123 * know the type beforehand. This code path only occurs during
124 * unlinked inode recovery (where it is safe to do this glock,
125 * which is not true in the general case).
126 */
127 inode->i_mode = mode = DT2IF(type);
128 if (type == DT_UNKNOWN) {
129 struct gfs2_holder gh;
130 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
131 if (unlikely(error))
132 goto fail_glock;
133 /* Inode is now uptodate */
134 mode = inode->i_mode;
135 gfs2_glock_dq_uninit(&gh);
136 }
137
138 if (S_ISREG(mode)) {
139 inode->i_op = &gfs2_file_iops;
140 inode->i_fop = &gfs2_file_fops;
141 inode->i_mapping->a_ops = &gfs2_file_aops;
142 } else if (S_ISDIR(mode)) {
143 inode->i_op = &gfs2_dir_iops;
144 inode->i_fop = &gfs2_dir_fops;
145 } else if (S_ISLNK(mode)) {
146 inode->i_op = &gfs2_symlink_iops;
147 } else {
148 inode->i_op = &gfs2_dev_iops;
149 }
150
133 unlock_new_inode(inode); 151 unlock_new_inode(inode);
134 } 152 }
135 153
136 return inode; 154 return inode;
155fail_glock:
156 gfs2_glock_dq(&ip->i_iopen_gh);
137fail_iopen: 157fail_iopen:
138 gfs2_glock_put(io_gl); 158 gfs2_glock_put(io_gl);
139fail_put: 159fail_put: