diff options
author | Bob Peterson <rpeterso@redhat.com> | 2010-04-14 11:58:16 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2010-04-14 11:48:05 -0400 |
commit | 1a0eae8848cde6e0734360f6456496c995ee1e23 (patch) | |
tree | 536f944468ef5bc6f47ec09325422adbc5a3907a /fs/gfs2/inode.c | |
parent | 602c89d2e3e8652f94a697c9a919be739b9bcdd5 (diff) |
GFS2: glock livelock
This patch fixes a couple gfs2 problems with the reclaiming of
unlinked dinodes. First, there were a couple of livelocks where
everything would come to a halt waiting for a glock that was
seemingly held by a process that no longer existed. In fact, the
process did exist, it just had the wrong pid number in the holder
information. Second, there was a lock ordering problem between
inode locking and glock locking. Third, glock/inode contention
could sometimes cause inodes to be improperly marked invalid by
iget_failed.
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
Diffstat (limited to 'fs/gfs2/inode.c')
-rw-r--r-- | fs/gfs2/inode.c | 101 |
1 files changed, 92 insertions, 9 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index b1bf2694fb2b..51d8061fa07a 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -158,7 +158,6 @@ void gfs2_set_iop(struct inode *inode) | |||
158 | * @sb: The super block | 158 | * @sb: The super block |
159 | * @no_addr: The inode number | 159 | * @no_addr: The inode number |
160 | * @type: The type of the inode | 160 | * @type: The type of the inode |
161 | * @skip_freeing: set this not return an inode if it is currently being freed. | ||
162 | * | 161 | * |
163 | * Returns: A VFS inode, or an error | 162 | * Returns: A VFS inode, or an error |
164 | */ | 163 | */ |
@@ -166,17 +165,14 @@ void gfs2_set_iop(struct inode *inode) | |||
166 | struct inode *gfs2_inode_lookup(struct super_block *sb, | 165 | struct inode *gfs2_inode_lookup(struct super_block *sb, |
167 | unsigned int type, | 166 | unsigned int type, |
168 | u64 no_addr, | 167 | u64 no_addr, |
169 | u64 no_formal_ino, int skip_freeing) | 168 | u64 no_formal_ino) |
170 | { | 169 | { |
171 | struct inode *inode; | 170 | struct inode *inode; |
172 | struct gfs2_inode *ip; | 171 | struct gfs2_inode *ip; |
173 | struct gfs2_glock *io_gl; | 172 | struct gfs2_glock *io_gl; |
174 | int error; | 173 | int error; |
175 | 174 | ||
176 | if (skip_freeing) | 175 | inode = gfs2_iget(sb, no_addr); |
177 | inode = gfs2_iget_skip(sb, no_addr); | ||
178 | else | ||
179 | inode = gfs2_iget(sb, no_addr); | ||
180 | ip = GFS2_I(inode); | 176 | ip = GFS2_I(inode); |
181 | 177 | ||
182 | if (!inode) | 178 | if (!inode) |
@@ -234,13 +230,100 @@ fail_glock: | |||
234 | fail_iopen: | 230 | fail_iopen: |
235 | gfs2_glock_put(io_gl); | 231 | gfs2_glock_put(io_gl); |
236 | fail_put: | 232 | fail_put: |
237 | ip->i_gl->gl_object = NULL; | 233 | if (inode->i_state & I_NEW) |
234 | ip->i_gl->gl_object = NULL; | ||
238 | gfs2_glock_put(ip->i_gl); | 235 | gfs2_glock_put(ip->i_gl); |
239 | fail: | 236 | fail: |
240 | iget_failed(inode); | 237 | if (inode->i_state & I_NEW) |
238 | iget_failed(inode); | ||
239 | else | ||
240 | iput(inode); | ||
241 | return ERR_PTR(error); | 241 | return ERR_PTR(error); |
242 | } | 242 | } |
243 | 243 | ||
244 | /** | ||
245 | * gfs2_unlinked_inode_lookup - Lookup an unlinked inode for reclamation | ||
246 | * @sb: The super block | ||
247 | * no_addr: The inode number | ||
248 | * @@inode: A pointer to the inode found, if any | ||
249 | * | ||
250 | * Returns: 0 and *inode if no errors occurred. If an error occurs, | ||
251 | * the resulting *inode may or may not be NULL. | ||
252 | */ | ||
253 | |||
254 | int gfs2_unlinked_inode_lookup(struct super_block *sb, u64 no_addr, | ||
255 | struct inode **inode) | ||
256 | { | ||
257 | struct gfs2_sbd *sdp; | ||
258 | struct gfs2_inode *ip; | ||
259 | struct gfs2_glock *io_gl; | ||
260 | int error; | ||
261 | struct gfs2_holder gh; | ||
262 | |||
263 | *inode = gfs2_iget_skip(sb, no_addr); | ||
264 | |||
265 | if (!(*inode)) | ||
266 | return -ENOBUFS; | ||
267 | |||
268 | if (!((*inode)->i_state & I_NEW)) | ||
269 | return -ENOBUFS; | ||
270 | |||
271 | ip = GFS2_I(*inode); | ||
272 | sdp = GFS2_SB(*inode); | ||
273 | ip->i_no_formal_ino = -1; | ||
274 | |||
275 | error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl); | ||
276 | if (unlikely(error)) | ||
277 | goto fail; | ||
278 | ip->i_gl->gl_object = ip; | ||
279 | |||
280 | error = gfs2_glock_get(sdp, no_addr, &gfs2_iopen_glops, CREATE, &io_gl); | ||
281 | if (unlikely(error)) | ||
282 | goto fail_put; | ||
283 | |||
284 | set_bit(GIF_INVALID, &ip->i_flags); | ||
285 | error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, LM_FLAG_TRY | GL_EXACT, | ||
286 | &ip->i_iopen_gh); | ||
287 | if (unlikely(error)) { | ||
288 | if (error == GLR_TRYFAILED) | ||
289 | error = 0; | ||
290 | goto fail_iopen; | ||
291 | } | ||
292 | ip->i_iopen_gh.gh_gl->gl_object = ip; | ||
293 | gfs2_glock_put(io_gl); | ||
294 | |||
295 | (*inode)->i_mode = DT2IF(DT_UNKNOWN); | ||
296 | |||
297 | /* | ||
298 | * We must read the inode in order to work out its type in | ||
299 | * this case. Note that this doesn't happen often as we normally | ||
300 | * know the type beforehand. This code path only occurs during | ||
301 | * unlinked inode recovery (where it is safe to do this glock, | ||
302 | * which is not true in the general case). | ||
303 | */ | ||
304 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY, | ||
305 | &gh); | ||
306 | if (unlikely(error)) { | ||
307 | if (error == GLR_TRYFAILED) | ||
308 | error = 0; | ||
309 | goto fail_glock; | ||
310 | } | ||
311 | /* Inode is now uptodate */ | ||
312 | gfs2_glock_dq_uninit(&gh); | ||
313 | gfs2_set_iop(*inode); | ||
314 | |||
315 | return 0; | ||
316 | fail_glock: | ||
317 | gfs2_glock_dq(&ip->i_iopen_gh); | ||
318 | fail_iopen: | ||
319 | gfs2_glock_put(io_gl); | ||
320 | fail_put: | ||
321 | ip->i_gl->gl_object = NULL; | ||
322 | gfs2_glock_put(ip->i_gl); | ||
323 | fail: | ||
324 | return error; | ||
325 | } | ||
326 | |||
244 | static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) | 327 | static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) |
245 | { | 328 | { |
246 | const struct gfs2_dinode *str = buf; | 329 | const struct gfs2_dinode *str = buf; |
@@ -862,7 +945,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, | |||
862 | goto fail_gunlock2; | 945 | goto fail_gunlock2; |
863 | 946 | ||
864 | inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode), inum.no_addr, | 947 | inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode), inum.no_addr, |
865 | inum.no_formal_ino, 0); | 948 | inum.no_formal_ino); |
866 | if (IS_ERR(inode)) | 949 | if (IS_ERR(inode)) |
867 | goto fail_gunlock2; | 950 | goto fail_gunlock2; |
868 | 951 | ||