aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/inode.c
diff options
context:
space:
mode:
authorBob Peterson <rpeterso@redhat.com>2008-04-29 13:35:48 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2008-05-12 03:54:53 -0400
commit091806edd458486af13ad83c9802f5b8b54d6d19 (patch)
treecf10d6aaf2e6bf0ed5b0ad94306623a2fc3fdb56 /fs/gfs2/inode.c
parent492c2e476eac010962850006c49df326919b284c (diff)
[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>
Diffstat (limited to 'fs/gfs2/inode.c')
-rw-r--r--fs/gfs2/inode.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 3a9ef526c308..09453d057e41 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -47,8 +47,7 @@ static int iget_test(struct inode *inode, void *opaque)
47 struct gfs2_inode *ip = GFS2_I(inode); 47 struct gfs2_inode *ip = GFS2_I(inode);
48 u64 *no_addr = opaque; 48 u64 *no_addr = opaque;
49 49
50 if (ip->i_no_addr == *no_addr && 50 if (ip->i_no_addr == *no_addr && test_bit(GIF_USER, &ip->i_flags))
51 inode->i_private != NULL)
52 return 1; 51 return 1;
53 52
54 return 0; 53 return 0;
@@ -61,6 +60,7 @@ static int iget_set(struct inode *inode, void *opaque)
61 60
62 inode->i_ino = (unsigned long)*no_addr; 61 inode->i_ino = (unsigned long)*no_addr;
63 ip->i_no_addr = *no_addr; 62 ip->i_no_addr = *no_addr;
63 set_bit(GIF_USER, &ip->i_flags);
64 return 0; 64 return 0;
65} 65}
66 66
@@ -86,7 +86,7 @@ static int iget_skip_test(struct inode *inode, void *opaque)
86 struct gfs2_inode *ip = GFS2_I(inode); 86 struct gfs2_inode *ip = GFS2_I(inode);
87 struct gfs2_skip_data *data = opaque; 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 if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)){ 90 if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)){
91 data->skipped = 1; 91 data->skipped = 1;
92 return 0; 92 return 0;
@@ -105,6 +105,7 @@ static int iget_skip_set(struct inode *inode, void *opaque)
105 return 1; 105 return 1;
106 inode->i_ino = (unsigned long)(data->no_addr); 106 inode->i_ino = (unsigned long)(data->no_addr);
107 ip->i_no_addr = data->no_addr; 107 ip->i_no_addr = data->no_addr;
108 set_bit(GIF_USER, &ip->i_flags);
108 return 0; 109 return 0;
109} 110}
110 111
@@ -166,7 +167,7 @@ void gfs2_set_iop(struct inode *inode)
166 * Returns: A VFS inode, or an error 167 * Returns: A VFS inode, or an error
167 */ 168 */
168 169
169struct inode *gfs2_inode_lookup(struct super_block *sb, 170struct inode *gfs2_inode_lookup(struct super_block *sb,
170 unsigned int type, 171 unsigned int type,
171 u64 no_addr, 172 u64 no_addr,
172 u64 no_formal_ino, int skip_freeing) 173 u64 no_formal_ino, int skip_freeing)
@@ -187,7 +188,6 @@ struct inode *gfs2_inode_lookup(struct super_block *sb,
187 188
188 if (inode->i_state & I_NEW) { 189 if (inode->i_state & I_NEW) {
189 struct gfs2_sbd *sdp = GFS2_SB(inode); 190 struct gfs2_sbd *sdp = GFS2_SB(inode);
190 inode->i_private = ip;
191 ip->i_no_formal_ino = no_formal_ino; 191 ip->i_no_formal_ino = no_formal_ino;
192 192
193 error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl); 193 error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);