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() ...
This commit is contained in:
@@ -317,6 +317,32 @@ int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes)
|
||||
}
|
||||
EXPORT_SYMBOL(iov_iter_fault_in_readable);
|
||||
|
||||
/*
|
||||
* Fault in one or more iovecs of the given iov_iter, to a maximum length of
|
||||
* bytes. For each iovec, fault in each page that constitutes the iovec.
|
||||
*
|
||||
* Return 0 on success, or non-zero if the memory could not be accessed (i.e.
|
||||
* because it is an invalid address).
|
||||
*/
|
||||
int iov_iter_fault_in_multipages_readable(struct iov_iter *i, size_t bytes)
|
||||
{
|
||||
size_t skip = i->iov_offset;
|
||||
const struct iovec *iov;
|
||||
int err;
|
||||
struct iovec v;
|
||||
|
||||
if (!(i->type & (ITER_BVEC|ITER_KVEC))) {
|
||||
iterate_iovec(i, bytes, v, iov, skip, ({
|
||||
err = fault_in_multipages_readable(v.iov_base,
|
||||
v.iov_len);
|
||||
if (unlikely(err))
|
||||
return err;
|
||||
0;}))
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iov_iter_fault_in_multipages_readable);
|
||||
|
||||
void iov_iter_init(struct iov_iter *i, int direction,
|
||||
const struct iovec *iov, unsigned long nr_segs,
|
||||
size_t count)
|
||||
@@ -766,3 +792,60 @@ const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags)
|
||||
flags);
|
||||
}
|
||||
EXPORT_SYMBOL(dup_iter);
|
||||
|
||||
int import_iovec(int type, const struct iovec __user * uvector,
|
||||
unsigned nr_segs, unsigned fast_segs,
|
||||
struct iovec **iov, struct iov_iter *i)
|
||||
{
|
||||
ssize_t n;
|
||||
struct iovec *p;
|
||||
n = rw_copy_check_uvector(type, uvector, nr_segs, fast_segs,
|
||||
*iov, &p);
|
||||
if (n < 0) {
|
||||
if (p != *iov)
|
||||
kfree(p);
|
||||
*iov = NULL;
|
||||
return n;
|
||||
}
|
||||
iov_iter_init(i, type, p, nr_segs, n);
|
||||
*iov = p == *iov ? NULL : p;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(import_iovec);
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
#include <linux/compat.h>
|
||||
|
||||
int compat_import_iovec(int type, const struct compat_iovec __user * uvector,
|
||||
unsigned nr_segs, unsigned fast_segs,
|
||||
struct iovec **iov, struct iov_iter *i)
|
||||
{
|
||||
ssize_t n;
|
||||
struct iovec *p;
|
||||
n = compat_rw_copy_check_uvector(type, uvector, nr_segs, fast_segs,
|
||||
*iov, &p);
|
||||
if (n < 0) {
|
||||
if (p != *iov)
|
||||
kfree(p);
|
||||
*iov = NULL;
|
||||
return n;
|
||||
}
|
||||
iov_iter_init(i, type, p, nr_segs, n);
|
||||
*iov = p == *iov ? NULL : p;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int import_single_range(int rw, void __user *buf, size_t len,
|
||||
struct iovec *iov, struct iov_iter *i)
|
||||
{
|
||||
if (len > MAX_RW_COUNT)
|
||||
len = MAX_RW_COUNT;
|
||||
if (unlikely(!access_ok(!rw, buf, len)))
|
||||
return -EFAULT;
|
||||
|
||||
iov->iov_base = buf;
|
||||
iov->iov_len = len;
|
||||
iov_iter_init(i, rw, iov, 1, len);
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user