Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[cascardo/linux.git] / fs / read_write.c
index 1adfb69..d065348 100644 (file)
@@ -232,23 +232,18 @@ EXPORT_SYMBOL(vfs_llseek);
 SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, origin)
 {
        off_t retval;
-       struct file * file;
-       int fput_needed;
-
-       retval = -EBADF;
-       file = fget_light(fd, &fput_needed);
-       if (!file)
-               goto bad;
+       struct fd f = fdget(fd);
+       if (!f.file)
+               return -EBADF;
 
        retval = -EINVAL;
        if (origin <= SEEK_MAX) {
-               loff_t res = vfs_llseek(file, offset, origin);
+               loff_t res = vfs_llseek(f.file, offset, origin);
                retval = res;
                if (res != (loff_t)retval)
                        retval = -EOVERFLOW;    /* LFS: should only happen on 32 bit platforms */
        }
-       fput_light(file, fput_needed);
-bad:
+       fdput(f);
        return retval;
 }
 
@@ -258,20 +253,17 @@ SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high,
                unsigned int, origin)
 {
        int retval;
-       struct file * file;
+       struct fd f = fdget(fd);
        loff_t offset;
-       int fput_needed;
 
-       retval = -EBADF;
-       file = fget_light(fd, &fput_needed);
-       if (!file)
-               goto bad;
+       if (!f.file)
+               return -EBADF;
 
        retval = -EINVAL;
        if (origin > SEEK_MAX)
                goto out_putf;
 
-       offset = vfs_llseek(file, ((loff_t) offset_high << 32) | offset_low,
+       offset = vfs_llseek(f.file, ((loff_t) offset_high << 32) | offset_low,
                        origin);
 
        retval = (int)offset;
@@ -281,8 +273,7 @@ SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high,
                        retval = 0;
        }
 out_putf:
-       fput_light(file, fput_needed);
-bad:
+       fdput(f);
        return retval;
 }
 #endif
@@ -461,34 +452,29 @@ static inline void file_pos_write(struct file *file, loff_t pos)
 
 SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
 {
-       struct file *file;
+       struct fd f = fdget(fd);
        ssize_t ret = -EBADF;
-       int fput_needed;
 
-       file = fget_light(fd, &fput_needed);
-       if (file) {
-               loff_t pos = file_pos_read(file);
-               ret = vfs_read(file, buf, count, &pos);
-               file_pos_write(file, pos);
-               fput_light(file, fput_needed);
+       if (f.file) {
+               loff_t pos = file_pos_read(f.file);
+               ret = vfs_read(f.file, buf, count, &pos);
+               file_pos_write(f.file, pos);
+               fdput(f);
        }
-
        return ret;
 }
 
 SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,
                size_t, count)
 {
-       struct file *file;
+       struct fd f = fdget(fd);
        ssize_t ret = -EBADF;
-       int fput_needed;
 
-       file = fget_light(fd, &fput_needed);
-       if (file) {
-               loff_t pos = file_pos_read(file);
-               ret = vfs_write(file, buf, count, &pos);
-               file_pos_write(file, pos);
-               fput_light(file, fput_needed);
+       if (f.file) {
+               loff_t pos = file_pos_read(f.file);
+               ret = vfs_write(f.file, buf, count, &pos);
+               file_pos_write(f.file, pos);
+               fdput(f);
        }
 
        return ret;
@@ -497,19 +483,18 @@ SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,
 SYSCALL_DEFINE(pread64)(unsigned int fd, char __user *buf,
                        size_t count, loff_t pos)
 {
-       struct file *file;
+       struct fd f;
        ssize_t ret = -EBADF;
-       int fput_needed;
 
        if (pos < 0)
                return -EINVAL;
 
-       file = fget_light(fd, &fput_needed);
-       if (file) {
+       f = fdget(fd);
+       if (f.file) {
                ret = -ESPIPE;
-               if (file->f_mode & FMODE_PREAD)
-                       ret = vfs_read(file, buf, count, &pos);
-               fput_light(file, fput_needed);
+               if (f.file->f_mode & FMODE_PREAD)
+                       ret = vfs_read(f.file, buf, count, &pos);
+               fdput(f);
        }
 
        return ret;
@@ -526,19 +511,18 @@ SYSCALL_ALIAS(sys_pread64, SyS_pread64);
 SYSCALL_DEFINE(pwrite64)(unsigned int fd, const char __user *buf,
                         size_t count, loff_t pos)
 {
-       struct file *file;
+       struct fd f;
        ssize_t ret = -EBADF;
-       int fput_needed;
 
        if (pos < 0)
                return -EINVAL;
 
-       file = fget_light(fd, &fput_needed);
-       if (file) {
+       f = fdget(fd);
+       if (f.file) {
                ret = -ESPIPE;
-               if (file->f_mode & FMODE_PWRITE)  
-                       ret = vfs_write(file, buf, count, &pos);
-               fput_light(file, fput_needed);
+               if (f.file->f_mode & FMODE_PWRITE)  
+                       ret = vfs_write(f.file, buf, count, &pos);
+               fdput(f);
        }
 
        return ret;
@@ -789,16 +773,14 @@ EXPORT_SYMBOL(vfs_writev);
 SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec,
                unsigned long, vlen)
 {
-       struct file *file;
+       struct fd f = fdget(fd);
        ssize_t ret = -EBADF;
-       int fput_needed;
 
-       file = fget_light(fd, &fput_needed);
-       if (file) {
-               loff_t pos = file_pos_read(file);
-               ret = vfs_readv(file, vec, vlen, &pos);
-               file_pos_write(file, pos);
-               fput_light(file, fput_needed);
+       if (f.file) {
+               loff_t pos = file_pos_read(f.file);
+               ret = vfs_readv(f.file, vec, vlen, &pos);
+               file_pos_write(f.file, pos);
+               fdput(f);
        }
 
        if (ret > 0)
@@ -810,16 +792,14 @@ SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec,
 SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec,
                unsigned long, vlen)
 {
-       struct file *file;
+       struct fd f = fdget(fd);
        ssize_t ret = -EBADF;
-       int fput_needed;
 
-       file = fget_light(fd, &fput_needed);
-       if (file) {
-               loff_t pos = file_pos_read(file);
-               ret = vfs_writev(file, vec, vlen, &pos);
-               file_pos_write(file, pos);
-               fput_light(file, fput_needed);
+       if (f.file) {
+               loff_t pos = file_pos_read(f.file);
+               ret = vfs_writev(f.file, vec, vlen, &pos);
+               file_pos_write(f.file, pos);
+               fdput(f);
        }
 
        if (ret > 0)
@@ -838,19 +818,18 @@ SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec,
                unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h)
 {
        loff_t pos = pos_from_hilo(pos_h, pos_l);
-       struct file *file;
+       struct fd f;
        ssize_t ret = -EBADF;
-       int fput_needed;
 
        if (pos < 0)
                return -EINVAL;
 
-       file = fget_light(fd, &fput_needed);
-       if (file) {
+       f = fdget(fd);
+       if (f.file) {
                ret = -ESPIPE;
-               if (file->f_mode & FMODE_PREAD)
-                       ret = vfs_readv(file, vec, vlen, &pos);
-               fput_light(file, fput_needed);
+               if (f.file->f_mode & FMODE_PREAD)
+                       ret = vfs_readv(f.file, vec, vlen, &pos);
+               fdput(f);
        }
 
        if (ret > 0)
@@ -863,19 +842,18 @@ SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec,
                unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h)
 {
        loff_t pos = pos_from_hilo(pos_h, pos_l);
-       struct file *file;
+       struct fd f;
        ssize_t ret = -EBADF;
-       int fput_needed;
 
        if (pos < 0)
                return -EINVAL;
 
-       file = fget_light(fd, &fput_needed);
-       if (file) {
+       f = fdget(fd);
+       if (f.file) {
                ret = -ESPIPE;
-               if (file->f_mode & FMODE_PWRITE)
-                       ret = vfs_writev(file, vec, vlen, &pos);
-               fput_light(file, fput_needed);
+               if (f.file->f_mode & FMODE_PWRITE)
+                       ret = vfs_writev(f.file, vec, vlen, &pos);
+               fdput(f);
        }
 
        if (ret > 0)
@@ -884,31 +862,31 @@ SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec,
        return ret;
 }
 
-static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
-                          size_t count, loff_t max)
+ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, size_t count,
+                   loff_t max)
 {
-       struct file * in_file, * out_file;
-       struct inode * in_inode, * out_inode;
+       struct fd in, out;
+       struct inode *in_inode, *out_inode;
        loff_t pos;
        ssize_t retval;
-       int fput_needed_in, fput_needed_out, fl;
+       int fl;
 
        /*
         * Get input file, and verify that it is ok..
         */
        retval = -EBADF;
-       in_file = fget_light(in_fd, &fput_needed_in);
-       if (!in_file)
+       in = fdget(in_fd);
+       if (!in.file)
                goto out;
-       if (!(in_file->f_mode & FMODE_READ))
+       if (!(in.file->f_mode & FMODE_READ))
                goto fput_in;
        retval = -ESPIPE;
        if (!ppos)
-               ppos = &in_file->f_pos;
+               ppos = &in.file->f_pos;
        else
-               if (!(in_file->f_mode & FMODE_PREAD))
+               if (!(in.file->f_mode & FMODE_PREAD))
                        goto fput_in;
-       retval = rw_verify_area(READ, in_file, ppos, count);
+       retval = rw_verify_area(READ, in.file, ppos, count);
        if (retval < 0)
                goto fput_in;
        count = retval;
@@ -917,15 +895,15 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
         * Get output file, and verify that it is ok..
         */
        retval = -EBADF;
-       out_file = fget_light(out_fd, &fput_needed_out);
-       if (!out_file)
+       out = fdget(out_fd);
+       if (!out.file)
                goto fput_in;
-       if (!(out_file->f_mode & FMODE_WRITE))
+       if (!(out.file->f_mode & FMODE_WRITE))
                goto fput_out;
        retval = -EINVAL;
-       in_inode = in_file->f_path.dentry->d_inode;
-       out_inode = out_file->f_path.dentry->d_inode;
-       retval = rw_verify_area(WRITE, out_file, &out_file->f_pos, count);
+       in_inode = in.file->f_path.dentry->d_inode;
+       out_inode = out.file->f_path.dentry->d_inode;
+       retval = rw_verify_area(WRITE, out.file, &out.file->f_pos, count);
        if (retval < 0)
                goto fput_out;
        count = retval;
@@ -949,10 +927,10 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
         * and the application is arguably buggy if it doesn't expect
         * EAGAIN on a non-blocking file descriptor.
         */
-       if (in_file->f_flags & O_NONBLOCK)
+       if (in.file->f_flags & O_NONBLOCK)
                fl = SPLICE_F_NONBLOCK;
 #endif
-       retval = do_splice_direct(in_file, ppos, out_file, count, fl);
+       retval = do_splice_direct(in.file, ppos, out.file, count, fl);
 
        if (retval > 0) {
                add_rchar(current, retval);
@@ -965,9 +943,9 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
                retval = -EOVERFLOW;
 
 fput_out:
-       fput_light(out_file, fput_needed_out);
+       fdput(out);
 fput_in:
-       fput_light(in_file, fput_needed_in);
+       fdput(in);
 out:
        return retval;
 }