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