lkml.org 
[lkml]   [2002]   [May]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    Subject[PATCH] 2.5.16 iget_locked [5/6]
    From

    This patch starts taking i_ino dependencies out of the VFS. The FS
    provided test and set callbacks become responsible for testing and
    setting inode->i_ino.

    Because most filesystems are based on 32-bit unique inode numbers
    several functions are duplicated to keep iget_locked as a fast path. We
    can avoid unnecessary pointer dereferences and function calls for this
    specific case.


    diff -urN iget_locked-4/Documentation/filesystems/porting iget_locked-5/Documentation/filesystems/porting
    --- iget_locked-4/Documentation/filesystems/porting Sun May 19 18:12:14 2002
    +++ iget_locked-5/Documentation/filesystems/porting Sun May 19 18:15:11 2002
    @@ -175,8 +175,10 @@
    called so the file system still has to finalize the initialization. Once
    the inode is initialized it must be unlocked by calling unlock_new_inode().

    -There is also a simpler iget_locked function that just takes the
    -superblock and inode number as arguments.
    +The filesystem is responsible for setting (and possibly testing) i_ino
    +when appropriate. There is also a simpler iget_locked function that
    +just takes the superblock and inode number as arguments and does the
    +test and set for you.

    e.g.
    inode = iget_locked(sb, ino);
    diff -urN iget_locked-4/fs/coda/cnode.c iget_locked-5/fs/coda/cnode.c
    --- iget_locked-4/fs/coda/cnode.c Sun May 19 18:07:01 2002
    +++ iget_locked-5/fs/coda/cnode.c Sun May 19 18:15:11 2002
    @@ -83,6 +83,7 @@

    if (inode->i_state & I_NEW) {
    cii = ITOC(inode);
    + inode->i_ino = ino;
    list_add(&cii->c_cilist, &sbi->sbi_cihead);
    unlock_new_inode(inode);
    }
    diff -urN iget_locked-4/fs/inode.c iget_locked-5/fs/inode.c
    --- iget_locked-4/fs/inode.c Sun May 19 18:11:28 2002
    +++ iget_locked-5/fs/inode.c Sun May 19 18:21:19 2002
    @@ -453,7 +453,32 @@
    * by hand after calling find_inode now! This simplifies iunique and won't
    * add any additional branch in the common code.
    */
    -static struct inode * find_inode(struct super_block * sb, unsigned long ino, struct list_head *head, int (*test)(struct inode *, void *), void *data)
    +static struct inode * find_inode(struct super_block * sb, struct list_head *head, int (*test)(struct inode *, void *), void *data)
    +{
    + struct list_head *tmp;
    + struct inode * inode;
    +
    + tmp = head;
    + for (;;) {
    + tmp = tmp->next;
    + inode = NULL;
    + if (tmp == head)
    + break;
    + inode = list_entry(tmp, struct inode, i_hash);
    + if (inode->i_sb != sb)
    + continue;
    + if (!test(inode, data))
    + continue;
    + break;
    + }
    + return inode;
    +}
    +
    +/*
    + * find_inode_fast is the fast path version of find_inode, see the comment at
    + * iget_locked for details.
    + */
    +static struct inode * find_inode_fast(struct super_block * sb, struct list_head *head, unsigned long ino)
    {
    struct list_head *tmp;
    struct inode * inode;
    @@ -469,8 +494,6 @@
    continue;
    if (inode->i_sb != sb)
    continue;
    - if (test && !test(inode, data))
    - continue;
    break;
    }
    return inode;
    @@ -523,10 +546,9 @@
    * We no longer cache the sb_flags in i_flags - see fs.h
    * -- rmk@arm.uk.linux.org
    */
    -static struct inode * get_new_inode(struct super_block *sb, unsigned long ino, struct list_head *head, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data)
    +static struct inode * get_new_inode(struct super_block *sb, struct list_head *head, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data)
    {
    struct inode * inode;
    - int err = 0;

    inode = alloc_inode(sb);
    if (inode) {
    @@ -534,10 +556,9 @@

    spin_lock(&inode_lock);
    /* We released the lock, so.. */
    - old = find_inode(sb, ino, head, test, data);
    + old = find_inode(sb, head, test, data);
    if (!old) {
    - inode->i_ino = ino;
    - if (set && set(inode, data))
    + if (set(inode, data))
    goto set_failed;

    inodes_stat.nr_inodes++;
    @@ -571,6 +592,49 @@
    return NULL;
    }

    +/*
    + * get_new_inode_fast is the fast path version of get_new_inode, see the
    + * comment at iget_locked for details.
    + */
    +static struct inode * get_new_inode_fast(struct super_block *sb, struct list_head *head, unsigned long ino)
    +{
    + struct inode * inode;
    +
    + inode = alloc_inode(sb);
    + if (inode) {
    + struct inode * old;
    +
    + spin_lock(&inode_lock);
    + /* We released the lock, so.. */
    + old = find_inode_fast(sb, head, ino);
    + if (!old) {
    + inode->i_ino = ino;
    + inodes_stat.nr_inodes++;
    + list_add(&inode->i_list, &inode_in_use);
    + list_add(&inode->i_hash, head);
    + inode->i_state = I_LOCK|I_NEW;
    + spin_unlock(&inode_lock);
    +
    + /* Return the locked inode with I_NEW set, the
    + * caller is responsible for filling in the contents
    + */
    + return inode;
    + }
    +
    + /*
    + * Uhhuh, somebody else created the same inode under
    + * us. Use the old inode instead of the one we just
    + * allocated.
    + */
    + __iget(old);
    + spin_unlock(&inode_lock);
    + destroy_inode(inode);
    + inode = old;
    + wait_on_inode(inode);
    + }
    + return inode;
    +}
    +
    static inline unsigned long hash(struct super_block *sb, unsigned long i_ino)
    {
    unsigned long tmp = i_ino + ((unsigned long) sb / L1_CACHE_BYTES);
    @@ -605,7 +669,8 @@
    retry:
    if (counter > max_reserved) {
    head = inode_hashtable + hash(sb,counter);
    - inode = find_inode(sb, res = counter++, head, NULL, NULL);
    + res = counter++;
    + inode = find_inode_fast(sb, head, res);
    if (!inode) {
    spin_unlock(&inode_lock);
    return res;
    @@ -644,7 +709,7 @@
    struct inode * inode;

    spin_lock(&inode_lock);
    - inode = find_inode(sb, ino, head, test, data);
    + inode = find_inode(sb, head, test, data);
    if (inode) {
    __iget(inode);
    spin_unlock(&inode_lock);
    @@ -657,12 +722,36 @@
    * get_new_inode() will do the right thing, re-trying the search
    * in case it had to block at any point.
    */
    - return get_new_inode(sb, ino, head, test, set, data);
    + return get_new_inode(sb, head, test, set, data);
    }

    +/*
    + * Because most filesystems are based on 32-bit unique inode numbers some
    + * functions are duplicated to keep iget_locked as a fast path. We can avoid
    + * unnecessary pointer dereferences and function calls for this specific
    + * case. The duplicated functions (find_inode_fast and get_new_inode_fast)
    + * have the same pre- and post-conditions as their original counterparts.
    + */
    struct inode *iget_locked(struct super_block *sb, unsigned long ino)
    {
    - return iget5_locked(sb, ino, NULL, NULL, NULL);
    + struct list_head * head = inode_hashtable + hash(sb, ino);
    + struct inode * inode;
    +
    + spin_lock(&inode_lock);
    + inode = find_inode_fast(sb, head, ino);
    + if (inode) {
    + __iget(inode);
    + spin_unlock(&inode_lock);
    + wait_on_inode(inode);
    + return inode;
    + }
    + spin_unlock(&inode_lock);
    +
    + /*
    + * get_new_inode_fast() will do the right thing, re-trying the search
    + * in case it had to block at any point.
    + */
    + return get_new_inode_fast(sb, head, ino);
    }

    EXPORT_SYMBOL(iget5_locked);
    diff -urN iget_locked-4/fs/nfs/inode.c iget_locked-5/fs/nfs/inode.c
    --- iget_locked-4/fs/nfs/inode.c Sun May 19 18:09:14 2002
    +++ iget_locked-5/fs/nfs/inode.c Sun May 19 18:15:11 2002
    @@ -661,6 +661,8 @@
    loff_t new_isize;
    time_t new_atime;

    + inode->i_ino = ino;
    +
    /* We can't support UPDATE_ATIME(), since the server will reset it */
    inode->i_flags |= S_NOATIME;
    inode->i_mode = fattr->mode;
    diff -urN iget_locked-4/fs/reiserfs/inode.c iget_locked-5/fs/reiserfs/inode.c
    --- iget_locked-4/fs/reiserfs/inode.c Sun May 19 18:10:06 2002
    +++ iget_locked-5/fs/reiserfs/inode.c Sun May 19 18:15:11 2002
    @@ -1136,7 +1136,8 @@
    int reiserfs_init_locked_inode (struct inode * inode, void *p)
    {
    struct reiserfs_iget_args *args = (struct reiserfs_iget_args *)p ;
    - INODE_PKEY(inode)->k_dir_id = cpu_to_le32(args->objectid);
    + inode->i_ino = args->objectid;
    + INODE_PKEY(inode)->k_dir_id = cpu_to_le32(args->dirid);
    return 0;
    }

    @@ -1149,7 +1150,7 @@
    unsigned long dirino;
    int retval;

    - dirino = args->objectid ;
    + dirino = args->dirid ;

    /* set version 1, version 2 could be used too, because stat data
    key is the same in both versions */
    @@ -1223,7 +1224,8 @@

    args = opaque;
    /* args is already in CPU order */
    - return le32_to_cpu(INODE_PKEY(inode)->k_dir_id) == args -> objectid;
    + return (inode->i_ino == args->objectid) &&
    + (le32_to_cpu(INODE_PKEY(inode)->k_dir_id) == args->dirid);
    }

    struct inode * reiserfs_iget (struct super_block * s, const struct cpu_key * key)
    @@ -1231,7 +1233,8 @@
    struct inode * inode;
    struct reiserfs_iget_args args ;

    - args.objectid = key->on_disk_key.k_dir_id ;
    + args.objectid = key->on_disk_key.k_objectid ;
    + args.dirid = key->on_disk_key.k_dir_id ;
    inode = iget5_locked (s, key->on_disk_key.k_objectid,
    reiserfs_find_actor, reiserfs_init_locked_inode, (void *)(&args));
    if (!inode)
    diff -urN iget_locked-4/fs/reiserfs/super.c iget_locked-5/fs/reiserfs/super.c
    --- iget_locked-4/fs/reiserfs/super.c Sun May 19 18:10:31 2002
    +++ iget_locked-5/fs/reiserfs/super.c Sun May 19 18:15:11 2002
    @@ -1067,7 +1067,8 @@
    printk("clm-7000: Detected readonly device, marking FS readonly\n") ;
    s->s_flags |= MS_RDONLY ;
    }
    - args.objectid = REISERFS_ROOT_PARENT_OBJECTID ;
    + args.objectid = REISERFS_ROOT_OBJECTID ;
    + args.dirid = REISERFS_ROOT_PARENT_OBJECTID ;
    root_inode = iget5_locked (s, REISERFS_ROOT_OBJECTID, reiserfs_find_actor, reiserfs_init_locked_inode, (void *)(&args));
    if (!root_inode) {
    printk ("reiserfs_fill_super: get root inode failed\n");
    diff -urN iget_locked-4/include/linux/reiserfs_fs.h iget_locked-5/include/linux/reiserfs_fs.h
    --- iget_locked-4/include/linux/reiserfs_fs.h Sun May 19 18:10:42 2002
    +++ iget_locked-5/include/linux/reiserfs_fs.h Sun May 19 18:15:11 2002
    @@ -1566,6 +1566,7 @@

    struct reiserfs_iget_args {
    __u32 objectid ;
    + __u32 dirid ;
    } ;

    /***************************************************************************/
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/
    \
     
     \ /
      Last update: 2005-03-22 13:26    [W:0.051 / U:31.964 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site