diff options
author | Roland Dreier <rdreier@cisco.com> | 2009-12-18 12:41:24 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2009-12-22 12:27:34 -0500 |
commit | 628ff7c1d8d8466a5ad8078bd0206a130f8b8a51 (patch) | |
tree | cc7ab0c90849be38e200fc6ff6a3a09e3caf0405 | |
parent | ed2617585f39dd12fae38c657bba68b9779ea10d (diff) |
anonfd: Allow making anon files read-only
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 <rolandd@cisco.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/anon_inodes.c | 12 | ||||
-rw-r--r-- | fs/eventfd.c | 2 | ||||
-rw-r--r-- | fs/eventpoll.c | 2 | ||||
-rw-r--r-- | fs/signalfd.c | 2 | ||||
-rw-r--r-- | fs/timerfd.c | 2 | ||||
-rw-r--r-- | kernel/perf_event.c | 2 | ||||
-rw-r--r-- | virt/kvm/kvm_main.c | 4 |
7 files changed, 17 insertions, 9 deletions
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c index 2c994591f4d7..598237e97221 100644 --- a/fs/anon_inodes.c +++ b/fs/anon_inodes.c | |||
@@ -89,11 +89,19 @@ struct file *anon_inode_getfile(const char *name, | |||
89 | struct qstr this; | 89 | struct qstr this; |
90 | struct path path; | 90 | struct path path; |
91 | struct file *file; | 91 | struct file *file; |
92 | fmode_t mode; | ||
92 | int error; | 93 | int error; |
93 | 94 | ||
94 | if (IS_ERR(anon_inode_inode)) | 95 | if (IS_ERR(anon_inode_inode)) |
95 | return ERR_PTR(-ENODEV); | 96 | return ERR_PTR(-ENODEV); |
96 | 97 | ||
98 | switch (flags & O_ACCMODE) { | ||
99 | case O_RDONLY: mode = FMODE_READ; break; | ||
100 | case O_WRONLY: mode = FMODE_WRITE; break; | ||
101 | case O_RDWR: mode = FMODE_READ | FMODE_WRITE; break; | ||
102 | default: return ERR_PTR(-EINVAL); | ||
103 | } | ||
104 | |||
97 | if (fops->owner && !try_module_get(fops->owner)) | 105 | if (fops->owner && !try_module_get(fops->owner)) |
98 | return ERR_PTR(-ENOENT); | 106 | return ERR_PTR(-ENOENT); |
99 | 107 | ||
@@ -121,13 +129,13 @@ struct file *anon_inode_getfile(const char *name, | |||
121 | d_instantiate(path.dentry, anon_inode_inode); | 129 | d_instantiate(path.dentry, anon_inode_inode); |
122 | 130 | ||
123 | error = -ENFILE; | 131 | error = -ENFILE; |
124 | file = alloc_file(&path, FMODE_READ | FMODE_WRITE, fops); | 132 | file = alloc_file(&path, mode, fops); |
125 | if (!file) | 133 | if (!file) |
126 | goto err_dput; | 134 | goto err_dput; |
127 | file->f_mapping = anon_inode_inode->i_mapping; | 135 | file->f_mapping = anon_inode_inode->i_mapping; |
128 | 136 | ||
129 | file->f_pos = 0; | 137 | file->f_pos = 0; |
130 | file->f_flags = O_RDWR | (flags & O_NONBLOCK); | 138 | file->f_flags = flags & (O_ACCMODE | O_NONBLOCK); |
131 | file->f_version = 0; | 139 | file->f_version = 0; |
132 | file->private_data = priv; | 140 | file->private_data = priv; |
133 | 141 | ||
diff --git a/fs/eventfd.c b/fs/eventfd.c index 8b47e4200e65..d26402ff06ea 100644 --- a/fs/eventfd.c +++ b/fs/eventfd.c | |||
@@ -339,7 +339,7 @@ struct file *eventfd_file_create(unsigned int count, int flags) | |||
339 | ctx->flags = flags; | 339 | ctx->flags = flags; |
340 | 340 | ||
341 | file = anon_inode_getfile("[eventfd]", &eventfd_fops, ctx, | 341 | file = anon_inode_getfile("[eventfd]", &eventfd_fops, ctx, |
342 | flags & EFD_SHARED_FCNTL_FLAGS); | 342 | O_RDWR | (flags & EFD_SHARED_FCNTL_FLAGS)); |
343 | if (IS_ERR(file)) | 343 | if (IS_ERR(file)) |
344 | eventfd_free_ctx(ctx); | 344 | eventfd_free_ctx(ctx); |
345 | 345 | ||
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 366c503f9657..bd056a5b4efc 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c | |||
@@ -1206,7 +1206,7 @@ SYSCALL_DEFINE1(epoll_create1, int, flags) | |||
1206 | * a file structure and a free file descriptor. | 1206 | * a file structure and a free file descriptor. |
1207 | */ | 1207 | */ |
1208 | error = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep, | 1208 | error = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep, |
1209 | flags & O_CLOEXEC); | 1209 | O_RDWR | (flags & O_CLOEXEC)); |
1210 | if (error < 0) | 1210 | if (error < 0) |
1211 | ep_free(ep); | 1211 | ep_free(ep); |
1212 | 1212 | ||
diff --git a/fs/signalfd.c b/fs/signalfd.c index b07565c94386..1dabe4ee02fe 100644 --- a/fs/signalfd.c +++ b/fs/signalfd.c | |||
@@ -236,7 +236,7 @@ SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask, | |||
236 | * anon_inode_getfd() will install the fd. | 236 | * anon_inode_getfd() will install the fd. |
237 | */ | 237 | */ |
238 | ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx, | 238 | ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx, |
239 | flags & (O_CLOEXEC | O_NONBLOCK)); | 239 | O_RDWR | (flags & (O_CLOEXEC | O_NONBLOCK))); |
240 | if (ufd < 0) | 240 | if (ufd < 0) |
241 | kfree(ctx); | 241 | kfree(ctx); |
242 | } else { | 242 | } else { |
diff --git a/fs/timerfd.c b/fs/timerfd.c index b042bd7034b1..1bfc95ad5f71 100644 --- a/fs/timerfd.c +++ b/fs/timerfd.c | |||
@@ -200,7 +200,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags) | |||
200 | hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS); | 200 | hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS); |
201 | 201 | ||
202 | ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx, | 202 | ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx, |
203 | flags & TFD_SHARED_FCNTL_FLAGS); | 203 | O_RDWR | (flags & TFD_SHARED_FCNTL_FLAGS)); |
204 | if (ufd < 0) | 204 | if (ufd < 0) |
205 | kfree(ctx); | 205 | kfree(ctx); |
206 | 206 | ||
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index e0eb4a2fe183..1f38270f08c7 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
@@ -4724,7 +4724,7 @@ SYSCALL_DEFINE5(perf_event_open, | |||
4724 | if (IS_ERR(event)) | 4724 | if (IS_ERR(event)) |
4725 | goto err_put_context; | 4725 | goto err_put_context; |
4726 | 4726 | ||
4727 | err = anon_inode_getfd("[perf_event]", &perf_fops, event, 0); | 4727 | err = anon_inode_getfd("[perf_event]", &perf_fops, event, O_RDWR); |
4728 | if (err < 0) | 4728 | if (err < 0) |
4729 | goto err_free_put_context; | 4729 | goto err_free_put_context; |
4730 | 4730 | ||
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index e1f2bf8d7b1e..b5af88167613 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -1177,7 +1177,7 @@ static struct file_operations kvm_vcpu_fops = { | |||
1177 | */ | 1177 | */ |
1178 | static int create_vcpu_fd(struct kvm_vcpu *vcpu) | 1178 | static int create_vcpu_fd(struct kvm_vcpu *vcpu) |
1179 | { | 1179 | { |
1180 | return anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu, 0); | 1180 | return anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu, O_RDWR); |
1181 | } | 1181 | } |
1182 | 1182 | ||
1183 | /* | 1183 | /* |
@@ -1638,7 +1638,7 @@ static int kvm_dev_ioctl_create_vm(void) | |||
1638 | kvm = kvm_create_vm(); | 1638 | kvm = kvm_create_vm(); |
1639 | if (IS_ERR(kvm)) | 1639 | if (IS_ERR(kvm)) |
1640 | return PTR_ERR(kvm); | 1640 | return PTR_ERR(kvm); |
1641 | fd = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm, 0); | 1641 | fd = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm, O_RDWR); |
1642 | if (fd < 0) | 1642 | if (fd < 0) |
1643 | kvm_put_kvm(kvm); | 1643 | kvm_put_kvm(kvm); |
1644 | 1644 | ||