Merge branch 'for-3.19' of git://linux-nfs.org/~bfields/linux
[cascardo/linux.git] / fs / nfsd / vfs.c
index 0a82e3c..5685c67 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/fs.h>
 #include <linux/file.h>
 #include <linux/splice.h>
+#include <linux/falloc.h>
 #include <linux/fcntl.h>
 #include <linux/namei.h>
 #include <linux/delay.h>
@@ -533,6 +534,26 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
 }
 #endif
 
+__be32 nfsd4_vfs_fallocate(struct svc_rqst *rqstp, struct svc_fh *fhp,
+                          struct file *file, loff_t offset, loff_t len,
+                          int flags)
+{
+       __be32 err;
+       int error;
+
+       if (!S_ISREG(file_inode(file)->i_mode))
+               return nfserr_inval;
+
+       err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry, NFSD_MAY_WRITE);
+       if (err)
+               return err;
+
+       error = vfs_fallocate(file, flags, offset, len);
+       if (!error)
+               error = commit_metadata(fhp);
+
+       return nfserrno(error);
+}
 #endif /* defined(CONFIG_NFSD_V4) */
 
 #ifdef CONFIG_NFSD_V3
@@ -881,7 +902,7 @@ static __be32
 nfsd_vfs_read(struct svc_rqst *rqstp, struct file *file,
              loff_t offset, struct kvec *vec, int vlen, unsigned long *count)
 {
-       if (file->f_op->splice_read && rqstp->rq_splice_ok)
+       if (file->f_op->splice_read && test_bit(RQ_SPLICE_OK, &rqstp->rq_flags))
                return nfsd_splice_read(rqstp, file, offset, count);
        else
                return nfsd_readv(file, offset, vec, vlen, count);
@@ -937,9 +958,10 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
        int                     stable = *stablep;
        int                     use_wgather;
        loff_t                  pos = offset;
+       loff_t                  end = LLONG_MAX;
        unsigned int            pflags = current->flags;
 
-       if (rqstp->rq_local)
+       if (test_bit(RQ_LOCAL, &rqstp->rq_flags))
                /*
                 * We want less throttling in balance_dirty_pages()
                 * and shrink_inactive_list() so that nfs to
@@ -967,10 +989,13 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
        fsnotify_modify(file);
 
        if (stable) {
-               if (use_wgather)
+               if (use_wgather) {
                        host_err = wait_for_concurrent_writes(file);
-               else
-                       host_err = vfs_fsync_range(file, offset, offset+*cnt, 0);
+               } else {
+                       if (*cnt)
+                               end = offset + *cnt - 1;
+                       host_err = vfs_fsync_range(file, offset, end, 0);
+               }
        }
 
 out_nfserr:
@@ -979,7 +1004,7 @@ out_nfserr:
                err = 0;
        else
                err = nfserrno(host_err);
-       if (rqstp->rq_local)
+       if (test_bit(RQ_LOCAL, &rqstp->rq_flags))
                tsk_restore_flags(current, pflags, PF_LESS_THROTTLE);
        return err;
 }