diff options
Diffstat (limited to 'fs/gfs2/inode.c')
| -rw-r--r-- | fs/gfs2/inode.c | 56 |
1 files changed, 41 insertions, 15 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 97d54a28776a..9134dcb89479 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
| @@ -40,37 +40,61 @@ struct gfs2_inum_range_host { | |||
| 40 | u64 ir_length; | 40 | u64 ir_length; |
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | struct gfs2_skip_data { | ||
| 44 | u64 no_addr; | ||
| 45 | int skipped; | ||
| 46 | int non_block; | ||
| 47 | }; | ||
| 48 | |||
| 43 | static int iget_test(struct inode *inode, void *opaque) | 49 | static int iget_test(struct inode *inode, void *opaque) |
| 44 | { | 50 | { |
| 45 | struct gfs2_inode *ip = GFS2_I(inode); | 51 | struct gfs2_inode *ip = GFS2_I(inode); |
| 46 | u64 *no_addr = opaque; | 52 | struct gfs2_skip_data *data = opaque; |
| 47 | 53 | ||
| 48 | if (ip->i_no_addr == *no_addr) | 54 | if (ip->i_no_addr == data->no_addr) { |
| 55 | if (data->non_block && | ||
| 56 | inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)) { | ||
| 57 | data->skipped = 1; | ||
| 58 | return 0; | ||
| 59 | } | ||
| 49 | return 1; | 60 | return 1; |
| 50 | 61 | } | |
| 51 | return 0; | 62 | return 0; |
| 52 | } | 63 | } |
| 53 | 64 | ||
| 54 | static int iget_set(struct inode *inode, void *opaque) | 65 | static int iget_set(struct inode *inode, void *opaque) |
| 55 | { | 66 | { |
| 56 | struct gfs2_inode *ip = GFS2_I(inode); | 67 | struct gfs2_inode *ip = GFS2_I(inode); |
| 57 | u64 *no_addr = opaque; | 68 | struct gfs2_skip_data *data = opaque; |
| 58 | 69 | ||
| 59 | inode->i_ino = (unsigned long)*no_addr; | 70 | if (data->skipped) |
| 60 | ip->i_no_addr = *no_addr; | 71 | return -ENOENT; |
| 72 | inode->i_ino = (unsigned long)(data->no_addr); | ||
| 73 | ip->i_no_addr = data->no_addr; | ||
| 61 | return 0; | 74 | return 0; |
| 62 | } | 75 | } |
| 63 | 76 | ||
| 64 | struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr) | 77 | struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr) |
| 65 | { | 78 | { |
| 66 | unsigned long hash = (unsigned long)no_addr; | 79 | unsigned long hash = (unsigned long)no_addr; |
| 67 | return ilookup5(sb, hash, iget_test, &no_addr); | 80 | struct gfs2_skip_data data; |
| 81 | |||
| 82 | data.no_addr = no_addr; | ||
| 83 | data.skipped = 0; | ||
| 84 | data.non_block = 0; | ||
| 85 | return ilookup5(sb, hash, iget_test, &data); | ||
| 68 | } | 86 | } |
| 69 | 87 | ||
| 70 | static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr) | 88 | static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr, |
| 89 | int non_block) | ||
| 71 | { | 90 | { |
| 91 | struct gfs2_skip_data data; | ||
| 72 | unsigned long hash = (unsigned long)no_addr; | 92 | unsigned long hash = (unsigned long)no_addr; |
| 73 | return iget5_locked(sb, hash, iget_test, iget_set, &no_addr); | 93 | |
| 94 | data.no_addr = no_addr; | ||
| 95 | data.skipped = 0; | ||
| 96 | data.non_block = non_block; | ||
| 97 | return iget5_locked(sb, hash, iget_test, iget_set, &data); | ||
| 74 | } | 98 | } |
| 75 | 99 | ||
| 76 | /** | 100 | /** |
| @@ -111,19 +135,20 @@ static void gfs2_set_iop(struct inode *inode) | |||
| 111 | * @sb: The super block | 135 | * @sb: The super block |
| 112 | * @no_addr: The inode number | 136 | * @no_addr: The inode number |
| 113 | * @type: The type of the inode | 137 | * @type: The type of the inode |
| 138 | * non_block: Can we block on inodes that are being freed? | ||
| 114 | * | 139 | * |
| 115 | * Returns: A VFS inode, or an error | 140 | * Returns: A VFS inode, or an error |
| 116 | */ | 141 | */ |
| 117 | 142 | ||
| 118 | struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, | 143 | struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, |
| 119 | u64 no_addr, u64 no_formal_ino) | 144 | u64 no_addr, u64 no_formal_ino, int non_block) |
| 120 | { | 145 | { |
| 121 | struct inode *inode; | 146 | struct inode *inode; |
| 122 | struct gfs2_inode *ip; | 147 | struct gfs2_inode *ip; |
| 123 | struct gfs2_glock *io_gl = NULL; | 148 | struct gfs2_glock *io_gl = NULL; |
| 124 | int error; | 149 | int error; |
| 125 | 150 | ||
| 126 | inode = gfs2_iget(sb, no_addr); | 151 | inode = gfs2_iget(sb, no_addr, non_block); |
| 127 | ip = GFS2_I(inode); | 152 | ip = GFS2_I(inode); |
| 128 | 153 | ||
| 129 | if (!inode) | 154 | if (!inode) |
| @@ -185,11 +210,12 @@ struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr, | |||
| 185 | { | 210 | { |
| 186 | struct super_block *sb = sdp->sd_vfs; | 211 | struct super_block *sb = sdp->sd_vfs; |
| 187 | struct gfs2_holder i_gh; | 212 | struct gfs2_holder i_gh; |
| 188 | struct inode *inode; | 213 | struct inode *inode = NULL; |
| 189 | int error; | 214 | int error; |
| 190 | 215 | ||
| 216 | /* Must not read in block until block type is verified */ | ||
| 191 | error = gfs2_glock_nq_num(sdp, no_addr, &gfs2_inode_glops, | 217 | error = gfs2_glock_nq_num(sdp, no_addr, &gfs2_inode_glops, |
| 192 | LM_ST_SHARED, LM_FLAG_ANY, &i_gh); | 218 | LM_ST_EXCLUSIVE, GL_SKIP, &i_gh); |
| 193 | if (error) | 219 | if (error) |
| 194 | return ERR_PTR(error); | 220 | return ERR_PTR(error); |
| 195 | 221 | ||
| @@ -197,7 +223,7 @@ struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr, | |||
| 197 | if (error) | 223 | if (error) |
| 198 | goto fail; | 224 | goto fail; |
| 199 | 225 | ||
| 200 | inode = gfs2_inode_lookup(sb, DT_UNKNOWN, no_addr, 0); | 226 | inode = gfs2_inode_lookup(sb, DT_UNKNOWN, no_addr, 0, 1); |
| 201 | if (IS_ERR(inode)) | 227 | if (IS_ERR(inode)) |
| 202 | goto fail; | 228 | goto fail; |
| 203 | 229 | ||
| @@ -843,7 +869,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, | |||
| 843 | goto fail_gunlock2; | 869 | goto fail_gunlock2; |
| 844 | 870 | ||
| 845 | inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode), inum.no_addr, | 871 | inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode), inum.no_addr, |
| 846 | inum.no_formal_ino); | 872 | inum.no_formal_ino, 0); |
| 847 | if (IS_ERR(inode)) | 873 | if (IS_ERR(inode)) |
| 848 | goto fail_gunlock2; | 874 | goto fail_gunlock2; |
| 849 | 875 | ||
