X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=fs%2Fgfs2%2Fops_super.c;h=18ed18c729e81e83411f5d96d89f7bf1252fd5b0;hb=8638460540749ddb1beca9e9a68d655a6fe6df65;hp=48a94522406ea50b57d59a7ad0244dacd7f4aff9;hpb=d92a8d48085df863032110d9ccb221cde98d14e1;p=linux-2.6 diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index 48a9452240..18ed18c729 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c @@ -1,6 +1,6 @@ /* * 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 @@ -18,21 +18,28 @@ #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,12 +51,15 @@ static int gfs2_write_inode(struct inode *inode, int sync) { - struct gfs2_inode *ip = get_v2ip(inode); - - 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; } @@ -62,12 +72,15 @@ 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; + if (!strncmp(sb->s_type->name, "gfs2meta", 8)) + return; /* meta fs. don't do nothin' */ + /* Unfreeze the filesystem, if we need to */ mutex_lock(&sdp->sd_freeze_lock); @@ -75,7 +88,6 @@ static void gfs2_put_super(struct super_block *sb) gfs2_glock_dq_uninit(&sdp->sd_freeze_gh); 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); @@ -88,7 +100,6 @@ 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 */ @@ -99,7 +110,6 @@ static void gfs2_put_super(struct super_block *sb) iput(sdp->sd_statfs_inode); iput(sdp->sd_rindex); iput(sdp->sd_quota_inode); - iput(sdp->sd_root_dir); gfs2_glock_put(sdp->sd_rename_gl); gfs2_glock_put(sdp->sd_trans_gl); @@ -109,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); iput(sdp->sd_ir_inode); iput(sdp->sd_sc_inode); - iput(sdp->sd_ut_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; } /** @@ -146,13 +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); - gfs2_log_flush(sdp); + struct gfs2_sbd *sdp = sb->s_fs_info; + gfs2_log_flush(sdp, NULL); } /** @@ -163,7 +161,7 @@ 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; for (;;) { @@ -194,7 +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); + struct gfs2_sbd *sdp = sb->s_fs_info; gfs2_unfreeze_fs(sdp); } @@ -206,9 +204,10 @@ 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; @@ -220,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; @@ -245,7 +242,7 @@ 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; error = gfs2_mount_args(sdp, data, 1); @@ -283,16 +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); - - 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); } } @@ -306,7 +307,7 @@ 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; if (args->ar_lockproto[0]) @@ -370,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,