Skip to content

Commit ed4878e

Browse files
AstralBobswhiteho
authored andcommitted
GFS2: Rework reclaiming unlinked dinodes
The previous patch I wrote for reclaiming unlinked dinodes had some shortcomings and did not prevent all hangs. This version is much cleaner and more logical, and has passed very difficult testing. Sorry for the churn. Signed-off-by: Bob Peterson <[email protected]> Signed-off-by: Steven Whitehouse <[email protected]>
1 parent d7dbf4f commit ed4878e

File tree

5 files changed

+54
-54
lines changed

5 files changed

+54
-54
lines changed

fs/gfs2/inode.c

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -242,34 +242,38 @@ struct inode *gfs2_inode_lookup(struct super_block *sb,
242242
}
243243

244244
/**
245-
* gfs2_unlinked_inode_lookup - Lookup an unlinked inode for reclamation
245+
* gfs2_process_unlinked_inode - Lookup an unlinked inode for reclamation
246+
* and try to reclaim it by doing iput.
247+
*
248+
* This function assumes no rgrp locks are currently held.
249+
*
246250
* @sb: The super block
247251
* no_addr: The inode number
248-
* @@inode: A pointer to the inode found, if any
249252
*
250-
* Returns: 0 and *inode if no errors occurred. If an error occurs,
251-
* the resulting *inode may or may not be NULL.
252253
*/
253254

254-
int gfs2_unlinked_inode_lookup(struct super_block *sb, u64 no_addr,
255-
struct inode **inode)
255+
void gfs2_process_unlinked_inode(struct super_block *sb, u64 no_addr)
256256
{
257257
struct gfs2_sbd *sdp;
258258
struct gfs2_inode *ip;
259259
struct gfs2_glock *io_gl;
260260
int error;
261261
struct gfs2_holder gh;
262+
struct inode *inode;
262263

263-
*inode = gfs2_iget_skip(sb, no_addr);
264+
inode = gfs2_iget_skip(sb, no_addr);
264265

265-
if (!(*inode))
266-
return -ENOBUFS;
266+
if (!inode)
267+
return;
267268

268-
if (!((*inode)->i_state & I_NEW))
269-
return -ENOBUFS;
269+
/* If it's not a new inode, someone's using it, so leave it alone. */
270+
if (!(inode->i_state & I_NEW)) {
271+
iput(inode);
272+
return;
273+
}
270274

271-
ip = GFS2_I(*inode);
272-
sdp = GFS2_SB(*inode);
275+
ip = GFS2_I(inode);
276+
sdp = GFS2_SB(inode);
273277
ip->i_no_formal_ino = -1;
274278

275279
error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
@@ -284,15 +288,13 @@ int gfs2_unlinked_inode_lookup(struct super_block *sb, u64 no_addr,
284288
set_bit(GIF_INVALID, &ip->i_flags);
285289
error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, LM_FLAG_TRY | GL_EXACT,
286290
&ip->i_iopen_gh);
287-
if (unlikely(error)) {
288-
if (error == GLR_TRYFAILED)
289-
error = 0;
291+
if (unlikely(error))
290292
goto fail_iopen;
291-
}
293+
292294
ip->i_iopen_gh.gh_gl->gl_object = ip;
293295
gfs2_glock_put(io_gl);
294296

295-
(*inode)->i_mode = DT2IF(DT_UNKNOWN);
297+
inode->i_mode = DT2IF(DT_UNKNOWN);
296298

297299
/*
298300
* We must read the inode in order to work out its type in
@@ -303,16 +305,17 @@ int gfs2_unlinked_inode_lookup(struct super_block *sb, u64 no_addr,
303305
*/
304306
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY,
305307
&gh);
306-
if (unlikely(error)) {
307-
if (error == GLR_TRYFAILED)
308-
error = 0;
308+
if (unlikely(error))
309309
goto fail_glock;
310-
}
310+
311311
/* Inode is now uptodate */
312312
gfs2_glock_dq_uninit(&gh);
313-
gfs2_set_iop(*inode);
313+
gfs2_set_iop(inode);
314+
315+
/* The iput will cause it to be deleted. */
316+
iput(inode);
317+
return;
314318

315-
return 0;
316319
fail_glock:
317320
gfs2_glock_dq(&ip->i_iopen_gh);
318321
fail_iopen:
@@ -321,7 +324,8 @@ int gfs2_unlinked_inode_lookup(struct super_block *sb, u64 no_addr,
321324
ip->i_gl->gl_object = NULL;
322325
gfs2_glock_put(ip->i_gl);
323326
fail:
324-
return error;
327+
iget_failed(inode);
328+
return;
325329
}
326330

327331
static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)

fs/gfs2/inode.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@ static inline void gfs2_inum_out(const struct gfs2_inode *ip,
8484
extern void gfs2_set_iop(struct inode *inode);
8585
extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type,
8686
u64 no_addr, u64 no_formal_ino);
87-
extern int gfs2_unlinked_inode_lookup(struct super_block *sb, u64 no_addr,
88-
struct inode **inode);
87+
extern void gfs2_process_unlinked_inode(struct super_block *sb, u64 no_addr);
8988
extern struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr);
9089

9190
extern int gfs2_inode_refresh(struct gfs2_inode *ip);

fs/gfs2/log.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,7 @@ static void gfs2_ordered_wait(struct gfs2_sbd *sdp)
696696
*
697697
*/
698698

699-
void __gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
699+
void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
700700
{
701701
struct gfs2_ail *ai;
702702

fs/gfs2/log.h

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -47,28 +47,21 @@ static inline void gfs2_log_pointers_init(struct gfs2_sbd *sdp,
4747
sdp->sd_log_head = sdp->sd_log_tail = value;
4848
}
4949

50-
unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct,
50+
extern unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct,
5151
unsigned int ssize);
5252

53-
int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks);
54-
void gfs2_log_incr_head(struct gfs2_sbd *sdp);
53+
extern int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks);
54+
extern void gfs2_log_incr_head(struct gfs2_sbd *sdp);
5555

56-
struct buffer_head *gfs2_log_get_buf(struct gfs2_sbd *sdp);
57-
struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp,
56+
extern struct buffer_head *gfs2_log_get_buf(struct gfs2_sbd *sdp);
57+
extern struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp,
5858
struct buffer_head *real);
59-
void __gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl);
59+
extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl);
60+
extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans);
61+
extern void gfs2_remove_from_ail(struct gfs2_bufdata *bd);
6062

61-
static inline void gfs2_log_flush(struct gfs2_sbd *sbd, struct gfs2_glock *gl)
62-
{
63-
if (!gl || test_bit(GLF_LFLUSH, &gl->gl_flags))
64-
__gfs2_log_flush(sbd, gl);
65-
}
66-
67-
void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans);
68-
void gfs2_remove_from_ail(struct gfs2_bufdata *bd);
69-
70-
void gfs2_log_shutdown(struct gfs2_sbd *sdp);
71-
void gfs2_meta_syncfs(struct gfs2_sbd *sdp);
72-
int gfs2_logd(void *data);
63+
extern void gfs2_log_shutdown(struct gfs2_sbd *sdp);
64+
extern void gfs2_meta_syncfs(struct gfs2_sbd *sdp);
65+
extern int gfs2_logd(void *data);
7366

7467
#endif /* __LOG_DOT_H__ */

fs/gfs2/rgrp.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,7 +1191,6 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line)
11911191
{
11921192
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
11931193
struct gfs2_alloc *al = ip->i_alloc;
1194-
struct inode *inode;
11951194
int error = 0;
11961195
u64 last_unlinked = NO_BLOCK, unlinked;
11971196

@@ -1209,22 +1208,27 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line)
12091208
if (error)
12101209
return error;
12111210

1211+
/* Find an rgrp suitable for allocation. If it encounters any unlinked
1212+
dinodes along the way, error will equal -EAGAIN and unlinked will
1213+
contains it block address. We then need to look up that inode and
1214+
try to free it, and try the allocation again. */
12121215
error = get_local_rgrp(ip, &unlinked, &last_unlinked);
12131216
if (error) {
12141217
if (ip != GFS2_I(sdp->sd_rindex))
12151218
gfs2_glock_dq_uninit(&al->al_ri_gh);
12161219
if (error != -EAGAIN)
12171220
return error;
1218-
error = gfs2_unlinked_inode_lookup(ip->i_inode.i_sb,
1219-
unlinked, &inode);
1220-
if (inode)
1221-
iput(inode);
1221+
1222+
gfs2_process_unlinked_inode(ip->i_inode.i_sb, unlinked);
1223+
/* regardless of whether or not gfs2_process_unlinked_inode
1224+
was successful, we don't want to repeat it again. */
1225+
last_unlinked = unlinked;
12221226
gfs2_log_flush(sdp, NULL);
1223-
if (error == GLR_TRYFAILED)
1224-
error = 0;
1227+
error = 0;
1228+
12251229
goto try_again;
12261230
}
1227-
1231+
/* no error, so we have the rgrp set in the inode's allocation. */
12281232
al->al_file = file;
12291233
al->al_line = line;
12301234

0 commit comments

Comments
 (0)