|
@@ -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)
|
|
@@ -887,28 +865,28 @@ SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec,
|
|
|
static 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;
|
|
|
}
|