block/md: fix md autodetection
[linux-2.6] / fs / read_write.c
1 /*
2  *  linux/fs/read_write.c
3  *
4  *  Copyright (C) 1991, 1992  Linus Torvalds
5  */
6
7 #include <linux/slab.h> 
8 #include <linux/stat.h>
9 #include <linux/fcntl.h>
10 #include <linux/file.h>
11 #include <linux/uio.h>
12 #include <linux/smp_lock.h>
13 #include <linux/fsnotify.h>
14 #include <linux/security.h>
15 #include <linux/module.h>
16 #include <linux/syscalls.h>
17 #include <linux/pagemap.h>
18 #include <linux/splice.h>
19 #include "read_write.h"
20
21 #include <asm/uaccess.h>
22 #include <asm/unistd.h>
23
24 const struct file_operations generic_ro_fops = {
25         .llseek         = generic_file_llseek,
26         .read           = do_sync_read,
27         .aio_read       = generic_file_aio_read,
28         .mmap           = generic_file_readonly_mmap,
29         .splice_read    = generic_file_splice_read,
30 };
31
32 EXPORT_SYMBOL(generic_ro_fops);
33
34 /**
35  * generic_file_llseek_unlocked - lockless generic llseek implementation
36  * @file:       file structure to seek on
37  * @offset:     file offset to seek to
38  * @origin:     type of seek
39  *
40  * Updates the file offset to the value specified by @offset and @origin.
41  * Locking must be provided by the caller.
42  */
43 loff_t
44 generic_file_llseek_unlocked(struct file *file, loff_t offset, int origin)
45 {
46         struct inode *inode = file->f_mapping->host;
47
48         switch (origin) {
49         case SEEK_END:
50                 offset += inode->i_size;
51                 break;
52         case SEEK_CUR:
53                 offset += file->f_pos;
54                 break;
55         }
56
57         if (offset < 0 || offset > inode->i_sb->s_maxbytes)
58                 return -EINVAL;
59
60         /* Special lock needed here? */
61         if (offset != file->f_pos) {
62                 file->f_pos = offset;
63                 file->f_version = 0;
64         }
65
66         return offset;
67 }
68 EXPORT_SYMBOL(generic_file_llseek_unlocked);
69
70 /**
71  * generic_file_llseek - generic llseek implementation for regular files
72  * @file:       file structure to seek on
73  * @offset:     file offset to seek to
74  * @origin:     type of seek
75  *
76  * This is a generic implemenation of ->llseek useable for all normal local
77  * filesystems.  It just updates the file offset to the value specified by
78  * @offset and @origin under i_mutex.
79  */
80 loff_t generic_file_llseek(struct file *file, loff_t offset, int origin)
81 {
82         loff_t rval;
83
84         mutex_lock(&file->f_dentry->d_inode->i_mutex);
85         rval = generic_file_llseek_unlocked(file, offset, origin);
86         mutex_unlock(&file->f_dentry->d_inode->i_mutex);
87
88         return rval;
89 }
90 EXPORT_SYMBOL(generic_file_llseek);
91
92 loff_t no_llseek(struct file *file, loff_t offset, int origin)
93 {
94         return -ESPIPE;
95 }
96 EXPORT_SYMBOL(no_llseek);
97
98 loff_t default_llseek(struct file *file, loff_t offset, int origin)
99 {
100         loff_t retval;
101
102         lock_kernel();
103         switch (origin) {
104                 case SEEK_END:
105                         offset += i_size_read(file->f_path.dentry->d_inode);
106                         break;
107                 case SEEK_CUR:
108                         offset += file->f_pos;
109         }
110         retval = -EINVAL;
111         if (offset >= 0) {
112                 if (offset != file->f_pos) {
113                         file->f_pos = offset;
114                         file->f_version = 0;
115                 }
116                 retval = offset;
117         }
118         unlock_kernel();
119         return retval;
120 }
121 EXPORT_SYMBOL(default_llseek);
122
123 loff_t vfs_llseek(struct file *file, loff_t offset, int origin)
124 {
125         loff_t (*fn)(struct file *, loff_t, int);
126
127         fn = no_llseek;
128         if (file->f_mode & FMODE_LSEEK) {
129                 fn = default_llseek;
130                 if (file->f_op && file->f_op->llseek)
131                         fn = file->f_op->llseek;
132         }
133         return fn(file, offset, origin);
134 }
135 EXPORT_SYMBOL(vfs_llseek);
136
137 asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
138 {
139         off_t retval;
140         struct file * file;
141         int fput_needed;
142
143         retval = -EBADF;
144         file = fget_light(fd, &fput_needed);
145         if (!file)
146                 goto bad;
147
148         retval = -EINVAL;
149         if (origin <= SEEK_MAX) {
150                 loff_t res = vfs_llseek(file, offset, origin);
151                 retval = res;
152                 if (res != (loff_t)retval)
153                         retval = -EOVERFLOW;    /* LFS: should only happen on 32 bit platforms */
154         }
155         fput_light(file, fput_needed);
156 bad:
157         return retval;
158 }
159
160 #ifdef __ARCH_WANT_SYS_LLSEEK
161 asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high,
162                            unsigned long offset_low, loff_t __user * result,
163                            unsigned int origin)
164 {
165         int retval;
166         struct file * file;
167         loff_t offset;
168         int fput_needed;
169
170         retval = -EBADF;
171         file = fget_light(fd, &fput_needed);
172         if (!file)
173                 goto bad;
174
175         retval = -EINVAL;
176         if (origin > SEEK_MAX)
177                 goto out_putf;
178
179         offset = vfs_llseek(file, ((loff_t) offset_high << 32) | offset_low,
180                         origin);
181
182         retval = (int)offset;
183         if (offset >= 0) {
184                 retval = -EFAULT;
185                 if (!copy_to_user(result, &offset, sizeof(offset)))
186                         retval = 0;
187         }
188 out_putf:
189         fput_light(file, fput_needed);
190 bad:
191         return retval;
192 }
193 #endif
194
195 /*
196  * rw_verify_area doesn't like huge counts. We limit
197  * them to something that fits in "int" so that others
198  * won't have to do range checks all the time.
199  */
200 #define MAX_RW_COUNT (INT_MAX & PAGE_CACHE_MASK)
201
202 int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count)
203 {
204         struct inode *inode;
205         loff_t pos;
206         int retval = -EINVAL;
207
208         inode = file->f_path.dentry->d_inode;
209         if (unlikely((ssize_t) count < 0))
210                 return retval;
211         pos = *ppos;
212         if (unlikely((pos < 0) || (loff_t) (pos + count) < 0))
213                 return retval;
214
215         if (unlikely(inode->i_flock && mandatory_lock(inode))) {
216                 retval = locks_mandatory_area(
217                         read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE,
218                         inode, file, pos, count);
219                 if (retval < 0)
220                         return retval;
221         }
222         retval = security_file_permission(file,
223                                 read_write == READ ? MAY_READ : MAY_WRITE);
224         if (retval)
225                 return retval;
226         return count > MAX_RW_COUNT ? MAX_RW_COUNT : count;
227 }
228
229 static void wait_on_retry_sync_kiocb(struct kiocb *iocb)
230 {
231         set_current_state(TASK_UNINTERRUPTIBLE);
232         if (!kiocbIsKicked(iocb))
233                 schedule();
234         else
235                 kiocbClearKicked(iocb);
236         __set_current_state(TASK_RUNNING);
237 }
238
239 ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
240 {
241         struct iovec iov = { .iov_base = buf, .iov_len = len };
242         struct kiocb kiocb;
243         ssize_t ret;
244
245         init_sync_kiocb(&kiocb, filp);
246         kiocb.ki_pos = *ppos;
247         kiocb.ki_left = len;
248
249         for (;;) {
250                 ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
251                 if (ret != -EIOCBRETRY)
252                         break;
253                 wait_on_retry_sync_kiocb(&kiocb);
254         }
255
256         if (-EIOCBQUEUED == ret)
257                 ret = wait_on_sync_kiocb(&kiocb);
258         *ppos = kiocb.ki_pos;
259         return ret;
260 }
261
262 EXPORT_SYMBOL(do_sync_read);
263
264 ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
265 {
266         ssize_t ret;
267
268         if (!(file->f_mode & FMODE_READ))
269                 return -EBADF;
270         if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read))
271                 return -EINVAL;
272         if (unlikely(!access_ok(VERIFY_WRITE, buf, count)))
273                 return -EFAULT;
274
275         ret = rw_verify_area(READ, file, pos, count);
276         if (ret >= 0) {
277                 count = ret;
278                 if (file->f_op->read)
279                         ret = file->f_op->read(file, buf, count, pos);
280                 else
281                         ret = do_sync_read(file, buf, count, pos);
282                 if (ret > 0) {
283                         fsnotify_access(file->f_path.dentry);
284                         add_rchar(current, ret);
285                 }
286                 inc_syscr(current);
287         }
288
289         return ret;
290 }
291
292 EXPORT_SYMBOL(vfs_read);
293
294 ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
295 {
296         struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len };
297         struct kiocb kiocb;
298         ssize_t ret;
299
300         init_sync_kiocb(&kiocb, filp);
301         kiocb.ki_pos = *ppos;
302         kiocb.ki_left = len;
303
304         for (;;) {
305                 ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
306                 if (ret != -EIOCBRETRY)
307                         break;
308                 wait_on_retry_sync_kiocb(&kiocb);
309         }
310
311         if (-EIOCBQUEUED == ret)
312                 ret = wait_on_sync_kiocb(&kiocb);
313         *ppos = kiocb.ki_pos;
314         return ret;
315 }
316
317 EXPORT_SYMBOL(do_sync_write);
318
319 ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
320 {
321         ssize_t ret;
322
323         if (!(file->f_mode & FMODE_WRITE))
324                 return -EBADF;
325         if (!file->f_op || (!file->f_op->write && !file->f_op->aio_write))
326                 return -EINVAL;
327         if (unlikely(!access_ok(VERIFY_READ, buf, count)))
328                 return -EFAULT;
329
330         ret = rw_verify_area(WRITE, file, pos, count);
331         if (ret >= 0) {
332                 count = ret;
333                 if (file->f_op->write)
334                         ret = file->f_op->write(file, buf, count, pos);
335                 else
336                         ret = do_sync_write(file, buf, count, pos);
337                 if (ret > 0) {
338                         fsnotify_modify(file->f_path.dentry);
339                         add_wchar(current, ret);
340                 }
341                 inc_syscw(current);
342         }
343
344         return ret;
345 }
346
347 EXPORT_SYMBOL(vfs_write);
348
349 static inline loff_t file_pos_read(struct file *file)
350 {
351         return file->f_pos;
352 }
353
354 static inline void file_pos_write(struct file *file, loff_t pos)
355 {
356         file->f_pos = pos;
357 }
358
359 asmlinkage ssize_t sys_read(unsigned int fd, char __user * buf, size_t count)
360 {
361         struct file *file;
362         ssize_t ret = -EBADF;
363         int fput_needed;
364
365         file = fget_light(fd, &fput_needed);
366         if (file) {
367                 loff_t pos = file_pos_read(file);
368                 ret = vfs_read(file, buf, count, &pos);
369                 file_pos_write(file, pos);
370                 fput_light(file, fput_needed);
371         }
372
373         return ret;
374 }
375
376 asmlinkage ssize_t sys_write(unsigned int fd, const char __user * buf, size_t count)
377 {
378         struct file *file;
379         ssize_t ret = -EBADF;
380         int fput_needed;
381
382         file = fget_light(fd, &fput_needed);
383         if (file) {
384                 loff_t pos = file_pos_read(file);
385                 ret = vfs_write(file, buf, count, &pos);
386                 file_pos_write(file, pos);
387                 fput_light(file, fput_needed);
388         }
389
390         return ret;
391 }
392
393 asmlinkage ssize_t sys_pread64(unsigned int fd, char __user *buf,
394                              size_t count, loff_t pos)
395 {
396         struct file *file;
397         ssize_t ret = -EBADF;
398         int fput_needed;
399
400         if (pos < 0)
401                 return -EINVAL;
402
403         file = fget_light(fd, &fput_needed);
404         if (file) {
405                 ret = -ESPIPE;
406                 if (file->f_mode & FMODE_PREAD)
407                         ret = vfs_read(file, buf, count, &pos);
408                 fput_light(file, fput_needed);
409         }
410
411         return ret;
412 }
413
414 asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char __user *buf,
415                               size_t count, loff_t pos)
416 {
417         struct file *file;
418         ssize_t ret = -EBADF;
419         int fput_needed;
420
421         if (pos < 0)
422                 return -EINVAL;
423
424         file = fget_light(fd, &fput_needed);
425         if (file) {
426                 ret = -ESPIPE;
427                 if (file->f_mode & FMODE_PWRITE)  
428                         ret = vfs_write(file, buf, count, &pos);
429                 fput_light(file, fput_needed);
430         }
431
432         return ret;
433 }
434
435 /*
436  * Reduce an iovec's length in-place.  Return the resulting number of segments
437  */
438 unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to)
439 {
440         unsigned long seg = 0;
441         size_t len = 0;
442
443         while (seg < nr_segs) {
444                 seg++;
445                 if (len + iov->iov_len >= to) {
446                         iov->iov_len = to - len;
447                         break;
448                 }
449                 len += iov->iov_len;
450                 iov++;
451         }
452         return seg;
453 }
454 EXPORT_SYMBOL(iov_shorten);
455
456 ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
457                 unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn)
458 {
459         struct kiocb kiocb;
460         ssize_t ret;
461
462         init_sync_kiocb(&kiocb, filp);
463         kiocb.ki_pos = *ppos;
464         kiocb.ki_left = len;
465         kiocb.ki_nbytes = len;
466
467         for (;;) {
468                 ret = fn(&kiocb, iov, nr_segs, kiocb.ki_pos);
469                 if (ret != -EIOCBRETRY)
470                         break;
471                 wait_on_retry_sync_kiocb(&kiocb);
472         }
473
474         if (ret == -EIOCBQUEUED)
475                 ret = wait_on_sync_kiocb(&kiocb);
476         *ppos = kiocb.ki_pos;
477         return ret;
478 }
479
480 /* Do it by hand, with file-ops */
481 ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
482                 unsigned long nr_segs, loff_t *ppos, io_fn_t fn)
483 {
484         struct iovec *vector = iov;
485         ssize_t ret = 0;
486
487         while (nr_segs > 0) {
488                 void __user *base;
489                 size_t len;
490                 ssize_t nr;
491
492                 base = vector->iov_base;
493                 len = vector->iov_len;
494                 vector++;
495                 nr_segs--;
496
497                 nr = fn(filp, base, len, ppos);
498
499                 if (nr < 0) {
500                         if (!ret)
501                                 ret = nr;
502                         break;
503                 }
504                 ret += nr;
505                 if (nr != len)
506                         break;
507         }
508
509         return ret;
510 }
511
512 /* A write operation does a read from user space and vice versa */
513 #define vrfy_dir(type) ((type) == READ ? VERIFY_WRITE : VERIFY_READ)
514
515 ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
516                               unsigned long nr_segs, unsigned long fast_segs,
517                               struct iovec *fast_pointer,
518                               struct iovec **ret_pointer)
519   {
520         unsigned long seg;
521         ssize_t ret;
522         struct iovec *iov = fast_pointer;
523
524         /*
525          * SuS says "The readv() function *may* fail if the iovcnt argument
526          * was less than or equal to 0, or greater than {IOV_MAX}.  Linux has
527          * traditionally returned zero for zero segments, so...
528          */
529         if (nr_segs == 0) {
530                 ret = 0;
531                 goto out;
532         }
533
534         /*
535          * First get the "struct iovec" from user memory and
536          * verify all the pointers
537          */
538         if (nr_segs > UIO_MAXIOV) {
539                 ret = -EINVAL;
540                 goto out;
541         }
542         if (nr_segs > fast_segs) {
543                 iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL);
544                 if (iov == NULL) {
545                         ret = -ENOMEM;
546                         goto out;
547                 }
548         }
549         if (copy_from_user(iov, uvector, nr_segs*sizeof(*uvector))) {
550                 ret = -EFAULT;
551                 goto out;
552         }
553
554         /*
555          * According to the Single Unix Specification we should return EINVAL
556          * if an element length is < 0 when cast to ssize_t or if the
557          * total length would overflow the ssize_t return value of the
558          * system call.
559          */
560         ret = 0;
561         for (seg = 0; seg < nr_segs; seg++) {
562                 void __user *buf = iov[seg].iov_base;
563                 ssize_t len = (ssize_t)iov[seg].iov_len;
564
565                 /* see if we we're about to use an invalid len or if
566                  * it's about to overflow ssize_t */
567                 if (len < 0 || (ret + len < ret)) {
568                         ret = -EINVAL;
569                         goto out;
570                 }
571                 if (unlikely(!access_ok(vrfy_dir(type), buf, len))) {
572                         ret = -EFAULT;
573                         goto out;
574                 }
575
576                 ret += len;
577         }
578 out:
579         *ret_pointer = iov;
580         return ret;
581 }
582
583 static ssize_t do_readv_writev(int type, struct file *file,
584                                const struct iovec __user * uvector,
585                                unsigned long nr_segs, loff_t *pos)
586 {
587         size_t tot_len;
588         struct iovec iovstack[UIO_FASTIOV];
589         struct iovec *iov = iovstack;
590         ssize_t ret;
591         io_fn_t fn;
592         iov_fn_t fnv;
593
594         if (!file->f_op) {
595                 ret = -EINVAL;
596                 goto out;
597         }
598
599         ret = rw_copy_check_uvector(type, uvector, nr_segs,
600                         ARRAY_SIZE(iovstack), iovstack, &iov);
601         if (ret <= 0)
602                 goto out;
603
604         tot_len = ret;
605         ret = rw_verify_area(type, file, pos, tot_len);
606         if (ret < 0)
607                 goto out;
608
609         fnv = NULL;
610         if (type == READ) {
611                 fn = file->f_op->read;
612                 fnv = file->f_op->aio_read;
613         } else {
614                 fn = (io_fn_t)file->f_op->write;
615                 fnv = file->f_op->aio_write;
616         }
617
618         if (fnv)
619                 ret = do_sync_readv_writev(file, iov, nr_segs, tot_len,
620                                                 pos, fnv);
621         else
622                 ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn);
623
624 out:
625         if (iov != iovstack)
626                 kfree(iov);
627         if ((ret + (type == READ)) > 0) {
628                 if (type == READ)
629                         fsnotify_access(file->f_path.dentry);
630                 else
631                         fsnotify_modify(file->f_path.dentry);
632         }
633         return ret;
634 }
635
636 ssize_t vfs_readv(struct file *file, const struct iovec __user *vec,
637                   unsigned long vlen, loff_t *pos)
638 {
639         if (!(file->f_mode & FMODE_READ))
640                 return -EBADF;
641         if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read))
642                 return -EINVAL;
643
644         return do_readv_writev(READ, file, vec, vlen, pos);
645 }
646
647 EXPORT_SYMBOL(vfs_readv);
648
649 ssize_t vfs_writev(struct file *file, const struct iovec __user *vec,
650                    unsigned long vlen, loff_t *pos)
651 {
652         if (!(file->f_mode & FMODE_WRITE))
653                 return -EBADF;
654         if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write))
655                 return -EINVAL;
656
657         return do_readv_writev(WRITE, file, vec, vlen, pos);
658 }
659
660 EXPORT_SYMBOL(vfs_writev);
661
662 asmlinkage ssize_t
663 sys_readv(unsigned long fd, const struct iovec __user *vec, unsigned long vlen)
664 {
665         struct file *file;
666         ssize_t ret = -EBADF;
667         int fput_needed;
668
669         file = fget_light(fd, &fput_needed);
670         if (file) {
671                 loff_t pos = file_pos_read(file);
672                 ret = vfs_readv(file, vec, vlen, &pos);
673                 file_pos_write(file, pos);
674                 fput_light(file, fput_needed);
675         }
676
677         if (ret > 0)
678                 add_rchar(current, ret);
679         inc_syscr(current);
680         return ret;
681 }
682
683 asmlinkage ssize_t
684 sys_writev(unsigned long fd, const struct iovec __user *vec, unsigned long vlen)
685 {
686         struct file *file;
687         ssize_t ret = -EBADF;
688         int fput_needed;
689
690         file = fget_light(fd, &fput_needed);
691         if (file) {
692                 loff_t pos = file_pos_read(file);
693                 ret = vfs_writev(file, vec, vlen, &pos);
694                 file_pos_write(file, pos);
695                 fput_light(file, fput_needed);
696         }
697
698         if (ret > 0)
699                 add_wchar(current, ret);
700         inc_syscw(current);
701         return ret;
702 }
703
704 static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
705                            size_t count, loff_t max)
706 {
707         struct file * in_file, * out_file;
708         struct inode * in_inode, * out_inode;
709         loff_t pos;
710         ssize_t retval;
711         int fput_needed_in, fput_needed_out, fl;
712
713         /*
714          * Get input file, and verify that it is ok..
715          */
716         retval = -EBADF;
717         in_file = fget_light(in_fd, &fput_needed_in);
718         if (!in_file)
719                 goto out;
720         if (!(in_file->f_mode & FMODE_READ))
721                 goto fput_in;
722         retval = -EINVAL;
723         in_inode = in_file->f_path.dentry->d_inode;
724         if (!in_inode)
725                 goto fput_in;
726         if (!in_file->f_op || !in_file->f_op->splice_read)
727                 goto fput_in;
728         retval = -ESPIPE;
729         if (!ppos)
730                 ppos = &in_file->f_pos;
731         else
732                 if (!(in_file->f_mode & FMODE_PREAD))
733                         goto fput_in;
734         retval = rw_verify_area(READ, in_file, ppos, count);
735         if (retval < 0)
736                 goto fput_in;
737         count = retval;
738
739         /*
740          * Get output file, and verify that it is ok..
741          */
742         retval = -EBADF;
743         out_file = fget_light(out_fd, &fput_needed_out);
744         if (!out_file)
745                 goto fput_in;
746         if (!(out_file->f_mode & FMODE_WRITE))
747                 goto fput_out;
748         retval = -EINVAL;
749         if (!out_file->f_op || !out_file->f_op->sendpage)
750                 goto fput_out;
751         out_inode = out_file->f_path.dentry->d_inode;
752         retval = rw_verify_area(WRITE, out_file, &out_file->f_pos, count);
753         if (retval < 0)
754                 goto fput_out;
755         count = retval;
756
757         if (!max)
758                 max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes);
759
760         pos = *ppos;
761         retval = -EINVAL;
762         if (unlikely(pos < 0))
763                 goto fput_out;
764         if (unlikely(pos + count > max)) {
765                 retval = -EOVERFLOW;
766                 if (pos >= max)
767                         goto fput_out;
768                 count = max - pos;
769         }
770
771         fl = 0;
772 #if 0
773         /*
774          * We need to debate whether we can enable this or not. The
775          * man page documents EAGAIN return for the output at least,
776          * and the application is arguably buggy if it doesn't expect
777          * EAGAIN on a non-blocking file descriptor.
778          */
779         if (in_file->f_flags & O_NONBLOCK)
780                 fl = SPLICE_F_NONBLOCK;
781 #endif
782         retval = do_splice_direct(in_file, ppos, out_file, count, fl);
783
784         if (retval > 0) {
785                 add_rchar(current, retval);
786                 add_wchar(current, retval);
787         }
788
789         inc_syscr(current);
790         inc_syscw(current);
791         if (*ppos > max)
792                 retval = -EOVERFLOW;
793
794 fput_out:
795         fput_light(out_file, fput_needed_out);
796 fput_in:
797         fput_light(in_file, fput_needed_in);
798 out:
799         return retval;
800 }
801
802 asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t __user *offset, size_t count)
803 {
804         loff_t pos;
805         off_t off;
806         ssize_t ret;
807
808         if (offset) {
809                 if (unlikely(get_user(off, offset)))
810                         return -EFAULT;
811                 pos = off;
812                 ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS);
813                 if (unlikely(put_user(pos, offset)))
814                         return -EFAULT;
815                 return ret;
816         }
817
818         return do_sendfile(out_fd, in_fd, NULL, count, 0);
819 }
820
821 asmlinkage ssize_t sys_sendfile64(int out_fd, int in_fd, loff_t __user *offset, size_t count)
822 {
823         loff_t pos;
824         ssize_t ret;
825
826         if (offset) {
827                 if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t))))
828                         return -EFAULT;
829                 ret = do_sendfile(out_fd, in_fd, &pos, count, 0);
830                 if (unlikely(put_user(pos, offset)))
831                         return -EFAULT;
832                 return ret;
833         }
834
835         return do_sendfile(out_fd, in_fd, NULL, count, 0);
836 }