diff options
author | Roland Dreier <rdreier@cisco.com> | 2009-12-18 09:41:24 -0800 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2009-12-22 12:27:34 -0500 |
commit | 628ff7c1d8d8466a5ad8078bd0206a130f8b8a51 (patch) | |
tree | cc7ab0c90849be38e200fc6ff6a3a09e3caf0405 /fs/anon_inodes.c | |
parent | ed2617585f39dd12fae38c657bba68b9779ea10d (diff) | |
download | lwn-628ff7c1d8d8466a5ad8078bd0206a130f8b8a51.tar.gz lwn-628ff7c1d8d8466a5ad8078bd0206a130f8b8a51.zip |
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>
Diffstat (limited to 'fs/anon_inodes.c')
-rw-r--r-- | fs/anon_inodes.c | 12 |
1 files changed, 10 insertions, 2 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, 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); @@ -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; |