2 * linux/kernel/vserver/inode.c
4 * Virtual Server: File System Support
6 * Copyright (C) 2004 Herbert Pƶtzl
8 * V0.01 separated from vcontext V0.05
12 #include <linux/config.h>
13 #include <linux/vs_base.h>
14 #include <linux/vs_context.h>
16 #include <linux/proc_fs.h>
17 #include <linux/namei.h>
18 #include <linux/vserver/inode.h>
20 #include <asm/errno.h>
21 #include <asm/uaccess.h>
24 static int __vc_get_iattr(struct inode *in, uint32_t *xid, uint32_t *flags, uint32_t *mask)
30 | (IS_BARRIER(in) ? IATTR_BARRIER : 0)
31 | (IS_IUNLINK(in) ? IATTR_IUNLINK : 0)
32 | (IS_IMMUTABLE(in) ? IATTR_IMMUTABLE : 0);
33 *mask = IATTR_IUNLINK | IATTR_IMMUTABLE;
35 if (S_ISDIR(in->i_mode))
36 *mask |= IATTR_BARRIER;
38 if (in->i_sb->s_flags & MS_TAGXID) {
43 if (in->i_sb->s_magic == PROC_SUPER_MAGIC) {
44 struct proc_dir_entry *entry = PROC_I(in)->pde;
46 // check for specific inodes ?
50 *flags |= (entry->vx_flags & IATTR_FLAGS);
52 *flags |= (PROC_I(in)->vx_flags & IATTR_FLAGS);
57 int vc_get_iattr(uint32_t id, void __user *data)
60 struct vcmd_ctx_iattr_v1 vc_data;
63 if (!vx_check(0, VX_ADMIN))
65 if (copy_from_user (&vc_data, data, sizeof(vc_data)))
68 ret = user_path_walk_link(vc_data.name, &nd);
70 ret = __vc_get_iattr(nd.dentry->d_inode,
71 &vc_data.xid, &vc_data.flags, &vc_data.mask);
75 if (copy_to_user (data, &vc_data, sizeof(vc_data)))
80 static int __vc_set_iattr(struct dentry *de, uint32_t *xid, uint32_t *flags, uint32_t *mask)
82 struct inode *in = de->d_inode;
83 int error = 0, is_proc = 0;
88 is_proc = (in->i_sb->s_magic == PROC_SUPER_MAGIC);
89 if ((*mask & IATTR_FLAGS) && !is_proc)
91 if ((*mask & IATTR_XID) && !(in->i_sb->s_flags & MS_TAGXID))
95 if (*mask & IATTR_XID)
98 if (*mask & IATTR_FLAGS) {
99 struct proc_dir_entry *entry = PROC_I(in)->pde;
100 unsigned int iflags = PROC_I(in)->vx_flags;
102 iflags = (iflags & ~(*mask & IATTR_FLAGS))
103 | (*flags & IATTR_FLAGS);
104 PROC_I(in)->vx_flags = iflags;
106 entry->vx_flags = iflags;
109 if (*mask & (IATTR_BARRIER | IATTR_IUNLINK | IATTR_IMMUTABLE)) {
112 attr.ia_valid = ATTR_ATTR_FLAG;
114 (IS_IMMUTABLE(in) ? ATTR_FLAG_IMMUTABLE : 0) |
115 (IS_IUNLINK(in) ? ATTR_FLAG_IUNLINK : 0) |
116 (IS_BARRIER(in) ? ATTR_FLAG_BARRIER : 0);
118 if (*mask & IATTR_IMMUTABLE) {
119 if (*flags & IATTR_IMMUTABLE)
120 attr.ia_attr_flags |= ATTR_FLAG_IMMUTABLE;
122 attr.ia_attr_flags &= ~ATTR_FLAG_IMMUTABLE;
124 if (*mask & IATTR_IUNLINK) {
125 if (*flags & IATTR_IUNLINK)
126 attr.ia_attr_flags |= ATTR_FLAG_IUNLINK;
128 attr.ia_attr_flags &= ~ATTR_FLAG_IUNLINK;
130 if (S_ISDIR(in->i_mode) && (*mask & IATTR_BARRIER)) {
131 if (*flags & IATTR_BARRIER)
132 attr.ia_attr_flags |= ATTR_FLAG_BARRIER;
134 attr.ia_attr_flags &= ~ATTR_FLAG_BARRIER;
136 if (in->i_op && in->i_op->setattr)
137 error = in->i_op->setattr(de, &attr);
139 error = inode_change_ok(in, &attr);
141 error = inode_setattr(in, &attr);
145 mark_inode_dirty(in);
150 int vc_set_iattr(uint32_t id, void __user *data)
153 struct vcmd_ctx_iattr_v1 vc_data;
156 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_LINUX_IMMUTABLE))
158 if (copy_from_user (&vc_data, data, sizeof(vc_data)))
161 ret = user_path_walk_link(vc_data.name, &nd);
163 ret = __vc_set_iattr(nd.dentry,
164 &vc_data.xid, &vc_data.flags, &vc_data.mask);
168 if (copy_to_user (data, &vc_data, sizeof(vc_data)))
173 int vc_iattr_ioctl(struct dentry *de, unsigned int cmd, unsigned long arg)
175 void __user *data = (void __user *)arg;
176 struct vcmd_ctx_iattr_v1 vc_data;
180 * I don't think we need any dget/dput pairs in here as long as
181 * this function is always called from sys_ioctl i.e., de is
182 * a field of a struct file that is guaranteed not to be freed.
184 if (cmd == FIOC_SETIATTR) {
185 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_LINUX_IMMUTABLE))
187 if (copy_from_user (&vc_data, data, sizeof(vc_data)))
189 ret = __vc_set_iattr(de,
190 &vc_data.xid, &vc_data.flags, &vc_data.mask);
193 if (!vx_check(0, VX_ADMIN))
195 ret = __vc_get_iattr(de->d_inode,
196 &vc_data.xid, &vc_data.flags, &vc_data.mask);
199 if (!ret && copy_to_user (data, &vc_data, sizeof(vc_data)))
205 #ifdef CONFIG_VSERVER_LEGACY
206 #include <linux/proc_fs.h>
208 #define PROC_DYNAMIC_FIRST 0xF0000000UL
210 int vx_proc_ioctl(struct inode * inode, struct file * filp,
211 unsigned int cmd, unsigned long arg)
213 struct proc_dir_entry *entry;
217 if (inode->i_ino < PROC_DYNAMIC_FIRST)
220 entry = PROC_I(inode)->pde;
226 /* fixme: if stealth, return -ENOTTY */
228 flags = entry->vx_flags;
229 if (capable(CAP_CONTEXT))
230 error = put_user(flags, (int *) arg);
234 /* fixme: if stealth, return -ENOTTY */
236 if (!capable(CAP_CONTEXT))
239 if (IS_RDONLY(inode))
242 if (get_user(flags, (int *) arg))
245 entry->vx_flags = flags;