diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-14 18:31:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-14 18:31:03 -0400 |
commit | ca2ec32658db160745990496f0f4580056a5dc9f (patch) | |
tree | d211f239219c85214da46dc1cbad4184a81d0248 /lib | |
parent | 6c8a53c9e6a151fffb07f8b4c34bd1e33dddd467 (diff) | |
parent | fdc81f45e9f57858da6351836507fbcf1b7583ee (diff) |
Merge branch 'for-linus-1' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs update from Al Viro:
"Part one:
- struct filename-related cleanups
- saner iov_iter_init() replacements (and switching the syscalls to
use of those)
- ntfs switch to ->write_iter() (Anton)
- aio cleanups and splitting iocb into common and async parts
(Christoph)
- assorted fixes (me, bfields, Andrew Elble)
There's a lot more, including the completion of switchover to
->{read,write}_iter(), d_inode/d_backing_inode annotations, f_flags
race fixes, etc, but that goes after #for-davem merge. David has
pulled it, and once it's in I'll send the next vfs pull request"
* 'for-linus-1' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (35 commits)
sg_start_req(): use import_iovec()
sg_start_req(): make sure that there's not too many elements in iovec
blk_rq_map_user(): use import_single_range()
sg_io(): use import_iovec()
process_vm_access: switch to {compat_,}import_iovec()
switch keyctl_instantiate_key_common() to iov_iter
switch {compat_,}do_readv_writev() to {compat_,}import_iovec()
aio_setup_vectored_rw(): switch to {compat_,}import_iovec()
vmsplice_to_user(): switch to import_iovec()
kill aio_setup_single_vector()
aio: simplify arguments of aio_setup_..._rw()
aio: lift iov_iter_init() into aio_setup_..._rw()
lift iov_iter into {compat_,}do_readv_writev()
NFS: fix BUG() crash in notify_change() with patch to chown_common()
dcache: return -ESTALE not -EBUSY on distributed fs race
NTFS: Version 2.1.32 - Update file write from aio_write to write_iter.
VFS: Add iov_iter_fault_in_multipages_readable()
drop bogus check in file_open_root()
switch security_inode_getattr() to struct path *
constify tomoyo_realpath_from_path()
...
Diffstat (limited to 'lib')
-rw-r--r-- | lib/iov_iter.c | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 9d96e283520c..75232ad0a5e7 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c | |||
@@ -317,6 +317,32 @@ int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes) | |||
317 | } | 317 | } |
318 | EXPORT_SYMBOL(iov_iter_fault_in_readable); | 318 | EXPORT_SYMBOL(iov_iter_fault_in_readable); |
319 | 319 | ||
320 | /* | ||
321 | * Fault in one or more iovecs of the given iov_iter, to a maximum length of | ||
322 | * bytes. For each iovec, fault in each page that constitutes the iovec. | ||
323 | * | ||
324 | * Return 0 on success, or non-zero if the memory could not be accessed (i.e. | ||
325 | * because it is an invalid address). | ||
326 | */ | ||
327 | int iov_iter_fault_in_multipages_readable(struct iov_iter *i, size_t bytes) | ||
328 | { | ||
329 | size_t skip = i->iov_offset; | ||
330 | const struct iovec *iov; | ||
331 | int err; | ||
332 | struct iovec v; | ||
333 | |||
334 | if (!(i->type & (ITER_BVEC|ITER_KVEC))) { | ||
335 | iterate_iovec(i, bytes, v, iov, skip, ({ | ||
336 | err = fault_in_multipages_readable(v.iov_base, | ||
337 | v.iov_len); | ||
338 | if (unlikely(err)) | ||
339 | return err; | ||
340 | 0;})) | ||
341 | } | ||
342 | return 0; | ||
343 | } | ||
344 | EXPORT_SYMBOL(iov_iter_fault_in_multipages_readable); | ||
345 | |||
320 | void iov_iter_init(struct iov_iter *i, int direction, | 346 | void iov_iter_init(struct iov_iter *i, int direction, |
321 | const struct iovec *iov, unsigned long nr_segs, | 347 | const struct iovec *iov, unsigned long nr_segs, |
322 | size_t count) | 348 | size_t count) |
@@ -766,3 +792,60 @@ const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags) | |||
766 | flags); | 792 | flags); |
767 | } | 793 | } |
768 | EXPORT_SYMBOL(dup_iter); | 794 | EXPORT_SYMBOL(dup_iter); |
795 | |||
796 | int import_iovec(int type, const struct iovec __user * uvector, | ||
797 | unsigned nr_segs, unsigned fast_segs, | ||
798 | struct iovec **iov, struct iov_iter *i) | ||
799 | { | ||
800 | ssize_t n; | ||
801 | struct iovec *p; | ||
802 | n = rw_copy_check_uvector(type, uvector, nr_segs, fast_segs, | ||
803 | *iov, &p); | ||
804 | if (n < 0) { | ||
805 | if (p != *iov) | ||
806 | kfree(p); | ||
807 | *iov = NULL; | ||
808 | return n; | ||
809 | } | ||
810 | iov_iter_init(i, type, p, nr_segs, n); | ||
811 | *iov = p == *iov ? NULL : p; | ||
812 | return 0; | ||
813 | } | ||
814 | EXPORT_SYMBOL(import_iovec); | ||
815 | |||
816 | #ifdef CONFIG_COMPAT | ||
817 | #include <linux/compat.h> | ||
818 | |||
819 | int compat_import_iovec(int type, const struct compat_iovec __user * uvector, | ||
820 | unsigned nr_segs, unsigned fast_segs, | ||
821 | struct iovec **iov, struct iov_iter *i) | ||
822 | { | ||
823 | ssize_t n; | ||
824 | struct iovec *p; | ||
825 | n = compat_rw_copy_check_uvector(type, uvector, nr_segs, fast_segs, | ||
826 | *iov, &p); | ||
827 | if (n < 0) { | ||
828 | if (p != *iov) | ||
829 | kfree(p); | ||
830 | *iov = NULL; | ||
831 | return n; | ||
832 | } | ||
833 | iov_iter_init(i, type, p, nr_segs, n); | ||
834 | *iov = p == *iov ? NULL : p; | ||
835 | return 0; | ||
836 | } | ||
837 | #endif | ||
838 | |||
839 | int import_single_range(int rw, void __user *buf, size_t len, | ||
840 | struct iovec *iov, struct iov_iter *i) | ||
841 | { | ||
842 | if (len > MAX_RW_COUNT) | ||
843 | len = MAX_RW_COUNT; | ||
844 | if (unlikely(!access_ok(!rw, buf, len))) | ||
845 | return -EFAULT; | ||
846 | |||
847 | iov->iov_base = buf; | ||
848 | iov->iov_len = len; | ||
849 | iov_iter_init(i, rw, iov, 1, len); | ||
850 | return 0; | ||
851 | } | ||