aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/ops_super.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_super.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_super.c')
-rw-r--r--fs/gfs2/ops_super.c112
1 files changed, 92 insertions, 20 deletions
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c
index 1c17acc946f9..317d497f8f88 100644
--- a/fs/gfs2/ops_super.c
+++ b/fs/gfs2/ops_super.c
@@ -19,6 +19,7 @@
19#include <linux/kthread.h> 19#include <linux/kthread.h>
20#include <linux/delay.h> 20#include <linux/delay.h>
21#include <linux/gfs2_ondisk.h> 21#include <linux/gfs2_ondisk.h>
22#include <linux/crc32.h>
22 23
23#include "gfs2.h" 24#include "gfs2.h"
24#include "lm_interface.h" 25#include "lm_interface.h"
@@ -36,6 +37,10 @@
36#include "super.h" 37#include "super.h"
37#include "sys.h" 38#include "sys.h"
38#include "util.h" 39#include "util.h"
40#include "trans.h"
41#include "dir.h"
42#include "eattr.h"
43#include "bmap.h"
39 44
40/** 45/**
41 * gfs2_write_inode - Make sure the inode is stable on the disk 46 * gfs2_write_inode - Make sure the inode is stable on the disk
@@ -47,12 +52,15 @@
47 52
48static int gfs2_write_inode(struct inode *inode, int sync) 53static int gfs2_write_inode(struct inode *inode, int sync)
49{ 54{
50 struct gfs2_inode *ip = inode->u.generic_ip; 55 struct gfs2_inode *ip = GFS2_I(inode);
51 56
52 if (current->flags & PF_MEMALLOC) 57 /* Check this is a "normal" inode */
53 return 0; 58 if (inode->u.generic_ip) {
54 if (ip && sync) 59 if (current->flags & PF_MEMALLOC)
55 gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl); 60 return 0;
61 if (sync)
62 gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl);
63 }
56 64
57 return 0; 65 return 0;
58} 66}
@@ -78,7 +86,6 @@ static void gfs2_put_super(struct super_block *sb)
78 gfs2_glock_dq_uninit(&sdp->sd_freeze_gh); 86 gfs2_glock_dq_uninit(&sdp->sd_freeze_gh);
79 mutex_unlock(&sdp->sd_freeze_lock); 87 mutex_unlock(&sdp->sd_freeze_lock);
80 88
81 kthread_stop(sdp->sd_inoded_process);
82 kthread_stop(sdp->sd_quotad_process); 89 kthread_stop(sdp->sd_quotad_process);
83 kthread_stop(sdp->sd_logd_process); 90 kthread_stop(sdp->sd_logd_process);
84 kthread_stop(sdp->sd_recoverd_process); 91 kthread_stop(sdp->sd_recoverd_process);
@@ -110,11 +117,9 @@ static void gfs2_put_super(struct super_block *sb)
110 gfs2_glock_dq_uninit(&sdp->sd_jinode_gh); 117 gfs2_glock_dq_uninit(&sdp->sd_jinode_gh);
111 gfs2_glock_dq_uninit(&sdp->sd_ir_gh); 118 gfs2_glock_dq_uninit(&sdp->sd_ir_gh);
112 gfs2_glock_dq_uninit(&sdp->sd_sc_gh); 119 gfs2_glock_dq_uninit(&sdp->sd_sc_gh);
113 gfs2_glock_dq_uninit(&sdp->sd_ut_gh);
114 gfs2_glock_dq_uninit(&sdp->sd_qc_gh); 120 gfs2_glock_dq_uninit(&sdp->sd_qc_gh);
115 iput(sdp->sd_ir_inode); 121 iput(sdp->sd_ir_inode);
116 iput(sdp->sd_sc_inode); 122 iput(sdp->sd_sc_inode);
117 iput(sdp->sd_ut_inode);
118 iput(sdp->sd_qc_inode); 123 iput(sdp->sd_qc_inode);
119 } 124 }
120 125
@@ -274,16 +279,20 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data)
274 279
275static void gfs2_clear_inode(struct inode *inode) 280static void gfs2_clear_inode(struct inode *inode)
276{ 281{
277 struct gfs2_inode *ip = inode->u.generic_ip; 282 /* This tells us its a "real" inode and not one which only
278 283 * serves to contain an address space (see rgrp.c, meta_io.c)
279 if (ip) { 284 * which therefore doesn't have its own glocks.
280 spin_lock(&ip->i_spin); 285 */
281 ip->i_vnode = NULL; 286 if (inode->u.generic_ip) {
282 inode->u.generic_ip = NULL; 287 struct gfs2_inode *ip = GFS2_I(inode);
283 spin_unlock(&ip->i_spin); 288 gfs2_glock_inode_squish(inode);
284 289 gfs2_assert(inode->i_sb->s_fs_info, ip->i_gl->gl_state == LM_ST_UNLOCKED);
290 ip->i_gl->gl_object = NULL;
285 gfs2_glock_schedule_for_reclaim(ip->i_gl); 291 gfs2_glock_schedule_for_reclaim(ip->i_gl);
286 gfs2_inode_put(ip); 292 gfs2_glock_put(ip->i_gl);
293 ip->i_gl = NULL;
294 if (ip->i_iopen_gh.gh_gl)
295 gfs2_glock_dq_uninit(&ip->i_iopen_gh);
287 } 296 }
288} 297}
289 298
@@ -361,6 +370,70 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
361 return 0; 370 return 0;
362} 371}
363 372
373/*
374 * We have to (at the moment) hold the inodes main lock to cover
375 * the gap between unlocking the shared lock on the iopen lock and
376 * taking the exclusive lock. I'd rather do a shared -> exclusive
377 * conversion on the iopen lock, but we can change that later. This
378 * is safe, just less efficient.
379 */
380static void gfs2_delete_inode(struct inode *inode)
381{
382 struct gfs2_sbd *sdp = inode->i_sb->s_fs_info;
383 struct gfs2_inode *ip = GFS2_I(inode);
384 struct gfs2_holder gh;
385 int error;
386
387 if (!inode->u.generic_ip)
388 goto out;
389
390 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &gh);
391 if (unlikely(error)) {
392 gfs2_glock_dq_uninit(&ip->i_iopen_gh);
393 goto out;
394 }
395
396 gfs2_glock_dq(&ip->i_iopen_gh);
397 gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh);
398 error = gfs2_glock_nq(&ip->i_iopen_gh);
399 if (error)
400 goto out_uninit;
401
402 if (S_ISDIR(ip->i_di.di_mode) &&
403 (ip->i_di.di_flags & GFS2_DIF_EXHASH)) {
404 error = gfs2_dir_exhash_dealloc(ip);
405 if (error)
406 goto out_unlock;
407 }
408
409 if (ip->i_di.di_eattr) {
410 error = gfs2_ea_dealloc(ip);
411 if (error)
412 goto out_unlock;
413 }
414
415 if (!gfs2_is_stuffed(ip)) {
416 error = gfs2_file_dealloc(ip);
417 if (error)
418 goto out_unlock;
419 }
420
421 error = gfs2_dinode_dealloc(ip);
422
423out_unlock:
424 gfs2_glock_dq(&ip->i_iopen_gh);
425out_uninit:
426 gfs2_holder_uninit(&ip->i_iopen_gh);
427 gfs2_glock_dq_uninit(&gh);
428 if (error)
429 fs_warn(sdp, "gfs2_delete_inode: %d\n", error);
430out:
431 truncate_inode_pages(&inode->i_data, 0);
432 clear_inode(inode);
433}
434
435
436
364static struct inode *gfs2_alloc_inode(struct super_block *sb) 437static struct inode *gfs2_alloc_inode(struct super_block *sb)
365{ 438{
366 struct gfs2_sbd *sdp = sb->s_fs_info; 439 struct gfs2_sbd *sdp = sb->s_fs_info;
@@ -370,8 +443,6 @@ static struct inode *gfs2_alloc_inode(struct super_block *sb)
370 if (ip) { 443 if (ip) {
371 ip->i_flags = 0; 444 ip->i_flags = 0;
372 ip->i_gl = NULL; 445 ip->i_gl = NULL;
373 ip->i_sbd = sdp;
374 ip->i_vnode = &ip->i_inode;
375 ip->i_greedy = gfs2_tune_get(sdp, gt_greedy_default); 446 ip->i_greedy = gfs2_tune_get(sdp, gt_greedy_default);
376 ip->i_last_pfault = jiffies; 447 ip->i_last_pfault = jiffies;
377 } 448 }
@@ -387,6 +458,7 @@ struct super_operations gfs2_super_ops = {
387 .alloc_inode = gfs2_alloc_inode, 458 .alloc_inode = gfs2_alloc_inode,
388 .destroy_inode = gfs2_destroy_inode, 459 .destroy_inode = gfs2_destroy_inode,
389 .write_inode = gfs2_write_inode, 460 .write_inode = gfs2_write_inode,
461 .delete_inode = gfs2_delete_inode,
390 .put_super = gfs2_put_super, 462 .put_super = gfs2_put_super,
391 .write_super = gfs2_write_super, 463 .write_super = gfs2_write_super,
392 .write_super_lockfs = gfs2_write_super_lockfs, 464 .write_super_lockfs = gfs2_write_super_lockfs,