Merge branch 'nfsd-next' of git://linux-nfs.org/~bfields/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 31 Jul 2012 21:42:28 +0000 (14:42 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 31 Jul 2012 21:42:28 +0000 (14:42 -0700)
Pull nfsd changes from J. Bruce Fields:
 "This has been an unusually quiet cycle--mostly bugfixes and cleanup.
  The one large piece is Stanislav's work to containerize the server's
  grace period--but that in itself is just one more step in a
  not-yet-complete project to allow fully containerized nfs service.

  There are a number of outstanding delegation, container, v4 state, and
  gss patches that aren't quite ready yet; 3.7 may be wilder."

* 'nfsd-next' of git://linux-nfs.org/~bfields/linux: (35 commits)
  NFSd: make boot_time variable per network namespace
  NFSd: make grace end flag per network namespace
  Lockd: move grace period management from lockd() to per-net functions
  LockD: pass actual network namespace to grace period management functions
  LockD: manage grace list per network namespace
  SUNRPC: service request network namespace helper introduced
  NFSd: make nfsd4_manager allocated per network namespace context.
  LockD: make lockd manager allocated per network namespace
  LockD: manage grace period per network namespace
  Lockd: add more debug to host shutdown functions
  Lockd: host complaining function introduced
  LockD: manage used host count per networks namespace
  LockD: manage garbage collection timeout per networks namespace
  LockD: make garbage collector network namespace aware.
  LockD: mark host per network namespace on garbage collect
  nfsd4: fix missing fault_inject.h include
  locks: move lease-specific code out of locks_delete_lock
  locks: prevent side-effects of locks_release_private before file_lock is initialized
  NFSd: set nfsd_serv to NULL after service destruction
  NFSd: introduce nfsd_destroy() helper
  ...

1  2 
fs/locks.c
fs/nfsd/vfs.c
include/linux/fs.h

diff --combined fs/locks.c
@@@ -308,7 -308,7 +308,7 @@@ static int flock_make_lock(struct file 
        return 0;
  }
  
 -static int assign_type(struct file_lock *fl, int type)
 +static int assign_type(struct file_lock *fl, long type)
  {
        switch (type) {
        case F_RDLCK:
@@@ -427,25 -427,15 +427,15 @@@ static void lease_break_callback(struc
        kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG);
  }
  
- static void lease_release_private_callback(struct file_lock *fl)
- {
-       if (!fl->fl_file)
-               return;
-       f_delown(fl->fl_file);
-       fl->fl_file->f_owner.signum = 0;
- }
  static const struct lock_manager_operations lease_manager_ops = {
        .lm_break = lease_break_callback,
-       .lm_release_private = lease_release_private_callback,
        .lm_change = lease_modify,
  };
  
  /*
   * Initialize a lease, use the default lock manager operations
   */
 -static int lease_init(struct file *filp, int type, struct file_lock *fl)
 +static int lease_init(struct file *filp, long type, struct file_lock *fl)
   {
        if (assign_type(fl, type) != 0)
                return -EINVAL;
  }
  
  /* Allocate a file_lock initialised to this type of lease */
 -static struct file_lock *lease_alloc(struct file *filp, int type)
 +static struct file_lock *lease_alloc(struct file *filp, long type)
  {
        struct file_lock *fl = locks_alloc_lock();
        int error = -ENOMEM;
@@@ -580,12 -570,6 +570,6 @@@ static void locks_delete_lock(struct fi
        fl->fl_next = NULL;
        list_del_init(&fl->fl_link);
  
-       fasync_helper(0, fl->fl_file, 0, &fl->fl_fasync);
-       if (fl->fl_fasync != NULL) {
-               printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync);
-               fl->fl_fasync = NULL;
-       }
        if (fl->fl_nspid) {
                put_pid(fl->fl_nspid);
                fl->fl_nspid = NULL;
@@@ -1155,8 -1139,18 +1139,18 @@@ int lease_modify(struct file_lock **bef
                return error;
        lease_clear_pending(fl, arg);
        locks_wake_up_blocks(fl);
-       if (arg == F_UNLCK)
+       if (arg == F_UNLCK) {
+               struct file *filp = fl->fl_file;
+               f_delown(filp);
+               filp->f_owner.signum = 0;
+               fasync_helper(0, fl->fl_file, 0, &fl->fl_fasync);
+               if (fl->fl_fasync != NULL) {
+                       printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync);
+                       fl->fl_fasync = NULL;
+               }
                locks_delete_lock(before);
+       }
        return 0;
  }
  
@@@ -1465,7 -1459,7 +1459,7 @@@ int generic_setlease(struct file *filp
        case F_WRLCK:
                return generic_add_lease(filp, arg, flp);
        default:
 -              BUG();
 +              return -EINVAL;
        }
  }
  EXPORT_SYMBOL(generic_setlease);
diff --combined fs/nfsd/vfs.c
@@@ -745,7 -745,7 +745,7 @@@ __be3
  nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
                        int may_flags, struct file **filp)
  {
 -      struct dentry   *dentry;
 +      struct path     path;
        struct inode    *inode;
        int             flags = O_RDONLY|O_LARGEFILE;
        __be32          err;
         * If we get here, then the client has already done an "open",
         * and (hopefully) checked permission - so allow OWNER_OVERRIDE
         * in case a chmod has now revoked permission.
+        *
+        * Arguably we should also allow the owner override for
+        * directories, but we never have and it doesn't seem to have
+        * caused anyone a problem.  If we were to change this, note
+        * also that our filldir callbacks would need a variant of
+        * lookup_one_len that doesn't check permissions.
         */
-       err = fh_verify(rqstp, fhp, type, may_flags | NFSD_MAY_OWNER_OVERRIDE);
+       if (type == S_IFREG)
+               may_flags |= NFSD_MAY_OWNER_OVERRIDE;
+       err = fh_verify(rqstp, fhp, type, may_flags);
        if (err)
                goto out;
  
 -      dentry = fhp->fh_dentry;
 -      inode = dentry->d_inode;
 +      path.mnt = fhp->fh_export->ex_path.mnt;
 +      path.dentry = fhp->fh_dentry;
 +      inode = path.dentry->d_inode;
  
        /* Disallow write access to files with the append-only bit set
         * or any access when mandatory locking enabled
                else
                        flags = O_WRONLY|O_LARGEFILE;
        }
 -      *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_path.mnt),
 -                          flags, current_cred());
 +      *filp = dentry_open(&path, flags, current_cred());
        if (IS_ERR(*filp))
                host_err = PTR_ERR(*filp);
        else {
@@@ -1329,7 -1337,7 +1337,7 @@@ nfsd_create(struct svc_rqst *rqstp, str
        err = 0;
        switch (type) {
        case S_IFREG:
 -              host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
 +              host_err = vfs_create(dirp, dchild, iap->ia_mode, true);
                if (!host_err)
                        nfsd_check_ignore_resizing(iap);
                break;
@@@ -1492,7 -1500,7 +1500,7 @@@ do_nfsd_create(struct svc_rqst *rqstp, 
                goto out;
        }
  
 -      host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
 +      host_err = vfs_create(dirp, dchild, iap->ia_mode, true);
        if (host_err < 0) {
                fh_drop_write(fhp);
                goto out_nfserr;
diff --combined include/linux/fs.h
@@@ -826,7 -826,7 +826,7 @@@ struct inode 
        struct list_head        i_lru;          /* inode LRU list */
        struct list_head        i_sb_list;
        union {
 -              struct list_head        i_dentry;
 +              struct hlist_head       i_dentry;
                struct rcu_head         i_rcu;
        };
        u64                     i_version;
@@@ -1163,9 -1163,10 +1163,10 @@@ struct lock_manager 
        struct list_head list;
  };
  
- void locks_start_grace(struct lock_manager *);
+ struct net;
+ void locks_start_grace(struct net *, struct lock_manager *);
  void locks_end_grace(struct lock_manager *);
- int locks_in_grace(void);
+ int locks_in_grace(struct net *);
  
  /* that will die - we need it for nfs_lock_info */
  #include <linux/nfs_fs_i.h>
@@@ -1571,7 -1572,7 +1572,7 @@@ extern void unlock_super(struct super_b
  /*
   * VFS helper functions..
   */
 -extern int vfs_create(struct inode *, struct dentry *, umode_t, struct nameidata *);
 +extern int vfs_create(struct inode *, struct dentry *, umode_t, bool);
  extern int vfs_mkdir(struct inode *, struct dentry *, umode_t);
  extern int vfs_mknod(struct inode *, struct dentry *, umode_t, dev_t);
  extern int vfs_symlink(struct inode *, struct dentry *, const char *);
@@@ -1666,7 -1667,7 +1667,7 @@@ struct file_operations 
  };
  
  struct inode_operations {
 -      struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
 +      struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
        void * (*follow_link) (struct dentry *, struct nameidata *);
        int (*permission) (struct inode *, int);
        struct posix_acl * (*get_acl)(struct inode *, int);
        int (*readlink) (struct dentry *, char __user *,int);
        void (*put_link) (struct dentry *, struct nameidata *, void *);
  
 -      int (*create) (struct inode *,struct dentry *,umode_t,struct nameidata *);
 +      int (*create) (struct inode *,struct dentry *, umode_t, bool);
        int (*link) (struct dentry *,struct inode *,struct dentry *);
        int (*unlink) (struct inode *,struct dentry *);
        int (*symlink) (struct inode *,struct dentry *,const char *);
        int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
                      u64 len);
        int (*update_time)(struct inode *, struct timespec *, int);
 +      int (*atomic_open)(struct inode *, struct dentry *,
 +                         struct file *, unsigned open_flag,
 +                         umode_t create_mode, int *opened);
  } ____cacheline_aligned;
  
  struct seq_file;
@@@ -1914,7 -1912,7 +1915,7 @@@ void free_anon_bdev(dev_t)
  struct super_block *sget(struct file_system_type *type,
                        int (*test)(struct super_block *,void *),
                        int (*set)(struct super_block *,void *),
 -                      void *data);
 +                      int flags, void *data);
  extern struct dentry *mount_pseudo(struct file_system_type *, char *,
        const struct super_operations *ops,
        const struct dentry_operations *dops,
@@@ -2060,17 -2058,10 +2061,17 @@@ extern long do_sys_open(int dfd, const 
  extern struct file *filp_open(const char *, int, umode_t);
  extern struct file *file_open_root(struct dentry *, struct vfsmount *,
                                   const char *, int);
 -extern struct file * dentry_open(struct dentry *, struct vfsmount *, int,
 -                               const struct cred *);
 +extern struct file * dentry_open(const struct path *, int, const struct cred *);
  extern int filp_close(struct file *, fl_owner_t id);
  extern char * getname(const char __user *);
 +enum {
 +      FILE_CREATED = 1,
 +      FILE_OPENED = 2
 +};
 +extern int finish_open(struct file *file, struct dentry *dentry,
 +                      int (*open)(struct inode *, struct file *),
 +                      int *opened);
 +extern int finish_no_open(struct file *file, struct dentry *dentry);
  
  /* fs/ioctl.c */
  
@@@ -2101,7 -2092,6 +2102,7 @@@ extern sector_t blkdev_max_block(struc
  extern void bd_forget(struct inode *inode);
  extern void bdput(struct block_device *);
  extern void invalidate_bdev(struct block_device *);
 +extern void iterate_bdevs(void (*)(struct block_device *, void *), void *);
  extern int sync_blockdev(struct block_device *bdev);
  extern void kill_bdev(struct block_device *);
  extern struct super_block *freeze_bdev(struct block_device *);
@@@ -2123,10 -2113,6 +2124,10 @@@ static inline int thaw_bdev(struct bloc
  {
        return 0;
  }
 +
 +static inline void iterate_bdevs(void (*f)(struct block_device *, void *), void *arg)
 +{
 +}
  #endif
  extern int sync_filesystem(struct super_block *);
  extern const struct file_operations def_blk_fops;
@@@ -2453,7 -2439,7 +2454,7 @@@ extern loff_t noop_llseek(struct file *
  extern loff_t no_llseek(struct file *file, loff_t offset, int origin);
  extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin);
  extern loff_t generic_file_llseek_size(struct file *file, loff_t offset,
 -              int origin, loff_t maxsize);
 +              int origin, loff_t maxsize, loff_t eof);
  extern int generic_file_open(struct inode * inode, struct file * filp);
  extern int nonseekable_open(struct inode * inode, struct file * filp);
  
@@@ -2575,7 -2561,7 +2576,7 @@@ extern int simple_write_end(struct fil
                        loff_t pos, unsigned len, unsigned copied,
                        struct page *page, void *fsdata);
  
 -extern struct dentry *simple_lookup(struct inode *, struct dentry *, struct nameidata *);
 +extern struct dentry *simple_lookup(struct inode *, struct dentry *, unsigned int flags);
  extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *);
  extern const struct file_operations simple_dir_operations;
  extern const struct inode_operations simple_dir_inode_operations;