Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 10 Oct 2008 18:02:22 +0000 (11:02 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 10 Oct 2008 18:02:22 +0000 (11:02 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw:
  GFS2: Support for I/O barriers
  GFS2: Add UUID to GFS2 sb
  GFS2: high time to take some time over atime
  GFS2: The war on bloat
  GFS2: GFS2 will panic if you misspell any mount options
  GFS2: Direct IO write at end of file error
  GFS2: Use an IS_ERR test rather than a NULL test
  GFS2: Fix race relating to glock min-hold time
  GFS2: Fix & clean up GFS2 rename
  GFS2: rm on multiple nodes causes panic
  GFS2: Fix metafs mounts
  GFS2: Fix debugfs glock file iterator

16 files changed:
fs/gfs2/glock.c
fs/gfs2/glock.h
fs/gfs2/incore.h
fs/gfs2/inode.c
fs/gfs2/inode.h
fs/gfs2/log.c
fs/gfs2/mount.c
fs/gfs2/ops_address.c
fs/gfs2/ops_file.c
fs/gfs2/ops_fstype.c
fs/gfs2/ops_inode.c
fs/gfs2/ops_super.c
fs/gfs2/super.c
fs/gfs2/super.h
fs/gfs2/sys.c
include/linux/gfs2_ondisk.h

index 13391e5..c962283 100644 (file)
@@ -1265,6 +1265,8 @@ static void blocking_cb(struct gfs2_sbd *sdp, struct lm_lockname *name,
        holdtime = gl->gl_tchange + gl->gl_ops->go_min_hold_time;
        if (time_before(now, holdtime))
                delay = holdtime - now;
+       if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags))
+               delay = gl->gl_ops->go_min_hold_time;
 
        spin_lock(&gl->gl_spin);
        handle_callback(gl, state, 1, delay);
@@ -1578,8 +1580,6 @@ static const char *hflags2str(char *buf, unsigned flags, unsigned long iflags)
                *p++ = 'a';
        if (flags & GL_EXACT)
                *p++ = 'E';
-       if (flags & GL_ATIME)
-               *p++ = 'a';
        if (flags & GL_NOCACHE)
                *p++ = 'c';
        if (test_bit(HIF_HOLDER, &iflags))
@@ -1816,15 +1816,17 @@ restart:
        if (gl) {
                gi->gl = hlist_entry(gl->gl_list.next,
                                     struct gfs2_glock, gl_list);
-               if (gi->gl)
-                       gfs2_glock_hold(gi->gl);
+       } else {
+               gi->gl = hlist_entry(gl_hash_table[gi->hash].hb_list.first,
+                                    struct gfs2_glock, gl_list);
        }
+       if (gi->gl)
+               gfs2_glock_hold(gi->gl);
        read_unlock(gl_lock_addr(gi->hash));
        if (gl)
                gfs2_glock_put(gl);
-       if (gl && gi->gl == NULL)
-               gi->hash++;
        while (gi->gl == NULL) {
+               gi->hash++;
                if (gi->hash >= GFS2_GL_HASH_SIZE)
                        return 1;
                read_lock(gl_lock_addr(gi->hash));
@@ -1833,7 +1835,6 @@ restart:
                if (gi->gl)
                        gfs2_glock_hold(gi->gl);
                read_unlock(gl_lock_addr(gi->hash));
-               gi->hash++;
        }
 
        if (gi->sdp != gi->gl->gl_sbd)
index 971d92a..695c6b1 100644 (file)
@@ -24,7 +24,6 @@
 #define GL_ASYNC               0x00000040
 #define GL_EXACT               0x00000080
 #define GL_SKIP                        0x00000100
-#define GL_ATIME               0x00000200
 #define GL_NOCACHE             0x00000400
 
 #define GLR_TRYFAILED          13
index 448697a..f566ec1 100644 (file)
@@ -386,20 +386,21 @@ struct gfs2_statfs_change_host {
 #define GFS2_DATA_ORDERED      2
 
 struct gfs2_args {
-       char ar_lockproto[GFS2_LOCKNAME_LEN]; /* Name of the Lock Protocol */
-       char ar_locktable[GFS2_LOCKNAME_LEN]; /* Name of the Lock Table */
-       char ar_hostdata[GFS2_LOCKNAME_LEN]; /* Host specific data */
-       int ar_spectator; /* Don't get a journal because we're always RO */
-       int ar_ignore_local_fs; /* Don't optimize even if local_fs is 1 */
-       int ar_localflocks; /* Let the VFS do flock|fcntl locks for us */
-       int ar_localcaching; /* Local-style caching (dangerous on multihost) */
-       int ar_debug; /* Oops on errors instead of trying to be graceful */
-       int ar_upgrade; /* Upgrade ondisk/multihost format */
-       unsigned int ar_num_glockd; /* Number of glockd threads */
-       int ar_posix_acl; /* Enable posix acls */
-       int ar_quota; /* off/account/on */
-       int ar_suiddir; /* suiddir support */
-       int ar_data; /* ordered/writeback */
+       char ar_lockproto[GFS2_LOCKNAME_LEN];   /* Name of the Lock Protocol */
+       char ar_locktable[GFS2_LOCKNAME_LEN];   /* Name of the Lock Table */
+       char ar_hostdata[GFS2_LOCKNAME_LEN];    /* Host specific data */
+       unsigned int ar_spectator:1;            /* Don't get a journal */
+       unsigned int ar_ignore_local_fs:1;      /* Ignore optimisations */
+       unsigned int ar_localflocks:1;          /* Let the VFS do flock|fcntl */
+       unsigned int ar_localcaching:1;         /* Local caching */
+       unsigned int ar_debug:1;                /* Oops on errors */
+       unsigned int ar_upgrade:1;              /* Upgrade ondisk format */
+       unsigned int ar_posix_acl:1;            /* Enable posix acls */
+       unsigned int ar_quota:2;                /* off/account/on */
+       unsigned int ar_suiddir:1;              /* suiddir support */
+       unsigned int ar_data:2;                 /* ordered/writeback */
+       unsigned int ar_meta:1;                 /* mount metafs */
+       unsigned int ar_num_glockd;             /* Number of glockd threads */
 };
 
 struct gfs2_tune {
@@ -419,7 +420,6 @@ struct gfs2_tune {
        unsigned int gt_quota_scale_den; /* Denominator */
        unsigned int gt_quota_cache_secs;
        unsigned int gt_quota_quantum; /* Secs between syncs to quota file */
-       unsigned int gt_atime_quantum; /* Min secs between atime updates */
        unsigned int gt_new_files_jdata;
        unsigned int gt_max_readahead; /* Max bytes to read-ahead from disk */
        unsigned int gt_stall_secs; /* Detects trouble! */
@@ -432,7 +432,7 @@ enum {
        SDF_JOURNAL_CHECKED     = 0,
        SDF_JOURNAL_LIVE        = 1,
        SDF_SHUTDOWN            = 2,
-       SDF_NOATIME             = 3,
+       SDF_NOBARRIERS          = 3,
 };
 
 #define GFS2_FSNAME_LEN                256
@@ -461,7 +461,6 @@ struct gfs2_sb_host {
 
 struct gfs2_sbd {
        struct super_block *sd_vfs;
-       struct super_block *sd_vfs_meta;
        struct kobject sd_kobj;
        unsigned long sd_flags; /* SDF_... */
        struct gfs2_sb_host sd_sb;
@@ -499,7 +498,9 @@ struct gfs2_sbd {
 
        /* Inode Stuff */
 
-       struct inode *sd_master_dir;
+       struct dentry *sd_master_dir;
+       struct dentry *sd_root_dir;
+
        struct inode *sd_jindex;
        struct inode *sd_inum_inode;
        struct inode *sd_statfs_inode;
@@ -634,7 +635,6 @@ struct gfs2_sbd {
        /* Debugging crud */
 
        unsigned long sd_last_warning;
-       struct vfsmount *sd_gfs2mnt;
        struct dentry *debugfs_dir;    /* debugfs directory */
        struct dentry *debugfs_dentry_glocks; /* for debugfs */
 };
index 8b0806a..7cee695 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/crc32.h>
 #include <linux/lm_interface.h>
 #include <linux/security.h>
+#include <linux/time.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -249,6 +250,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
 {
        struct gfs2_dinode_host *di = &ip->i_di;
        const struct gfs2_dinode *str = buf;
+       struct timespec atime;
        u16 height, depth;
 
        if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)))
@@ -275,8 +277,10 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
        di->di_size = be64_to_cpu(str->di_size);
        i_size_write(&ip->i_inode, di->di_size);
        gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks));
-       ip->i_inode.i_atime.tv_sec = be64_to_cpu(str->di_atime);
-       ip->i_inode.i_atime.tv_nsec = be32_to_cpu(str->di_atime_nsec);
+       atime.tv_sec = be64_to_cpu(str->di_atime);
+       atime.tv_nsec = be32_to_cpu(str->di_atime_nsec);
+       if (timespec_compare(&ip->i_inode.i_atime, &atime) < 0)
+               ip->i_inode.i_atime = atime;
        ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime);
        ip->i_inode.i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec);
        ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime);
@@ -1033,13 +1037,11 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
 
        if (bh)
                brelse(bh);
-       if (!inode)
-               return ERR_PTR(-ENOMEM);
        return inode;
 
 fail_gunlock2:
        gfs2_glock_dq_uninit(ghs + 1);
-       if (inode)
+       if (inode && !IS_ERR(inode))
                iput(inode);
 fail_gunlock:
        gfs2_glock_dq(ghs);
@@ -1140,54 +1142,6 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
        return 0;
 }
 
-/*
- * gfs2_ok_to_move - check if it's ok to move a directory to another directory
- * @this: move this
- * @to: to here
- *
- * Follow @to back to the root and make sure we don't encounter @this
- * Assumes we already hold the rename lock.
- *
- * Returns: errno
- */
-
-int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
-{
-       struct inode *dir = &to->i_inode;
-       struct super_block *sb = dir->i_sb;
-       struct inode *tmp;
-       struct qstr dotdot;
-       int error = 0;
-
-       gfs2_str2qstr(&dotdot, "..");
-
-       igrab(dir);
-
-       for (;;) {
-               if (dir == &this->i_inode) {
-                       error = -EINVAL;
-                       break;
-               }
-               if (dir == sb->s_root->d_inode) {
-                       error = 0;
-                       break;
-               }
-
-               tmp = gfs2_lookupi(dir, &dotdot, 1);
-               if (IS_ERR(tmp)) {
-                       error = PTR_ERR(tmp);
-                       break;
-               }
-
-               iput(dir);
-               dir = tmp;
-       }
-
-       iput(dir);
-
-       return error;
-}
-
 /**
  * gfs2_readlinki - return the contents of a symlink
  * @ip: the symlink's inode
@@ -1207,8 +1161,8 @@ int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len)
        unsigned int x;
        int error;
 
-       gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &i_gh);
-       error = gfs2_glock_nq_atime(&i_gh);
+       gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh);
+       error = gfs2_glock_nq(&i_gh);
        if (error) {
                gfs2_holder_uninit(&i_gh);
                return error;
@@ -1243,101 +1197,6 @@ out:
        return error;
 }
 
-/**
- * gfs2_glock_nq_atime - Acquire a hold on an inode's glock, and
- *       conditionally update the inode's atime
- * @gh: the holder to acquire
- *
- * Tests atime (access time) for gfs2_read, gfs2_readdir and gfs2_mmap
- * Update if the difference between the current time and the inode's current
- * atime is greater than an interval specified at mount.
- *
- * Returns: errno
- */
-
-int gfs2_glock_nq_atime(struct gfs2_holder *gh)
-{
-       struct gfs2_glock *gl = gh->gh_gl;
-       struct gfs2_sbd *sdp = gl->gl_sbd;
-       struct gfs2_inode *ip = gl->gl_object;
-       s64 quantum = gfs2_tune_get(sdp, gt_atime_quantum);
-       unsigned int state;
-       int flags;
-       int error;
-       struct timespec tv = CURRENT_TIME;
-
-       if (gfs2_assert_warn(sdp, gh->gh_flags & GL_ATIME) ||
-           gfs2_assert_warn(sdp, !(gh->gh_flags & GL_ASYNC)) ||
-           gfs2_assert_warn(sdp, gl->gl_ops == &gfs2_inode_glops))
-               return -EINVAL;
-
-       state = gh->gh_state;
-       flags = gh->gh_flags;
-
-       error = gfs2_glock_nq(gh);
-       if (error)
-               return error;
-
-       if (test_bit(SDF_NOATIME, &sdp->sd_flags) ||
-           (sdp->sd_vfs->s_flags & MS_RDONLY))
-               return 0;
-
-       if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) {
-               gfs2_glock_dq(gh);
-               gfs2_holder_reinit(LM_ST_EXCLUSIVE, gh->gh_flags & ~LM_FLAG_ANY,
-                                  gh);
-               error = gfs2_glock_nq(gh);
-               if (error)
-                       return error;
-
-               /* Verify that atime hasn't been updated while we were
-                  trying to get exclusive lock. */
-
-               tv = CURRENT_TIME;
-               if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) {
-                       struct buffer_head *dibh;
-                       struct gfs2_dinode *di;
-
-                       error = gfs2_trans_begin(sdp, RES_DINODE, 0);
-                       if (error == -EROFS)
-                               return 0;
-                       if (error)
-                               goto fail;
-
-                       error = gfs2_meta_inode_buffer(ip, &dibh);
-                       if (error)
-                               goto fail_end_trans;
-
-                       ip->i_inode.i_atime = tv;
-
-                       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-                       di = (struct gfs2_dinode *)dibh->b_data;
-                       di->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
-                       di->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec);
-                       brelse(dibh);
-
-                       gfs2_trans_end(sdp);
-               }
-
-               /* If someone else has asked for the glock,
-                  unlock and let them have it. Then reacquire
-                  in the original state. */
-               if (gfs2_glock_is_blocking(gl)) {
-                       gfs2_glock_dq(gh);
-                       gfs2_holder_reinit(state, flags, gh);
-                       return gfs2_glock_nq(gh);
-               }
-       }
-
-       return 0;
-
-fail_end_trans:
-       gfs2_trans_end(sdp);
-fail:
-       gfs2_glock_dq(gh);
-       return error;
-}
-
 static int
 __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr)
 {
index 58f9607..2d43f69 100644 (file)
@@ -91,9 +91,7 @@ int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
 int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
                   const struct gfs2_inode *ip);
 int gfs2_permission(struct inode *inode, int mask);
-int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to);
 int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len);
-int gfs2_glock_nq_atime(struct gfs2_holder *gh);
 int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr);
 struct inode *gfs2_lookup_simple(struct inode *dip, const char *name);
 void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf);
index 6c6af9f..ad30585 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
+#include <linux/bio.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -584,7 +585,6 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull)
        memset(bh->b_data, 0, bh->b_size);
        set_buffer_uptodate(bh);
        clear_buffer_dirty(bh);
-       unlock_buffer(bh);
 
        gfs2_ail1_empty(sdp, 0);
        tail = current_tail(sdp);
@@ -601,8 +601,23 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull)
        hash = gfs2_disk_hash(bh->b_data, sizeof(struct gfs2_log_header));
        lh->lh_hash = cpu_to_be32(hash);
 
-       set_buffer_dirty(bh);
-       if (sync_dirty_buffer(bh))
+       bh->b_end_io = end_buffer_write_sync;
+       if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags))
+               goto skip_barrier;
+       get_bh(bh);
+       submit_bh(WRITE_BARRIER | (1 << BIO_RW_META), bh);
+       wait_on_buffer(bh);
+       if (buffer_eopnotsupp(bh)) {
+               clear_buffer_eopnotsupp(bh);
+               set_buffer_uptodate(bh);
+               set_bit(SDF_NOBARRIERS, &sdp->sd_flags);
+               lock_buffer(bh);
+skip_barrier:
+               get_bh(bh);
+               submit_bh(WRITE_SYNC | (1 << BIO_RW_META), bh);
+               wait_on_buffer(bh);
+       }
+       if (!buffer_uptodate(bh))
                gfs2_io_error_bh(sdp, bh);
        brelse(bh);
 
index b941f9f..df48333 100644 (file)
@@ -42,6 +42,7 @@ enum {
        Opt_nosuiddir,
        Opt_data_writeback,
        Opt_data_ordered,
+       Opt_meta,
        Opt_err,
 };
 
@@ -66,6 +67,7 @@ static match_table_t tokens = {
        {Opt_nosuiddir, "nosuiddir"},
        {Opt_data_writeback, "data=writeback"},
        {Opt_data_ordered, "data=ordered"},
+       {Opt_meta, "meta"},
        {Opt_err, NULL}
 };
 
@@ -239,6 +241,11 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount)
                case Opt_data_ordered:
                        args->ar_data = GFS2_DATA_ORDERED;
                        break;
+               case Opt_meta:
+                       if (remount && args->ar_meta != 1)
+                               goto cant_remount;
+                       args->ar_meta = 1;
+                       break;
                case Opt_err:
                default:
                        fs_info(sdp, "unknown option: %s\n", o);
index e64a1b0..2756381 100644 (file)
@@ -512,8 +512,8 @@ static int gfs2_readpage(struct file *file, struct page *page)
        int error;
 
        unlock_page(page);
-       gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
-       error = gfs2_glock_nq_atime(&gh);
+       gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
+       error = gfs2_glock_nq(&gh);
        if (unlikely(error))
                goto out;
        error = AOP_TRUNCATED_PAGE;
@@ -594,8 +594,8 @@ static int gfs2_readpages(struct file *file, struct address_space *mapping,
        struct gfs2_holder gh;
        int ret;
 
-       gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
-       ret = gfs2_glock_nq_atime(&gh);
+       gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
+       ret = gfs2_glock_nq(&gh);
        if (unlikely(ret))
                goto out_uninit;
        if (!gfs2_is_stuffed(ip))
@@ -636,8 +636,8 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
        unsigned to = from + len;
        struct page *page;
 
-       gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME, &ip->i_gh);
-       error = gfs2_glock_nq_atime(&ip->i_gh);
+       gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh);
+       error = gfs2_glock_nq(&ip->i_gh);
        if (unlikely(error))
                goto out_uninit;
 
@@ -975,7 +975,7 @@ static int gfs2_ok_for_dio(struct gfs2_inode *ip, int rw, loff_t offset)
        if (gfs2_is_stuffed(ip))
                return 0;
 
-       if (offset > i_size_read(&ip->i_inode))
+       if (offset >= i_size_read(&ip->i_inode))
                return 0;
        return 1;
 }
@@ -1000,8 +1000,8 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
         * unfortunately have the option of only flushing a range like
         * the VFS does.
         */
-       gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, GL_ATIME, &gh);
-       rv = gfs2_glock_nq_atime(&gh);
+       gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, 0, &gh);
+       rv = gfs2_glock_nq(&gh);
        if (rv)
                return rv;
        rv = gfs2_ok_for_dio(ip, rw, offset);
index e9a366d..3a747f8 100644 (file)
@@ -89,8 +89,8 @@ static int gfs2_readdir(struct file *file, void *dirent, filldir_t filldir)
        u64 offset = file->f_pos;
        int error;
 
-       gfs2_holder_init(dip->i_gl, LM_ST_SHARED, GL_ATIME, &d_gh);
-       error = gfs2_glock_nq_atime(&d_gh);
+       gfs2_holder_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
+       error = gfs2_glock_nq(&d_gh);
        if (error) {
                gfs2_holder_uninit(&d_gh);
                return error;
@@ -153,8 +153,8 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
        int error;
        u32 fsflags;
 
-       gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
-       error = gfs2_glock_nq_atime(&gh);
+       gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
+       error = gfs2_glock_nq(&gh);
        if (error)
                return error;
 
@@ -351,8 +351,8 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page)
        struct gfs2_alloc *al;
        int ret;
 
-       gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME, &gh);
-       ret = gfs2_glock_nq_atime(&gh);
+       gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
+       ret = gfs2_glock_nq(&gh);
        if (ret)
                goto out;
 
@@ -434,8 +434,8 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)
        struct gfs2_holder i_gh;
        int error;
 
-       gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &i_gh);
-       error = gfs2_glock_nq_atime(&i_gh);
+       gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh);
+       error = gfs2_glock_nq(&i_gh);
        if (error) {
                gfs2_holder_uninit(&i_gh);
                return error;
index b4d1d64..b117fcf 100644 (file)
 #define DO 0
 #define UNDO 1
 
+static const u32 gfs2_old_fs_formats[] = {
+        0
+};
+
+static const u32 gfs2_old_multihost_formats[] = {
+        0
+};
+
+/**
+ * gfs2_tune_init - Fill a gfs2_tune structure with default values
+ * @gt: tune
+ *
+ */
+
+static void gfs2_tune_init(struct gfs2_tune *gt)
+{
+       spin_lock_init(&gt->gt_spin);
+
+       gt->gt_demote_secs = 300;
+       gt->gt_incore_log_blocks = 1024;
+       gt->gt_log_flush_secs = 60;
+       gt->gt_recoverd_secs = 60;
+       gt->gt_logd_secs = 1;
+       gt->gt_quotad_secs = 5;
+       gt->gt_quota_simul_sync = 64;
+       gt->gt_quota_warn_period = 10;
+       gt->gt_quota_scale_num = 1;
+       gt->gt_quota_scale_den = 1;
+       gt->gt_quota_cache_secs = 300;
+       gt->gt_quota_quantum = 60;
+       gt->gt_new_files_jdata = 0;
+       gt->gt_max_readahead = 1 << 18;
+       gt->gt_stall_secs = 600;
+       gt->gt_complain_secs = 10;
+       gt->gt_statfs_quantum = 30;
+       gt->gt_statfs_slow = 0;
+}
+
 static struct gfs2_sbd *init_sbd(struct super_block *sb)
 {
        struct gfs2_sbd *sdp;
@@ -96,21 +134,271 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
        return sdp;
 }
 
-static void init_vfs(struct super_block *sb, unsigned noatime)
+
+/**
+ * gfs2_check_sb - Check superblock
+ * @sdp: the filesystem
+ * @sb: The superblock
+ * @silent: Don't print a message if the check fails
+ *
+ * Checks the version code of the FS is one that we understand how to
+ * read and that the sizes of the various on-disk structures have not
+ * changed.
+ */
+
+static int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent)
 {
-       struct gfs2_sbd *sdp = sb->s_fs_info;
+       unsigned int x;
 
-       sb->s_magic = GFS2_MAGIC;
-       sb->s_op = &gfs2_super_ops;
-       sb->s_export_op = &gfs2_export_ops;
-       sb->s_time_gran = 1;
-       sb->s_maxbytes = MAX_LFS_FILESIZE;
+       if (sb->sb_magic != GFS2_MAGIC ||
+           sb->sb_type != GFS2_METATYPE_SB) {
+               if (!silent)
+                       printk(KERN_WARNING "GFS2: not a GFS2 filesystem\n");
+               return -EINVAL;
+       }
+
+       /*  If format numbers match exactly, we're done.  */
+
+       if (sb->sb_fs_format == GFS2_FORMAT_FS &&
+           sb->sb_multihost_format == GFS2_FORMAT_MULTI)
+               return 0;
+
+       if (sb->sb_fs_format != GFS2_FORMAT_FS) {
+               for (x = 0; gfs2_old_fs_formats[x]; x++)
+                       if (gfs2_old_fs_formats[x] == sb->sb_fs_format)
+                               break;
+
+               if (!gfs2_old_fs_formats[x]) {
+                       printk(KERN_WARNING
+                              "GFS2: code version (%u, %u) is incompatible "
+                              "with ondisk format (%u, %u)\n",
+                              GFS2_FORMAT_FS, GFS2_FORMAT_MULTI,
+                              sb->sb_fs_format, sb->sb_multihost_format);
+                       printk(KERN_WARNING
+                              "GFS2: I don't know how to upgrade this FS\n");
+                       return -EINVAL;
+               }
+       }
+
+       if (sb->sb_multihost_format != GFS2_FORMAT_MULTI) {
+               for (x = 0; gfs2_old_multihost_formats[x]; x++)
+                       if (gfs2_old_multihost_formats[x] ==
+                           sb->sb_multihost_format)
+                               break;
+
+               if (!gfs2_old_multihost_formats[x]) {
+                       printk(KERN_WARNING
+                              "GFS2: code version (%u, %u) is incompatible "
+                              "with ondisk format (%u, %u)\n",
+                              GFS2_FORMAT_FS, GFS2_FORMAT_MULTI,
+                              sb->sb_fs_format, sb->sb_multihost_format);
+                       printk(KERN_WARNING
+                              "GFS2: I don't know how to upgrade this FS\n");
+                       return -EINVAL;
+               }
+       }
+
+       if (!sdp->sd_args.ar_upgrade) {
+               printk(KERN_WARNING
+                      "GFS2: code version (%u, %u) is incompatible "
+                      "with ondisk format (%u, %u)\n",
+                      GFS2_FORMAT_FS, GFS2_FORMAT_MULTI,
+                      sb->sb_fs_format, sb->sb_multihost_format);
+               printk(KERN_INFO
+                      "GFS2: Use the \"upgrade\" mount option to upgrade "
+                      "the FS\n");
+               printk(KERN_INFO "GFS2: See the manual for more details\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void end_bio_io_page(struct bio *bio, int error)
+{
+       struct page *page = bio->bi_private;
 
-       if (sb->s_flags & (MS_NOATIME | MS_NODIRATIME))
-               set_bit(noatime, &sdp->sd_flags);
+       if (!error)
+               SetPageUptodate(page);
+       else
+               printk(KERN_WARNING "gfs2: error %d reading superblock\n", error);
+       unlock_page(page);
+}
+
+static void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf)
+{
+       const struct gfs2_sb *str = buf;
+
+       sb->sb_magic = be32_to_cpu(str->sb_header.mh_magic);
+       sb->sb_type = be32_to_cpu(str->sb_header.mh_type);
+       sb->sb_format = be32_to_cpu(str->sb_header.mh_format);
+       sb->sb_fs_format = be32_to_cpu(str->sb_fs_format);
+       sb->sb_multihost_format = be32_to_cpu(str->sb_multihost_format);
+       sb->sb_bsize = be32_to_cpu(str->sb_bsize);
+       sb->sb_bsize_shift = be32_to_cpu(str->sb_bsize_shift);
+       sb->sb_master_dir.no_addr = be64_to_cpu(str->sb_master_dir.no_addr);
+       sb->sb_master_dir.no_formal_ino = be64_to_cpu(str->sb_master_dir.no_formal_ino);
+       sb->sb_root_dir.no_addr = be64_to_cpu(str->sb_root_dir.no_addr);
+       sb->sb_root_dir.no_formal_ino = be64_to_cpu(str->sb_root_dir.no_formal_ino);
+
+       memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN);
+       memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN);
+}
+
+/**
+ * gfs2_read_super - Read the gfs2 super block from disk
+ * @sdp: The GFS2 super block
+ * @sector: The location of the super block
+ * @error: The error code to return
+ *
+ * This uses the bio functions to read the super block from disk
+ * because we want to be 100% sure that we never read cached data.
+ * A super block is read twice only during each GFS2 mount and is
+ * never written to by the filesystem. The first time its read no
+ * locks are held, and the only details which are looked at are those
+ * relating to the locking protocol. Once locking is up and working,
+ * the sb is read again under the lock to establish the location of
+ * the master directory (contains pointers to journals etc) and the
+ * root directory.
+ *
+ * Returns: 0 on success or error
+ */
+
+static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector)
+{
+       struct super_block *sb = sdp->sd_vfs;
+       struct gfs2_sb *p;
+       struct page *page;
+       struct bio *bio;
+
+       page = alloc_page(GFP_NOFS);
+       if (unlikely(!page))
+               return -ENOBUFS;
+
+       ClearPageUptodate(page);
+       ClearPageDirty(page);
+       lock_page(page);
+
+       bio = bio_alloc(GFP_NOFS, 1);
+       if (unlikely(!bio)) {
+               __free_page(page);
+               return -ENOBUFS;
+       }
 
-       /* Don't let the VFS update atimes.  GFS2 handles this itself. */
-       sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
+       bio->bi_sector = sector * (sb->s_blocksize >> 9);
+       bio->bi_bdev = sb->s_bdev;
+       bio_add_page(bio, page, PAGE_SIZE, 0);
+
+       bio->bi_end_io = end_bio_io_page;
+       bio->bi_private = page;
+       submit_bio(READ_SYNC | (1 << BIO_RW_META), bio);
+       wait_on_page_locked(page);
+       bio_put(bio);
+       if (!PageUptodate(page)) {
+               __free_page(page);
+               return -EIO;
+       }
+       p = kmap(page);
+       gfs2_sb_in(&sdp->sd_sb, p);
+       kunmap(page);
+       __free_page(page);
+       return 0;
+}
+/**
+ * gfs2_read_sb - Read super block
+ * @sdp: The GFS2 superblock
+ * @gl: the glock for the superblock (assumed to be held)
+ * @silent: Don't print message if mount fails
+ *
+ */
+
+static int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent)
+{
+       u32 hash_blocks, ind_blocks, leaf_blocks;
+       u32 tmp_blocks;
+       unsigned int x;
+       int error;
+
+       error = gfs2_read_super(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift);
+       if (error) {
+               if (!silent)
+                       fs_err(sdp, "can't read superblock\n");
+               return error;
+       }
+
+       error = gfs2_check_sb(sdp, &sdp->sd_sb, silent);
+       if (error)
+               return error;
+
+       sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift -
+                              GFS2_BASIC_BLOCK_SHIFT;
+       sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift;
+       sdp->sd_diptrs = (sdp->sd_sb.sb_bsize -
+                         sizeof(struct gfs2_dinode)) / sizeof(u64);
+       sdp->sd_inptrs = (sdp->sd_sb.sb_bsize -
+                         sizeof(struct gfs2_meta_header)) / sizeof(u64);
+       sdp->sd_jbsize = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header);
+       sdp->sd_hash_bsize = sdp->sd_sb.sb_bsize / 2;
+       sdp->sd_hash_bsize_shift = sdp->sd_sb.sb_bsize_shift - 1;
+       sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(u64);
+       sdp->sd_qc_per_block = (sdp->sd_sb.sb_bsize -
+                               sizeof(struct gfs2_meta_header)) /
+                               sizeof(struct gfs2_quota_change);
+
+       /* Compute maximum reservation required to add a entry to a directory */
+
+       hash_blocks = DIV_ROUND_UP(sizeof(u64) * (1 << GFS2_DIR_MAX_DEPTH),
+                            sdp->sd_jbsize);
+
+       ind_blocks = 0;
+       for (tmp_blocks = hash_blocks; tmp_blocks > sdp->sd_diptrs;) {
+               tmp_blocks = DIV_ROUND_UP(tmp_blocks, sdp->sd_inptrs);
+               ind_blocks += tmp_blocks;
+       }
+
+       leaf_blocks = 2 + GFS2_DIR_MAX_DEPTH;
+
+       sdp->sd_max_dirres = hash_blocks + ind_blocks + leaf_blocks;
+
+       sdp->sd_heightsize[0] = sdp->sd_sb.sb_bsize -
+                               sizeof(struct gfs2_dinode);
+       sdp->sd_heightsize[1] = sdp->sd_sb.sb_bsize * sdp->sd_diptrs;
+       for (x = 2;; x++) {
+               u64 space, d;
+               u32 m;
+
+               space = sdp->sd_heightsize[x - 1] * sdp->sd_inptrs;
+               d = space;
+               m = do_div(d, sdp->sd_inptrs);
+
+               if (d != sdp->sd_heightsize[x - 1] || m)
+                       break;
+               sdp->sd_heightsize[x] = space;
+       }
+       sdp->sd_max_height = x;
+       sdp->sd_heightsize[x] = ~0;
+       gfs2_assert(sdp, sdp->sd_max_height <= GFS2_MAX_META_HEIGHT);
+
+       sdp->sd_jheightsize[0] = sdp->sd_sb.sb_bsize -
+                                sizeof(struct gfs2_dinode);
+       sdp->sd_jheightsize[1] = sdp->sd_jbsize * sdp->sd_diptrs;
+       for (x = 2;; x++) {
+               u64 space, d;
+               u32 m;
+
+               space = sdp->sd_jheightsize[x - 1] * sdp->sd_inptrs;
+               d = space;
+               m = do_div(d, sdp->sd_inptrs);
+
+               if (d != sdp->sd_jheightsize[x - 1] || m)
+                       break;
+               sdp->sd_jheightsize[x] = space;
+       }
+       sdp->sd_max_jheight = x;
+       sdp->sd_jheightsize[x] = ~0;
+       gfs2_assert(sdp, sdp->sd_max_jheight <= GFS2_MAX_META_HEIGHT);
+
+       return 0;
 }
 
 static int init_names(struct gfs2_sbd *sdp, int silent)
@@ -224,51 +512,59 @@ fail:
        return error;
 }
 
-static inline struct inode *gfs2_lookup_root(struct super_block *sb,
-                                            u64 no_addr)
+static int gfs2_lookup_root(struct super_block *sb, struct dentry **dptr,
+                           u64 no_addr, const char *name)
 {
-       return gfs2_inode_lookup(sb, DT_DIR, no_addr, 0, 0);
+       struct gfs2_sbd *sdp = sb->s_fs_info;
+       struct dentry *dentry;
+       struct inode *inode;
+
+       inode = gfs2_inode_lookup(sb, DT_DIR, no_addr, 0, 0);
+       if (IS_ERR(inode)) {
+               fs_err(sdp, "can't read in %s inode: %ld\n", name, PTR_ERR(inode));
+               return PTR_ERR(inode);
+       }
+       dentry = d_alloc_root(inode);
+       if (!dentry) {
+               fs_err(sdp, "can't alloc %s dentry\n", name);
+               iput(inode);
+               return -ENOMEM;
+       }
+       dentry->d_op = &gfs2_dops;
+       *dptr = dentry;
+       return 0;
 }
 
-static int init_sb(struct gfs2_sbd *sdp, int silent, int undo)
+static int init_sb(struct gfs2_sbd *sdp, int silent)
 {
        struct super_block *sb = sdp->sd_vfs;
        struct gfs2_holder sb_gh;
        u64 no_addr;
-       struct inode *inode;
-       int error = 0;
+       int ret;
 
-       if (undo) {
-               if (sb->s_root) {
-                       dput(sb->s_root);
-                       sb->s_root = NULL;
-               }
-               return 0;
+       ret = gfs2_glock_nq_num(sdp, GFS2_SB_LOCK, &gfs2_meta_glops,
+                               LM_ST_SHARED, 0, &sb_gh);
+       if (ret) {
+               fs_err(sdp, "can't acquire superblock glock: %d\n", ret);
+               return ret;
        }
 
-       error = gfs2_glock_nq_num(sdp, GFS2_SB_LOCK, &gfs2_meta_glops,
-                                LM_ST_SHARED, 0, &sb_gh);
-       if (error) {
-               fs_err(sdp, "can't acquire superblock glock: %d\n", error);
-               return error;
-       }
-
-       error = gfs2_read_sb(sdp, sb_gh.gh_gl, silent);
-       if (error) {
-               fs_err(sdp, "can't read superblock: %d\n", error);
+       ret = gfs2_read_sb(sdp, sb_gh.gh_gl, silent);
+       if (ret) {
+               fs_err(sdp, "can't read superblock: %d\n", ret);
                goto out;
        }
 
        /* Set up the buffer cache and SB for real */
        if (sdp->sd_sb.sb_bsize < bdev_hardsect_size(sb->s_bdev)) {
-               error = -EINVAL;
+               ret = -EINVAL;
                fs_err(sdp, "FS block size (%u) is too small for device "
                       "block size (%u)\n",
                       sdp->sd_sb.sb_bsize, bdev_hardsect_size(sb->s_bdev));
                goto out;
        }
        if (sdp->sd_sb.sb_bsize > PAGE_SIZE) {
-               error = -EINVAL;
+               ret = -EINVAL;
                fs_err(sdp, "FS block size (%u) is too big for machine "
                       "page size (%u)\n",
                       sdp->sd_sb.sb_bsize, (unsigned int)PAGE_SIZE);
@@ -278,26 +574,21 @@ static int init_sb(struct gfs2_sbd *sdp, int silent, int undo)
 
        /* Get the root inode */
        no_addr = sdp->sd_sb.sb_root_dir.no_addr;
-       if (sb->s_type == &gfs2meta_fs_type)
-               no_addr = sdp->sd_sb.sb_master_dir.no_addr;
-       inode = gfs2_lookup_root(sb, no_addr);
-       if (IS_ERR(inode)) {
-               error = PTR_ERR(inode);
-               fs_err(sdp, "can't read in root inode: %d\n", error);
+       ret = gfs2_lookup_root(sb, &sdp->sd_root_dir, no_addr, "root");
+       if (ret)
                goto out;
-       }
 
-       sb->s_root = d_alloc_root(inode);
-       if (!sb->s_root) {
-               fs_err(sdp, "can't get root dentry\n");
-               error = -ENOMEM;
-               iput(inode);
-       } else
-               sb->s_root->d_op = &gfs2_dops;
-       
+       /* Get the master inode */
+       no_addr = sdp->sd_sb.sb_master_dir.no_addr;
+       ret = gfs2_lookup_root(sb, &sdp->sd_master_dir, no_addr, "master");
+       if (ret) {
+               dput(sdp->sd_root_dir);
+               goto out;
+       }
+       sb->s_root = dget(sdp->sd_args.ar_meta ? sdp->sd_master_dir : sdp->sd_root_dir);
 out:
        gfs2_glock_dq_uninit(&sb_gh);
-       return error;
+       return ret;
 }
 
 /**
@@ -372,6 +663,7 @@ static void gfs2_lm_others_may_mount(struct gfs2_sbd *sdp)
 
 static int init_journal(struct gfs2_sbd *sdp, int undo)
 {
+       struct inode *master = sdp->sd_master_dir->d_inode;
        struct gfs2_holder ji_gh;
        struct task_struct *p;
        struct gfs2_inode *ip;
@@ -383,7 +675,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
                goto fail_recoverd;
        }
 
-       sdp->sd_jindex = gfs2_lookup_simple(sdp->sd_master_dir, "jindex");
+       sdp->sd_jindex = gfs2_lookup_simple(master, "jindex");
        if (IS_ERR(sdp->sd_jindex)) {
                fs_err(sdp, "can't lookup journal index: %d\n", error);
                return PTR_ERR(sdp->sd_jindex);
@@ -506,25 +798,17 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo)
 {
        int error = 0;
        struct gfs2_inode *ip;
-       struct inode *inode;
+       struct inode *master = sdp->sd_master_dir->d_inode;
 
        if (undo)
                goto fail_qinode;
 
-       inode = gfs2_lookup_root(sdp->sd_vfs, sdp->sd_sb.sb_master_dir.no_addr);
-       if (IS_ERR(inode)) {
-               error = PTR_ERR(inode);
-               fs_err(sdp, "can't read in master directory: %d\n", error);
-               goto fail;
-       }
-       sdp->sd_master_dir = inode;
-
        error = init_journal(sdp, undo);
        if (error)
-               goto fail_master;
+               goto fail;
 
        /* Read in the master inode number inode */
-       sdp->sd_inum_inode = gfs2_lookup_simple(sdp->sd_master_dir, "inum");
+       sdp->sd_inum_inode = gfs2_lookup_simple(master, "inum");
        if (IS_ERR(sdp->sd_inum_inode)) {
                error = PTR_ERR(sdp->sd_inum_inode);
                fs_err(sdp, "can't read in inum inode: %d\n", error);
@@ -533,7 +817,7 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo)
 
 
        /* Read in the master statfs inode */
-       sdp->sd_statfs_inode = gfs2_lookup_simple(sdp->sd_master_dir, "statfs");
+       sdp->sd_statfs_inode = gfs2_lookup_simple(master, "statfs");
        if (IS_ERR(sdp->sd_statfs_inode)) {
                error = PTR_ERR(sdp->sd_statfs_inode);
                fs_err(sdp, "can't read in statfs inode: %d\n", error);
@@ -541,7 +825,7 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo)
        }
 
        /* Read in the resource index inode */
-       sdp->sd_rindex = gfs2_lookup_simple(sdp->sd_master_dir, "rindex");
+       sdp->sd_rindex = gfs2_lookup_simple(master, "rindex");
        if (IS_ERR(sdp->sd_rindex)) {
                error = PTR_ERR(sdp->sd_rindex);
                fs_err(sdp, "can't get resource index inode: %d\n", error);
@@ -552,7 +836,7 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo)
        sdp->sd_rindex_uptodate = 0;
 
        /* Read in the quota inode */
-       sdp->sd_quota_inode = gfs2_lookup_simple(sdp->sd_master_dir, "quota");
+       sdp->sd_quota_inode = gfs2_lookup_simple(master, "quota");
        if (IS_ERR(sdp->sd_quota_inode)) {
                error = PTR_ERR(sdp->sd_quota_inode);
                fs_err(sdp, "can't get quota file inode: %d\n", error);
@@ -571,8 +855,6 @@ fail_inum:
        iput(sdp->sd_inum_inode);
 fail_journal:
        init_journal(sdp, UNDO);
-fail_master:
-       iput(sdp->sd_master_dir);
 fail:
        return error;
 }
@@ -583,6 +865,7 @@ static int init_per_node(struct gfs2_sbd *sdp, int undo)
        char buf[30];
        int error = 0;
        struct gfs2_inode *ip;
+       struct inode *master = sdp->sd_master_dir->d_inode;
 
        if (sdp->sd_args.ar_spectator)
                return 0;
@@ -590,7 +873,7 @@ static int init_per_node(struct gfs2_sbd *sdp, int undo)
        if (undo)
                goto fail_qc_gh;
 
-       pn = gfs2_lookup_simple(sdp->sd_master_dir, "per_node");
+       pn = gfs2_lookup_simple(master, "per_node");
        if (IS_ERR(pn)) {
                error = PTR_ERR(pn);
                fs_err(sdp, "can't find per_node directory: %d\n", error);
@@ -800,7 +1083,11 @@ static int fill_super(struct super_block *sb, void *data, int silent)
                goto fail;
        }
 
-       init_vfs(sb, SDF_NOATIME);
+       sb->s_magic = GFS2_MAGIC;
+       sb->s_op = &gfs2_super_ops;
+       sb->s_export_op = &gfs2_export_ops;
+       sb->s_time_gran = 1;
+       sb->s_maxbytes = MAX_LFS_FILESIZE;
 
        /* Set up the buffer cache and fill in some fake block size values
           to allow us to read-in the on-disk superblock. */
@@ -828,7 +1115,7 @@ static int fill_super(struct super_block *sb, void *data, int silent)
        if (error)
                goto fail_lm;
 
-       error = init_sb(sdp, silent, DO);
+       error = init_sb(sdp, silent);
        if (error)
                goto fail_locking;
 
@@ -869,7 +1156,11 @@ fail_per_node:
 fail_inodes:
        init_inodes(sdp, UNDO);
 fail_sb:
-       init_sb(sdp, 0, UNDO);
+       if (sdp->sd_root_dir)
+               dput(sdp->sd_root_dir);
+       if (sdp->sd_master_dir)
+               dput(sdp->sd_master_dir);
+       sb->s_root = NULL;
 fail_locking:
        init_locking(sdp, &mount_gh, UNDO);
 fail_lm:
@@ -887,151 +1178,63 @@ fail:
 }
 
 static int gfs2_get_sb(struct file_system_type *fs_type, int flags,
-               const char *dev_name, void *data, struct vfsmount *mnt)
+                      const char *dev_name, void *data, struct vfsmount *mnt)
 {
-       struct super_block *sb;
-       struct gfs2_sbd *sdp;
-       int error = get_sb_bdev(fs_type, flags, dev_name, data, fill_super, mnt);
-       if (error)
-               goto out;
-       sb = mnt->mnt_sb;
-       sdp = sb->s_fs_info;
-       sdp->sd_gfs2mnt = mnt;
-out:
-       return error;
+       return get_sb_bdev(fs_type, flags, dev_name, data, fill_super, mnt);
 }
 
-static int fill_super_meta(struct super_block *sb, struct super_block *new,
-                          void *data, int silent)
+static struct super_block *get_gfs2_sb(const char *dev_name)
 {
-       struct gfs2_sbd *sdp = sb->s_fs_info;
-       struct inode *inode;
-       int error = 0;
-
-       new->s_fs_info = sdp;
-       sdp->sd_vfs_meta = sb;
-
-       init_vfs(new, SDF_NOATIME);
-
-        /* Get the master inode */
-       inode = igrab(sdp->sd_master_dir);
-
-       new->s_root = d_alloc_root(inode);
-       if (!new->s_root) {
-               fs_err(sdp, "can't get root dentry\n");
-               error = -ENOMEM;
-               iput(inode);
-       } else
-               new->s_root->d_op = &gfs2_dops;
-
-       return error;
-}
-
-static int set_bdev_super(struct super_block *s, void *data)
-{
-       s->s_bdev = data;
-       s->s_dev = s->s_bdev->bd_dev;
-       return 0;
-}
-
-static int test_bdev_super(struct super_block *s, void *data)
-{
-       return s->s_bdev == data;
-}
-
-static struct super_block* get_gfs2_sb(const char *dev_name)
-{
-       struct kstat stat;
+       struct super_block *sb;
        struct nameidata nd;
-       struct super_block *sb = NULL, *s;
        int error;
 
        error = path_lookup(dev_name, LOOKUP_FOLLOW, &nd);
        if (error) {
-               printk(KERN_WARNING "GFS2: path_lookup on %s returned error\n",
-                      dev_name);
-               goto out;
-       }
-       error = vfs_getattr(nd.path.mnt, nd.path.dentry, &stat);
-
-       list_for_each_entry(s, &gfs2_fs_type.fs_supers, s_instances) {
-               if ((S_ISBLK(stat.mode) && s->s_dev == stat.rdev) ||
-                   (S_ISDIR(stat.mode) &&
-                    s == nd.path.dentry->d_inode->i_sb)) {
-                       sb = s;
-                       goto free_nd;
-               }
+               printk(KERN_WARNING "GFS2: path_lookup on %s returned error %d\n",
+                      dev_name, error);
+               return NULL;
        }
-
-       printk(KERN_WARNING "GFS2: Unrecognized block device or "
-              "mount point %s\n", dev_name);
-
-free_nd:
+       sb = nd.path.dentry->d_inode->i_sb;
+       if (sb && (sb->s_type == &gfs2_fs_type))
+               atomic_inc(&sb->s_active);
+       else
+               sb = NULL;
        path_put(&nd.path);
-out:
        return sb;
 }
 
 static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags,
                            const char *dev_name, void *data, struct vfsmount *mnt)
 {
-       int error = 0;
-       struct super_block *sb = NULL, *new;
+       struct super_block *sb = NULL;
        struct gfs2_sbd *sdp;
 
        sb = get_gfs2_sb(dev_name);
        if (!sb) {
                printk(KERN_WARNING "GFS2: gfs2 mount does not exist\n");
-               error = -ENOENT;
-               goto error;
+               return -ENOENT;
        }
        sdp = sb->s_fs_info;
-       if (sdp->sd_vfs_meta) {
-               printk(KERN_WARNING "GFS2: gfs2meta mount already exists\n");
-               error = -EBUSY;
-               goto error;
-       }
-       down(&sb->s_bdev->bd_mount_sem);
-       new = sget(fs_type, test_bdev_super, set_bdev_super, sb->s_bdev);
-       up(&sb->s_bdev->bd_mount_sem);
-       if (IS_ERR(new)) {
-               error = PTR_ERR(new);
-               goto error;
-       }
-       new->s_flags = flags;
-       strlcpy(new->s_id, sb->s_id, sizeof(new->s_id));
-       sb_set_blocksize(new, sb->s_blocksize);
-       error = fill_super_meta(sb, new, data, flags & MS_SILENT ? 1 : 0);
-       if (error) {
-               up_write(&new->s_umount);
-               deactivate_super(new);
-               goto error;
-       }
-
-       new->s_flags |= MS_ACTIVE;
-
-       /* Grab a reference to the gfs2 mount point */
-       atomic_inc(&sdp->sd_gfs2mnt->mnt_count);
-       return simple_set_mnt(mnt, new);
-error:
-       return error;
+       mnt->mnt_sb = sb;
+       mnt->mnt_root = dget(sdp->sd_master_dir);
+       return 0;
 }
 
 static void gfs2_kill_sb(struct super_block *sb)
 {
-       if (sb->s_fs_info) {
-               gfs2_delete_debugfs_file(sb->s_fs_info);
-               gfs2_meta_syncfs(sb->s_fs_info);
+       struct gfs2_sbd *sdp = sb->s_fs_info;
+       if (sdp) {
+               gfs2_meta_syncfs(sdp);
+               dput(sdp->sd_root_dir);
+               dput(sdp->sd_master_dir);
+               sdp->sd_root_dir = NULL;
+               sdp->sd_master_dir = NULL;
        }
+       shrink_dcache_sb(sb);
        kill_block_super(sb);
-}
-
-static void gfs2_kill_sb_meta(struct super_block *sb)
-{
-       struct gfs2_sbd *sdp = sb->s_fs_info;
-       generic_shutdown_super(sb);
-       sdp->sd_vfs_meta = NULL;
-       atomic_dec(&sdp->sd_gfs2mnt->mnt_count);
+       if (sdp)
+               gfs2_delete_debugfs_file(sdp);
 }
 
 struct file_system_type gfs2_fs_type = {
@@ -1046,7 +1249,6 @@ struct file_system_type gfs2meta_fs_type = {
        .name = "gfs2meta",
        .fs_flags = FS_REQUIRES_DEV,
        .get_sb = gfs2_get_sb_meta,
-       .kill_sb = gfs2_kill_sb_meta,
        .owner = THIS_MODULE,
 };
 
index e2c62f7..534e1e2 100644 (file)
@@ -159,9 +159,13 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
        gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
        gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1);
 
-       error = gfs2_glock_nq_m(2, ghs);
+       error = gfs2_glock_nq(ghs); /* parent */
        if (error)
-               goto out;
+               goto out_parent;
+
+       error = gfs2_glock_nq(ghs + 1); /* child */
+       if (error)
+               goto out_child;
 
        error = gfs2_permission(dir, MAY_WRITE | MAY_EXEC);
        if (error)
@@ -245,8 +249,10 @@ out_alloc:
        if (alloc_required)
                gfs2_alloc_put(dip);
 out_gunlock:
-       gfs2_glock_dq_m(2, ghs);
-out:
+       gfs2_glock_dq(ghs + 1);
+out_child:
+       gfs2_glock_dq(ghs);
+out_parent:
        gfs2_holder_uninit(ghs);
        gfs2_holder_uninit(ghs + 1);
        if (!error) {
@@ -302,7 +308,7 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
 
        error = gfs2_unlink_ok(dip, &dentry->d_name, ip);
        if (error)
-               goto out_rgrp;
+               goto out_gunlock;
 
        error = gfs2_trans_begin(sdp, 2*RES_DINODE + RES_LEAF + RES_RG_BIT, 0);
        if (error)
@@ -316,6 +322,7 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
 
 out_end_trans:
        gfs2_trans_end(sdp);
+out_gunlock:
        gfs2_glock_dq(ghs + 2);
 out_rgrp:
        gfs2_holder_uninit(ghs + 2);
@@ -485,7 +492,6 @@ static int gfs2_rmdir(struct inode *dir, struct dentry *dentry)
        struct gfs2_holder ri_gh;
        int error;
 
-
        error = gfs2_rindex_hold(sdp, &ri_gh);
        if (error)
                return error;
@@ -495,9 +501,17 @@ static int gfs2_rmdir(struct inode *dir, struct dentry *dentry)
        rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr);
        gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2);
 
-       error = gfs2_glock_nq_m(3, ghs);
+       error = gfs2_glock_nq(ghs); /* parent */
        if (error)
-               goto out;
+               goto out_parent;
+
+       error = gfs2_glock_nq(ghs + 1); /* child */
+       if (error)
+               goto out_child;
+
+       error = gfs2_glock_nq(ghs + 2); /* rgrp */
+       if (error)
+               goto out_rgrp;
 
        error = gfs2_unlink_ok(dip, &dentry->d_name, ip);
        if (error)
@@ -523,11 +537,15 @@ static int gfs2_rmdir(struct inode *dir, struct dentry *dentry)
        gfs2_trans_end(sdp);
 
 out_gunlock:
-       gfs2_glock_dq_m(3, ghs);
-out:
-       gfs2_holder_uninit(ghs);
-       gfs2_holder_uninit(ghs + 1);
+       gfs2_glock_dq(ghs + 2);
+out_rgrp:
        gfs2_holder_uninit(ghs + 2);
+       gfs2_glock_dq(ghs + 1);
+out_child:
+       gfs2_holder_uninit(ghs + 1);
+       gfs2_glock_dq(ghs);
+out_parent:
+       gfs2_holder_uninit(ghs);
        gfs2_glock_dq_uninit(&ri_gh);
        return error;
 }
@@ -571,6 +589,54 @@ static int gfs2_mknod(struct inode *dir, struct dentry *dentry, int mode,
        return 0;
 }
 
+/*
+ * gfs2_ok_to_move - check if it's ok to move a directory to another directory
+ * @this: move this
+ * @to: to here
+ *
+ * Follow @to back to the root and make sure we don't encounter @this
+ * Assumes we already hold the rename lock.
+ *
+ * Returns: errno
+ */
+
+static int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
+{
+       struct inode *dir = &to->i_inode;
+       struct super_block *sb = dir->i_sb;
+       struct inode *tmp;
+       struct qstr dotdot;
+       int error = 0;
+
+       gfs2_str2qstr(&dotdot, "..");
+
+       igrab(dir);
+
+       for (;;) {
+               if (dir == &this->i_inode) {
+                       error = -EINVAL;
+                       break;
+               }
+               if (dir == sb->s_root->d_inode) {
+                       error = 0;
+                       break;
+               }
+
+               tmp = gfs2_lookupi(dir, &dotdot, 1);
+               if (IS_ERR(tmp)) {
+                       error = PTR_ERR(tmp);
+                       break;
+               }
+
+               iput(dir);
+               dir = tmp;
+       }
+
+       iput(dir);
+
+       return error;
+}
+
 /**
  * gfs2_rename - Rename a file
  * @odir: Parent directory of old file name
@@ -589,7 +655,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
        struct gfs2_inode *ip = GFS2_I(odentry->d_inode);
        struct gfs2_inode *nip = NULL;
        struct gfs2_sbd *sdp = GFS2_SB(odir);
-       struct gfs2_holder ghs[5], r_gh;
+       struct gfs2_holder ghs[5], r_gh = { .gh_gl = NULL, };
        struct gfs2_rgrpd *nrgd;
        unsigned int num_gh;
        int dir_rename = 0;
@@ -603,19 +669,20 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
                        return 0;
        }
 
-       /* Make sure we aren't trying to move a dirctory into it's subdir */
-
-       if (S_ISDIR(ip->i_inode.i_mode) && odip != ndip) {
-               dir_rename = 1;
 
-               error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE, 0,
-                                          &r_gh);
+       if (odip != ndip) {
+               error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE,
+                                          0, &r_gh);
                if (error)
                        goto out;
 
-               error = gfs2_ok_to_move(ip, ndip);
-               if (error)
-                       goto out_gunlock_r;
+               if (S_ISDIR(ip->i_inode.i_mode)) {
+                       dir_rename = 1;
+                       /* don't move a dirctory into it's subdir */
+                       error = gfs2_ok_to_move(ip, ndip);
+                       if (error)
+                               goto out_gunlock_r;
+               }
        }
 
        num_gh = 1;
@@ -639,9 +706,11 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
                        gfs2_holder_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh++);
        }
 
-       error = gfs2_glock_nq_m(num_gh, ghs);
-       if (error)
-               goto out_uninit;
+       for (x = 0; x < num_gh; x++) {
+               error = gfs2_glock_nq(ghs + x);
+               if (error)
+                       goto out_gunlock;
+       }
 
        /* Check out the old directory */
 
@@ -804,12 +873,12 @@ out_alloc:
        if (alloc_required)
                gfs2_alloc_put(ndip);
 out_gunlock:
-       gfs2_glock_dq_m(num_gh, ghs);
-out_uninit:
-       for (x = 0; x < num_gh; x++)
+       while (x--) {
+               gfs2_glock_dq(ghs + x);
                gfs2_holder_uninit(ghs + x);
+       }
 out_gunlock_r:
-       if (dir_rename)
+       if (r_gh.gh_gl)
                gfs2_glock_dq_uninit(&r_gh);
 out:
        return error;
index f66ea0f..d5355d9 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
 #include <linux/lm_interface.h>
+#include <linux/time.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -38,6 +39,7 @@
 #include "dir.h"
 #include "eattr.h"
 #include "bmap.h"
+#include "meta_io.h"
 
 /**
  * gfs2_write_inode - Make sure the inode is stable on the disk
 static int gfs2_write_inode(struct inode *inode, int sync)
 {
        struct gfs2_inode *ip = GFS2_I(inode);
-
-       /* Check this is a "normal" inode */
-       if (test_bit(GIF_USER, &ip->i_flags)) {
-               if (current->flags & PF_MEMALLOC)
-                       return 0;
-               if (sync)
-                       gfs2_log_flush(GFS2_SB(inode), ip->i_gl);
+       struct gfs2_sbd *sdp = GFS2_SB(inode);
+       struct gfs2_holder gh;
+       struct buffer_head *bh;
+       struct timespec atime;
+       struct gfs2_dinode *di;
+       int ret = 0;
+
+       /* Check this is a "normal" inode, etc */
+       if (!test_bit(GIF_USER, &ip->i_flags) ||
+           (current->flags & PF_MEMALLOC))
+               return 0;
+       ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
+       if (ret)
+               goto do_flush;
+       ret = gfs2_trans_begin(sdp, RES_DINODE, 0);
+       if (ret)
+               goto do_unlock;
+       ret = gfs2_meta_inode_buffer(ip, &bh);
+       if (ret == 0) {
+               di = (struct gfs2_dinode *)bh->b_data;
+               atime.tv_sec = be64_to_cpu(di->di_atime);
+               atime.tv_nsec = be32_to_cpu(di->di_atime_nsec);
+               if (timespec_compare(&inode->i_atime, &atime) > 0) {
+                       gfs2_trans_add_bh(ip->i_gl, bh, 1);
+                       gfs2_dinode_out(ip, bh->b_data);
+               }
+               brelse(bh);
        }
+       gfs2_trans_end(sdp);
+do_unlock:
+       gfs2_glock_dq_uninit(&gh);
+do_flush:
+       if (sync != 0)
+               gfs2_log_flush(GFS2_SB(inode), ip->i_gl);
+       return ret;
+}
 
-       return 0;
+/**
+ * gfs2_make_fs_ro - Turn a Read-Write FS into a Read-Only one
+ * @sdp: the filesystem
+ *
+ * Returns: errno
+ */
+
+static int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
+{
+       struct gfs2_holder t_gh;
+       int error;
+
+       gfs2_quota_sync(sdp);
+       gfs2_statfs_sync(sdp);
+
+       error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE,
+                                  &t_gh);
+       if (error && !test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
+               return error;
+
+       gfs2_meta_syncfs(sdp);
+       gfs2_log_shutdown(sdp);
+
+       clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags);
+
+       if (t_gh.gh_gl)
+               gfs2_glock_dq_uninit(&t_gh);
+
+       gfs2_quota_cleanup(sdp);
+
+       return error;
 }
 
 /**
@@ -73,12 +133,6 @@ static void gfs2_put_super(struct super_block *sb)
        struct gfs2_sbd *sdp = sb->s_fs_info;
        int error;
 
-       if (!sdp)
-               return;
-
-       if (!strncmp(sb->s_type->name, "gfs2meta", 8))
-               return; /* Nothing to do */
-
        /*  Unfreeze the filesystem, if we need to  */
 
        mutex_lock(&sdp->sd_freeze_lock);
@@ -101,7 +155,6 @@ static void gfs2_put_super(struct super_block *sb)
 
        /*  Release stuff  */
 
-       iput(sdp->sd_master_dir);
        iput(sdp->sd_jindex);
        iput(sdp->sd_inum_inode);
        iput(sdp->sd_statfs_inode);
@@ -152,6 +205,7 @@ static void gfs2_write_super(struct super_block *sb)
  *
  * Flushes the log to disk.
  */
+
 static int gfs2_sync_fs(struct super_block *sb, int wait)
 {
        sb->s_dirt = 0;
@@ -270,14 +324,6 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data)
                }
        }
 
-       if (*flags & (MS_NOATIME | MS_NODIRATIME))
-               set_bit(SDF_NOATIME, &sdp->sd_flags);
-       else
-               clear_bit(SDF_NOATIME, &sdp->sd_flags);
-
-       /* Don't let the VFS update atimes.  GFS2 handles this itself. */
-       *flags |= MS_NOATIME | MS_NODIRATIME;
-
        return error;
 }
 
@@ -295,6 +341,7 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data)
  * inode's blocks, or alternatively pass the baton on to another
  * node for later deallocation.
  */
+
 static void gfs2_drop_inode(struct inode *inode)
 {
        struct gfs2_inode *ip = GFS2_I(inode);
@@ -333,6 +380,16 @@ static void gfs2_clear_inode(struct inode *inode)
        }
 }
 
+static int is_ancestor(const struct dentry *d1, const struct dentry *d2)
+{
+       do {
+               if (d1 == d2)
+                       return 1;
+               d1 = d1->d_parent;
+       } while (!IS_ROOT(d1));
+       return 0;
+}
+
 /**
  * gfs2_show_options - Show mount options for /proc/mounts
  * @s: seq_file structure
@@ -346,6 +403,8 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
        struct gfs2_sbd *sdp = mnt->mnt_sb->s_fs_info;
        struct gfs2_args *args = &sdp->sd_args;
 
+       if (is_ancestor(mnt->mnt_root, sdp->sd_master_dir))
+               seq_printf(s, ",meta");
        if (args->ar_lockproto[0])
                seq_printf(s, ",lockproto=%s", args->ar_lockproto);
        if (args->ar_locktable[0])
@@ -414,6 +473,7 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
  * 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;
@@ -478,8 +538,6 @@ out:
        clear_inode(inode);
 }
 
-
-
 static struct inode *gfs2_alloc_inode(struct super_block *sb)
 {
        struct gfs2_inode *ip;
index ca83199..c3ba3d9 100644 (file)
 #include "trans.h"
 #include "util.h"
 
-static const u32 gfs2_old_fs_formats[] = {
-        0
-};
-
-static const u32 gfs2_old_multihost_formats[] = {
-        0
-};
-
-/**
- * gfs2_tune_init - Fill a gfs2_tune structure with default values
- * @gt: tune
- *
- */
-
-void gfs2_tune_init(struct gfs2_tune *gt)
-{
-       spin_lock_init(&gt->gt_spin);
-
-       gt->gt_demote_secs = 300;
-       gt->gt_incore_log_blocks = 1024;
-       gt->gt_log_flush_secs = 60;
-       gt->gt_recoverd_secs = 60;
-       gt->gt_logd_secs = 1;
-       gt->gt_quotad_secs = 5;
-       gt->gt_quota_simul_sync = 64;
-       gt->gt_quota_warn_period = 10;
-       gt->gt_quota_scale_num = 1;
-       gt->gt_quota_scale_den = 1;
-       gt->gt_quota_cache_secs = 300;
-       gt->gt_quota_quantum = 60;
-       gt->gt_atime_quantum = 3600;
-       gt->gt_new_files_jdata = 0;
-       gt->gt_max_readahead = 1 << 18;
-       gt->gt_stall_secs = 600;
-       gt->gt_complain_secs = 10;
-       gt->gt_statfs_quantum = 30;
-       gt->gt_statfs_slow = 0;
-}
-
-/**
- * gfs2_check_sb - Check superblock
- * @sdp: the filesystem
- * @sb: The superblock
- * @silent: Don't print a message if the check fails
- *
- * Checks the version code of the FS is one that we understand how to
- * read and that the sizes of the various on-disk structures have not
- * changed.
- */
-
-int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent)
-{
-       unsigned int x;
-
-       if (sb->sb_magic != GFS2_MAGIC ||
-           sb->sb_type != GFS2_METATYPE_SB) {
-               if (!silent)
-                       printk(KERN_WARNING "GFS2: not a GFS2 filesystem\n");
-               return -EINVAL;
-       }
-
-       /*  If format numbers match exactly, we're done.  */
-
-       if (sb->sb_fs_format == GFS2_FORMAT_FS &&
-           sb->sb_multihost_format == GFS2_FORMAT_MULTI)
-               return 0;
-
-       if (sb->sb_fs_format != GFS2_FORMAT_FS) {
-               for (x = 0; gfs2_old_fs_formats[x]; x++)
-                       if (gfs2_old_fs_formats[x] == sb->sb_fs_format)
-                               break;
-
-               if (!gfs2_old_fs_formats[x]) {
-                       printk(KERN_WARNING
-                              "GFS2: code version (%u, %u) is incompatible "
-                              "with ondisk format (%u, %u)\n",
-                              GFS2_FORMAT_FS, GFS2_FORMAT_MULTI,
-                              sb->sb_fs_format, sb->sb_multihost_format);
-                       printk(KERN_WARNING
-                              "GFS2: I don't know how to upgrade this FS\n");
-                       return -EINVAL;
-               }
-       }
-
-       if (sb->sb_multihost_format != GFS2_FORMAT_MULTI) {
-               for (x = 0; gfs2_old_multihost_formats[x]; x++)
-                       if (gfs2_old_multihost_formats[x] ==
-                           sb->sb_multihost_format)
-                               break;
-
-               if (!gfs2_old_multihost_formats[x]) {
-                       printk(KERN_WARNING
-                              "GFS2: code version (%u, %u) is incompatible "
-                              "with ondisk format (%u, %u)\n",
-                              GFS2_FORMAT_FS, GFS2_FORMAT_MULTI,
-                              sb->sb_fs_format, sb->sb_multihost_format);
-                       printk(KERN_WARNING
-                              "GFS2: I don't know how to upgrade this FS\n");
-                       return -EINVAL;
-               }
-       }
-
-       if (!sdp->sd_args.ar_upgrade) {
-               printk(KERN_WARNING
-                      "GFS2: code version (%u, %u) is incompatible "
-                      "with ondisk format (%u, %u)\n",
-                      GFS2_FORMAT_FS, GFS2_FORMAT_MULTI,
-                      sb->sb_fs_format, sb->sb_multihost_format);
-               printk(KERN_INFO
-                      "GFS2: Use the \"upgrade\" mount option to upgrade "
-                      "the FS\n");
-               printk(KERN_INFO "GFS2: See the manual for more details\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-
-static void end_bio_io_page(struct bio *bio, int error)
-{
-       struct page *page = bio->bi_private;
-
-       if (!error)
-               SetPageUptodate(page);
-       else
-               printk(KERN_WARNING "gfs2: error %d reading superblock\n", error);
-       unlock_page(page);
-}
-
-static void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf)
-{
-       const struct gfs2_sb *str = buf;
-
-       sb->sb_magic = be32_to_cpu(str->sb_header.mh_magic);
-       sb->sb_type = be32_to_cpu(str->sb_header.mh_type);
-       sb->sb_format = be32_to_cpu(str->sb_header.mh_format);
-       sb->sb_fs_format = be32_to_cpu(str->sb_fs_format);
-       sb->sb_multihost_format = be32_to_cpu(str->sb_multihost_format);
-       sb->sb_bsize = be32_to_cpu(str->sb_bsize);
-       sb->sb_bsize_shift = be32_to_cpu(str->sb_bsize_shift);
-       sb->sb_master_dir.no_addr = be64_to_cpu(str->sb_master_dir.no_addr);
-       sb->sb_master_dir.no_formal_ino = be64_to_cpu(str->sb_master_dir.no_formal_ino);
-       sb->sb_root_dir.no_addr = be64_to_cpu(str->sb_root_dir.no_addr);
-       sb->sb_root_dir.no_formal_ino = be64_to_cpu(str->sb_root_dir.no_formal_ino);
-
-       memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN);
-       memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN);
-}
-
-/**
- * gfs2_read_super - Read the gfs2 super block from disk
- * @sdp: The GFS2 super block
- * @sector: The location of the super block
- * @error: The error code to return
- *
- * This uses the bio functions to read the super block from disk
- * because we want to be 100% sure that we never read cached data.
- * A super block is read twice only during each GFS2 mount and is
- * never written to by the filesystem. The first time its read no
- * locks are held, and the only details which are looked at are those
- * relating to the locking protocol. Once locking is up and working,
- * the sb is read again under the lock to establish the location of
- * the master directory (contains pointers to journals etc) and the
- * root directory.
- *
- * Returns: 0 on success or error
- */
-
-int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector)
-{
-       struct super_block *sb = sdp->sd_vfs;
-       struct gfs2_sb *p;
-       struct page *page;
-       struct bio *bio;
-
-       page = alloc_page(GFP_NOFS);
-       if (unlikely(!page))
-               return -ENOBUFS;
-
-       ClearPageUptodate(page);
-       ClearPageDirty(page);
-       lock_page(page);
-
-       bio = bio_alloc(GFP_NOFS, 1);
-       if (unlikely(!bio)) {
-               __free_page(page);
-               return -ENOBUFS;
-       }
-
-       bio->bi_sector = sector * (sb->s_blocksize >> 9);
-       bio->bi_bdev = sb->s_bdev;
-       bio_add_page(bio, page, PAGE_SIZE, 0);
-
-       bio->bi_end_io = end_bio_io_page;
-       bio->bi_private = page;
-       submit_bio(READ_SYNC | (1 << BIO_RW_META), bio);
-       wait_on_page_locked(page);
-       bio_put(bio);
-       if (!PageUptodate(page)) {
-               __free_page(page);
-               return -EIO;
-       }
-       p = kmap(page);
-       gfs2_sb_in(&sdp->sd_sb, p);
-       kunmap(page);
-       __free_page(page);
-       return 0;
-}
-
-/**
- * gfs2_read_sb - Read super block
- * @sdp: The GFS2 superblock
- * @gl: the glock for the superblock (assumed to be held)
- * @silent: Don't print message if mount fails
- *
- */
-
-int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent)
-{
-       u32 hash_blocks, ind_blocks, leaf_blocks;
-       u32 tmp_blocks;
-       unsigned int x;
-       int error;
-
-       error = gfs2_read_super(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift);
-       if (error) {
-               if (!silent)
-                       fs_err(sdp, "can't read superblock\n");
-               return error;
-       }
-
-       error = gfs2_check_sb(sdp, &sdp->sd_sb, silent);
-       if (error)
-               return error;
-
-       sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift -
-                              GFS2_BASIC_BLOCK_SHIFT;
-       sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift;
-       sdp->sd_diptrs = (sdp->sd_sb.sb_bsize -
-                         sizeof(struct gfs2_dinode)) / sizeof(u64);
-       sdp->sd_inptrs = (sdp->sd_sb.sb_bsize -
-                         sizeof(struct gfs2_meta_header)) / sizeof(u64);
-       sdp->sd_jbsize = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header);
-       sdp->sd_hash_bsize = sdp->sd_sb.sb_bsize / 2;
-       sdp->sd_hash_bsize_shift = sdp->sd_sb.sb_bsize_shift - 1;
-       sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(u64);
-       sdp->sd_qc_per_block = (sdp->sd_sb.sb_bsize -
-                               sizeof(struct gfs2_meta_header)) /
-                               sizeof(struct gfs2_quota_change);
-
-       /* Compute maximum reservation required to add a entry to a directory */
-
-       hash_blocks = DIV_ROUND_UP(sizeof(u64) * (1 << GFS2_DIR_MAX_DEPTH),
-                            sdp->sd_jbsize);
-
-       ind_blocks = 0;
-       for (tmp_blocks = hash_blocks; tmp_blocks > sdp->sd_diptrs;) {
-               tmp_blocks = DIV_ROUND_UP(tmp_blocks, sdp->sd_inptrs);
-               ind_blocks += tmp_blocks;
-       }
-
-       leaf_blocks = 2 + GFS2_DIR_MAX_DEPTH;
-
-       sdp->sd_max_dirres = hash_blocks + ind_blocks + leaf_blocks;
-
-       sdp->sd_heightsize[0] = sdp->sd_sb.sb_bsize -
-                               sizeof(struct gfs2_dinode);
-       sdp->sd_heightsize[1] = sdp->sd_sb.sb_bsize * sdp->sd_diptrs;
-       for (x = 2;; x++) {
-               u64 space, d;
-               u32 m;
-
-               space = sdp->sd_heightsize[x - 1] * sdp->sd_inptrs;
-               d = space;
-               m = do_div(d, sdp->sd_inptrs);
-
-               if (d != sdp->sd_heightsize[x - 1] || m)
-                       break;
-               sdp->sd_heightsize[x] = space;
-       }
-       sdp->sd_max_height = x;
-       sdp->sd_heightsize[x] = ~0;
-       gfs2_assert(sdp, sdp->sd_max_height <= GFS2_MAX_META_HEIGHT);
-
-       sdp->sd_jheightsize[0] = sdp->sd_sb.sb_bsize -
-                                sizeof(struct gfs2_dinode);
-       sdp->sd_jheightsize[1] = sdp->sd_jbsize * sdp->sd_diptrs;
-       for (x = 2;; x++) {
-               u64 space, d;
-               u32 m;
-
-               space = sdp->sd_jheightsize[x - 1] * sdp->sd_inptrs;
-               d = space;
-               m = do_div(d, sdp->sd_inptrs);
-
-               if (d != sdp->sd_jheightsize[x - 1] || m)
-                       break;
-               sdp->sd_jheightsize[x] = space;
-       }
-       sdp->sd_max_jheight = x;
-       sdp->sd_jheightsize[x] = ~0;
-       gfs2_assert(sdp, sdp->sd_max_jheight <= GFS2_MAX_META_HEIGHT);
-
-       return 0;
-}
-
 /**
  * gfs2_jindex_hold - Grab a lock on the jindex
  * @sdp: The GFS2 superblock
@@ -581,39 +274,6 @@ fail:
        return error;
 }
 
-/**
- * gfs2_make_fs_ro - Turn a Read-Write FS into a Read-Only one
- * @sdp: the filesystem
- *
- * Returns: errno
- */
-
-int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
-{
-       struct gfs2_holder t_gh;
-       int error;
-
-       gfs2_quota_sync(sdp);
-       gfs2_statfs_sync(sdp);
-
-       error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE,
-                                  &t_gh);
-       if (error && !test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
-               return error;
-
-       gfs2_meta_syncfs(sdp);
-       gfs2_log_shutdown(sdp);
-
-       clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags);
-
-       if (t_gh.gh_gl)
-               gfs2_glock_dq_uninit(&t_gh);
-
-       gfs2_quota_cleanup(sdp);
-
-       return error;
-}
-
 static void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf)
 {
        const struct gfs2_statfs_change *str = buf;
index 44361ec..50a4c9b 100644 (file)
 
 #include "incore.h"
 
-void gfs2_tune_init(struct gfs2_tune *gt);
-
-int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent);
-int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent);
-int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector);
 void gfs2_lm_unmount(struct gfs2_sbd *sdp);
 
 static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp)
@@ -40,7 +35,6 @@ int gfs2_lookup_in_master_dir(struct gfs2_sbd *sdp, char *filename,
                              struct gfs2_inode **ipp);
 
 int gfs2_make_fs_rw(struct gfs2_sbd *sdp);
-int gfs2_make_fs_ro(struct gfs2_sbd *sdp);
 
 int gfs2_statfs_init(struct gfs2_sbd *sdp);
 void gfs2_statfs_change(struct gfs2_sbd *sdp,
index 7484655..7e1879f 100644 (file)
@@ -269,14 +269,6 @@ ARGS_ATTR(quota,           "%u\n");
 ARGS_ATTR(suiddir,         "%d\n");
 ARGS_ATTR(data,            "%d\n");
 
-/* one oddball doesn't fit the macro mold */
-static ssize_t noatime_show(struct gfs2_sbd *sdp, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%d\n",
-                       !!test_bit(SDF_NOATIME, &sdp->sd_flags));
-}
-static struct args_attr args_attr_noatime = __ATTR_RO(noatime);
-
 static struct attribute *args_attrs[] = {
        &args_attr_lockproto.attr,
        &args_attr_locktable.attr,
@@ -292,7 +284,6 @@ static struct attribute *args_attrs[] = {
        &args_attr_quota.attr,
        &args_attr_suiddir.attr,
        &args_attr_data.attr,
-       &args_attr_noatime.attr,
        NULL,
 };
 
@@ -407,7 +398,6 @@ TUNE_ATTR(incore_log_blocks, 0);
 TUNE_ATTR(log_flush_secs, 0);
 TUNE_ATTR(quota_warn_period, 0);
 TUNE_ATTR(quota_quantum, 0);
-TUNE_ATTR(atime_quantum, 0);
 TUNE_ATTR(max_readahead, 0);
 TUNE_ATTR(complain_secs, 0);
 TUNE_ATTR(statfs_slow, 0);
@@ -427,7 +417,6 @@ static struct attribute *tune_attrs[] = {
        &tune_attr_log_flush_secs.attr,
        &tune_attr_quota_warn_period.attr,
        &tune_attr_quota_quantum.attr,
-       &tune_attr_atime_quantum.attr,
        &tune_attr_max_readahead.attr,
        &tune_attr_complain_secs.attr,
        &tune_attr_statfs_slow.attr,
index c3c19f9..14d0df0 100644 (file)
@@ -118,7 +118,11 @@ struct gfs2_sb {
 
        char sb_lockproto[GFS2_LOCKNAME_LEN];
        char sb_locktable[GFS2_LOCKNAME_LEN];
-       /* In gfs1, quota and license dinodes followed */
+
+       struct gfs2_inum __pad3; /* Was quota inode in gfs1 */
+       struct gfs2_inum __pad4; /* Was licence inode in gfs1 */
+#define GFS2_HAS_UUID 1
+       __u8 sb_uuid[16]; /* The UUID, maybe 0 for backwards compat */
 };
 
 /*