Commit 4a47ae69 authored by Linus Torvalds's avatar Linus Torvalds

Add infrastructure for the VFS layer to mark files seekable.

We use a FMODE_LSEEK flag to match the existing read/write
bits. This allows us to check for seekability on a VFS level
for lseek/pread/pwrite, and cleans things up.

Update some sites that used the numeric constants to use 
the symbolic values instead.
parent 7d95b6c7
...@@ -44,6 +44,7 @@ static int fifo_open(struct inode *inode, struct file *filp) ...@@ -44,6 +44,7 @@ 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;
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; filp->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK;
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;
......
...@@ -1141,7 +1141,7 @@ int status; ...@@ -1141,7 +1141,7 @@ 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; filp->f_mode = FMODE_WRITE | FMODE_LSEEK;
else else
return nfserrno(status); return nfserrno(status);
} }
...@@ -1153,7 +1153,7 @@ nfs4_file_downgrade(struct file *filp, unsigned int share_access) ...@@ -1153,7 +1153,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; filp->f_mode = FMODE_READ | FMODE_LSEEK;
} }
} }
......
...@@ -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; f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK;
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);
......
...@@ -656,13 +656,13 @@ int do_pipe(int *fd) ...@@ -656,13 +656,13 @@ int do_pipe(int *fd)
f1->f_pos = f2->f_pos = 0; f1->f_pos = f2->f_pos = 0;
f1->f_flags = O_RDONLY; f1->f_flags = O_RDONLY;
f1->f_op = &read_pipe_fops; f1->f_op = &read_pipe_fops;
f1->f_mode = 1; f1->f_mode = FMODE_READ;
f1->f_version = 0; f1->f_version = 0;
/* write file */ /* write file */
f2->f_flags = O_WRONLY; f2->f_flags = O_WRONLY;
f2->f_op = &write_pipe_fops; f2->f_op = &write_pipe_fops;
f2->f_mode = 2; f2->f_mode = FMODE_WRITE;
f2->f_version = 0; f2->f_version = 0;
fd_install(i, f1); fd_install(i, f1);
......
...@@ -113,9 +113,12 @@ loff_t vfs_llseek(struct file *file, loff_t offset, int origin) ...@@ -113,9 +113,12 @@ loff_t vfs_llseek(struct file *file, loff_t offset, int origin)
{ {
loff_t (*fn)(struct file *, loff_t, int); loff_t (*fn)(struct file *, loff_t, int);
fn = default_llseek; fn = no_llseek;
if (file->f_op && file->f_op->llseek) if (file->f_mode & FMODE_LSEEK) {
fn = file->f_op->llseek; fn = default_llseek;
if (file->f_op && file->f_op->llseek)
fn = file->f_op->llseek;
}
return fn(file, offset, origin); return fn(file, offset, origin);
} }
EXPORT_SYMBOL(vfs_llseek); EXPORT_SYMBOL(vfs_llseek);
...@@ -310,7 +313,9 @@ asmlinkage ssize_t sys_pread64(unsigned int fd, char __user *buf, ...@@ -310,7 +313,9 @@ 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 = vfs_read(file, buf, count, &pos); ret = -ESPIPE;
if (file->f_mode & FMODE_LSEEK)
ret = vfs_read(file, buf, count, &pos);
fput_light(file, fput_needed); fput_light(file, fput_needed);
} }
...@@ -329,7 +334,9 @@ asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char __user *buf, ...@@ -329,7 +334,9 @@ 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 = vfs_write(file, buf, count, &pos); ret = -ESPIPE;
if (file->f_mode & FMODE_LSEEK)
ret = vfs_write(file, buf, count, &pos);
fput_light(file, fput_needed); fput_light(file, fput_needed);
} }
......
...@@ -74,6 +74,7 @@ extern int leases_enable, dir_notify_enable, lease_break_time; ...@@ -74,6 +74,7 @@ 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 */
#define RW_MASK 1 #define RW_MASK 1
#define RWA_MASK 2 #define RWA_MASK 2
......
...@@ -401,7 +401,7 @@ int sock_map_fd(struct socket *sock) ...@@ -401,7 +401,7 @@ int sock_map_fd(struct socket *sock)
sock->file = file; sock->file = file;
file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops; file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops;
file->f_mode = 3; file->f_mode = FMODE_READ | FMODE_WRITE;
file->f_flags = O_RDWR; file->f_flags = O_RDWR;
file->f_pos = 0; file->f_pos = 0;
fd_install(fd, file); fd_install(fd, file);
......
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