]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge branch 'flock' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/bkl
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 28 Oct 2010 01:13:34 +0000 (18:13 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 28 Oct 2010 01:13:34 +0000 (18:13 -0700)
* 'flock' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/bkl:
  locks: turn lock_flocks into a spinlock
  fasync: re-organize fasync entry insertion to allow it under a spinlock
  locks/nfsd: allocate file lock outside of spinlock
  lockd: fix nlmsvc_notify_blocked locking
  lockd: push lock_flocks down

1  2 
fs/Kconfig
fs/locks.c
include/linux/fs.h

diff --combined fs/Kconfig
index b5e582bd769dd974fcb671adfac389f6c72d02e1,3d185308ec883bd0c06be0d151385c65e15b3353..97673c955484463e4181d4e3f689742bbe558a06
@@@ -47,13 -47,9 +47,12 @@@ source "fs/nilfs2/Kconfig
  
  endif # BLOCK
  
 +config EXPORTFS
 +      tristate
 +
  config FILE_LOCKING
        bool "Enable POSIX file locking API" if EMBEDDED
        default y
-       select BKL # while lockd still uses it.
        help
          This option enables standard file locking support, required
            for filesystems like NFS and for the flock() system
@@@ -225,6 -221,9 +224,6 @@@ config LOCKD_V
        depends on FILE_LOCKING
        default y
  
 -config EXPORTFS
 -      tristate
 -
  config NFS_ACL_SUPPORT
        tristate
        select FS_POSIX_ACL
diff --combined fs/locks.c
index 4de3a2666810535d1be9d12662b0544474f619c8,74c3df99c0e144702d259991ed42c84d93593adf..50ec15927aab3164a456875e6c11b1f4fa2f8bef
@@@ -142,6 -142,7 +142,7 @@@ int lease_break_time = 45
  
  static LIST_HEAD(file_lock_list);
  static LIST_HEAD(blocked_list);
+ static DEFINE_SPINLOCK(file_lock_lock);
  
  /*
   * Protects the two list heads above, plus the inode->i_flock list
   */
  void lock_flocks(void)
  {
-       lock_kernel();
+       spin_lock(&file_lock_lock);
  }
  EXPORT_SYMBOL_GPL(lock_flocks);
  
  void unlock_flocks(void)
  {
-       unlock_kernel();
+       spin_unlock(&file_lock_lock);
  }
  EXPORT_SYMBOL_GPL(unlock_flocks);
  
  static struct kmem_cache *filelock_cache __read_mostly;
  
  /* Allocate an empty lock structure. */
- static struct file_lock *locks_alloc_lock(void)
+ struct file_lock *locks_alloc_lock(void)
  {
        return kmem_cache_alloc(filelock_cache, GFP_KERNEL);
  }
+ EXPORT_SYMBOL_GPL(locks_alloc_lock);
  
  void locks_release_private(struct file_lock *fl)
  {
@@@ -1365,7 -1367,6 +1367,6 @@@ int fcntl_getlease(struct file *filp
  int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
  {
        struct file_lock *fl, **before, **my_before = NULL, *lease;
-       struct file_lock *new_fl = NULL;
        struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        int error, rdlease_count = 0, wrlease_count = 0;
        lease = *flp;
  
        if (arg != F_UNLCK) {
-               error = -ENOMEM;
-               new_fl = locks_alloc_lock();
-               if (new_fl == NULL)
-                       goto out;
                error = -EAGAIN;
                if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
                        goto out;
                goto out;
        }
  
-       error = 0;
        if (arg == F_UNLCK)
                goto out;
  
        if (!leases_enable)
                goto out;
  
-       locks_copy_lock(new_fl, lease);
-       locks_insert_lock(before, new_fl);
-       *flp = new_fl;
+       locks_insert_lock(before, lease);
        return 0;
  
  out:
-       if (new_fl != NULL)
-               locks_free_lock(new_fl);
+       locks_free_lock(lease);
        return error;
  }
  EXPORT_SYMBOL(generic_setlease);
@@@ -1514,26 -1505,38 +1505,38 @@@ EXPORT_SYMBOL_GPL(vfs_setlease)
   */
  int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
  {
-       struct file_lock fl, *flp = &fl;
+       struct file_lock *fl;
+       struct fasync_struct *new;
        struct inode *inode = filp->f_path.dentry->d_inode;
        int error;
  
-       locks_init_lock(&fl);
-       error = lease_init(filp, arg, &fl);
-       if (error)
-               return error;
+       fl = lease_alloc(filp, arg);
+       if (IS_ERR(fl))
+               return PTR_ERR(fl);
  
+       new = fasync_alloc();
+       if (!new) {
+               locks_free_lock(fl);
+               return -ENOMEM;
+       }
        lock_flocks();
-       error = __vfs_setlease(filp, arg, &flp);
+       error = __vfs_setlease(filp, arg, &fl);
        if (error || arg == F_UNLCK)
                goto out_unlock;
  
-       error = fasync_helper(fd, filp, 1, &flp->fl_fasync);
+       /*
+        * fasync_insert_entry() returns the old entry if any.
+        * If there was no old entry, then it used 'new' and
+        * inserted it into the fasync list. Clear new so that
+        * we don't release it here.
+        */
+       if (!fasync_insert_entry(fd, filp, &fl->fl_fasync, new))
+               new = NULL;
        if (error < 0) {
                /* remove lease just inserted by setlease */
-               flp->fl_type = F_UNLCK | F_INPROGRESS;
-               flp->fl_break_time = jiffies - 10;
+               fl->fl_type = F_UNLCK | F_INPROGRESS;
+               fl->fl_break_time = jiffies - 10;
                time_out_leases(inode);
                goto out_unlock;
        }
        error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0);
  out_unlock:
        unlock_flocks();
+       if (new)
+               fasync_free(new);
        return error;
  }
  
@@@ -2109,7 -2114,7 +2114,7 @@@ EXPORT_SYMBOL_GPL(vfs_cancel_lock)
  #include <linux/seq_file.h>
  
  static void lock_get_status(struct seq_file *f, struct file_lock *fl,
 -                                                      int id, char *pfx)
 +                          loff_t id, char *pfx)
  {
        struct inode *inode = NULL;
        unsigned int fl_pid;
        if (fl->fl_file != NULL)
                inode = fl->fl_file->f_path.dentry->d_inode;
  
 -      seq_printf(f, "%d:%s ", id, pfx);
 +      seq_printf(f, "%lld:%s ", id, pfx);
        if (IS_POSIX(fl)) {
                seq_printf(f, "%6s %s ",
                             (fl->fl_flags & FL_ACCESS) ? "ACCESS" : "POSIX ",
@@@ -2185,27 -2190,24 +2190,27 @@@ static int locks_show(struct seq_file *
  
        fl = list_entry(v, struct file_lock, fl_link);
  
 -      lock_get_status(f, fl, (long)f->private, "");
 +      lock_get_status(f, fl, *((loff_t *)f->private), "");
  
        list_for_each_entry(bfl, &fl->fl_block, fl_block)
 -              lock_get_status(f, bfl, (long)f->private, " ->");
 +              lock_get_status(f, bfl, *((loff_t *)f->private), " ->");
  
 -      f->private++;
        return 0;
  }
  
  static void *locks_start(struct seq_file *f, loff_t *pos)
  {
 +      loff_t *p = f->private;
 +
        lock_flocks();
 -      f->private = (void *)1;
 +      *p = (*pos + 1);
        return seq_list_start(&file_lock_list, *pos);
  }
  
  static void *locks_next(struct seq_file *f, void *v, loff_t *pos)
  {
 +      loff_t *p = f->private;
 +      ++*p;
        return seq_list_next(v, &file_lock_list, pos);
  }
  
@@@ -2223,14 -2225,14 +2228,14 @@@ static const struct seq_operations lock
  
  static int locks_open(struct inode *inode, struct file *filp)
  {
 -      return seq_open(filp, &locks_seq_operations);
 +      return seq_open_private(filp, &locks_seq_operations, sizeof(loff_t));
  }
  
  static const struct file_operations proc_locks_operations = {
        .open           = locks_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
 -      .release        = seq_release,
 +      .release        = seq_release_private,
  };
  
  static int __init proc_locks_init(void)
diff --combined include/linux/fs.h
index 240eb1d4f87645672217429ed0699cf21ce84d72,56285e5e1de4b6d80c8efd61ddf5495071c6a38a..b2a6009cba10f6e018093dd50fec8d913e7d5817
@@@ -34,9 -34,9 +34,9 @@@
  
  /* And dynamically-tunable limits and defaults: */
  struct files_stat_struct {
 -      int nr_files;           /* read only */
 -      int nr_free_files;      /* read only */
 -      int max_files;          /* tunable */
 +      unsigned long nr_files;         /* read only */
 +      unsigned long nr_free_files;    /* read only */
 +      unsigned long max_files;                /* tunable */
  };
  
  struct inodes_stat_t {
@@@ -92,9 -92,6 +92,9 @@@
  /* Expect random access pattern */
  #define FMODE_RANDOM          ((__force fmode_t)0x1000)
  
 +/* File is huge (eg. /dev/kmem): treat loff_t as unsigned */
 +#define FMODE_UNSIGNED_OFFSET ((__force fmode_t)0x2000)
 +
  /* File was opened by fanotify and shouldn't generate fanotify events */
  #define FMODE_NONOTIFY                ((__force fmode_t)0x1000000)
  
@@@ -405,7 -402,7 +405,7 @@@ extern void __init inode_init_early(voi
  extern void __init files_init(unsigned long);
  
  extern struct files_stat_struct files_stat;
 -extern int get_max_files(void);
 +extern unsigned long get_max_files(void);
  extern int sysctl_nr_open;
  extern struct inodes_stat_t inodes_stat;
  extern int leases_enable, lease_break_time;
@@@ -725,8 -722,7 +725,8 @@@ struct posix_acl
  
  struct inode {
        struct hlist_node       i_hash;
 -      struct list_head        i_list;         /* backing dev IO list */
 +      struct list_head        i_wb_list;      /* backing dev IO list */
 +      struct list_head        i_lru;          /* inode LRU list */
        struct list_head        i_sb_list;
        struct list_head        i_dentry;
        unsigned long           i_ino;
        void                    *i_private; /* fs or device private pointer */
  };
  
 +static inline int inode_unhashed(struct inode *inode)
 +{
 +      return hlist_unhashed(&inode->i_hash);
 +}
 +
  /*
   * inode->i_mutex nesting subclasses for the lock validator:
   *
@@@ -1122,6 -1113,7 +1122,7 @@@ extern int fcntl_getlease(struct file *
  
  /* fs/locks.c */
  extern void locks_init_lock(struct file_lock *);
+ extern struct file_lock * locks_alloc_lock(void);
  extern void locks_copy_lock(struct file_lock *, struct file_lock *);
  extern void __locks_copy_lock(struct file_lock *, const struct file_lock *);
  extern void locks_remove_posix(struct file *, fl_owner_t);
@@@ -1310,6 -1302,11 +1311,11 @@@ struct fasync_struct 
  
  /* SMP safe fasync helpers: */
  extern int fasync_helper(int, struct file *, int, struct fasync_struct **);
+ extern struct fasync_struct *fasync_insert_entry(int, struct file *, struct fasync_struct **, struct fasync_struct *);
+ extern int fasync_remove_entry(struct file *, struct fasync_struct **);
+ extern struct fasync_struct *fasync_alloc(void);
+ extern void fasync_free(struct fasync_struct *);
  /* can be called from interrupts */
  extern void kill_fasync(struct fasync_struct **, int, int);
  
@@@ -1648,17 -1645,16 +1654,17 @@@ struct super_operations 
   *
   * Q: What is the difference between I_WILL_FREE and I_FREEING?
   */
 -#define I_DIRTY_SYNC          1
 -#define I_DIRTY_DATASYNC      2
 -#define I_DIRTY_PAGES         4
 +#define I_DIRTY_SYNC          (1 << 0)
 +#define I_DIRTY_DATASYNC      (1 << 1)
 +#define I_DIRTY_PAGES         (1 << 2)
  #define __I_NEW                       3
  #define I_NEW                 (1 << __I_NEW)
 -#define I_WILL_FREE           16
 -#define I_FREEING             32
 -#define I_CLEAR                       64
 +#define I_WILL_FREE           (1 << 4)
 +#define I_FREEING             (1 << 5)
 +#define I_CLEAR                       (1 << 6)
  #define __I_SYNC              7
  #define I_SYNC                        (1 << __I_SYNC)
 +#define I_REFERENCED          (1 << 8)
  
  #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES)
  
@@@ -1750,7 -1746,6 +1756,7 @@@ static inline void file_accessed(struc
  }
  
  int sync_inode(struct inode *inode, struct writeback_control *wbc);
 +int sync_inode_metadata(struct inode *inode, int wait);
  
  struct file_system_type {
        const char *name;
@@@ -2095,6 -2090,7 +2101,6 @@@ extern int check_disk_change(struct blo
  extern int __invalidate_device(struct block_device *);
  extern int invalidate_partition(struct gendisk *, int);
  #endif
 -extern int invalidate_inodes(struct super_block *);
  unsigned long invalidate_mapping_pages(struct address_space *mapping,
                                        pgoff_t start, pgoff_t end);
  
@@@ -2178,7 -2174,7 +2184,7 @@@ extern loff_t vfs_llseek(struct file *f
  
  extern int inode_init_always(struct super_block *, struct inode *);
  extern void inode_init_once(struct inode *);
 -extern void inode_add_to_lists(struct super_block *, struct inode *);
 +extern void ihold(struct inode * inode);
  extern void iput(struct inode *);
  extern struct inode * igrab(struct inode *);
  extern ino_t iunique(struct super_block *, ino_t);
@@@ -2198,11 -2194,11 +2204,11 @@@ extern struct inode * iget_locked(struc
  extern int insert_inode_locked4(struct inode *, unsigned long, int (*test)(struct inode *, void *), void *);
  extern int insert_inode_locked(struct inode *);
  extern void unlock_new_inode(struct inode *);
 +extern unsigned int get_next_ino(void);
  
  extern void __iget(struct inode * inode);
  extern void iget_failed(struct inode *);
  extern void end_writeback(struct inode *);
 -extern void destroy_inode(struct inode *);
  extern void __destroy_inode(struct inode *);
  extern struct inode *new_inode(struct super_block *);
  extern int should_remove_suid(struct dentry *);
@@@ -2210,11 -2206,9 +2216,11 @@@ extern int file_remove_suid(struct fil
  
  extern void __insert_inode_hash(struct inode *, unsigned long hashval);
  extern void remove_inode_hash(struct inode *);
 -static inline void insert_inode_hash(struct inode *inode) {
 +static inline void insert_inode_hash(struct inode *inode)
 +{
        __insert_inode_hash(inode, inode->i_ino);
  }
 +extern void inode_sb_list_add(struct inode *inode);
  
  #ifdef CONFIG_BLOCK
  extern void submit_bio(int, struct bio *);
@@@ -2497,10 -2491,7 +2503,10 @@@ ssize_t simple_attr_write(struct file *
  struct ctl_table;
  int proc_nr_files(struct ctl_table *table, int write,
                  void __user *buffer, size_t *lenp, loff_t *ppos);
 -
 +int proc_nr_dentry(struct ctl_table *table, int write,
 +                void __user *buffer, size_t *lenp, loff_t *ppos);
 +int proc_nr_inodes(struct ctl_table *table, int write,
 +                 void __user *buffer, size_t *lenp, loff_t *ppos);
  int __init get_filesystem_list(char *buf);
  
  #define ACC_MODE(x) ("\004\002\006\006"[(x)&O_ACCMODE])