diff options
Diffstat (limited to 'fs/gfs2/ops_super.c')
-rw-r--r-- | fs/gfs2/ops_super.c | 112 |
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 | ||
48 | static int gfs2_write_inode(struct inode *inode, int sync) | 53 | static 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 | ||
275 | static void gfs2_clear_inode(struct inode *inode) | 280 | static 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 | */ | ||
380 | static 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 | |||
423 | out_unlock: | ||
424 | gfs2_glock_dq(&ip->i_iopen_gh); | ||
425 | out_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); | ||
430 | out: | ||
431 | truncate_inode_pages(&inode->i_data, 0); | ||
432 | clear_inode(inode); | ||
433 | } | ||
434 | |||
435 | |||
436 | |||
364 | static struct inode *gfs2_alloc_inode(struct super_block *sb) | 437 | static 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, |