Commit 915a29ec authored by Linus Torvalds's avatar Linus Torvalds

Add pread/pwrite support bits to match the lseek bit.

This also removes the ESPIPE logic from pipes and seq_files,
since the VFS layer now supports it. 
parent e37eeb70
......@@ -477,6 +477,9 @@ asmlinkage ssize_t sys32_pread(unsigned int fd, char * buf,
goto out;
if (pos < 0)
goto out;
ret = -ESPIPE;
if (!(file->f_mode & FMODE_PREAD))
goto out;
ret = read(file, buf, count, &pos);
if (ret > 0)
dnotify_parent(file->f_dentry, DN_ACCESS);
......@@ -511,6 +514,10 @@ asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char * buf,
if (pos < 0)
goto out;
ret = -ESPIPE;
if (!(file->f_mode & FMODE_PWRITE))
goto out;
ret = write(file, buf, count, &pos);
if (ret > 0)
dnotify_parent(file->f_dentry, DN_MODIFY);
......
......@@ -44,7 +44,9 @@ static int fifo_open(struct inode *inode, struct file *filp)
goto err_nocleanup;
}
filp->f_version = 0;
filp->f_mode &= ~FMODE_LSEEK;
/* We can only do regular read/write on fifos */
filp->f_mode &= (FMODE_READ | FMODE_WRITE);
switch (filp->f_mode) {
case 1:
......
......@@ -117,7 +117,7 @@ int open_private_file(struct file *filp, struct dentry *dentry, int flags)
memset(filp, 0, sizeof(*filp));
eventpoll_init_file(filp);
filp->f_flags = flags;
filp->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK;
filp->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
atomic_set(&filp->f_count, 1);
filp->f_dentry = dentry;
filp->f_mapping = dentry->d_inode->i_mapping;
......
......@@ -1140,10 +1140,9 @@ int status;
if (share_access & NFS4_SHARE_ACCESS_WRITE) {
status = get_write_access(filp->f_dentry->d_inode);
if (!status)
filp->f_mode = FMODE_WRITE | FMODE_LSEEK;
else
if (status)
return nfserrno(status);
filp->f_mode = (filp->f_mode | FMODE_WRITE) & ~FMODE_READ;
}
return nfs_ok;
}
......@@ -1153,7 +1152,7 @@ nfs4_file_downgrade(struct file *filp, unsigned int share_access)
{
if (share_access & NFS4_SHARE_ACCESS_WRITE) {
put_write_access(filp->f_dentry->d_inode);
filp->f_mode = FMODE_READ | FMODE_LSEEK;
filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE;
}
}
......
......@@ -781,7 +781,7 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
if (!f)
goto cleanup_dentry;
f->f_flags = flags;
f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK;
f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
inode = dentry->d_inode;
if (f->f_mode & FMODE_WRITE) {
error = get_write_access(inode);
......
......@@ -94,10 +94,6 @@ pipe_readv(struct file *filp, const struct iovec *_iov,
struct iovec *iov = (struct iovec *)_iov;
size_t total_len;
/* pread is not allowed on pipes. */
if (unlikely(ppos != &filp->f_pos))
return -ESPIPE;
total_len = iov_length(iov, nr_segs);
/* Null read succeeds. */
if (unlikely(total_len == 0))
......@@ -187,10 +183,6 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
struct iovec *iov = (struct iovec *)_iov;
size_t total_len;
/* pwrite is not allowed on pipes. */
if (unlikely(ppos != &filp->f_pos))
return -ESPIPE;
total_len = iov_length(iov, nr_segs);
/* Null write succeeds. */
if (unlikely(total_len == 0))
......
......@@ -314,7 +314,7 @@ asmlinkage ssize_t sys_pread64(unsigned int fd, char __user *buf,
file = fget_light(fd, &fput_needed);
if (file) {
ret = -ESPIPE;
if (file->f_mode & FMODE_LSEEK)
if (file->f_mode & FMODE_PREAD)
ret = vfs_read(file, buf, count, &pos);
fput_light(file, fput_needed);
}
......@@ -335,7 +335,7 @@ asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char __user *buf,
file = fget_light(fd, &fput_needed);
if (file) {
ret = -ESPIPE;
if (file->f_mode & FMODE_LSEEK)
if (file->f_mode & FMODE_PWRITE)
ret = vfs_write(file, buf, count, &pos);
fput_light(file, fput_needed);
}
......
......@@ -35,6 +35,9 @@ int seq_open(struct file *file, struct seq_operations *op)
sema_init(&p->sem, 1);
p->op = op;
file->private_data = p;
/* SEQ files support lseek, but not pread/pwrite */
file->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
return 0;
}
EXPORT_SYMBOL(seq_open);
......@@ -54,9 +57,6 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
void *p;
int err = 0;
if (ppos != &file->f_pos)
return -EPIPE;
down(&m->sem);
/* grab buffer if we didn't have one */
if (!m->buf) {
......
......@@ -74,7 +74,11 @@ extern int leases_enable, dir_notify_enable, lease_break_time;
#define FMODE_READ 1
#define FMODE_WRITE 2
#define FMODE_LSEEK 4 /* Internal kernel extension */
/* Internal kernel extensions */
#define FMODE_LSEEK 4
#define FMODE_PREAD 8
#define FMODE_PWRITE FMODE_PREAD /* These go hand in hand */
#define RW_MASK 1
#define RWA_MASK 2
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment