aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/ops_export.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-06-14 15:32:57 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2006-06-14 15:32:57 -0400
commitfeaa7bba026c181ce071d5a4884f7f9dd26207a1 (patch)
treec858deb225917265cb07820730e9764674d133e8 /fs/gfs2/ops_export.c
parent22da645fd6675b7abc55cf937ddf6132f343e5b9 (diff)
[GFS2] Fix unlinked file handling
This patch fixes the way we have been dealing with unlinked, but still open files. It removes all limits (other than memory for inodes, as per every other filesystem) on numbers of these which we can support on GFS2. It also means that (like other fs) its the responsibility of the last process to close the file to deallocate the storage, rather than the person who did the unlinking. Note that with GFS2, those two events might take place on different nodes. Also there are a number of other changes: o We use the Linux inode subsystem as it was intended to be used, wrt allocating GFS2 inodes o The Linux inode cache is now the point which we use for local enforcement of only holding one copy of the inode in core at once (previous to this we used the glock layer). o We no longer use the unlinked "special" file. We just ignore it completely. This makes unlinking more efficient. o We now use the 4th block allocation state. The previously unused state is used to track unlinked but still open inodes. o gfs2_inoded is no longer needed o Several fields are now no longer needed (and removed) from the in core struct gfs2_inode o Several fields are no longer needed (and removed) from the in core superblock There are a number of future possible optimisations and clean ups which have been made possible by this patch. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/ops_export.c')
-rw-r--r--fs/gfs2/ops_export.c60
1 files changed, 24 insertions, 36 deletions
diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c
index a376ead7d0cd..eacc1c092f91 100644
--- a/fs/gfs2/ops_export.c
+++ b/fs/gfs2/ops_export.c
@@ -66,7 +66,7 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *fh, int *len,
66{ 66{
67 struct inode *inode = dentry->d_inode; 67 struct inode *inode = dentry->d_inode;
68 struct super_block *sb = inode->i_sb; 68 struct super_block *sb = inode->i_sb;
69 struct gfs2_inode *ip = inode->u.generic_ip; 69 struct gfs2_inode *ip = GFS2_I(inode);
70 70
71 if (*len < 4 || (connectable && *len < 8)) 71 if (*len < 4 || (connectable && *len < 8))
72 return 255; 72 return 255;
@@ -86,8 +86,8 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *fh, int *len,
86 86
87 spin_lock(&dentry->d_lock); 87 spin_lock(&dentry->d_lock);
88 inode = dentry->d_parent->d_inode; 88 inode = dentry->d_parent->d_inode;
89 ip = inode->u.generic_ip; 89 ip = GFS2_I(inode);
90 gfs2_inode_hold(ip); 90 igrab(inode);
91 spin_unlock(&dentry->d_lock); 91 spin_unlock(&dentry->d_lock);
92 92
93 fh[4] = ip->i_num.no_formal_ino >> 32; 93 fh[4] = ip->i_num.no_formal_ino >> 32;
@@ -100,7 +100,7 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *fh, int *len,
100 fh[7] = cpu_to_be32(fh[7]); 100 fh[7] = cpu_to_be32(fh[7]);
101 *len = 8; 101 *len = 8;
102 102
103 gfs2_inode_put(ip); 103 iput(inode);
104 104
105 return *len; 105 return *len;
106} 106}
@@ -142,8 +142,8 @@ static int gfs2_get_name(struct dentry *parent, char *name,
142 if (!S_ISDIR(dir->i_mode) || !inode) 142 if (!S_ISDIR(dir->i_mode) || !inode)
143 return -EINVAL; 143 return -EINVAL;
144 144
145 dip = dir->u.generic_ip; 145 dip = GFS2_I(dir);
146 ip = inode->u.generic_ip; 146 ip = GFS2_I(inode);
147 147
148 *name = 0; 148 *name = 0;
149 gnfd.inum = ip->i_num; 149 gnfd.inum = ip->i_num;
@@ -189,39 +189,30 @@ static struct dentry *gfs2_get_parent(struct dentry *child)
189static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_p) 189static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_p)
190{ 190{
191 struct gfs2_sbd *sdp = sb->s_fs_info; 191 struct gfs2_sbd *sdp = sb->s_fs_info;
192 struct gfs2_inum *inum = (struct gfs2_inum *)inum_p; 192 struct gfs2_inum *inum = inum_p;
193 struct gfs2_holder i_gh, ri_gh, rgd_gh; 193 struct gfs2_holder i_gh, ri_gh, rgd_gh;
194 struct gfs2_rgrpd *rgd; 194 struct gfs2_rgrpd *rgd;
195 struct gfs2_inode *ip;
196 struct inode *inode; 195 struct inode *inode;
197 struct dentry *dentry; 196 struct dentry *dentry;
198 int error; 197 int error;
199 198
200 /* System files? */ 199 /* System files? */
201 200
202 inode = gfs2_iget(sb, inum); 201 inode = gfs2_ilookup(sb, inum);
203 if (inode) { 202 if (inode) {
204 ip = inode->u.generic_ip; 203 if (GFS2_I(inode)->i_num.no_formal_ino != inum->no_formal_ino) {
205 if (ip->i_num.no_formal_ino != inum->no_formal_ino) {
206 iput(inode); 204 iput(inode);
207 return ERR_PTR(-ESTALE); 205 return ERR_PTR(-ESTALE);
208 } 206 }
209 goto out_inode; 207 goto out_inode;
210 } 208 }
211 209
212 error = gfs2_glock_nq_num(sdp, 210 error = gfs2_glock_nq_num(sdp, inum->no_addr, &gfs2_inode_glops,
213 inum->no_addr, &gfs2_inode_glops,
214 LM_ST_SHARED, LM_FLAG_ANY | GL_LOCAL_EXCL, 211 LM_ST_SHARED, LM_FLAG_ANY | GL_LOCAL_EXCL,
215 &i_gh); 212 &i_gh);
216 if (error) 213 if (error)
217 return ERR_PTR(error); 214 return ERR_PTR(error);
218 215
219 error = gfs2_inode_get(i_gh.gh_gl, inum, NO_CREATE, &ip);
220 if (error)
221 goto fail;
222 if (ip)
223 goto out_ip;
224
225 error = gfs2_rindex_hold(sdp, &ri_gh); 216 error = gfs2_rindex_hold(sdp, &ri_gh);
226 if (error) 217 if (error)
227 goto fail; 218 goto fail;
@@ -242,32 +233,29 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_p)
242 gfs2_glock_dq_uninit(&rgd_gh); 233 gfs2_glock_dq_uninit(&rgd_gh);
243 gfs2_glock_dq_uninit(&ri_gh); 234 gfs2_glock_dq_uninit(&ri_gh);
244 235
245 error = gfs2_inode_get(i_gh.gh_gl, inum, CREATE, &ip); 236 inode = gfs2_inode_lookup(sb, inum, DT_UNKNOWN);
246 if (error) 237 if (!inode)
238 goto fail;
239 if (IS_ERR(inode)) {
240 error = PTR_ERR(inode);
247 goto fail; 241 goto fail;
242 }
248 243
249 error = gfs2_inode_refresh(ip); 244 error = gfs2_inode_refresh(GFS2_I(inode));
250 if (error) { 245 if (error) {
251 gfs2_inode_put(ip); 246 iput(inode);
252 goto fail; 247 goto fail;
253 } 248 }
254 249
255 out_ip:
256 error = -EIO; 250 error = -EIO;
257 if (ip->i_di.di_flags & GFS2_DIF_SYSTEM) { 251 if (GFS2_I(inode)->i_di.di_flags & GFS2_DIF_SYSTEM) {
258 gfs2_inode_put(ip); 252 iput(inode);
259 goto fail; 253 goto fail;
260 } 254 }
261 255
262 gfs2_glock_dq_uninit(&i_gh); 256 gfs2_glock_dq_uninit(&i_gh);
263 257
264 inode = gfs2_ip2v(ip); 258out_inode:
265 gfs2_inode_put(ip);
266
267 if (!inode)
268 return ERR_PTR(-ENOMEM);
269
270 out_inode:
271 dentry = d_alloc_anon(inode); 259 dentry = d_alloc_anon(inode);
272 if (!dentry) { 260 if (!dentry) {
273 iput(inode); 261 iput(inode);
@@ -276,13 +264,13 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_p)
276 264
277 return dentry; 265 return dentry;
278 266
279 fail_rgd: 267fail_rgd:
280 gfs2_glock_dq_uninit(&rgd_gh); 268 gfs2_glock_dq_uninit(&rgd_gh);
281 269
282 fail_rindex: 270fail_rindex:
283 gfs2_glock_dq_uninit(&ri_gh); 271 gfs2_glock_dq_uninit(&ri_gh);
284 272
285 fail: 273fail:
286 gfs2_glock_dq_uninit(&i_gh); 274 gfs2_glock_dq_uninit(&i_gh);
287 return ERR_PTR(error); 275 return ERR_PTR(error);
288} 276}