]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 9 Jul 2013 18:26:44 +0000 (11:26 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 9 Jul 2013 18:26:44 +0000 (11:26 -0700)
Pull third set of VFS updates from Al Viro:
 "Misc stuff all over the place.  There will be one more pile in a
  couple of days"

This is an "evil merge" that also uses the new d_count helper in
fs/configfs/dir.c, missed by commit 84d08fa888e7 ("helper for reading
->d_count")

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  ncpfs: fix error return code in ncp_parse_options()
  locks: move file_lock_list to a set of percpu hlist_heads and convert file_lock_lock to an lglock
  seq_file: add seq_list_*_percpu helpers
  f2fs: fix readdir incorrectness
  mode_t whack-a-mole...
  lustre: kill the pointless wrapper
  helper for reading ->d_count

26 files changed:
drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h
drivers/staging/lustre/lustre/include/linux/lvfs.h
drivers/staging/lustre/lustre/include/lprocfs_status.h
drivers/staging/lustre/lustre/llite/dcache.c
drivers/staging/lustre/lustre/llite/llite_internal.h
drivers/staging/lustre/lustre/llite/llite_lib.c
drivers/staging/lustre/lustre/llite/namei.c
drivers/staging/lustre/lustre/lvfs/lvfs_linux.c
drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
fs/autofs4/expire.c
fs/autofs4/root.c
fs/ceph/inode.c
fs/ceph/mds_client.c
fs/coda/dir.c
fs/configfs/dir.c
fs/ecryptfs/inode.c
fs/f2fs/dir.c
fs/locks.c
fs/ncpfs/inode.c
fs/nfs/dir.c
fs/nfs/unlink.c
fs/nilfs2/super.c
fs/seq_file.c
include/linux/dcache.h
include/linux/fs.h
include/linux/seq_file.h

index f0508084e8c554dcfecbf9d57712ed6bf18d2e35..a8e9c0c8ffd235d0965ef2cf1cd76cdd0bb8801e 100644 (file)
@@ -60,8 +60,6 @@ truncate_complete_page(struct address_space *mapping, struct page *page)
        ll_delete_from_page_cache(page);
 }
 
-#  define d_refcount(d)                 ((d)->d_count)
-
 #ifdef ATTR_OPEN
 # define ATTR_FROM_OPEN ATTR_OPEN
 #else
index b4db6cb581bdb855912f44c40ed55fec3f8e4ebd..eb59ac7d5946b3dda15b3f909ad88833c2ccbbfd 100644 (file)
@@ -99,7 +99,7 @@ static inline void l_dput(struct dentry *de)
        if (!de || IS_ERR(de))
                return;
        //shrink_dcache_parent(de);
-       LASSERT(d_refcount(de) > 0);
+       LASSERT(d_count(de) > 0);
        dput(de);
 }
 
index e770d0260576a95af516511d90fdc62c94170c0b..55f182205d7850618bb8d9fd1a0f18cff0e7f6ee 100644 (file)
@@ -53,7 +53,7 @@ struct lprocfs_vars {
        /**
         * /proc file mode.
         */
-       mode_t                  proc_mode;
+       umode_t                 proc_mode;
 };
 
 struct lprocfs_static_vars {
@@ -600,11 +600,11 @@ extern int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list);
 extern int lprocfs_obd_cleanup(struct obd_device *obd);
 
 extern int lprocfs_seq_create(proc_dir_entry_t *parent, const char *name,
-                             mode_t mode,
+                             umode_t mode,
                              const struct file_operations *seq_fops,
                              void *data);
 extern int lprocfs_obd_seq_create(struct obd_device *dev, const char *name,
-                                 mode_t mode,
+                                 umode_t mode,
                                  const struct file_operations *seq_fops,
                                  void *data);
 
index 7d6abfff9740d36da38e3751652b083e05bb23cd..ff0d085077c845627bc42d8b9714459f134af633 100644 (file)
@@ -98,7 +98,7 @@ int ll_dcompare(const struct dentry *parent, const struct inode *pinode,
 
        CDEBUG(D_DENTRY, "found name %.*s(%p) flags %#x refc %d\n",
               name->len, name->name, dentry, dentry->d_flags,
-              d_refcount(dentry));
+              d_count(dentry));
 
        /* mountpoint is always valid */
        if (d_mountpoint((struct dentry *)dentry))
@@ -165,7 +165,7 @@ static int ll_ddelete(const struct dentry *de)
               list_empty(&de->d_subdirs) ? "" : "subdirs");
 
        /* kernel >= 2.6.38 last refcount is decreased after this function. */
-       LASSERT(d_refcount(de) == 1);
+       LASSERT(d_count(de) == 1);
 
        /* Disable this piece of code temproarily because this is called
         * inside dcache_lock so it's not appropriate to do lots of work
@@ -190,7 +190,7 @@ static int ll_set_dd(struct dentry *de)
 
        CDEBUG(D_DENTRY, "ldd on dentry %.*s (%p) parent %p inode %p refc %d\n",
                de->d_name.len, de->d_name.name, de, de->d_parent, de->d_inode,
-               d_refcount(de));
+               d_count(de));
 
        if (de->d_fsdata == NULL) {
                struct ll_dentry_data *lld;
@@ -540,7 +540,7 @@ out:
                CDEBUG(D_DENTRY, "revalidated dentry %.*s (%p) parent %p "
                       "inode %p refc %d\n", de->d_name.len,
                       de->d_name.name, de, de->d_parent, de->d_inode,
-                      d_refcount(de));
+                      d_count(de));
 
                ll_set_lock_data(exp, de->d_inode, it, &bits);
 
index 992cd203ca1a1121c8f42f65479588b42015c255..5227c5c4ebe21845905104d1f99bdc2ced46f6d1 100644 (file)
@@ -1529,12 +1529,12 @@ static inline void d_lustre_invalidate(struct dentry *dentry, int nested)
 {
        CDEBUG(D_DENTRY, "invalidate dentry %.*s (%p) parent %p inode %p "
               "refc %d\n", dentry->d_name.len, dentry->d_name.name, dentry,
-              dentry->d_parent, dentry->d_inode, d_refcount(dentry));
+              dentry->d_parent, dentry->d_inode, d_count(dentry));
 
        spin_lock_nested(&dentry->d_lock,
                         nested ? DENTRY_D_LOCK_NESTED : DENTRY_D_LOCK_NORMAL);
        __d_lustre_invalidate(dentry);
-       if (d_refcount(dentry) == 0)
+       if (d_count(dentry) == 0)
                __d_drop(dentry);
        spin_unlock(&dentry->d_lock);
 }
index 2311b20ee99a29f74d5c474703229fa0c6f135f3..afae8010623d5ddbd90e21aac9ecb9a22453e58e 100644 (file)
@@ -659,7 +659,7 @@ void lustre_dump_dentry(struct dentry *dentry, int recur)
               " flags=0x%x, fsdata=%p, %d subdirs\n", dentry,
               dentry->d_name.len, dentry->d_name.name,
               dentry->d_parent->d_name.len, dentry->d_parent->d_name.name,
-              dentry->d_parent, dentry->d_inode, d_refcount(dentry),
+              dentry->d_parent, dentry->d_inode, d_count(dentry),
               dentry->d_flags, dentry->d_fsdata, subdirs);
        if (dentry->d_inode != NULL)
                ll_dump_inode(dentry->d_inode);
index 58d59aa126191cea965a6338428ada342448e3af..ff8f63de5612a03f7baae80efcb252ab865719ce 100644 (file)
@@ -409,7 +409,7 @@ struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de)
                        iput(inode);
                        CDEBUG(D_DENTRY,
                               "Reuse dentry %p inode %p refc %d flags %#x\n",
-                             new, new->d_inode, d_refcount(new), new->d_flags);
+                             new, new->d_inode, d_count(new), new->d_flags);
                        return new;
                }
        }
@@ -417,7 +417,7 @@ struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de)
        __d_lustre_invalidate(de);
        d_add(de, inode);
        CDEBUG(D_DENTRY, "Add dentry %p inode %p refc %d flags %#x\n",
-              de, de->d_inode, d_refcount(de), de->d_flags);
+              de, de->d_inode, d_count(de), de->d_flags);
        return de;
 }
 
index 1e6f32c3549b321e56d0bc154539932dec5be6d3..e70d8fe99888fd82c44c94eea26d3c2226af2c3b 100644 (file)
@@ -121,8 +121,8 @@ void push_ctxt(struct lvfs_run_ctxt *save, struct lvfs_run_ctxt *new_ctx,
        OBD_SET_CTXT_MAGIC(save);
 
        save->fs = get_fs();
-       LASSERT(d_refcount(cfs_fs_pwd(current->fs)));
-       LASSERT(d_refcount(new_ctx->pwd));
+       LASSERT(d_count(cfs_fs_pwd(current->fs)));
+       LASSERT(d_count(new_ctx->pwd));
        save->pwd = dget(cfs_fs_pwd(current->fs));
        save->pwdmnt = mntget(cfs_fs_mnt(current->fs));
        save->luc.luc_umask = current_umask();
index 3b157f89c3008912d9c94248b0c030485c1aea1f..f7af3d6a4efcbf52f1cba02c6ad717c6efdbb879 100644 (file)
@@ -73,7 +73,7 @@ proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
                                     struct file_operations *fops)
 {
        proc_dir_entry_t *proc;
-       mode_t mode = 0;
+       umode_t mode = 0;
 
        if (root == NULL || name == NULL || fops == NULL)
                return ERR_PTR(-EINVAL);
@@ -140,7 +140,7 @@ int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
 
        while (list->name != NULL) {
                struct proc_dir_entry *proc;
-               mode_t mode = 0;
+               umode_t mode = 0;
 
                if (list->proc_mode != 0000) {
                        mode = list->proc_mode;
@@ -1899,7 +1899,7 @@ EXPORT_SYMBOL(lprocfs_find_named_value);
 
 int lprocfs_seq_create(proc_dir_entry_t *parent,
                       const char *name,
-                      mode_t mode,
+                      umode_t mode,
                       const struct file_operations *seq_fops,
                       void *data)
 {
@@ -1919,7 +1919,7 @@ EXPORT_SYMBOL(lprocfs_seq_create);
 
 int lprocfs_obd_seq_create(struct obd_device *dev,
                           const char *name,
-                          mode_t mode,
+                          umode_t mode,
                           const struct file_operations *seq_fops,
                           void *data)
 {
index 13ddec92341cdaaa63cf811ee1037a2038994191..3d9d3f5d5dda688bcd9bfc666210553ffa73be0d 100644 (file)
@@ -109,7 +109,7 @@ cont:
 
        spin_lock_nested(&q->d_lock, DENTRY_D_LOCK_NESTED);
        /* Already gone or negative dentry (under construction) - try next */
-       if (q->d_count == 0 || !simple_positive(q)) {
+       if (!d_count(q) || !simple_positive(q)) {
                spin_unlock(&q->d_lock);
                next = q->d_u.d_child.next;
                goto cont;
@@ -267,7 +267,7 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
                        else
                                ino_count++;
 
-                       if (p->d_count > ino_count) {
+                       if (d_count(p) > ino_count) {
                                top_ino->last_used = jiffies;
                                dput(p);
                                return 1;
@@ -409,7 +409,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
                if (!exp_leaves) {
                        /* Path walk currently on this dentry? */
                        ino_count = atomic_read(&ino->count) + 1;
-                       if (dentry->d_count > ino_count)
+                       if (d_count(dentry) > ino_count)
                                goto next;
 
                        if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) {
@@ -423,7 +423,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
                } else {
                        /* Path walk currently on this dentry? */
                        ino_count = atomic_read(&ino->count) + 1;
-                       if (dentry->d_count > ino_count)
+                       if (d_count(dentry) > ino_count)
                                goto next;
 
                        expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
index ca8e55548d9893eebf82e4261e79dc84c3b06409..92ef341ba0cf35c1bd1b5f001b9b39068979f6ff 100644 (file)
@@ -179,7 +179,7 @@ static struct dentry *autofs4_lookup_active(struct dentry *dentry)
                spin_lock(&active->d_lock);
 
                /* Already gone? */
-               if (active->d_count == 0)
+               if (!d_count(active))
                        goto next;
 
                qstr = &active->d_name;
index be0f7e20d62ed230186019d65297e8f45f2f4ab2..bd2289a4f40dfbcabc17287ed854d154f96609d1 100644 (file)
@@ -903,8 +903,8 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in,
        } else if (realdn) {
                dout("dn %p (%d) spliced with %p (%d) "
                     "inode %p ino %llx.%llx\n",
-                    dn, dn->d_count,
-                    realdn, realdn->d_count,
+                    dn, d_count(dn),
+                    realdn, d_count(realdn),
                     realdn->d_inode, ceph_vinop(realdn->d_inode));
                dput(dn);
                dn = realdn;
index 74fd2898b2ab43012ab1c3fbf25f619fbd7df3b2..99890b02a10be7b08955353190af317d8eb21a69 100644 (file)
@@ -1553,7 +1553,7 @@ retry:
        *base = ceph_ino(temp->d_inode);
        *plen = len;
        dout("build_path on %p %d built %llx '%.*s'\n",
-            dentry, dentry->d_count, *base, len, path);
+            dentry, d_count(dentry), *base, len, path);
        return path;
 }
 
index 14a14808320cf1e555d8ca14fdd604590d8b723f..190effc6a6fae2e09f0826979c201c532003b1b8 100644 (file)
@@ -526,7 +526,7 @@ static int coda_dentry_revalidate(struct dentry *de, unsigned int flags)
        if (cii->c_flags & C_FLUSH) 
                coda_flag_inode_children(inode, C_FLUSH);
 
-       if (de->d_count > 1)
+       if (d_count(de) > 1)
                /* pretend it's valid, but don't change the flags */
                goto out;
 
index 64e5323cbbb014c4c2240c733d667b2e704bcdcc..5e7c60c1cb63ff541b855bfe227dbf9fde5b1708 100644 (file)
@@ -387,7 +387,7 @@ static void remove_dir(struct dentry * d)
        if (d->d_inode)
                simple_rmdir(parent->d_inode,d);
 
-       pr_debug(" o %s removing done (%d)\n",d->d_name.name, d->d_count);
+       pr_debug(" o %s removing done (%d)\n",d->d_name.name, d_count(d));
 
        dput(parent);
 }
index a2f2bb2c256dd24cf8a9e597cbbe7f97a290f282..67e9b6339691f9cc01a378564fa5aa0527da1977 100644 (file)
@@ -358,7 +358,7 @@ static int ecryptfs_lookup_interpose(struct dentry *dentry,
 
        lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent));
        fsstack_copy_attr_atime(dir_inode, lower_dentry->d_parent->d_inode);
-       BUG_ON(!lower_dentry->d_count);
+       BUG_ON(!d_count(lower_dentry));
 
        ecryptfs_set_dentry_private(dentry, dentry_info);
        ecryptfs_set_dentry_lower(dentry, lower_dentry);
index 9d1cd423450d1ba12049a987a0e5478424a33850..62f0d5977c64f3526e0720653fe33039c85355e3 100644 (file)
@@ -610,13 +610,12 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
 {
        struct inode *inode = file_inode(file);
        unsigned long npages = dir_blocks(inode);
-       unsigned int bit_pos = 0, start_bit_pos = 0;
+       unsigned int bit_pos = 0;
        struct f2fs_dentry_block *dentry_blk = NULL;
        struct f2fs_dir_entry *de = NULL;
        struct page *dentry_page = NULL;
        unsigned int n = ((unsigned long)ctx->pos / NR_DENTRY_IN_BLOCK);
        unsigned char d_type = DT_UNKNOWN;
-       int slots;
 
        bit_pos = ((unsigned long)ctx->pos % NR_DENTRY_IN_BLOCK);
 
@@ -625,7 +624,6 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
                if (IS_ERR(dentry_page))
                        continue;
 
-               start_bit_pos = bit_pos;
                dentry_blk = kmap(dentry_page);
                while (bit_pos < NR_DENTRY_IN_BLOCK) {
                        bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
@@ -634,19 +632,19 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
                        if (bit_pos >= NR_DENTRY_IN_BLOCK)
                                break;
 
-                       ctx->pos += bit_pos - start_bit_pos;
                        de = &dentry_blk->dentry[bit_pos];
                        if (de->file_type < F2FS_FT_MAX)
                                d_type = f2fs_filetype_table[de->file_type];
                        else
                                d_type = DT_UNKNOWN;
                        if (!dir_emit(ctx,
-                                     dentry_blk->filename[bit_pos],
-                                     le16_to_cpu(de->name_len),
-                                     le32_to_cpu(de->ino), d_type))
-                               goto success;
-                       slots = GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
-                       bit_pos += slots;
+                                       dentry_blk->filename[bit_pos],
+                                       le16_to_cpu(de->name_len),
+                                       le32_to_cpu(de->ino), d_type))
+                               goto stop;
+
+                       bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
+                       ctx->pos = n * NR_DENTRY_IN_BLOCK + bit_pos;
                }
                bit_pos = 0;
                ctx->pos = (n + 1) * NR_DENTRY_IN_BLOCK;
@@ -654,7 +652,7 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
                f2fs_put_page(dentry_page, 1);
                dentry_page = NULL;
        }
-success:
+stop:
        if (dentry_page && !IS_ERR(dentry_page)) {
                kunmap(dentry_page);
                f2fs_put_page(dentry_page, 1);
index 04e2c1fdb157afeb0bc8fe278a74909cd239126b..b27a3005d78df9fccd74343bd4a9f93f9f6753b1 100644 (file)
 #include <linux/rcupdate.h>
 #include <linux/pid_namespace.h>
 #include <linux/hashtable.h>
+#include <linux/percpu.h>
+#include <linux/lglock.h>
 
 #include <asm/uaccess.h>
 
@@ -155,11 +157,13 @@ int lease_break_time = 45;
        for (lockp = &inode->i_flock; *lockp != NULL; lockp = &(*lockp)->fl_next)
 
 /*
- * The global file_lock_list is only used for displaying /proc/locks. Protected
- * by the file_lock_lock.
+ * The global file_lock_list is only used for displaying /proc/locks, so we
+ * keep a list on each CPU, with each list protected by its own spinlock via
+ * the file_lock_lglock. Note that alterations to the list also require that
+ * the relevant i_lock is held.
  */
-static HLIST_HEAD(file_lock_list);
-static DEFINE_SPINLOCK(file_lock_lock);
+DEFINE_STATIC_LGLOCK(file_lock_lglock);
+static DEFINE_PER_CPU(struct hlist_head, file_lock_list);
 
 /*
  * The blocked_hash is used to find POSIX lock loops for deadlock detection.
@@ -506,20 +510,30 @@ static int posix_same_owner(struct file_lock *fl1, struct file_lock *fl2)
        return fl1->fl_owner == fl2->fl_owner;
 }
 
+/* Must be called with the i_lock held! */
 static inline void
 locks_insert_global_locks(struct file_lock *fl)
 {
-       spin_lock(&file_lock_lock);
-       hlist_add_head(&fl->fl_link, &file_lock_list);
-       spin_unlock(&file_lock_lock);
+       lg_local_lock(&file_lock_lglock);
+       fl->fl_link_cpu = smp_processor_id();
+       hlist_add_head(&fl->fl_link, this_cpu_ptr(&file_lock_list));
+       lg_local_unlock(&file_lock_lglock);
 }
 
+/* Must be called with the i_lock held! */
 static inline void
 locks_delete_global_locks(struct file_lock *fl)
 {
-       spin_lock(&file_lock_lock);
+       /*
+        * Avoid taking lock if already unhashed. This is safe since this check
+        * is done while holding the i_lock, and new insertions into the list
+        * also require that it be held.
+        */
+       if (hlist_unhashed(&fl->fl_link))
+               return;
+       lg_local_lock_cpu(&file_lock_lglock, fl->fl_link_cpu);
        hlist_del_init(&fl->fl_link);
-       spin_unlock(&file_lock_lock);
+       lg_local_unlock_cpu(&file_lock_lglock, fl->fl_link_cpu);
 }
 
 static unsigned long
@@ -1454,7 +1468,7 @@ static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp
        if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
                goto out;
        if ((arg == F_WRLCK)
-           && ((dentry->d_count > 1)
+           && ((d_count(dentry) > 1)
                || (atomic_read(&inode->i_count) > 1)))
                goto out;
 
@@ -2243,6 +2257,11 @@ EXPORT_SYMBOL_GPL(vfs_cancel_lock);
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 
+struct locks_iterator {
+       int     li_cpu;
+       loff_t  li_pos;
+};
+
 static void lock_get_status(struct seq_file *f, struct file_lock *fl,
                            loff_t id, char *pfx)
 {
@@ -2316,39 +2335,41 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
 
 static int locks_show(struct seq_file *f, void *v)
 {
+       struct locks_iterator *iter = f->private;
        struct file_lock *fl, *bfl;
 
        fl = hlist_entry(v, struct file_lock, fl_link);
 
-       lock_get_status(f, fl, *((loff_t *)f->private), "");
+       lock_get_status(f, fl, iter->li_pos, "");
 
        list_for_each_entry(bfl, &fl->fl_block, fl_block)
-               lock_get_status(f, bfl, *((loff_t *)f->private), " ->");
+               lock_get_status(f, bfl, iter->li_pos, " ->");
 
        return 0;
 }
 
 static void *locks_start(struct seq_file *f, loff_t *pos)
 {
-       loff_t *p = f->private;
+       struct locks_iterator *iter = f->private;
 
-       spin_lock(&file_lock_lock);
+       iter->li_pos = *pos + 1;
+       lg_global_lock(&file_lock_lglock);
        spin_lock(&blocked_lock_lock);
-       *p = (*pos + 1);
-       return seq_hlist_start(&file_lock_list, *pos);
+       return seq_hlist_start_percpu(&file_lock_list, &iter->li_cpu, *pos);
 }
 
 static void *locks_next(struct seq_file *f, void *v, loff_t *pos)
 {
-       loff_t *p = f->private;
-       ++*p;
-       return seq_hlist_next(v, &file_lock_list, pos);
+       struct locks_iterator *iter = f->private;
+
+       ++iter->li_pos;
+       return seq_hlist_next_percpu(v, &file_lock_list, &iter->li_cpu, pos);
 }
 
 static void locks_stop(struct seq_file *f, void *v)
 {
        spin_unlock(&blocked_lock_lock);
-       spin_unlock(&file_lock_lock);
+       lg_global_unlock(&file_lock_lglock);
 }
 
 static const struct seq_operations locks_seq_operations = {
@@ -2360,7 +2381,8 @@ static const struct seq_operations locks_seq_operations = {
 
 static int locks_open(struct inode *inode, struct file *filp)
 {
-       return seq_open_private(filp, &locks_seq_operations, sizeof(loff_t));
+       return seq_open_private(filp, &locks_seq_operations,
+                                       sizeof(struct locks_iterator));
 }
 
 static const struct file_operations proc_locks_operations = {
@@ -2460,9 +2482,16 @@ EXPORT_SYMBOL(lock_may_write);
 
 static int __init filelock_init(void)
 {
+       int i;
+
        filelock_cache = kmem_cache_create("file_lock_cache",
                        sizeof(struct file_lock), 0, SLAB_PANIC, NULL);
 
+       lg_lock_init(&file_lock_lglock, "file_lock_lglock");
+
+       for_each_possible_cpu(i)
+               INIT_HLIST_HEAD(per_cpu_ptr(&file_lock_list, i));
+
        return 0;
 }
 
index 0765ad12c3827cf9822dacc1875cb64a957c9864..4659da67e7f6d0efa17f06934ed9f7200c3dadfd 100644 (file)
@@ -403,18 +403,24 @@ static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options)
                switch (optval) {
                        case 'u':
                                data->uid = make_kuid(current_user_ns(), optint);
-                               if (!uid_valid(data->uid))
+                               if (!uid_valid(data->uid)) {
+                                       ret = -EINVAL;
                                        goto err;
+                               }
                                break;
                        case 'g':
                                data->gid = make_kgid(current_user_ns(), optint);
-                               if (!gid_valid(data->gid))
+                               if (!gid_valid(data->gid)) {
+                                       ret = -EINVAL;
                                        goto err;
+                               }
                                break;
                        case 'o':
                                data->mounted_uid = make_kuid(current_user_ns(), optint);
-                               if (!uid_valid(data->mounted_uid))
+                               if (!uid_valid(data->mounted_uid)) {
+                                       ret = -EINVAL;
                                        goto err;
+                               }
                                break;
                        case 'm':
                                data->file_mode = optint;
index d7ed697133f0b6c6ac667c4e3e334646a6a67b63..c933bdfbcb1f7b3f15be78f9f261db42de9385fb 100644 (file)
@@ -1721,7 +1721,7 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry)
                dir->i_ino, dentry->d_name.name);
 
        spin_lock(&dentry->d_lock);
-       if (dentry->d_count > 1) {
+       if (d_count(dentry) > 1) {
                spin_unlock(&dentry->d_lock);
                /* Start asynchronous writeout of the inode */
                write_inode_now(dentry->d_inode, 0);
@@ -1866,7 +1866,7 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n",
                 old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
                 new_dentry->d_parent->d_name.name, new_dentry->d_name.name,
-                new_dentry->d_count);
+                d_count(new_dentry));
 
        /*
         * For non-directories, check whether the target is busy and if so,
@@ -1884,7 +1884,7 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        rehash = new_dentry;
                }
 
-               if (new_dentry->d_count > 2) {
+               if (d_count(new_dentry) > 2) {
                        int err;
 
                        /* copy the target dentry's name */
index 1f1f38f0c5d58703ca66c8477d551b708d9cab7b..60395ad3a2e475076ee3382e05b221aacdcaa60b 100644 (file)
@@ -479,7 +479,7 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
 
        dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n",
                dentry->d_parent->d_name.name, dentry->d_name.name,
-               dentry->d_count);
+               d_count(dentry));
        nfs_inc_stats(dir, NFSIOS_SILLYRENAME);
 
        /*
index 1427de5ebf4d7d2a66d05d3ef0b164ef4a9312d5..af3ba0478cdf5d7acedd8fba777f9217ae00f986 100644 (file)
@@ -996,7 +996,7 @@ static int nilfs_attach_snapshot(struct super_block *s, __u64 cno,
 
 static int nilfs_tree_was_touched(struct dentry *root_dentry)
 {
-       return root_dentry->d_count > 1;
+       return d_count(root_dentry) > 1;
 }
 
 /**
index 774c1eb7f1c926c73a7018ae47d9cfb03f75da76..3135c2525c76635606ae9722f6badb5a11e44543 100644 (file)
@@ -921,3 +921,57 @@ struct hlist_node *seq_hlist_next_rcu(void *v,
                return rcu_dereference(node->next);
 }
 EXPORT_SYMBOL(seq_hlist_next_rcu);
+
+/**
+ * seq_hlist_start_precpu - start an iteration of a percpu hlist array
+ * @head: pointer to percpu array of struct hlist_heads
+ * @cpu:  pointer to cpu "cursor"
+ * @pos:  start position of sequence
+ *
+ * Called at seq_file->op->start().
+ */
+struct hlist_node *
+seq_hlist_start_percpu(struct hlist_head __percpu *head, int *cpu, loff_t pos)
+{
+       struct hlist_node *node;
+
+       for_each_possible_cpu(*cpu) {
+               hlist_for_each(node, per_cpu_ptr(head, *cpu)) {
+                       if (pos-- == 0)
+                               return node;
+               }
+       }
+       return NULL;
+}
+EXPORT_SYMBOL(seq_hlist_start_percpu);
+
+/**
+ * seq_hlist_next_percpu - move to the next position of the percpu hlist array
+ * @v:    pointer to current hlist_node
+ * @head: pointer to percpu array of struct hlist_heads
+ * @cpu:  pointer to cpu "cursor"
+ * @pos:  start position of sequence
+ *
+ * Called at seq_file->op->next().
+ */
+struct hlist_node *
+seq_hlist_next_percpu(void *v, struct hlist_head __percpu *head,
+                       int *cpu, loff_t *pos)
+{
+       struct hlist_node *node = v;
+
+       ++*pos;
+
+       if (node->next)
+               return node->next;
+
+       for (*cpu = cpumask_next(*cpu, cpu_possible_mask); *cpu < nr_cpu_ids;
+            *cpu = cpumask_next(*cpu, cpu_possible_mask)) {
+               struct hlist_head *bucket = per_cpu_ptr(head, *cpu);
+
+               if (!hlist_empty(bucket))
+                       return bucket->first;
+       }
+       return NULL;
+}
+EXPORT_SYMBOL(seq_hlist_next_percpu);
index f42dbe1454793870dba2d4afd456f51bc2c8b2a5..3092df3614ae4651a867571ccbaa1d670e97c314 100644 (file)
@@ -324,6 +324,11 @@ static inline int __d_rcu_to_refcount(struct dentry *dentry, unsigned seq)
        return ret;
 }
 
+static inline unsigned d_count(struct dentry *dentry)
+{
+       return dentry->d_count;
+}
+
 /* validate "insecure" dentry pointer */
 extern int d_validate(struct dentry *, struct dentry *);
 
index 99be011e00dea1eeb6f2b48f7cc81035dd0acf82..834c9e5113d958d11c544b546201157d74cafe1d 100644 (file)
@@ -954,6 +954,7 @@ struct file_lock {
        unsigned int fl_flags;
        unsigned char fl_type;
        unsigned int fl_pid;
+       int fl_link_cpu;                /* what cpu's list is this on? */
        struct pid *fl_nspid;
        wait_queue_head_t fl_wait;
        struct file *fl_file;
index 2da29ac178fc25ccf01fca81552bf9f515e3c945..4e32edc8f506b89f13b0260200498b5cf87b490a 100644 (file)
@@ -173,4 +173,10 @@ extern struct hlist_node *seq_hlist_start_head_rcu(struct hlist_head *head,
 extern struct hlist_node *seq_hlist_next_rcu(void *v,
                                                   struct hlist_head *head,
                                                   loff_t *ppos);
+
+/* Helpers for iterating over per-cpu hlist_head-s in seq_files */
+extern struct hlist_node *seq_hlist_start_percpu(struct hlist_head __percpu *head, int *cpu, loff_t pos);
+
+extern struct hlist_node *seq_hlist_next_percpu(void *v, struct hlist_head __percpu *head, int *cpu, loff_t *pos);
+
 #endif