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, ...@@ -477,6 +477,9 @@ asmlinkage ssize_t sys32_pread(unsigned int fd, char * buf,
goto out; goto out;
if (pos < 0) if (pos < 0)
goto out; goto out;
ret = -ESPIPE;
if (!(file->f_mode & FMODE_PREAD))
goto out;
ret = read(file, buf, count, &pos); ret = read(file, buf, count, &pos);
if (ret > 0) if (ret > 0)
dnotify_parent(file->f_dentry, DN_ACCESS); dnotify_parent(file->f_dentry, DN_ACCESS);
...@@ -511,6 +514,10 @@ asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char * buf, ...@@ -511,6 +514,10 @@ asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char * buf,
if (pos < 0) if (pos < 0)
goto out; goto out;
ret = -ESPIPE;
if (!(file->f_mode & FMODE_PWRITE))
goto out;
ret = write(file, buf, count, &pos); ret = write(file, buf, count, &pos);
if (ret > 0) if (ret > 0)
dnotify_parent(file->f_dentry, DN_MODIFY); dnotify_parent(file->f_dentry, DN_MODIFY);
......
...@@ -44,7 +44,9 @@ static int fifo_open(struct inode *inode, struct file *filp) ...@@ -44,7 +44,9 @@ static int fifo_open(struct inode *inode, struct file *filp)
goto err_nocleanup; goto err_nocleanup;
} }
filp->f_version = 0; 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) { switch (filp->f_mode) {
case 1: case 1:
......
...@@ -117,7 +117,7 @@ int open_private_file(struct file *filp, struct dentry *dentry, int flags) ...@@ -117,7 +117,7 @@ int open_private_file(struct file *filp, struct dentry *dentry, int flags)
memset(filp, 0, sizeof(*filp)); memset(filp, 0, sizeof(*filp));
eventpoll_init_file(filp); eventpoll_init_file(filp);
filp->f_flags = flags; 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); atomic_set(&filp->f_count, 1);
filp->f_dentry = dentry; filp->f_dentry = dentry;
filp->f_mapping = dentry->d_inode->i_mapping; filp->f_mapping = dentry->d_inode->i_mapping;
......
...@@ -1140,10 +1140,9 @@ int status; ...@@ -1140,10 +1140,9 @@ int status;
if (share_access & NFS4_SHARE_ACCESS_WRITE) { if (share_access & NFS4_SHARE_ACCESS_WRITE) {
status = get_write_access(filp->f_dentry->d_inode); status = get_write_access(filp->f_dentry->d_inode);
if (!status) if (status)
filp->f_mode = FMODE_WRITE | FMODE_LSEEK;
else
return nfserrno(status); return nfserrno(status);
filp->f_mode = (filp->f_mode | FMODE_WRITE) & ~FMODE_READ;
} }
return nfs_ok; return nfs_ok;
} }
...@@ -1153,7 +1152,7 @@ nfs4_file_downgrade(struct file *filp, unsigned int share_access) ...@@ -1153,7 +1152,7 @@ nfs4_file_downgrade(struct file *filp, unsigned int share_access)
{ {
if (share_access & NFS4_SHARE_ACCESS_WRITE) { if (share_access & NFS4_SHARE_ACCESS_WRITE) {
put_write_access(filp->f_dentry->d_inode); 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) ...@@ -781,7 +781,7 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
if (!f) if (!f)
goto cleanup_dentry; goto cleanup_dentry;
f->f_flags = flags; 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; inode = dentry->d_inode;
if (f->f_mode & FMODE_WRITE) { if (f->f_mode & FMODE_WRITE) {
error = get_write_access(inode); error = get_write_access(inode);
......
...@@ -94,10 +94,6 @@ pipe_readv(struct file *filp, const struct iovec *_iov, ...@@ -94,10 +94,6 @@ pipe_readv(struct file *filp, const struct iovec *_iov,
struct iovec *iov = (struct iovec *)_iov; struct iovec *iov = (struct iovec *)_iov;
size_t total_len; 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); total_len = iov_length(iov, nr_segs);
/* Null read succeeds. */ /* Null read succeeds. */
if (unlikely(total_len == 0)) if (unlikely(total_len == 0))
...@@ -187,10 +183,6 @@ pipe_writev(struct file *filp, const struct iovec *_iov, ...@@ -187,10 +183,6 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
struct iovec *iov = (struct iovec *)_iov; struct iovec *iov = (struct iovec *)_iov;
size_t total_len; 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); total_len = iov_length(iov, nr_segs);
/* Null write succeeds. */ /* Null write succeeds. */
if (unlikely(total_len == 0)) if (unlikely(total_len == 0))
......
...@@ -314,7 +314,7 @@ asmlinkage ssize_t sys_pread64(unsigned int fd, char __user *buf, ...@@ -314,7 +314,7 @@ asmlinkage ssize_t sys_pread64(unsigned int fd, char __user *buf,
file = fget_light(fd, &fput_needed); file = fget_light(fd, &fput_needed);
if (file) { if (file) {
ret = -ESPIPE; ret = -ESPIPE;
if (file->f_mode & FMODE_LSEEK) if (file->f_mode & FMODE_PREAD)
ret = vfs_read(file, buf, count, &pos); ret = vfs_read(file, buf, count, &pos);
fput_light(file, fput_needed); fput_light(file, fput_needed);
} }
...@@ -335,7 +335,7 @@ asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char __user *buf, ...@@ -335,7 +335,7 @@ asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char __user *buf,
file = fget_light(fd, &fput_needed); file = fget_light(fd, &fput_needed);
if (file) { if (file) {
ret = -ESPIPE; ret = -ESPIPE;
if (file->f_mode & FMODE_LSEEK) if (file->f_mode & FMODE_PWRITE)
ret = vfs_write(file, buf, count, &pos); ret = vfs_write(file, buf, count, &pos);
fput_light(file, fput_needed); fput_light(file, fput_needed);
} }
......
...@@ -35,6 +35,9 @@ int seq_open(struct file *file, struct seq_operations *op) ...@@ -35,6 +35,9 @@ int seq_open(struct file *file, struct seq_operations *op)
sema_init(&p->sem, 1); sema_init(&p->sem, 1);
p->op = op; p->op = op;
file->private_data = p; file->private_data = p;
/* SEQ files support lseek, but not pread/pwrite */
file->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
return 0; return 0;
} }
EXPORT_SYMBOL(seq_open); EXPORT_SYMBOL(seq_open);
...@@ -54,9 +57,6 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) ...@@ -54,9 +57,6 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
void *p; void *p;
int err = 0; int err = 0;
if (ppos != &file->f_pos)
return -EPIPE;
down(&m->sem); down(&m->sem);
/* grab buffer if we didn't have one */ /* grab buffer if we didn't have one */
if (!m->buf) { if (!m->buf) {
......
...@@ -74,7 +74,11 @@ extern int leases_enable, dir_notify_enable, lease_break_time; ...@@ -74,7 +74,11 @@ extern int leases_enable, dir_notify_enable, lease_break_time;
#define FMODE_READ 1 #define FMODE_READ 1
#define FMODE_WRITE 2 #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 RW_MASK 1
#define RWA_MASK 2 #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