Commit 091806edd458486af13ad83c9802f5b8b54d6d19
Committed by
Steven Whitehouse
1 parent
492c2e476e
Exists in
master
and in
7 other branches
[GFS2] filesystem consistency error from do_strip
This patch fixes a GFS2 filesystem consistency error reported from function do_strip. The problem was caused by a timing window that allowed two vfs inodes to be created in memory that point to the same file. The problem is fixed by making the vfs's iget_test, iget_set mechanism check and set a new bit in the in-core gfs2_inode structure while the vfs inode spin_lock is held. Signed-off-by: Bob Peterson <rpeterso@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Showing 5 changed files with 20 additions and 15 deletions Side-by-side Diff
fs/gfs2/glops.c
fs/gfs2/incore.h
fs/gfs2/inode.c
... | ... | @@ -47,8 +47,7 @@ |
47 | 47 | struct gfs2_inode *ip = GFS2_I(inode); |
48 | 48 | u64 *no_addr = opaque; |
49 | 49 | |
50 | - if (ip->i_no_addr == *no_addr && | |
51 | - inode->i_private != NULL) | |
50 | + if (ip->i_no_addr == *no_addr && test_bit(GIF_USER, &ip->i_flags)) | |
52 | 51 | return 1; |
53 | 52 | |
54 | 53 | return 0; |
... | ... | @@ -61,6 +60,7 @@ |
61 | 60 | |
62 | 61 | inode->i_ino = (unsigned long)*no_addr; |
63 | 62 | ip->i_no_addr = *no_addr; |
63 | + set_bit(GIF_USER, &ip->i_flags); | |
64 | 64 | return 0; |
65 | 65 | } |
66 | 66 | |
... | ... | @@ -86,7 +86,7 @@ |
86 | 86 | struct gfs2_inode *ip = GFS2_I(inode); |
87 | 87 | struct gfs2_skip_data *data = opaque; |
88 | 88 | |
89 | - if (ip->i_no_addr == data->no_addr && inode->i_private != NULL){ | |
89 | + if (ip->i_no_addr == data->no_addr && test_bit(GIF_USER, &ip->i_flags)){ | |
90 | 90 | if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)){ |
91 | 91 | data->skipped = 1; |
92 | 92 | return 0; |
... | ... | @@ -105,6 +105,7 @@ |
105 | 105 | return 1; |
106 | 106 | inode->i_ino = (unsigned long)(data->no_addr); |
107 | 107 | ip->i_no_addr = data->no_addr; |
108 | + set_bit(GIF_USER, &ip->i_flags); | |
108 | 109 | return 0; |
109 | 110 | } |
110 | 111 | |
... | ... | @@ -166,7 +167,7 @@ |
166 | 167 | * Returns: A VFS inode, or an error |
167 | 168 | */ |
168 | 169 | |
169 | -struct inode *gfs2_inode_lookup(struct super_block *sb, | |
170 | +struct inode *gfs2_inode_lookup(struct super_block *sb, | |
170 | 171 | unsigned int type, |
171 | 172 | u64 no_addr, |
172 | 173 | u64 no_formal_ino, int skip_freeing) |
... | ... | @@ -187,7 +188,6 @@ |
187 | 188 | |
188 | 189 | if (inode->i_state & I_NEW) { |
189 | 190 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
190 | - inode->i_private = ip; | |
191 | 191 | ip->i_no_formal_ino = no_formal_ino; |
192 | 192 | |
193 | 193 | error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl); |
fs/gfs2/meta_io.c
1 | 1 | /* |
2 | 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
3 | - * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | |
3 | + * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. | |
4 | 4 | * |
5 | 5 | * This copyrighted material is made available to anyone wishing to use, |
6 | 6 | * modify, copy, or redistribute it subject to the terms and conditions |
7 | 7 | |
... | ... | @@ -69,13 +69,15 @@ |
69 | 69 | struct inode *gfs2_aspace_get(struct gfs2_sbd *sdp) |
70 | 70 | { |
71 | 71 | struct inode *aspace; |
72 | + struct gfs2_inode *ip; | |
72 | 73 | |
73 | 74 | aspace = new_inode(sdp->sd_vfs); |
74 | 75 | if (aspace) { |
75 | 76 | mapping_set_gfp_mask(aspace->i_mapping, GFP_NOFS); |
76 | 77 | aspace->i_mapping->a_ops = &aspace_aops; |
77 | 78 | aspace->i_size = ~0ULL; |
78 | - aspace->i_private = NULL; | |
79 | + ip = GFS2_I(aspace); | |
80 | + clear_bit(GIF_USER, &ip->i_flags); | |
79 | 81 | insert_inode_hash(aspace); |
80 | 82 | } |
81 | 83 | return aspace; |
fs/gfs2/ops_super.c
1 | 1 | /* |
2 | 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
3 | - * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | |
3 | + * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. | |
4 | 4 | * |
5 | 5 | * This copyrighted material is made available to anyone wishing to use, |
6 | 6 | * modify, copy, or redistribute it subject to the terms and conditions |
... | ... | @@ -52,7 +52,7 @@ |
52 | 52 | struct gfs2_inode *ip = GFS2_I(inode); |
53 | 53 | |
54 | 54 | /* Check this is a "normal" inode */ |
55 | - if (inode->i_private) { | |
55 | + if (test_bit(GIF_USER, &ip->i_flags)) { | |
56 | 56 | if (current->flags & PF_MEMALLOC) |
57 | 57 | return 0; |
58 | 58 | if (sync) |
... | ... | @@ -297,8 +297,9 @@ |
297 | 297 | */ |
298 | 298 | static void gfs2_drop_inode(struct inode *inode) |
299 | 299 | { |
300 | - if (inode->i_private && inode->i_nlink) { | |
301 | - struct gfs2_inode *ip = GFS2_I(inode); | |
300 | + struct gfs2_inode *ip = GFS2_I(inode); | |
301 | + | |
302 | + if (test_bit(GIF_USER, &ip->i_flags) && inode->i_nlink) { | |
302 | 303 | struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl; |
303 | 304 | if (gl && test_bit(GLF_DEMOTE, &gl->gl_flags)) |
304 | 305 | clear_nlink(inode); |
305 | 306 | |
... | ... | @@ -314,12 +315,13 @@ |
314 | 315 | |
315 | 316 | static void gfs2_clear_inode(struct inode *inode) |
316 | 317 | { |
318 | + struct gfs2_inode *ip = GFS2_I(inode); | |
319 | + | |
317 | 320 | /* This tells us its a "real" inode and not one which only |
318 | 321 | * serves to contain an address space (see rgrp.c, meta_io.c) |
319 | 322 | * which therefore doesn't have its own glocks. |
320 | 323 | */ |
321 | - if (inode->i_private) { | |
322 | - struct gfs2_inode *ip = GFS2_I(inode); | |
324 | + if (test_bit(GIF_USER, &ip->i_flags)) { | |
323 | 325 | ip->i_gl->gl_object = NULL; |
324 | 326 | gfs2_glock_schedule_for_reclaim(ip->i_gl); |
325 | 327 | gfs2_glock_put(ip->i_gl); |
... | ... | @@ -419,7 +421,7 @@ |
419 | 421 | struct gfs2_holder gh; |
420 | 422 | int error; |
421 | 423 | |
422 | - if (!inode->i_private) | |
424 | + if (!test_bit(GIF_USER, &ip->i_flags)) | |
423 | 425 | goto out; |
424 | 426 | |
425 | 427 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); |