diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cachefiles/daemon.c | 13 | ||||
-rw-r--r-- | fs/cachefiles/interface.c | 11 | ||||
-rw-r--r-- | fs/cachefiles/internal.h | 4 | ||||
-rw-r--r-- | fs/cachefiles/namei.c | 28 | ||||
-rw-r--r-- | fs/direct-io.c | 3 | ||||
-rw-r--r-- | fs/jffs2/dir.c | 11 | ||||
-rw-r--r-- | fs/ncpfs/dir.c | 2 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 4 | ||||
-rw-r--r-- | fs/proc_namespace.c | 2 | ||||
-rw-r--r-- | fs/read_write.c | 197 | ||||
-rw-r--r-- | fs/splice.c | 5 |
11 files changed, 207 insertions, 73 deletions
diff --git a/fs/cachefiles/daemon.c b/fs/cachefiles/daemon.c index 452e98dd7560..1ee54ffd3a24 100644 --- a/fs/cachefiles/daemon.c +++ b/fs/cachefiles/daemon.c | |||
@@ -162,6 +162,8 @@ static ssize_t cachefiles_daemon_read(struct file *file, char __user *_buffer, | |||
162 | size_t buflen, loff_t *pos) | 162 | size_t buflen, loff_t *pos) |
163 | { | 163 | { |
164 | struct cachefiles_cache *cache = file->private_data; | 164 | struct cachefiles_cache *cache = file->private_data; |
165 | unsigned long long b_released; | ||
166 | unsigned f_released; | ||
165 | char buffer[256]; | 167 | char buffer[256]; |
166 | int n; | 168 | int n; |
167 | 169 | ||
@@ -174,6 +176,8 @@ static ssize_t cachefiles_daemon_read(struct file *file, char __user *_buffer, | |||
174 | cachefiles_has_space(cache, 0, 0); | 176 | cachefiles_has_space(cache, 0, 0); |
175 | 177 | ||
176 | /* summarise */ | 178 | /* summarise */ |
179 | f_released = atomic_xchg(&cache->f_released, 0); | ||
180 | b_released = atomic_long_xchg(&cache->b_released, 0); | ||
177 | clear_bit(CACHEFILES_STATE_CHANGED, &cache->flags); | 181 | clear_bit(CACHEFILES_STATE_CHANGED, &cache->flags); |
178 | 182 | ||
179 | n = snprintf(buffer, sizeof(buffer), | 183 | n = snprintf(buffer, sizeof(buffer), |
@@ -183,15 +187,18 @@ static ssize_t cachefiles_daemon_read(struct file *file, char __user *_buffer, | |||
183 | " fstop=%llx" | 187 | " fstop=%llx" |
184 | " brun=%llx" | 188 | " brun=%llx" |
185 | " bcull=%llx" | 189 | " bcull=%llx" |
186 | " bstop=%llx", | 190 | " bstop=%llx" |
191 | " freleased=%x" | ||
192 | " breleased=%llx", | ||
187 | test_bit(CACHEFILES_CULLING, &cache->flags) ? '1' : '0', | 193 | test_bit(CACHEFILES_CULLING, &cache->flags) ? '1' : '0', |
188 | (unsigned long long) cache->frun, | 194 | (unsigned long long) cache->frun, |
189 | (unsigned long long) cache->fcull, | 195 | (unsigned long long) cache->fcull, |
190 | (unsigned long long) cache->fstop, | 196 | (unsigned long long) cache->fstop, |
191 | (unsigned long long) cache->brun, | 197 | (unsigned long long) cache->brun, |
192 | (unsigned long long) cache->bcull, | 198 | (unsigned long long) cache->bcull, |
193 | (unsigned long long) cache->bstop | 199 | (unsigned long long) cache->bstop, |
194 | ); | 200 | f_released, |
201 | b_released); | ||
195 | 202 | ||
196 | if (n > buflen) | 203 | if (n > buflen) |
197 | return -EMSGSIZE; | 204 | return -EMSGSIZE; |
diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index 675a3332d72f..861d611b8c05 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c | |||
@@ -291,15 +291,8 @@ static void cachefiles_drop_object(struct fscache_object *_object) | |||
291 | } | 291 | } |
292 | 292 | ||
293 | /* note that the object is now inactive */ | 293 | /* note that the object is now inactive */ |
294 | if (test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags)) { | 294 | if (test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags)) |
295 | write_lock(&cache->active_lock); | 295 | cachefiles_mark_object_inactive(cache, object); |
296 | if (!test_and_clear_bit(CACHEFILES_OBJECT_ACTIVE, | ||
297 | &object->flags)) | ||
298 | BUG(); | ||
299 | rb_erase(&object->active_node, &cache->active_nodes); | ||
300 | wake_up_bit(&object->flags, CACHEFILES_OBJECT_ACTIVE); | ||
301 | write_unlock(&cache->active_lock); | ||
302 | } | ||
303 | 296 | ||
304 | dput(object->dentry); | 297 | dput(object->dentry); |
305 | object->dentry = NULL; | 298 | object->dentry = NULL; |
diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h index 9c4b737a54df..2fcde1a34b7c 100644 --- a/fs/cachefiles/internal.h +++ b/fs/cachefiles/internal.h | |||
@@ -66,6 +66,8 @@ struct cachefiles_cache { | |||
66 | struct rb_root active_nodes; /* active nodes (can't be culled) */ | 66 | struct rb_root active_nodes; /* active nodes (can't be culled) */ |
67 | rwlock_t active_lock; /* lock for active_nodes */ | 67 | rwlock_t active_lock; /* lock for active_nodes */ |
68 | atomic_t gravecounter; /* graveyard uniquifier */ | 68 | atomic_t gravecounter; /* graveyard uniquifier */ |
69 | atomic_t f_released; /* number of objects released lately */ | ||
70 | atomic_long_t b_released; /* number of blocks released lately */ | ||
69 | unsigned frun_percent; /* when to stop culling (% files) */ | 71 | unsigned frun_percent; /* when to stop culling (% files) */ |
70 | unsigned fcull_percent; /* when to start culling (% files) */ | 72 | unsigned fcull_percent; /* when to start culling (% files) */ |
71 | unsigned fstop_percent; /* when to stop allocating (% files) */ | 73 | unsigned fstop_percent; /* when to stop allocating (% files) */ |
@@ -157,6 +159,8 @@ extern char *cachefiles_cook_key(const u8 *raw, int keylen, uint8_t type); | |||
157 | /* | 159 | /* |
158 | * namei.c | 160 | * namei.c |
159 | */ | 161 | */ |
162 | extern void cachefiles_mark_object_inactive(struct cachefiles_cache *cache, | ||
163 | struct cachefiles_object *object); | ||
160 | extern int cachefiles_delete_object(struct cachefiles_cache *cache, | 164 | extern int cachefiles_delete_object(struct cachefiles_cache *cache, |
161 | struct cachefiles_object *object); | 165 | struct cachefiles_object *object); |
162 | extern int cachefiles_walk_to_object(struct cachefiles_object *parent, | 166 | extern int cachefiles_walk_to_object(struct cachefiles_object *parent, |
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index 1c2334c163dd..4ae75006e73b 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c | |||
@@ -258,6 +258,28 @@ requeue: | |||
258 | } | 258 | } |
259 | 259 | ||
260 | /* | 260 | /* |
261 | * Mark an object as being inactive. | ||
262 | */ | ||
263 | void cachefiles_mark_object_inactive(struct cachefiles_cache *cache, | ||
264 | struct cachefiles_object *object) | ||
265 | { | ||
266 | write_lock(&cache->active_lock); | ||
267 | rb_erase(&object->active_node, &cache->active_nodes); | ||
268 | clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags); | ||
269 | write_unlock(&cache->active_lock); | ||
270 | |||
271 | wake_up_bit(&object->flags, CACHEFILES_OBJECT_ACTIVE); | ||
272 | |||
273 | /* This object can now be culled, so we need to let the daemon know | ||
274 | * that there is something it can remove if it needs to. | ||
275 | */ | ||
276 | atomic_long_add(d_backing_inode(object->dentry)->i_blocks, | ||
277 | &cache->b_released); | ||
278 | if (atomic_inc_return(&cache->f_released)) | ||
279 | cachefiles_state_changed(cache); | ||
280 | } | ||
281 | |||
282 | /* | ||
261 | * delete an object representation from the cache | 283 | * delete an object representation from the cache |
262 | * - file backed objects are unlinked | 284 | * - file backed objects are unlinked |
263 | * - directory backed objects are stuffed into the graveyard for userspace to | 285 | * - directory backed objects are stuffed into the graveyard for userspace to |
@@ -684,11 +706,7 @@ mark_active_timed_out: | |||
684 | 706 | ||
685 | check_error: | 707 | check_error: |
686 | _debug("check error %d", ret); | 708 | _debug("check error %d", ret); |
687 | write_lock(&cache->active_lock); | 709 | cachefiles_mark_object_inactive(cache, object); |
688 | rb_erase(&object->active_node, &cache->active_nodes); | ||
689 | clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags); | ||
690 | wake_up_bit(&object->flags, CACHEFILES_OBJECT_ACTIVE); | ||
691 | write_unlock(&cache->active_lock); | ||
692 | release_dentry: | 710 | release_dentry: |
693 | dput(object->dentry); | 711 | dput(object->dentry); |
694 | object->dentry = NULL; | 712 | object->dentry = NULL; |
diff --git a/fs/direct-io.c b/fs/direct-io.c index 1b2f7ffc8b84..85463171053b 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c | |||
@@ -445,7 +445,8 @@ static struct bio *dio_await_one(struct dio *dio) | |||
445 | __set_current_state(TASK_UNINTERRUPTIBLE); | 445 | __set_current_state(TASK_UNINTERRUPTIBLE); |
446 | dio->waiter = current; | 446 | dio->waiter = current; |
447 | spin_unlock_irqrestore(&dio->bio_lock, flags); | 447 | spin_unlock_irqrestore(&dio->bio_lock, flags); |
448 | if (!blk_poll(bdev_get_queue(dio->bio_bdev), dio->bio_cookie)) | 448 | if (!(dio->iocb->ki_flags & IOCB_HIPRI) || |
449 | !blk_poll(bdev_get_queue(dio->bio_bdev), dio->bio_cookie)) | ||
449 | io_schedule(); | 450 | io_schedule(); |
450 | /* wake up sets us TASK_RUNNING */ | 451 | /* wake up sets us TASK_RUNNING */ |
451 | spin_lock_irqsave(&dio->bio_lock, flags); | 452 | spin_lock_irqsave(&dio->bio_lock, flags); |
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index d211b8e18566..30c4c9ebb693 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c | |||
@@ -843,9 +843,14 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, | |||
843 | 843 | ||
844 | pr_notice("%s(): Link succeeded, unlink failed (err %d). You now have a hard link\n", | 844 | pr_notice("%s(): Link succeeded, unlink failed (err %d). You now have a hard link\n", |
845 | __func__, ret); | 845 | __func__, ret); |
846 | /* Might as well let the VFS know */ | 846 | /* |
847 | d_instantiate(new_dentry, d_inode(old_dentry)); | 847 | * We can't keep the target in dcache after that. |
848 | ihold(d_inode(old_dentry)); | 848 | * For one thing, we can't afford dentry aliases for directories. |
849 | * For another, if there was a victim, we _can't_ set new inode | ||
850 | * for that sucker and we have to trigger mount eviction - the | ||
851 | * caller won't do it on its own since we are returning an error. | ||
852 | */ | ||
853 | d_invalidate(new_dentry); | ||
849 | new_dir_i->i_mtime = new_dir_i->i_ctime = ITIME(now); | 854 | new_dir_i->i_mtime = new_dir_i->i_ctime = ITIME(now); |
850 | return ret; | 855 | return ret; |
851 | } | 856 | } |
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index 26c2de2de13f..b7f8eaeea5d8 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c | |||
@@ -633,7 +633,7 @@ ncp_fill_cache(struct file *file, struct dir_context *ctx, | |||
633 | d_rehash(newdent); | 633 | d_rehash(newdent); |
634 | } else { | 634 | } else { |
635 | spin_lock(&dentry->d_lock); | 635 | spin_lock(&dentry->d_lock); |
636 | NCP_FINFO(inode)->flags &= ~NCPI_DIR_CACHE; | 636 | NCP_FINFO(dir)->flags &= ~NCPI_DIR_CACHE; |
637 | spin_unlock(&dentry->d_lock); | 637 | spin_unlock(&dentry->d_lock); |
638 | } | 638 | } |
639 | } else { | 639 | } else { |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 5d2a57e4c03a..d40010e4f1a9 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -870,7 +870,7 @@ __be32 nfsd_readv(struct file *file, loff_t offset, struct kvec *vec, int vlen, | |||
870 | 870 | ||
871 | oldfs = get_fs(); | 871 | oldfs = get_fs(); |
872 | set_fs(KERNEL_DS); | 872 | set_fs(KERNEL_DS); |
873 | host_err = vfs_readv(file, (struct iovec __user *)vec, vlen, &offset); | 873 | host_err = vfs_readv(file, (struct iovec __user *)vec, vlen, &offset, 0); |
874 | set_fs(oldfs); | 874 | set_fs(oldfs); |
875 | return nfsd_finish_read(file, count, host_err); | 875 | return nfsd_finish_read(file, count, host_err); |
876 | } | 876 | } |
@@ -957,7 +957,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
957 | 957 | ||
958 | /* Write the data. */ | 958 | /* Write the data. */ |
959 | oldfs = get_fs(); set_fs(KERNEL_DS); | 959 | oldfs = get_fs(); set_fs(KERNEL_DS); |
960 | host_err = vfs_writev(file, (struct iovec __user *)vec, vlen, &pos); | 960 | host_err = vfs_writev(file, (struct iovec __user *)vec, vlen, &pos, 0); |
961 | set_fs(oldfs); | 961 | set_fs(oldfs); |
962 | if (host_err < 0) | 962 | if (host_err < 0) |
963 | goto out_nfserr; | 963 | goto out_nfserr; |
diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c index 2256e7e23e67..3f1190d18991 100644 --- a/fs/proc_namespace.c +++ b/fs/proc_namespace.c | |||
@@ -199,6 +199,8 @@ static int show_vfsstat(struct seq_file *m, struct vfsmount *mnt) | |||
199 | if (sb->s_op->show_devname) { | 199 | if (sb->s_op->show_devname) { |
200 | seq_puts(m, "device "); | 200 | seq_puts(m, "device "); |
201 | err = sb->s_op->show_devname(m, mnt_path.dentry); | 201 | err = sb->s_op->show_devname(m, mnt_path.dentry); |
202 | if (err) | ||
203 | goto out; | ||
202 | } else { | 204 | } else { |
203 | if (r->mnt_devname) { | 205 | if (r->mnt_devname) { |
204 | seq_puts(m, "device "); | 206 | seq_puts(m, "device "); |
diff --git a/fs/read_write.c b/fs/read_write.c index dadf24e5c95b..cf377cf9dfe3 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
@@ -693,12 +693,17 @@ unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to) | |||
693 | EXPORT_SYMBOL(iov_shorten); | 693 | EXPORT_SYMBOL(iov_shorten); |
694 | 694 | ||
695 | static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter, | 695 | static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter, |
696 | loff_t *ppos, iter_fn_t fn) | 696 | loff_t *ppos, iter_fn_t fn, int flags) |
697 | { | 697 | { |
698 | struct kiocb kiocb; | 698 | struct kiocb kiocb; |
699 | ssize_t ret; | 699 | ssize_t ret; |
700 | 700 | ||
701 | if (flags & ~RWF_HIPRI) | ||
702 | return -EOPNOTSUPP; | ||
703 | |||
701 | init_sync_kiocb(&kiocb, filp); | 704 | init_sync_kiocb(&kiocb, filp); |
705 | if (flags & RWF_HIPRI) | ||
706 | kiocb.ki_flags |= IOCB_HIPRI; | ||
702 | kiocb.ki_pos = *ppos; | 707 | kiocb.ki_pos = *ppos; |
703 | 708 | ||
704 | ret = fn(&kiocb, iter); | 709 | ret = fn(&kiocb, iter); |
@@ -709,10 +714,13 @@ static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter, | |||
709 | 714 | ||
710 | /* Do it by hand, with file-ops */ | 715 | /* Do it by hand, with file-ops */ |
711 | static ssize_t do_loop_readv_writev(struct file *filp, struct iov_iter *iter, | 716 | static ssize_t do_loop_readv_writev(struct file *filp, struct iov_iter *iter, |
712 | loff_t *ppos, io_fn_t fn) | 717 | loff_t *ppos, io_fn_t fn, int flags) |
713 | { | 718 | { |
714 | ssize_t ret = 0; | 719 | ssize_t ret = 0; |
715 | 720 | ||
721 | if (flags & ~RWF_HIPRI) | ||
722 | return -EOPNOTSUPP; | ||
723 | |||
716 | while (iov_iter_count(iter)) { | 724 | while (iov_iter_count(iter)) { |
717 | struct iovec iovec = iov_iter_iovec(iter); | 725 | struct iovec iovec = iov_iter_iovec(iter); |
718 | ssize_t nr; | 726 | ssize_t nr; |
@@ -813,7 +821,8 @@ out: | |||
813 | 821 | ||
814 | static ssize_t do_readv_writev(int type, struct file *file, | 822 | static ssize_t do_readv_writev(int type, struct file *file, |
815 | const struct iovec __user * uvector, | 823 | const struct iovec __user * uvector, |
816 | unsigned long nr_segs, loff_t *pos) | 824 | unsigned long nr_segs, loff_t *pos, |
825 | int flags) | ||
817 | { | 826 | { |
818 | size_t tot_len; | 827 | size_t tot_len; |
819 | struct iovec iovstack[UIO_FASTIOV]; | 828 | struct iovec iovstack[UIO_FASTIOV]; |
@@ -845,9 +854,9 @@ static ssize_t do_readv_writev(int type, struct file *file, | |||
845 | } | 854 | } |
846 | 855 | ||
847 | if (iter_fn) | 856 | if (iter_fn) |
848 | ret = do_iter_readv_writev(file, &iter, pos, iter_fn); | 857 | ret = do_iter_readv_writev(file, &iter, pos, iter_fn, flags); |
849 | else | 858 | else |
850 | ret = do_loop_readv_writev(file, &iter, pos, fn); | 859 | ret = do_loop_readv_writev(file, &iter, pos, fn, flags); |
851 | 860 | ||
852 | if (type != READ) | 861 | if (type != READ) |
853 | file_end_write(file); | 862 | file_end_write(file); |
@@ -864,40 +873,40 @@ out: | |||
864 | } | 873 | } |
865 | 874 | ||
866 | ssize_t vfs_readv(struct file *file, const struct iovec __user *vec, | 875 | ssize_t vfs_readv(struct file *file, const struct iovec __user *vec, |
867 | unsigned long vlen, loff_t *pos) | 876 | unsigned long vlen, loff_t *pos, int flags) |
868 | { | 877 | { |
869 | if (!(file->f_mode & FMODE_READ)) | 878 | if (!(file->f_mode & FMODE_READ)) |
870 | return -EBADF; | 879 | return -EBADF; |
871 | if (!(file->f_mode & FMODE_CAN_READ)) | 880 | if (!(file->f_mode & FMODE_CAN_READ)) |
872 | return -EINVAL; | 881 | return -EINVAL; |
873 | 882 | ||
874 | return do_readv_writev(READ, file, vec, vlen, pos); | 883 | return do_readv_writev(READ, file, vec, vlen, pos, flags); |
875 | } | 884 | } |
876 | 885 | ||
877 | EXPORT_SYMBOL(vfs_readv); | 886 | EXPORT_SYMBOL(vfs_readv); |
878 | 887 | ||
879 | ssize_t vfs_writev(struct file *file, const struct iovec __user *vec, | 888 | ssize_t vfs_writev(struct file *file, const struct iovec __user *vec, |
880 | unsigned long vlen, loff_t *pos) | 889 | unsigned long vlen, loff_t *pos, int flags) |
881 | { | 890 | { |
882 | if (!(file->f_mode & FMODE_WRITE)) | 891 | if (!(file->f_mode & FMODE_WRITE)) |
883 | return -EBADF; | 892 | return -EBADF; |
884 | if (!(file->f_mode & FMODE_CAN_WRITE)) | 893 | if (!(file->f_mode & FMODE_CAN_WRITE)) |
885 | return -EINVAL; | 894 | return -EINVAL; |
886 | 895 | ||
887 | return do_readv_writev(WRITE, file, vec, vlen, pos); | 896 | return do_readv_writev(WRITE, file, vec, vlen, pos, flags); |
888 | } | 897 | } |
889 | 898 | ||
890 | EXPORT_SYMBOL(vfs_writev); | 899 | EXPORT_SYMBOL(vfs_writev); |
891 | 900 | ||
892 | SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, | 901 | static ssize_t do_readv(unsigned long fd, const struct iovec __user *vec, |
893 | unsigned long, vlen) | 902 | unsigned long vlen, int flags) |
894 | { | 903 | { |
895 | struct fd f = fdget_pos(fd); | 904 | struct fd f = fdget_pos(fd); |
896 | ssize_t ret = -EBADF; | 905 | ssize_t ret = -EBADF; |
897 | 906 | ||
898 | if (f.file) { | 907 | if (f.file) { |
899 | loff_t pos = file_pos_read(f.file); | 908 | loff_t pos = file_pos_read(f.file); |
900 | ret = vfs_readv(f.file, vec, vlen, &pos); | 909 | ret = vfs_readv(f.file, vec, vlen, &pos, flags); |
901 | if (ret >= 0) | 910 | if (ret >= 0) |
902 | file_pos_write(f.file, pos); | 911 | file_pos_write(f.file, pos); |
903 | fdput_pos(f); | 912 | fdput_pos(f); |
@@ -909,15 +918,15 @@ SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, | |||
909 | return ret; | 918 | return ret; |
910 | } | 919 | } |
911 | 920 | ||
912 | SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec, | 921 | static ssize_t do_writev(unsigned long fd, const struct iovec __user *vec, |
913 | unsigned long, vlen) | 922 | unsigned long vlen, int flags) |
914 | { | 923 | { |
915 | struct fd f = fdget_pos(fd); | 924 | struct fd f = fdget_pos(fd); |
916 | ssize_t ret = -EBADF; | 925 | ssize_t ret = -EBADF; |
917 | 926 | ||
918 | if (f.file) { | 927 | if (f.file) { |
919 | loff_t pos = file_pos_read(f.file); | 928 | loff_t pos = file_pos_read(f.file); |
920 | ret = vfs_writev(f.file, vec, vlen, &pos); | 929 | ret = vfs_writev(f.file, vec, vlen, &pos, flags); |
921 | if (ret >= 0) | 930 | if (ret >= 0) |
922 | file_pos_write(f.file, pos); | 931 | file_pos_write(f.file, pos); |
923 | fdput_pos(f); | 932 | fdput_pos(f); |
@@ -935,10 +944,9 @@ static inline loff_t pos_from_hilo(unsigned long high, unsigned long low) | |||
935 | return (((loff_t)high << HALF_LONG_BITS) << HALF_LONG_BITS) | low; | 944 | return (((loff_t)high << HALF_LONG_BITS) << HALF_LONG_BITS) | low; |
936 | } | 945 | } |
937 | 946 | ||
938 | SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec, | 947 | static ssize_t do_preadv(unsigned long fd, const struct iovec __user *vec, |
939 | unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h) | 948 | unsigned long vlen, loff_t pos, int flags) |
940 | { | 949 | { |
941 | loff_t pos = pos_from_hilo(pos_h, pos_l); | ||
942 | struct fd f; | 950 | struct fd f; |
943 | ssize_t ret = -EBADF; | 951 | ssize_t ret = -EBADF; |
944 | 952 | ||
@@ -949,7 +957,7 @@ SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec, | |||
949 | if (f.file) { | 957 | if (f.file) { |
950 | ret = -ESPIPE; | 958 | ret = -ESPIPE; |
951 | if (f.file->f_mode & FMODE_PREAD) | 959 | if (f.file->f_mode & FMODE_PREAD) |
952 | ret = vfs_readv(f.file, vec, vlen, &pos); | 960 | ret = vfs_readv(f.file, vec, vlen, &pos, flags); |
953 | fdput(f); | 961 | fdput(f); |
954 | } | 962 | } |
955 | 963 | ||
@@ -959,10 +967,9 @@ SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec, | |||
959 | return ret; | 967 | return ret; |
960 | } | 968 | } |
961 | 969 | ||
962 | SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec, | 970 | static ssize_t do_pwritev(unsigned long fd, const struct iovec __user *vec, |
963 | unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h) | 971 | unsigned long vlen, loff_t pos, int flags) |
964 | { | 972 | { |
965 | loff_t pos = pos_from_hilo(pos_h, pos_l); | ||
966 | struct fd f; | 973 | struct fd f; |
967 | ssize_t ret = -EBADF; | 974 | ssize_t ret = -EBADF; |
968 | 975 | ||
@@ -973,7 +980,7 @@ SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec, | |||
973 | if (f.file) { | 980 | if (f.file) { |
974 | ret = -ESPIPE; | 981 | ret = -ESPIPE; |
975 | if (f.file->f_mode & FMODE_PWRITE) | 982 | if (f.file->f_mode & FMODE_PWRITE) |
976 | ret = vfs_writev(f.file, vec, vlen, &pos); | 983 | ret = vfs_writev(f.file, vec, vlen, &pos, flags); |
977 | fdput(f); | 984 | fdput(f); |
978 | } | 985 | } |
979 | 986 | ||
@@ -983,11 +990,64 @@ SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec, | |||
983 | return ret; | 990 | return ret; |
984 | } | 991 | } |
985 | 992 | ||
993 | SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, | ||
994 | unsigned long, vlen) | ||
995 | { | ||
996 | return do_readv(fd, vec, vlen, 0); | ||
997 | } | ||
998 | |||
999 | SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec, | ||
1000 | unsigned long, vlen) | ||
1001 | { | ||
1002 | return do_writev(fd, vec, vlen, 0); | ||
1003 | } | ||
1004 | |||
1005 | SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec, | ||
1006 | unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h) | ||
1007 | { | ||
1008 | loff_t pos = pos_from_hilo(pos_h, pos_l); | ||
1009 | |||
1010 | return do_preadv(fd, vec, vlen, pos, 0); | ||
1011 | } | ||
1012 | |||
1013 | SYSCALL_DEFINE6(preadv2, unsigned long, fd, const struct iovec __user *, vec, | ||
1014 | unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h, | ||
1015 | int, flags) | ||
1016 | { | ||
1017 | loff_t pos = pos_from_hilo(pos_h, pos_l); | ||
1018 | |||
1019 | if (pos == -1) | ||
1020 | return do_readv(fd, vec, vlen, flags); | ||
1021 | |||
1022 | return do_preadv(fd, vec, vlen, pos, flags); | ||
1023 | } | ||
1024 | |||
1025 | SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec, | ||
1026 | unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h) | ||
1027 | { | ||
1028 | loff_t pos = pos_from_hilo(pos_h, pos_l); | ||
1029 | |||
1030 | return do_pwritev(fd, vec, vlen, pos, 0); | ||
1031 | } | ||
1032 | |||
1033 | SYSCALL_DEFINE6(pwritev2, unsigned long, fd, const struct iovec __user *, vec, | ||
1034 | unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h, | ||
1035 | int, flags) | ||
1036 | { | ||
1037 | loff_t pos = pos_from_hilo(pos_h, pos_l); | ||
1038 | |||
1039 | if (pos == -1) | ||
1040 | return do_writev(fd, vec, vlen, flags); | ||
1041 | |||
1042 | return do_pwritev(fd, vec, vlen, pos, flags); | ||
1043 | } | ||
1044 | |||
986 | #ifdef CONFIG_COMPAT | 1045 | #ifdef CONFIG_COMPAT |
987 | 1046 | ||
988 | static ssize_t compat_do_readv_writev(int type, struct file *file, | 1047 | static ssize_t compat_do_readv_writev(int type, struct file *file, |
989 | const struct compat_iovec __user *uvector, | 1048 | const struct compat_iovec __user *uvector, |
990 | unsigned long nr_segs, loff_t *pos) | 1049 | unsigned long nr_segs, loff_t *pos, |
1050 | int flags) | ||
991 | { | 1051 | { |
992 | compat_ssize_t tot_len; | 1052 | compat_ssize_t tot_len; |
993 | struct iovec iovstack[UIO_FASTIOV]; | 1053 | struct iovec iovstack[UIO_FASTIOV]; |
@@ -1019,9 +1079,9 @@ static ssize_t compat_do_readv_writev(int type, struct file *file, | |||
1019 | } | 1079 | } |
1020 | 1080 | ||
1021 | if (iter_fn) | 1081 | if (iter_fn) |
1022 | ret = do_iter_readv_writev(file, &iter, pos, iter_fn); | 1082 | ret = do_iter_readv_writev(file, &iter, pos, iter_fn, flags); |
1023 | else | 1083 | else |
1024 | ret = do_loop_readv_writev(file, &iter, pos, fn); | 1084 | ret = do_loop_readv_writev(file, &iter, pos, fn, flags); |
1025 | 1085 | ||
1026 | if (type != READ) | 1086 | if (type != READ) |
1027 | file_end_write(file); | 1087 | file_end_write(file); |
@@ -1039,7 +1099,7 @@ out: | |||
1039 | 1099 | ||
1040 | static size_t compat_readv(struct file *file, | 1100 | static size_t compat_readv(struct file *file, |
1041 | const struct compat_iovec __user *vec, | 1101 | const struct compat_iovec __user *vec, |
1042 | unsigned long vlen, loff_t *pos) | 1102 | unsigned long vlen, loff_t *pos, int flags) |
1043 | { | 1103 | { |
1044 | ssize_t ret = -EBADF; | 1104 | ssize_t ret = -EBADF; |
1045 | 1105 | ||
@@ -1050,7 +1110,7 @@ static size_t compat_readv(struct file *file, | |||
1050 | if (!(file->f_mode & FMODE_CAN_READ)) | 1110 | if (!(file->f_mode & FMODE_CAN_READ)) |
1051 | goto out; | 1111 | goto out; |
1052 | 1112 | ||
1053 | ret = compat_do_readv_writev(READ, file, vec, vlen, pos); | 1113 | ret = compat_do_readv_writev(READ, file, vec, vlen, pos, flags); |
1054 | 1114 | ||
1055 | out: | 1115 | out: |
1056 | if (ret > 0) | 1116 | if (ret > 0) |
@@ -1059,9 +1119,9 @@ out: | |||
1059 | return ret; | 1119 | return ret; |
1060 | } | 1120 | } |
1061 | 1121 | ||
1062 | COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd, | 1122 | static size_t do_compat_readv(compat_ulong_t fd, |
1063 | const struct compat_iovec __user *,vec, | 1123 | const struct compat_iovec __user *vec, |
1064 | compat_ulong_t, vlen) | 1124 | compat_ulong_t vlen, int flags) |
1065 | { | 1125 | { |
1066 | struct fd f = fdget_pos(fd); | 1126 | struct fd f = fdget_pos(fd); |
1067 | ssize_t ret; | 1127 | ssize_t ret; |
@@ -1070,16 +1130,24 @@ COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd, | |||
1070 | if (!f.file) | 1130 | if (!f.file) |
1071 | return -EBADF; | 1131 | return -EBADF; |
1072 | pos = f.file->f_pos; | 1132 | pos = f.file->f_pos; |
1073 | ret = compat_readv(f.file, vec, vlen, &pos); | 1133 | ret = compat_readv(f.file, vec, vlen, &pos, flags); |
1074 | if (ret >= 0) | 1134 | if (ret >= 0) |
1075 | f.file->f_pos = pos; | 1135 | f.file->f_pos = pos; |
1076 | fdput_pos(f); | 1136 | fdput_pos(f); |
1077 | return ret; | 1137 | return ret; |
1138 | |||
1139 | } | ||
1140 | |||
1141 | COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd, | ||
1142 | const struct compat_iovec __user *,vec, | ||
1143 | compat_ulong_t, vlen) | ||
1144 | { | ||
1145 | return do_compat_readv(fd, vec, vlen, 0); | ||
1078 | } | 1146 | } |
1079 | 1147 | ||
1080 | static long __compat_sys_preadv64(unsigned long fd, | 1148 | static long do_compat_preadv64(unsigned long fd, |
1081 | const struct compat_iovec __user *vec, | 1149 | const struct compat_iovec __user *vec, |
1082 | unsigned long vlen, loff_t pos) | 1150 | unsigned long vlen, loff_t pos, int flags) |
1083 | { | 1151 | { |
1084 | struct fd f; | 1152 | struct fd f; |
1085 | ssize_t ret; | 1153 | ssize_t ret; |
@@ -1091,7 +1159,7 @@ static long __compat_sys_preadv64(unsigned long fd, | |||
1091 | return -EBADF; | 1159 | return -EBADF; |
1092 | ret = -ESPIPE; | 1160 | ret = -ESPIPE; |
1093 | if (f.file->f_mode & FMODE_PREAD) | 1161 | if (f.file->f_mode & FMODE_PREAD) |
1094 | ret = compat_readv(f.file, vec, vlen, &pos); | 1162 | ret = compat_readv(f.file, vec, vlen, &pos, flags); |
1095 | fdput(f); | 1163 | fdput(f); |
1096 | return ret; | 1164 | return ret; |
1097 | } | 1165 | } |
@@ -1101,7 +1169,7 @@ COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd, | |||
1101 | const struct compat_iovec __user *,vec, | 1169 | const struct compat_iovec __user *,vec, |
1102 | unsigned long, vlen, loff_t, pos) | 1170 | unsigned long, vlen, loff_t, pos) |
1103 | { | 1171 | { |
1104 | return __compat_sys_preadv64(fd, vec, vlen, pos); | 1172 | return do_compat_preadv64(fd, vec, vlen, pos, 0); |
1105 | } | 1173 | } |
1106 | #endif | 1174 | #endif |
1107 | 1175 | ||
@@ -1111,12 +1179,25 @@ COMPAT_SYSCALL_DEFINE5(preadv, compat_ulong_t, fd, | |||
1111 | { | 1179 | { |
1112 | loff_t pos = ((loff_t)pos_high << 32) | pos_low; | 1180 | loff_t pos = ((loff_t)pos_high << 32) | pos_low; |
1113 | 1181 | ||
1114 | return __compat_sys_preadv64(fd, vec, vlen, pos); | 1182 | return do_compat_preadv64(fd, vec, vlen, pos, 0); |
1183 | } | ||
1184 | |||
1185 | COMPAT_SYSCALL_DEFINE6(preadv2, compat_ulong_t, fd, | ||
1186 | const struct compat_iovec __user *,vec, | ||
1187 | compat_ulong_t, vlen, u32, pos_low, u32, pos_high, | ||
1188 | int, flags) | ||
1189 | { | ||
1190 | loff_t pos = ((loff_t)pos_high << 32) | pos_low; | ||
1191 | |||
1192 | if (pos == -1) | ||
1193 | return do_compat_readv(fd, vec, vlen, flags); | ||
1194 | |||
1195 | return do_compat_preadv64(fd, vec, vlen, pos, flags); | ||
1115 | } | 1196 | } |
1116 | 1197 | ||
1117 | static size_t compat_writev(struct file *file, | 1198 | static size_t compat_writev(struct file *file, |
1118 | const struct compat_iovec __user *vec, | 1199 | const struct compat_iovec __user *vec, |
1119 | unsigned long vlen, loff_t *pos) | 1200 | unsigned long vlen, loff_t *pos, int flags) |
1120 | { | 1201 | { |
1121 | ssize_t ret = -EBADF; | 1202 | ssize_t ret = -EBADF; |
1122 | 1203 | ||
@@ -1127,7 +1208,7 @@ static size_t compat_writev(struct file *file, | |||
1127 | if (!(file->f_mode & FMODE_CAN_WRITE)) | 1208 | if (!(file->f_mode & FMODE_CAN_WRITE)) |
1128 | goto out; | 1209 | goto out; |
1129 | 1210 | ||
1130 | ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos); | 1211 | ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos, 0); |
1131 | 1212 | ||
1132 | out: | 1213 | out: |
1133 | if (ret > 0) | 1214 | if (ret > 0) |
@@ -1136,9 +1217,9 @@ out: | |||
1136 | return ret; | 1217 | return ret; |
1137 | } | 1218 | } |
1138 | 1219 | ||
1139 | COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd, | 1220 | static size_t do_compat_writev(compat_ulong_t fd, |
1140 | const struct compat_iovec __user *, vec, | 1221 | const struct compat_iovec __user* vec, |
1141 | compat_ulong_t, vlen) | 1222 | compat_ulong_t vlen, int flags) |
1142 | { | 1223 | { |
1143 | struct fd f = fdget_pos(fd); | 1224 | struct fd f = fdget_pos(fd); |
1144 | ssize_t ret; | 1225 | ssize_t ret; |
@@ -1147,16 +1228,23 @@ COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd, | |||
1147 | if (!f.file) | 1228 | if (!f.file) |
1148 | return -EBADF; | 1229 | return -EBADF; |
1149 | pos = f.file->f_pos; | 1230 | pos = f.file->f_pos; |
1150 | ret = compat_writev(f.file, vec, vlen, &pos); | 1231 | ret = compat_writev(f.file, vec, vlen, &pos, flags); |
1151 | if (ret >= 0) | 1232 | if (ret >= 0) |
1152 | f.file->f_pos = pos; | 1233 | f.file->f_pos = pos; |
1153 | fdput_pos(f); | 1234 | fdput_pos(f); |
1154 | return ret; | 1235 | return ret; |
1155 | } | 1236 | } |
1156 | 1237 | ||
1157 | static long __compat_sys_pwritev64(unsigned long fd, | 1238 | COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd, |
1239 | const struct compat_iovec __user *, vec, | ||
1240 | compat_ulong_t, vlen) | ||
1241 | { | ||
1242 | return do_compat_writev(fd, vec, vlen, 0); | ||
1243 | } | ||
1244 | |||
1245 | static long do_compat_pwritev64(unsigned long fd, | ||
1158 | const struct compat_iovec __user *vec, | 1246 | const struct compat_iovec __user *vec, |
1159 | unsigned long vlen, loff_t pos) | 1247 | unsigned long vlen, loff_t pos, int flags) |
1160 | { | 1248 | { |
1161 | struct fd f; | 1249 | struct fd f; |
1162 | ssize_t ret; | 1250 | ssize_t ret; |
@@ -1168,7 +1256,7 @@ static long __compat_sys_pwritev64(unsigned long fd, | |||
1168 | return -EBADF; | 1256 | return -EBADF; |
1169 | ret = -ESPIPE; | 1257 | ret = -ESPIPE; |
1170 | if (f.file->f_mode & FMODE_PWRITE) | 1258 | if (f.file->f_mode & FMODE_PWRITE) |
1171 | ret = compat_writev(f.file, vec, vlen, &pos); | 1259 | ret = compat_writev(f.file, vec, vlen, &pos, flags); |
1172 | fdput(f); | 1260 | fdput(f); |
1173 | return ret; | 1261 | return ret; |
1174 | } | 1262 | } |
@@ -1178,7 +1266,7 @@ COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd, | |||
1178 | const struct compat_iovec __user *,vec, | 1266 | const struct compat_iovec __user *,vec, |
1179 | unsigned long, vlen, loff_t, pos) | 1267 | unsigned long, vlen, loff_t, pos) |
1180 | { | 1268 | { |
1181 | return __compat_sys_pwritev64(fd, vec, vlen, pos); | 1269 | return do_compat_pwritev64(fd, vec, vlen, pos, 0); |
1182 | } | 1270 | } |
1183 | #endif | 1271 | #endif |
1184 | 1272 | ||
@@ -1188,8 +1276,21 @@ COMPAT_SYSCALL_DEFINE5(pwritev, compat_ulong_t, fd, | |||
1188 | { | 1276 | { |
1189 | loff_t pos = ((loff_t)pos_high << 32) | pos_low; | 1277 | loff_t pos = ((loff_t)pos_high << 32) | pos_low; |
1190 | 1278 | ||
1191 | return __compat_sys_pwritev64(fd, vec, vlen, pos); | 1279 | return do_compat_pwritev64(fd, vec, vlen, pos, 0); |
1280 | } | ||
1281 | |||
1282 | COMPAT_SYSCALL_DEFINE6(pwritev2, compat_ulong_t, fd, | ||
1283 | const struct compat_iovec __user *,vec, | ||
1284 | compat_ulong_t, vlen, u32, pos_low, u32, pos_high, int, flags) | ||
1285 | { | ||
1286 | loff_t pos = ((loff_t)pos_high << 32) | pos_low; | ||
1287 | |||
1288 | if (pos == -1) | ||
1289 | return do_compat_writev(fd, vec, vlen, flags); | ||
1290 | |||
1291 | return do_compat_pwritev64(fd, vec, vlen, pos, flags); | ||
1192 | } | 1292 | } |
1293 | |||
1193 | #endif | 1294 | #endif |
1194 | 1295 | ||
1195 | static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, | 1296 | static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, |
diff --git a/fs/splice.c b/fs/splice.c index 82bc0d64fc38..9947b5c69664 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -185,6 +185,9 @@ ssize_t splice_to_pipe(struct pipe_inode_info *pipe, | |||
185 | unsigned int spd_pages = spd->nr_pages; | 185 | unsigned int spd_pages = spd->nr_pages; |
186 | int ret, do_wakeup, page_nr; | 186 | int ret, do_wakeup, page_nr; |
187 | 187 | ||
188 | if (!spd_pages) | ||
189 | return 0; | ||
190 | |||
188 | ret = 0; | 191 | ret = 0; |
189 | do_wakeup = 0; | 192 | do_wakeup = 0; |
190 | page_nr = 0; | 193 | page_nr = 0; |
@@ -577,7 +580,7 @@ static ssize_t kernel_readv(struct file *file, const struct iovec *vec, | |||
577 | old_fs = get_fs(); | 580 | old_fs = get_fs(); |
578 | set_fs(get_ds()); | 581 | set_fs(get_ds()); |
579 | /* The cast to a user pointer is valid due to the set_fs() */ | 582 | /* The cast to a user pointer is valid due to the set_fs() */ |
580 | res = vfs_readv(file, (const struct iovec __user *)vec, vlen, &pos); | 583 | res = vfs_readv(file, (const struct iovec __user *)vec, vlen, &pos, 0); |
581 | set_fs(old_fs); | 584 | set_fs(old_fs); |
582 | 585 | ||
583 | return res; | 586 | return res; |