Skip to content

Commit

Permalink
anonfd: Allow making anon files read-only
Browse files Browse the repository at this point in the history
It seems a couple places such as arch/ia64/kernel/perfmon.c and
drivers/infiniband/core/uverbs_main.c could use anon_inode_getfile()
instead of a private pseudo-fs + alloc_file(), if only there were a way
to get a read-only file.  So provide this by having anon_inode_getfile()
create a read-only file if we pass O_RDONLY in flags.

Signed-off-by: Roland Dreier <[email protected]>
Signed-off-by: Al Viro <[email protected]>
  • Loading branch information
Roland Dreier authored and Al Viro committed Dec 22, 2009
1 parent ed26175 commit 628ff7c
Show file tree
Hide file tree
Showing 7 changed files with 17 additions and 9 deletions.
12 changes: 10 additions & 2 deletions fs/anon_inodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,19 @@ struct file *anon_inode_getfile(const char *name,
struct qstr this;
struct path path;
struct file *file;
fmode_t mode;
int error;

if (IS_ERR(anon_inode_inode))
return ERR_PTR(-ENODEV);

switch (flags & O_ACCMODE) {
case O_RDONLY: mode = FMODE_READ; break;
case O_WRONLY: mode = FMODE_WRITE; break;
case O_RDWR: mode = FMODE_READ | FMODE_WRITE; break;
default: return ERR_PTR(-EINVAL);
}

if (fops->owner && !try_module_get(fops->owner))
return ERR_PTR(-ENOENT);

Expand Down Expand Up @@ -121,13 +129,13 @@ struct file *anon_inode_getfile(const char *name,
d_instantiate(path.dentry, anon_inode_inode);

error = -ENFILE;
file = alloc_file(&path, FMODE_READ | FMODE_WRITE, fops);
file = alloc_file(&path, mode, fops);
if (!file)
goto err_dput;
file->f_mapping = anon_inode_inode->i_mapping;

file->f_pos = 0;
file->f_flags = O_RDWR | (flags & O_NONBLOCK);
file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
file->f_version = 0;
file->private_data = priv;

Expand Down
2 changes: 1 addition & 1 deletion fs/eventfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ struct file *eventfd_file_create(unsigned int count, int flags)
ctx->flags = flags;

file = anon_inode_getfile("[eventfd]", &eventfd_fops, ctx,
flags & EFD_SHARED_FCNTL_FLAGS);
O_RDWR | (flags & EFD_SHARED_FCNTL_FLAGS));
if (IS_ERR(file))
eventfd_free_ctx(ctx);

Expand Down
2 changes: 1 addition & 1 deletion fs/eventpoll.c
Original file line number Diff line number Diff line change
Expand Up @@ -1206,7 +1206,7 @@ SYSCALL_DEFINE1(epoll_create1, int, flags)
* a file structure and a free file descriptor.
*/
error = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep,
flags & O_CLOEXEC);
O_RDWR | (flags & O_CLOEXEC));
if (error < 0)
ep_free(ep);

Expand Down
2 changes: 1 addition & 1 deletion fs/signalfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask,
* anon_inode_getfd() will install the fd.
*/
ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx,
flags & (O_CLOEXEC | O_NONBLOCK));
O_RDWR | (flags & (O_CLOEXEC | O_NONBLOCK)));
if (ufd < 0)
kfree(ctx);
} else {
Expand Down
2 changes: 1 addition & 1 deletion fs/timerfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS);

ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx,
flags & TFD_SHARED_FCNTL_FLAGS);
O_RDWR | (flags & TFD_SHARED_FCNTL_FLAGS));
if (ufd < 0)
kfree(ctx);

Expand Down
2 changes: 1 addition & 1 deletion kernel/perf_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -4724,7 +4724,7 @@ SYSCALL_DEFINE5(perf_event_open,
if (IS_ERR(event))
goto err_put_context;

err = anon_inode_getfd("[perf_event]", &perf_fops, event, 0);
err = anon_inode_getfd("[perf_event]", &perf_fops, event, O_RDWR);
if (err < 0)
goto err_free_put_context;

Expand Down
4 changes: 2 additions & 2 deletions virt/kvm/kvm_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1177,7 +1177,7 @@ static struct file_operations kvm_vcpu_fops = {
*/
static int create_vcpu_fd(struct kvm_vcpu *vcpu)
{
return anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu, 0);
return anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu, O_RDWR);
}

/*
Expand Down Expand Up @@ -1638,7 +1638,7 @@ static int kvm_dev_ioctl_create_vm(void)
kvm = kvm_create_vm();
if (IS_ERR(kvm))
return PTR_ERR(kvm);
fd = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm, 0);
fd = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm, O_RDWR);
if (fd < 0)
kvm_put_kvm(kvm);

Expand Down

0 comments on commit 628ff7c

Please sign in to comment.