X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=fs%2Fgfs2%2Fops_super.c;h=6ced71240379d2c75c5b95adc9bb1fc6a40437b5;hb=e9fc2aa091ab8fa46e60d4c9d06a89305c441652;hp=ca6a4d81bc265639b71806f3e1a55ab9cf22fa35;hpb=b3b94faa5fe5968827ba0640ee9fba4b3e7f736e;p=linux-2.6 diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index ca6a4d81bc..6ced712403 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c @@ -1,10 +1,10 @@ /* * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. - * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU General Public License v.2. + * of the GNU General Public License version 2. */ #include @@ -12,27 +12,34 @@ #include #include #include -#include #include +#include #include #include #include #include -#include +#include +#include #include "gfs2.h" +#include "lm_interface.h" +#include "incore.h" #include "glock.h" #include "inode.h" #include "lm.h" #include "log.h" #include "mount.h" #include "ops_super.h" -#include "page.h" #include "quota.h" #include "recovery.h" #include "rgrp.h" #include "super.h" #include "sys.h" +#include "util.h" +#include "trans.h" +#include "dir.h" +#include "eattr.h" +#include "bmap.h" /** * gfs2_write_inode - Make sure the inode is stable on the disk @@ -44,14 +51,15 @@ static int gfs2_write_inode(struct inode *inode, int sync) { - struct gfs2_inode *ip = get_v2ip(inode); - - atomic_inc(&ip->i_sbd->sd_ops_super); - - if (current->flags & PF_MEMALLOC) - return 0; - if (ip && sync) - gfs2_log_flush_glock(ip->i_gl); + struct gfs2_inode *ip = GFS2_I(inode); + + /* Check this is a "normal" inode */ + if (inode->u.generic_ip) { + if (current->flags & PF_MEMALLOC) + return 0; + if (sync) + gfs2_log_flush(GFS2_SB(inode), ip->i_gl); + } return 0; } @@ -64,22 +72,22 @@ static int gfs2_write_inode(struct inode *inode, int sync) static void gfs2_put_super(struct super_block *sb) { - struct gfs2_sbd *sdp = get_v2sdp(sb); + struct gfs2_sbd *sdp = sb->s_fs_info; int error; if (!sdp) return; - atomic_inc(&sdp->sd_ops_super); + if (!strncmp(sb->s_type->name, "gfs2meta", 8)) + return; /* meta fs. don't do nothin' */ /* Unfreeze the filesystem, if we need to */ - down(&sdp->sd_freeze_lock); + mutex_lock(&sdp->sd_freeze_lock); if (sdp->sd_freeze_count) gfs2_glock_dq_uninit(&sdp->sd_freeze_gh); - up(&sdp->sd_freeze_lock); + mutex_unlock(&sdp->sd_freeze_lock); - kthread_stop(sdp->sd_inoded_process); kthread_stop(sdp->sd_quotad_process); kthread_stop(sdp->sd_logd_process); kthread_stop(sdp->sd_recoverd_process); @@ -92,18 +100,16 @@ static void gfs2_put_super(struct super_block *sb) if (error) gfs2_io_error(sdp); } - /* At this point, we're through modifying the disk */ /* Release stuff */ - gfs2_inode_put(sdp->sd_master_dir); - gfs2_inode_put(sdp->sd_jindex); - gfs2_inode_put(sdp->sd_inum_inode); - gfs2_inode_put(sdp->sd_statfs_inode); - gfs2_inode_put(sdp->sd_rindex); - gfs2_inode_put(sdp->sd_quota_inode); - gfs2_inode_put(sdp->sd_root_dir); + iput(sdp->sd_master_dir); + iput(sdp->sd_jindex); + iput(sdp->sd_inum_inode); + iput(sdp->sd_statfs_inode); + iput(sdp->sd_rindex); + iput(sdp->sd_quota_inode); gfs2_glock_put(sdp->sd_rename_gl); gfs2_glock_put(sdp->sd_trans_gl); @@ -113,36 +119,24 @@ static void gfs2_put_super(struct super_block *sb) gfs2_glock_dq_uninit(&sdp->sd_jinode_gh); gfs2_glock_dq_uninit(&sdp->sd_ir_gh); gfs2_glock_dq_uninit(&sdp->sd_sc_gh); - gfs2_glock_dq_uninit(&sdp->sd_ut_gh); gfs2_glock_dq_uninit(&sdp->sd_qc_gh); - gfs2_inode_put(sdp->sd_ir_inode); - gfs2_inode_put(sdp->sd_sc_inode); - gfs2_inode_put(sdp->sd_ut_inode); - gfs2_inode_put(sdp->sd_qc_inode); + iput(sdp->sd_ir_inode); + iput(sdp->sd_sc_inode); + iput(sdp->sd_qc_inode); } gfs2_glock_dq_uninit(&sdp->sd_live_gh); - gfs2_clear_rgrpd(sdp); gfs2_jindex_free(sdp); - /* Take apart glock structures and buffer lists */ gfs2_gl_hash_clear(sdp, WAIT); - /* Unmount the locking protocol */ gfs2_lm_unmount(sdp); /* At this point, we're through participating in the lockspace */ - gfs2_sys_fs_del(sdp); - - /* Get rid of any extra inodes */ - while (invalidate_inodes(sb)) - yield(); - vfree(sdp); - - set_v2sdp(sb, NULL); + sb->s_fs_info = NULL; } /** @@ -150,14 +144,13 @@ static void gfs2_put_super(struct super_block *sb) * @sb: the filesystem * * This function is called every time sync(2) is called. - * After this exits, all dirty buffers and synced. + * After this exits, all dirty buffers are synced. */ static void gfs2_write_super(struct super_block *sb) { - struct gfs2_sbd *sdp = get_v2sdp(sb); - atomic_inc(&sdp->sd_ops_super); - gfs2_log_flush(sdp); + struct gfs2_sbd *sdp = sb->s_fs_info; + gfs2_log_flush(sdp, NULL); } /** @@ -168,11 +161,9 @@ static void gfs2_write_super(struct super_block *sb) static void gfs2_write_super_lockfs(struct super_block *sb) { - struct gfs2_sbd *sdp = get_v2sdp(sb); + struct gfs2_sbd *sdp = sb->s_fs_info; int error; - atomic_inc(&sdp->sd_ops_super); - for (;;) { error = gfs2_freeze_fs(sdp); if (!error) @@ -201,9 +192,7 @@ static void gfs2_write_super_lockfs(struct super_block *sb) static void gfs2_unlockfs(struct super_block *sb) { - struct gfs2_sbd *sdp = get_v2sdp(sb); - - atomic_inc(&sdp->sd_ops_super); + struct gfs2_sbd *sdp = sb->s_fs_info; gfs2_unfreeze_fs(sdp); } @@ -215,14 +204,13 @@ static void gfs2_unlockfs(struct super_block *sb) * Returns: 0 on success or error code */ -static int gfs2_statfs(struct super_block *sb, struct kstatfs *buf) +static int gfs2_statfs(struct dentry *dentry, struct kstatfs *buf) { - struct gfs2_sbd *sdp = get_v2sdp(sb); + struct super_block *sb = dentry->d_inode->i_sb; + struct gfs2_sbd *sdp = sb->s_fs_info; struct gfs2_statfs_change sc; int error; - atomic_inc(&sdp->sd_ops_super); - if (gfs2_tune_get(sdp, gt_statfs_slow)) error = gfs2_statfs_slow(sdp, &sc); else @@ -231,8 +219,6 @@ static int gfs2_statfs(struct super_block *sb, struct kstatfs *buf) if (error) return error; - memset(buf, 0, sizeof(struct kstatfs)); - buf->f_type = GFS2_MAGIC; buf->f_bsize = sdp->sd_sb.sb_bsize; buf->f_blocks = sc.sc_total; @@ -256,11 +242,9 @@ static int gfs2_statfs(struct super_block *sb, struct kstatfs *buf) static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data) { - struct gfs2_sbd *sdp = get_v2sdp(sb); + struct gfs2_sbd *sdp = sb->s_fs_info; int error; - atomic_inc(&sdp->sd_ops_super); - error = gfs2_mount_args(sdp, data, 1); if (error) return error; @@ -296,18 +280,20 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data) static void gfs2_clear_inode(struct inode *inode) { - struct gfs2_inode *ip = get_v2ip(inode); - - atomic_inc(&get_v2sdp(inode->i_sb)->sd_ops_super); - - if (ip) { - spin_lock(&ip->i_spin); - ip->i_vnode = NULL; - set_v2ip(inode, NULL); - spin_unlock(&ip->i_spin); - + /* This tells us its a "real" inode and not one which only + * serves to contain an address space (see rgrp.c, meta_io.c) + * which therefore doesn't have its own glocks. + */ + if (inode->u.generic_ip) { + struct gfs2_inode *ip = GFS2_I(inode); + gfs2_glock_inode_squish(inode); + gfs2_assert(inode->i_sb->s_fs_info, ip->i_gl->gl_state == LM_ST_UNLOCKED); + ip->i_gl->gl_object = NULL; gfs2_glock_schedule_for_reclaim(ip->i_gl); - gfs2_inode_put(ip); + gfs2_glock_put(ip->i_gl); + ip->i_gl = NULL; + if (ip->i_iopen_gh.gh_gl) + gfs2_glock_dq_uninit(&ip->i_iopen_gh); } } @@ -321,11 +307,9 @@ static void gfs2_clear_inode(struct inode *inode) static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) { - struct gfs2_sbd *sdp = get_v2sdp(mnt->mnt_sb); + struct gfs2_sbd *sdp = mnt->mnt_sb->s_fs_info; struct gfs2_args *args = &sdp->sd_args; - atomic_inc(&sdp->sd_ops_super); - if (args->ar_lockproto[0]) seq_printf(s, ",lockproto=%s", args->ar_lockproto); if (args->ar_locktable[0]) @@ -387,8 +371,95 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) return 0; } +/* + * We have to (at the moment) hold the inodes main lock to cover + * the gap between unlocking the shared lock on the iopen lock and + * taking the exclusive lock. I'd rather do a shared -> exclusive + * conversion on the iopen lock, but we can change that later. This + * is safe, just less efficient. + */ +static void gfs2_delete_inode(struct inode *inode) +{ + struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; + struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_holder gh; + int error; + + if (!inode->u.generic_ip) + goto out; + + error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &gh); + if (unlikely(error)) { + gfs2_glock_dq_uninit(&ip->i_iopen_gh); + goto out; + } + + gfs2_glock_dq(&ip->i_iopen_gh); + gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh); + error = gfs2_glock_nq(&ip->i_iopen_gh); + if (error) + goto out_uninit; + + if (S_ISDIR(ip->i_di.di_mode) && + (ip->i_di.di_flags & GFS2_DIF_EXHASH)) { + error = gfs2_dir_exhash_dealloc(ip); + if (error) + goto out_unlock; + } + + if (ip->i_di.di_eattr) { + error = gfs2_ea_dealloc(ip); + if (error) + goto out_unlock; + } + + if (!gfs2_is_stuffed(ip)) { + error = gfs2_file_dealloc(ip); + if (error) + goto out_unlock; + } + + error = gfs2_dinode_dealloc(ip); + +out_unlock: + gfs2_glock_dq(&ip->i_iopen_gh); +out_uninit: + gfs2_holder_uninit(&ip->i_iopen_gh); + gfs2_glock_dq_uninit(&gh); + if (error) + fs_warn(sdp, "gfs2_delete_inode: %d\n", error); +out: + truncate_inode_pages(&inode->i_data, 0); + clear_inode(inode); +} + + + +static struct inode *gfs2_alloc_inode(struct super_block *sb) +{ + struct gfs2_sbd *sdp = sb->s_fs_info; + struct gfs2_inode *ip; + + ip = kmem_cache_alloc(gfs2_inode_cachep, GFP_KERNEL); + if (ip) { + ip->i_flags = 0; + ip->i_gl = NULL; + ip->i_greedy = gfs2_tune_get(sdp, gt_greedy_default); + ip->i_last_pfault = jiffies; + } + return &ip->i_inode; +} + +static void gfs2_destroy_inode(struct inode *inode) +{ + kmem_cache_free(gfs2_inode_cachep, inode); +} + struct super_operations gfs2_super_ops = { + .alloc_inode = gfs2_alloc_inode, + .destroy_inode = gfs2_destroy_inode, .write_inode = gfs2_write_inode, + .delete_inode = gfs2_delete_inode, .put_super = gfs2_put_super, .write_super = gfs2_write_super, .write_super_lockfs = gfs2_write_super_lockfs,