]> git.neil.brown.name Git - LaFS.git/commitdiff
lafs_iget takes a filesystem-inode rather than a super_block.
authorNeilBrown <neilb@suse.de>
Mon, 7 Mar 2011 05:58:56 +0000 (16:58 +1100)
committerNeilBrown <neilb@suse.de>
Mon, 7 Mar 2011 05:58:56 +0000 (16:58 +1100)
On the path to reducing the number of superblocks.... each superblock
can hold multiple subset filesystems so we need more than the
inode number to identify a file - we need the filesystem inode too.

So change lafs_iget to take a filesystem inode rather than a
superblock.

We still need to get at the superblock.  In a few patches we can just
use ->i_sb, but for now it might not be the same so stash it in
i_private.

Signed-off-by: NeilBrown <neilb@suse.de>
dir.c
inode.c
lafs.h
roll.c
snapshot.c
super.c

diff --git a/dir.c b/dir.c
index beab1b3b33baf20c3884ead8c065d9a37c14611a..e0e6d4cf773692a9419a2441a5af6597081831cc 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -631,7 +631,7 @@ lafs_dir_roll_mini(struct inode *dir, int handle, int dirop,
        int last;
 
        if (inum)
-               inode = lafs_iget(dir->i_sb, inum, SYNC);
+               inode = lafs_iget(LAFSI(dir)->filesys, inum, SYNC);
        if (IS_ERR(inode))
                return PTR_ERR(inode);
        if (!inode && dirop != DIROP_REN_TARGET)
@@ -1803,7 +1803,7 @@ lafs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 
        if (err < 0)
                ERR_PTR(err);
-       ino = lafs_iget(dir->i_sb, inum, SYNC);
+       ino = lafs_iget(LAFSI(dir)->filesys, inum, SYNC);
 
        if (IS_ERR(ino))
                return ERR_PTR(PTR_ERR(ino));
diff --git a/inode.c b/inode.c
index 4e10c2272a2f2313164243ace76ac6d4a052d42e..7605323f094998ca68bad98a87863db2330ee00a 100644 (file)
--- a/inode.c
+++ b/inode.c
@@ -20,64 +20,74 @@ static void check_atime_ref(struct inode *ino, int async);
  * is slightly non-trivial.
  * iget*_locked will normally wait for any inode with one
  * of the flags I_FREEING I_CLEAR I_WILL_FREE I_NEW
- * to either be unhashed or has the flag cleared.
+ * to either be unhashed or have the flag cleared.
  * We cannot afford that wait in the cleaner as we could deadlock.
  * So we use iget5_locked and provide a test function that fails
  * if it finds the inode with any of those flags set.
- * If it does see the inode like that it clear the inum
- * that is passed in (by reference) so that it knows to continue
+ * If it does see the inode like that it sets a flag in the 'ikey'
+ * that is passed in by reference so that it knows to continue
  * failing (for consistency) and so that the 'set' function
  * we provide can know to fail the 'set'.
  * The result of this is that if iget finds an inode it would
- * have to wait on, the inum is cleared and NULL is returned.
+ * have to wait on, a flag is set and NULL is returned.
  * An unfortunate side effect is that an inode will be allocated
  * and then destroyed to no avail.
  * This is avoided by calling ilookup5 first.  This also allows
  * us to only allocate/load the data block if there really seems
  * to be a need.
  */
-#define NO_INO (~(ino_t)0)
+struct ikey {
+       ino_t inum;
+       struct inode *fsys;
+       bool was_busy;
+};
+
+static int sync_itest(struct inode *inode, void *data)
+{
+       struct ikey *ik = data;
+
+       if (inode->i_ino != ik->inum ||
+           LAFSI(inode)->filesys != ik->fsys)
+               return 0;
+       return 1;
+}
+
 static int async_itest(struct inode *inode, void *data)
 {
-       ino_t *inump = data;
-       ino_t inum = *inump;
+       struct ikey *ik = data;
 
-       if (inum == NO_INO)
+       if (ik->was_busy)
                /* found and is freeing */
                return 0;
-       if (inode->i_ino != inum)
+       if (!sync_itest(inode, data))
                return 0;
        if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE|I_NEW)) {
-               *inump = NO_INO;
+               ik->was_busy = true;
                return 0;
        }
        return 1;
 }
 
-static int async_iset(struct inode *inode, void *data)
+static int iset(struct inode *inode, void *data)
 {
-       ino_t *inump = data;
-       if (!*inump)
+       struct ikey *ik = data;
+       if (ik->was_busy)
                return -EBUSY;
-       inode->i_ino = *inump;
+       inode->i_ino = ik->inum;
+       LAFSI(inode)->filesys = ik->fsys;
        return 0;
 }
 
 struct inode *
-lafs_iget(struct super_block *sb, ino_t inum, int async)
+lafs_iget(struct inode *fsys, ino_t inum, int async)
 {
        /* find, and load if needed, this inum */
        struct inode *ino = NULL;
        struct inode *oldino;
        struct datablock *b = NULL;
-       struct inode *inodefile;
-       struct sb_key *k;
+       struct ikey ik = { .inum = inum, .fsys = fsys, };
        int err = 0;
-
-       BUG_ON(inum == NO_INO);
-
-       k = sb->s_fs_info;
-       inodefile = k->root;
+       struct super_block *sb = fsys->i_private;
 
        if (async) {
                /* We cannot afford to block on 'freeing_inode'
@@ -88,13 +98,13 @@ lafs_iget(struct super_block *sb, ino_t inum, int async)
                 * alloc/free if the inode is locked in some way.
                 */
                while (!ino) {
-                       ino_t inum2 = inum;
+
                        err = 0;
-                       ino = ilookup5(sb, inum, async_itest, &inum2);
+                       ino = ilookup5(sb, inum, async_itest, &ik);
                        if (ino)
                                break;
 
-                       if (inum2 == NO_INO)
+                       if (ik.was_busy)
                                err = -EAGAIN;
 
                        /* For async we will always want the dblock loaded,
@@ -102,7 +112,7 @@ lafs_iget(struct super_block *sb, ino_t inum, int async)
                         * to fail -EAGAIN once we have an I_NEW inode.
                         */
                        if (!b)
-                               b = lafs_get_block(inodefile, inum, NULL,
+                               b = lafs_get_block(fsys, inum, NULL,
                                                   GFP_NOFS, MKREF(iget));
                        if (!b)
                                return ERR_PTR(-ENOMEM);
@@ -112,12 +122,11 @@ lafs_iget(struct super_block *sb, ino_t inum, int async)
 
                        if (!err) {
                                /* Have the block, so safe to iget */
-                               inum2 = inum;
                                ino = iget5_locked(sb, inum,
-                                                  async_itest, async_iset,
-                                                  &inum2);
+                                                  async_itest, iset,
+                                                  &ik);
                                if (!ino) {
-                                       if (inum2 == NO_INO)
+                                       if (ik.was_busy)
                                                err = -EAGAIN;
                                        else
                                                err = -ENOMEM;
@@ -132,7 +141,7 @@ lafs_iget(struct super_block *sb, ino_t inum, int async)
                        }
                }
        } else
-               ino = iget_locked(sb, inum);
+               ino = iget5_locked(sb, inum, sync_itest, iset, &ik);
 
        if (!ino) {
                putdref(b, MKREF(iget));
@@ -149,7 +158,7 @@ lafs_iget(struct super_block *sb, ino_t inum, int async)
                return ERR_PTR(-ENOENT);
        }
 
-       LAFSI(ino)->filesys = igrab(inodefile);
+       igrab(LAFSI(ino)->filesys);
 
        /* surprisingly the inode bdi does not default to the
         * super_blocks bdi...
@@ -158,7 +167,7 @@ lafs_iget(struct super_block *sb, ino_t inum, int async)
        /* Need to load block 'inum' from an inode file...
         */
        if (!b) {
-               b = lafs_get_block(inodefile, inum, NULL, GFP_KERNEL, MKREF(iget));
+               b = lafs_get_block(fsys, inum, NULL, GFP_KERNEL, MKREF(iget));
                if (!b)
                        err = -ENOMEM;
                else
@@ -200,7 +209,7 @@ lafs_iget(struct super_block *sb, ino_t inum, int async)
 out:
        if (b && test_and_clear_bit(B_Async, &b->b.flags)) {
                putdref(b, MKREF(async));
-               lafs_wake_thread(fs_from_sb(sb));
+               lafs_wake_thread(fs_from_inode(fsys));
        }
        putdref(b, MKREF(iget));
        return ino;
@@ -227,7 +236,7 @@ lafs_iget_fs(struct fs *fs, int fsnum, int inum, int async)
                struct inode *filesys;
                struct super_block *sb2;
 
-               filesys = lafs_iget(sb, fsnum, async);
+               filesys = lafs_iget(fs->ss[0].root, fsnum, async);
                if (IS_ERR(filesys))
                        return filesys;
                if (LAFSI(filesys)->type != TypeInodeFile) {
@@ -240,15 +249,18 @@ lafs_iget_fs(struct fs *fs, int fsnum, int inum, int async)
                        iput(filesys);
                        return ERR_PTR(PTR_ERR(sb2));
                }
-               rv = lafs_iget(sb2, inum, async);
+               rv = lafs_iget(filesys, inum, async);
                if (IS_ERR(rv))
                        deactivate_locked_super(sb2);
                else
                        up_write(&sb2->s_umount);
-       } else {
-               rv = lafs_iget(sb, inum, async);
+       } else if (inum) {
+               rv = lafs_iget(fs->ss[0].root, inum, async);
                if (!IS_ERR(rv))
                        atomic_inc(&sb->s_active);
+       } else {
+               rv = igrab(fs->ss[0].root);
+               atomic_inc(&sb->s_active);
        }
        return rv;
 }
@@ -1543,7 +1555,7 @@ static int
 choose_free_inum(struct fs *fs, struct super_block *sb, u32 *inump,
                 struct datablock **bp, int *restarted)
 {
-       struct inode *im = lafs_iget(sb, 1, SYNC);
+       struct inode *im = lafs_iget(ino_from_sb(sb), 1, SYNC);
        loff_t bnum;
        struct datablock *b;
        char *buf;
@@ -1814,7 +1826,7 @@ retry:
        lafs_iounlock_block(&b->b);
 
        inode_map_new_commit(&imni);
-       ino = lafs_iget(sb, b->b.fileaddr, SYNC);
+       ino = lafs_iget(ino_from_sb(sb), b->b.fileaddr, SYNC);
        if (IS_ERR(ino)) {
                lafs_cluster_update_abort(&ui);
                LAFS_BUG(1, &b->b);
@@ -1843,7 +1855,7 @@ abort:
 
 static int inode_map_free(struct fs *fs, struct super_block *sb, u32 inum)
 {
-       struct inode *im = lafs_iget(sb, 1, SYNC);
+       struct inode *im = lafs_iget(ino_from_sb(sb), 1, SYNC);
        int bit;
        unsigned long *buf;
        struct datablock *b;
@@ -1894,7 +1906,7 @@ int lafs_inode_inuse(struct fs *fs, struct super_block *sb, u32 inum)
        /* This is used during roll-forward to register a newly created
         * inode in the inode map
         */
-       struct inode *im = lafs_iget(sb, 1, SYNC);
+       struct inode *im = lafs_iget(ino_from_sb(sb), 1, SYNC);
        int bit;
        unsigned long *buf;
        struct datablock *b;
diff --git a/lafs.h b/lafs.h
index 1be035488c365354c9a9da9708422e8d86bf4089..5b1afbf2bbca7f9d3b24e60ea5b72ee66bb976fe 100644 (file)
--- a/lafs.h
+++ b/lafs.h
@@ -138,7 +138,7 @@ int lafs_super_wait(struct fs *fs);
 /* inode.c */
 void lafs_add_atime_offset(struct timespec *atime, int offset);
 int __must_check lafs_mount(struct fs *fs);
-struct inode *lafs_iget(struct super_block *fs, ino_t inum, int async);
+struct inode *lafs_iget(struct inode *filesys, ino_t inum, int async);
 struct inode *lafs_iget_fs(struct fs *fs, int fsnum, int inum, int async);
 int __must_check lafs_import_inode(struct inode *ino, struct datablock *b);
 void lafs_inode_checkpin(struct inode *ino);
diff --git a/roll.c b/roll.c
index f1dd2696503cbee09ffa96bdcbcefb242857cf0e..063960685ad40a86a961712e4bb4937590c835d2 100644 (file)
--- a/roll.c
+++ b/roll.c
@@ -783,8 +783,9 @@ int
 lafs_mount(struct fs *fs)
 {
        struct datablock *b = NULL;
-       struct inode *ino;
+       struct inode *rootino;
        struct inode *rootdir;
+       struct inode *aino, *oino;
        struct dentry *de;
        int err;
        int d;
@@ -792,14 +793,16 @@ lafs_mount(struct fs *fs)
        int orphan_count;
 
        fs->rolled = 0;
-       fs->ss[0].root = ino = iget_locked(fs->prime_sb, 0);
-       LAFSI(ino)->filesys = ino;
-       k->root = ino;
+       fs->ss[0].root = rootino = iget_locked(fs->prime_sb, 0);
+       k->root = rootino;
+       LAFSI(rootino)->filesys = rootino;
+
+       rootino->i_private = fs->prime_sb;
 
        err = -ENOMEM;
-       if (!ino)
+       if (!rootino)
                goto err;
-       b = lafs_get_block(ino, 0, NULL, GFP_KERNEL, MKREF(mount));
+       b = lafs_get_block(rootino, 0, NULL, GFP_KERNEL, MKREF(mount));
        if (!b)
                goto err;
        set_bit(B_Root, &b->b.flags);
@@ -812,15 +815,15 @@ lafs_mount(struct fs *fs)
        if (err)
                goto err;
 
-       err = lafs_import_inode(ino, b);
+       err = lafs_import_inode(rootino, b);
        if (err)
                goto err;
        putdref(b, MKREF(mount));
        b = NULL;
 
-       unlock_new_inode(ino);
+       unlock_new_inode(rootino);
 
-       rootdir = lafs_iget(fs->prime_sb, 2, SYNC);
+       rootdir = lafs_iget(rootino, 2, SYNC);
        err = PTR_ERR(rootdir);
        if (IS_ERR(rootdir))
                goto err;
@@ -832,29 +835,29 @@ lafs_mount(struct fs *fs)
        }
        fs->prime_sb->s_root = de;
 
-       ino = lafs_iget(fs->prime_sb, 8, SYNC);
-       err = PTR_ERR(ino);
-       if (IS_ERR(ino))
+       oino = lafs_iget(rootino, 8, SYNC);
+       err = PTR_ERR(oino);
+       if (IS_ERR(oino))
                goto err;
-       if (LAFSI(ino)->type != TypeOrphanList) {
-               iput(ino);
+       if (LAFSI(oino)->type != TypeOrphanList) {
+               iput(oino);
                err = -EINVAL;
                goto err;
        }
-       fs->orphans = ino;
+       fs->orphans = oino;
        for (d = 0; d < fs->devices ; d++) {
-               ino = lafs_iget(fs->prime_sb,
-                               fs->devs[d].usage_inum,
-                               SYNC);
-               err = PTR_ERR(ino);
-               if (IS_ERR(ino))
+               struct inode *sino = lafs_iget(rootino,
+                                              fs->devs[d].usage_inum,
+                                              SYNC);
+               err = PTR_ERR(sino);
+               if (IS_ERR(sino))
                        goto err;
-               if (LAFSI(ino)->type != TypeSegmentMap) {
-                       iput(ino);
+               if (LAFSI(sino)->type != TypeSegmentMap) {
+                       iput(sino);
                        err = -EINVAL;
                        goto err;
                }
-               fs->devs[d].segsum = ino;
+               fs->devs[d].segsum = sino;
        }
        orphan_count = lafs_count_orphans(fs->orphans);
        LAFSI(fs->orphans)->md.orphan.nextfree = orphan_count;
@@ -873,15 +876,15 @@ lafs_mount(struct fs *fs)
                INIT_LIST_HEAD(&fs->cleaner.seg[d].cleaning);
        }
 
-       ino = lafs_iget(fs->prime_sb, 3, SYNC);
-       if (!IS_ERR(ino)) {
-               if (LAFSI(ino)->type != TypeAccessTime) {
-                       iput(ino);
+       aino = lafs_iget(rootino, 3, SYNC);
+       if (!IS_ERR(aino)) {
+               if (LAFSI(aino)->type != TypeAccessTime) {
+                       iput(aino);
                        err = -EINVAL;
                } else
-                       LAFSI(fs->ss[0].root)->md.fs.accesstime = ino;
-       } else if (PTR_ERR(ino) != -ENOENT)
-               err = PTR_ERR(ino);
+                       LAFSI(fs->ss[0].root)->md.fs.accesstime = aino;
+       } else if (PTR_ERR(aino) != -ENOENT)
+               err = PTR_ERR(aino);
 
 err:
        putdref(b, MKREF(mount));
index 4489ed396ade63627e00ece3701629579d42f0b6..23cf5a3dd13166fe576094eaf1f06cb6b142c406 100644 (file)
@@ -161,15 +161,17 @@ lafs_snap_get_sb(struct file_system_type *fstype,
                /* already existed */
                kfree(sk);
        } else {
-               struct inode *rootdir;
+               struct inode *rootino, *rootdir;
                struct datablock *b;
                sb->s_flags = flags | MS_RDONLY;
 
                atomic_inc(&fs->prime_sb->s_active);
 
-               fs->ss[s].root = sk->k.root = iget_locked(sb, 0);
-               LAFSI(fs->ss[s].root)->filesys = fs->ss[s].root;
-               b = lafs_get_block(fs->ss[s].root, 0, NULL, GFP_KERNEL,
+               rootino = iget_locked(sb, 0);
+               rootino->i_private = sb;
+               fs->ss[s].root = sk->k.root = rootino;
+               LAFSI(rootino)->filesys = rootino;
+               b = lafs_get_block(rootino, 0, NULL, GFP_KERNEL,
                                   MKREF(snap));
                b->b.physaddr = fs->ss[s].root_addr;
                set_bit(B_PhysValid, &b->b.flags);
@@ -181,12 +183,12 @@ lafs_snap_get_sb(struct file_system_type *fstype,
                if (!err)
                        err = lafs_import_inode(fs->ss[s].root, b);
                putdref(b, MKREF(snap));
-               unlock_new_inode(fs->ss[s].root);
+               unlock_new_inode(rootino);
                if (err) {
                        deactivate_locked_super(sb);
                        goto fail;
                }
-               rootdir = lafs_iget(sb, 2, SYNC);
+               rootdir = lafs_iget(rootino, 2, SYNC);
                sb->s_root = d_alloc_root(rootdir);
                sb->s_op = fs->prime_sb->s_op;
                sb->s_flags |= MS_ACTIVE;
diff --git a/super.c b/super.c
index e473565fb2302c893df2a0c6a08284d05f5db4ce..46e8eecdb4de9af5f925ddaf0d560a718afd50b4 100644 (file)
--- a/super.c
+++ b/super.c
@@ -1025,6 +1025,8 @@ struct super_block *lafs_get_subset_sb(struct inode *ino)
                struct inode *rootdir, *imapfile;
                int err = 0;
 
+               ino->i_private = sb;
+
                igrab(ino);
                sb->s_blocksize = fs->blocksize;
                sb->s_blocksize_bits = fs->blocksize_bits;
@@ -1032,7 +1034,7 @@ struct super_block *lafs_get_subset_sb(struct inode *ino)
                sb->s_op = &lafs_sops;
                sb->s_export_op = &lafs_export_ops;
                sb->s_time_gran = 2;
-               rootdir = lafs_iget(sb, 2, SYNC);
+               rootdir = lafs_iget(ino, 2, SYNC);
                if (IS_ERR(rootdir) && PTR_ERR(rootdir) == -ENOENT) {
                        rootdir = lafs_new_inode(fs, sb, NULL,
                                                 TypeDir, 2, 0755, NULL);
@@ -1044,7 +1046,7 @@ struct super_block *lafs_get_subset_sb(struct inode *ino)
                        err = PTR_ERR(rootdir);
                else {
                        sb->s_root = d_alloc_root(rootdir);
-                       imapfile = lafs_iget(sb, 1, SYNC);
+                       imapfile = lafs_iget(ino, 1, SYNC);
                        if (IS_ERR(imapfile) && PTR_ERR(imapfile) == -ENOENT)
                                imapfile = lafs_new_inode(fs, sb, NULL,
                                                          TypeInodeMap, 1, 0, NULL);
@@ -1056,7 +1058,7 @@ struct super_block *lafs_get_subset_sb(struct inode *ino)
                }
 
                if (!err) {
-                       struct inode *atime = lafs_iget(sb, 3, SYNC);
+                       struct inode *atime = lafs_iget(ino, 3, SYNC);
                        if (!IS_ERR(atime)) {
                                if (LAFSI(atime)->type != TypeAccessTime) {
                                        iput(atime);
@@ -1265,7 +1267,7 @@ static struct inode *lafs_nfs_get_inode(struct super_block *sb,
 {
        struct inode *inode;
 
-       inode = lafs_iget(sb, ino, SYNC);
+       inode = lafs_iget(ino_from_sb(sb), ino, SYNC);
        if (IS_ERR(inode))
                return ERR_CAST(inode);
        if (generation && inode->i_generation != generation) {
@@ -1293,7 +1295,8 @@ static struct dentry *lafs_fh_to_parent(struct super_block *sb, struct fid *fid,
 static struct dentry *lafs_get_parent(struct dentry *child)
 {
        ino_t inum = LAFSI(child->d_inode)->md.file.parent;
-       struct inode *inode = lafs_iget(child->d_inode->i_sb, inum, SYNC);
+       struct inode *inode = lafs_iget(LAFSI(child->d_inode)->filesys,
+                                       inum, SYNC);
        if (IS_ERR(inode))
                return ERR_CAST(inode);
        return d_obtain_alias(inode);