diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-16 23:27:56 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-16 23:27:56 -0400 |
commit | 4fc8adcfec3da639da76e8314c9ccefe5bf9a045 (patch) | |
tree | e07a2dea8acf04d8bbbecd4fd3a571653ecdd953 /fs/nfs | |
parent | 84588e7a5d8220446d677d7b909a20ee7a4496b9 (diff) | |
parent | aa4d86163e4e91a1ac560954a554bab417e338f4 (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.c | 36 | ||||
-rw-r--r-- | fs/nfs/file.c | 15 | ||||
-rw-r--r-- | fs/nfs/read.c | 8 |
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 | */ |
254 | ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t pos) | 253 | ssize_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 | */ |
963 | ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter, | 962 | ssize_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); |
1051 | out_unlock: | 1040 | out_unlock: |
1052 | mutex_unlock(&inode->i_mutex); | 1041 | mutex_unlock(&inode->i_mutex); |
1053 | out: | ||
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 | ||
118 | static void nfs_readpage_release(struct nfs_page *req) | 118 | static 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 | } |