Commit 091806edd458486af13ad83c9802f5b8b54d6d19

Authored by Bob Peterson
Committed by Steven Whitehouse
1 parent 492c2e476e

[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

... ... @@ -249,7 +249,7 @@
249 249 struct gfs2_inode *ip = gl->gl_object;
250 250 int error = 0;
251 251  
252   - if (!ip)
  252 + if (!ip || (gh->gh_flags & GL_SKIP))
253 253 return 0;
254 254  
255 255 if (test_bit(GIF_INVALID, &ip->i_flags)) {
... ... @@ -236,6 +236,7 @@
236 236 GIF_INVALID = 0,
237 237 GIF_QD_LOCKED = 1,
238 238 GIF_SW_PAGED = 3,
  239 + GIF_USER = 4, /* user inode, not metadata addr space */
239 240 };
240 241  
241 242 struct gfs2_dinode_host {
... ... @@ -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);
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;
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);