aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-04-16 23:27:56 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-16 23:27:56 -0400
commit4fc8adcfec3da639da76e8314c9ccefe5bf9a045 (patch)
treee07a2dea8acf04d8bbbecd4fd3a571653ecdd953 /fs/nfs
parent84588e7a5d8220446d677d7b909a20ee7a4496b9 (diff)
parentaa4d86163e4e91a1ac560954a554bab417e338f4 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull third hunk of vfs changes from Al Viro: "This contains the ->direct_IO() changes from Omar + saner generic_write_checks() + dealing with fcntl()/{read,write}() races (mirroring O_APPEND/O_DIRECT into iocb->ki_flags and instead of repeatedly looking at ->f_flags, which can be changed by fcntl(2), check ->ki_flags - which cannot) + infrastructure bits for dhowells' d_inode annotations + Christophs switch of /dev/loop to vfs_iter_write()" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (30 commits) block: loop: switch to VFS ITER_BVEC configfs: Fix inconsistent use of file_inode() vs file->f_path.dentry->d_inode VFS: Make pathwalk use d_is_reg() rather than S_ISREG() VFS: Fix up debugfs to use d_is_dir() in place of S_ISDIR() VFS: Combine inode checks with d_is_negative() and d_is_positive() in pathwalk NFS: Don't use d_inode as a variable name VFS: Impose ordering on accesses of d_inode and d_flags VFS: Add owner-filesystem positive/negative dentry checks nfs: generic_write_checks() shouldn't be done on swapout... ocfs2: use __generic_file_write_iter() mirror O_APPEND and O_DIRECT into iocb->ki_flags switch generic_write_checks() to iocb and iter ocfs2: move generic_write_checks() before the alignment checks ocfs2_file_write_iter: stop messing with ppos udf_file_write_iter: reorder and simplify fuse: ->direct_IO() doesn't need generic_write_checks() ext4_file_write_iter: move generic_write_checks() up xfs_file_aio_write_checks: switch to iocb/iov_iter generic_write_checks(): drop isblk argument blkdev_write_iter: expand generic_file_checks() call in there ...
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/direct.c36
-rw-r--r--fs/nfs/file.c15
-rw-r--r--fs/nfs/read.c8
3 files changed, 25 insertions, 34 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index c3929fb2ab26..682f65fe09b5 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -240,7 +240,6 @@ static int nfs_direct_cmp_commit_data_verf(struct nfs_direct_req *dreq,
240 240
241/** 241/**
242 * nfs_direct_IO - NFS address space operation for direct I/O 242 * nfs_direct_IO - NFS address space operation for direct I/O
243 * @rw: direction (read or write)
244 * @iocb: target I/O control block 243 * @iocb: target I/O control block
245 * @iov: array of vectors that define I/O buffer 244 * @iov: array of vectors that define I/O buffer
246 * @pos: offset in file to begin the operation 245 * @pos: offset in file to begin the operation
@@ -251,7 +250,7 @@ static int nfs_direct_cmp_commit_data_verf(struct nfs_direct_req *dreq,
251 * shunt off direct read and write requests before the VFS gets them, 250 * shunt off direct read and write requests before the VFS gets them,
252 * so this method is only ever called for swap. 251 * so this method is only ever called for swap.
253 */ 252 */
254ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t pos) 253ssize_t nfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t pos)
255{ 254{
256 struct inode *inode = iocb->ki_filp->f_mapping->host; 255 struct inode *inode = iocb->ki_filp->f_mapping->host;
257 256
@@ -267,9 +266,9 @@ ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t
267#else 266#else
268 VM_BUG_ON(iov_iter_count(iter) != PAGE_SIZE); 267 VM_BUG_ON(iov_iter_count(iter) != PAGE_SIZE);
269 268
270 if (rw == READ) 269 if (iov_iter_rw(iter) == READ)
271 return nfs_file_direct_read(iocb, iter, pos); 270 return nfs_file_direct_read(iocb, iter, pos);
272 return nfs_file_direct_write(iocb, iter, pos); 271 return nfs_file_direct_write(iocb, iter);
273#endif /* CONFIG_NFS_SWAP */ 272#endif /* CONFIG_NFS_SWAP */
274} 273}
275 274
@@ -960,8 +959,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
960 * Note that O_APPEND is not supported for NFS direct writes, as there 959 * Note that O_APPEND is not supported for NFS direct writes, as there
961 * is no atomic O_APPEND write facility in the NFS protocol. 960 * is no atomic O_APPEND write facility in the NFS protocol.
962 */ 961 */
963ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter, 962ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter)
964 loff_t pos)
965{ 963{
966 ssize_t result = -EINVAL; 964 ssize_t result = -EINVAL;
967 struct file *file = iocb->ki_filp; 965 struct file *file = iocb->ki_filp;
@@ -969,25 +967,16 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
969 struct inode *inode = mapping->host; 967 struct inode *inode = mapping->host;
970 struct nfs_direct_req *dreq; 968 struct nfs_direct_req *dreq;
971 struct nfs_lock_context *l_ctx; 969 struct nfs_lock_context *l_ctx;
972 loff_t end; 970 loff_t pos, end;
973 size_t count = iov_iter_count(iter);
974 end = (pos + count - 1) >> PAGE_CACHE_SHIFT;
975
976 nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES, count);
977 971
978 dfprintk(FILE, "NFS: direct write(%pD2, %zd@%Ld)\n", 972 dfprintk(FILE, "NFS: direct write(%pD2, %zd@%Ld)\n",
979 file, count, (long long) pos); 973 file, iov_iter_count(iter), (long long) iocb->ki_pos);
980 974
981 result = generic_write_checks(file, &pos, &count, 0); 975 nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES,
982 if (result) 976 iov_iter_count(iter));
983 goto out;
984 977
985 result = -EINVAL; 978 pos = iocb->ki_pos;
986 if ((ssize_t) count < 0) 979 end = (pos + iov_iter_count(iter) - 1) >> PAGE_CACHE_SHIFT;
987 goto out;
988 result = 0;
989 if (!count)
990 goto out;
991 980
992 mutex_lock(&inode->i_mutex); 981 mutex_lock(&inode->i_mutex);
993 982
@@ -1002,7 +991,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
1002 goto out_unlock; 991 goto out_unlock;
1003 } 992 }
1004 993
1005 task_io_account_write(count); 994 task_io_account_write(iov_iter_count(iter));
1006 995
1007 result = -ENOMEM; 996 result = -ENOMEM;
1008 dreq = nfs_direct_req_alloc(); 997 dreq = nfs_direct_req_alloc();
@@ -1010,7 +999,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
1010 goto out_unlock; 999 goto out_unlock;
1011 1000
1012 dreq->inode = inode; 1001 dreq->inode = inode;
1013 dreq->bytes_left = count; 1002 dreq->bytes_left = iov_iter_count(iter);
1014 dreq->io_start = pos; 1003 dreq->io_start = pos;
1015 dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); 1004 dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
1016 l_ctx = nfs_get_lock_context(dreq->ctx); 1005 l_ctx = nfs_get_lock_context(dreq->ctx);
@@ -1050,7 +1039,6 @@ out_release:
1050 nfs_direct_req_release(dreq); 1039 nfs_direct_req_release(dreq);
1051out_unlock: 1040out_unlock:
1052 mutex_unlock(&inode->i_mutex); 1041 mutex_unlock(&inode->i_mutex);
1053out:
1054 return result; 1042 return result;
1055} 1043}
1056 1044
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index f6a3adedf027..c40e4363e746 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -170,7 +170,7 @@ nfs_file_read(struct kiocb *iocb, struct iov_iter *to)
170 struct inode *inode = file_inode(iocb->ki_filp); 170 struct inode *inode = file_inode(iocb->ki_filp);
171 ssize_t result; 171 ssize_t result;
172 172
173 if (iocb->ki_filp->f_flags & O_DIRECT) 173 if (iocb->ki_flags & IOCB_DIRECT)
174 return nfs_file_direct_read(iocb, to, iocb->ki_pos); 174 return nfs_file_direct_read(iocb, to, iocb->ki_pos);
175 175
176 dprintk("NFS: read(%pD2, %zu@%lu)\n", 176 dprintk("NFS: read(%pD2, %zu@%lu)\n",
@@ -674,17 +674,20 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)
674 unsigned long written = 0; 674 unsigned long written = 0;
675 ssize_t result; 675 ssize_t result;
676 size_t count = iov_iter_count(from); 676 size_t count = iov_iter_count(from);
677 loff_t pos = iocb->ki_pos;
678 677
679 result = nfs_key_timeout_notify(file, inode); 678 result = nfs_key_timeout_notify(file, inode);
680 if (result) 679 if (result)
681 return result; 680 return result;
682 681
683 if (file->f_flags & O_DIRECT) 682 if (iocb->ki_flags & IOCB_DIRECT) {
684 return nfs_file_direct_write(iocb, from, pos); 683 result = generic_write_checks(iocb, from);
684 if (result <= 0)
685 return result;
686 return nfs_file_direct_write(iocb, from);
687 }
685 688
686 dprintk("NFS: write(%pD2, %zu@%Ld)\n", 689 dprintk("NFS: write(%pD2, %zu@%Ld)\n",
687 file, count, (long long) pos); 690 file, count, (long long) iocb->ki_pos);
688 691
689 result = -EBUSY; 692 result = -EBUSY;
690 if (IS_SWAPFILE(inode)) 693 if (IS_SWAPFILE(inode))
@@ -692,7 +695,7 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)
692 /* 695 /*
693 * O_APPEND implies that we must revalidate the file length. 696 * O_APPEND implies that we must revalidate the file length.
694 */ 697 */
695 if (file->f_flags & O_APPEND) { 698 if (iocb->ki_flags & IOCB_APPEND) {
696 result = nfs_revalidate_file_size(inode, file); 699 result = nfs_revalidate_file_size(inode, file);
697 if (result) 700 if (result)
698 goto out; 701 goto out;
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 568ecf0a880f..b8f5c63f77b2 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -117,15 +117,15 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
117 117
118static void nfs_readpage_release(struct nfs_page *req) 118static void nfs_readpage_release(struct nfs_page *req)
119{ 119{
120 struct inode *d_inode = req->wb_context->dentry->d_inode; 120 struct inode *inode = req->wb_context->dentry->d_inode;
121 121
122 dprintk("NFS: read done (%s/%llu %d@%lld)\n", d_inode->i_sb->s_id, 122 dprintk("NFS: read done (%s/%llu %d@%lld)\n", inode->i_sb->s_id,
123 (unsigned long long)NFS_FILEID(d_inode), req->wb_bytes, 123 (unsigned long long)NFS_FILEID(inode), req->wb_bytes,
124 (long long)req_offset(req)); 124 (long long)req_offset(req));
125 125
126 if (nfs_page_group_sync_on_bit(req, PG_UNLOCKPAGE)) { 126 if (nfs_page_group_sync_on_bit(req, PG_UNLOCKPAGE)) {
127 if (PageUptodate(req->wb_page)) 127 if (PageUptodate(req->wb_page))
128 nfs_readpage_to_fscache(d_inode, req->wb_page, 0); 128 nfs_readpage_to_fscache(inode, req->wb_page, 0);
129 129
130 unlock_page(req->wb_page); 130 unlock_page(req->wb_page);
131 } 131 }