]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.apparmor/fsetattr.diff
Revert "Move xen patchset to new version's subdir."
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.apparmor / fsetattr.diff
1 Subject: VFS: new fsetattr() file operation
2
3 From: Miklos Szeredi <mszeredi@suse.cz>
4
5 Add a new file operation: f_op->fsetattr(), that is invoked by
6 ftruncate, fchmod, fchown and utimensat. Fall back to i_op->setattr()
7 if it is not defined.
8
9 For the reasons why we need this, see patch adding fgetattr().
10
11 ftruncate() already passed the open file to the filesystem via the
12 ia_file member of struct iattr. However it is cleaner to have a
13 separate file operation for this, so remove ia_file, ATTR_FILE and
14 convert existing users: fuse and AFS.
15
16 Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> ---
17 Signed-off-by: John Johansen <jjohansen@suse.de> ---
18
19 ---
20 fs/afs/dir.c | 1 +
21 fs/afs/file.c | 1 +
22 fs/afs/inode.c | 19 +++++++++++++++----
23 fs/afs/internal.h | 1 +
24 fs/attr.c | 19 +++++++++++++++----
25 fs/fuse/dir.c | 20 +++++++++-----------
26 fs/fuse/file.c | 7 +++++++
27 fs/fuse/fuse_i.h | 4 ++++
28 fs/open.c | 20 ++++++++------------
29 fs/utimes.c | 9 +++++----
30 include/linux/fs.h | 9 ++-------
31 11 files changed, 68 insertions(+), 42 deletions(-)
32
33 --- a/fs/afs/dir.c
34 +++ b/fs/afs/dir.c
35 @@ -45,6 +45,7 @@ const struct file_operations afs_dir_fil
36 .release = afs_release,
37 .readdir = afs_readdir,
38 .lock = afs_lock,
39 + .fsetattr = afs_fsetattr,
40 };
41
42 const struct inode_operations afs_dir_inode_operations = {
43 --- a/fs/afs/file.c
44 +++ b/fs/afs/file.c
45 @@ -36,6 +36,7 @@ const struct file_operations afs_file_op
46 .fsync = afs_fsync,
47 .lock = afs_lock,
48 .flock = afs_flock,
49 + .fsetattr = afs_fsetattr,
50 };
51
52 const struct inode_operations afs_file_inode_operations = {
53 --- a/fs/afs/inode.c
54 +++ b/fs/afs/inode.c
55 @@ -358,7 +358,8 @@ void afs_clear_inode(struct inode *inode
56 /*
57 * set the attributes of an inode
58 */
59 -int afs_setattr(struct dentry *dentry, struct iattr *attr)
60 +static int afs_do_setattr(struct dentry *dentry, struct iattr *attr,
61 + struct file *file)
62 {
63 struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
64 struct key *key;
65 @@ -380,8 +381,8 @@ int afs_setattr(struct dentry *dentry, s
66 afs_writeback_all(vnode);
67 }
68
69 - if (attr->ia_valid & ATTR_FILE) {
70 - key = attr->ia_file->private_data;
71 + if (file) {
72 + key = file->private_data;
73 } else {
74 key = afs_request_key(vnode->volume->cell);
75 if (IS_ERR(key)) {
76 @@ -391,10 +392,20 @@ int afs_setattr(struct dentry *dentry, s
77 }
78
79 ret = afs_vnode_setattr(vnode, key, attr);
80 - if (!(attr->ia_valid & ATTR_FILE))
81 + if (!file)
82 key_put(key);
83
84 error:
85 _leave(" = %d", ret);
86 return ret;
87 }
88 +
89 +int afs_setattr(struct dentry *dentry, struct iattr *attr)
90 +{
91 + return afs_do_setattr(dentry, attr, NULL);
92 +}
93 +
94 +int afs_fsetattr(struct file *file, struct iattr *attr)
95 +{
96 + return afs_do_setattr(file->f_path.dentry, attr, file);
97 +}
98 --- a/fs/afs/internal.h
99 +++ b/fs/afs/internal.h
100 @@ -548,6 +548,7 @@ extern void afs_zap_data(struct afs_vnod
101 extern int afs_validate(struct afs_vnode *, struct key *);
102 extern int afs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
103 extern int afs_setattr(struct dentry *, struct iattr *);
104 +extern int afs_fsetattr(struct file *, struct iattr *);
105 extern void afs_clear_inode(struct inode *);
106
107 /*
108 --- a/fs/attr.c
109 +++ b/fs/attr.c
110 @@ -100,8 +100,8 @@ int inode_setattr(struct inode * inode,
111 }
112 EXPORT_SYMBOL(inode_setattr);
113
114 -int notify_change(struct dentry *dentry, struct vfsmount *mnt,
115 - struct iattr *attr)
116 +int fnotify_change(struct dentry *dentry, struct vfsmount *mnt,
117 + struct iattr *attr, struct file *file)
118 {
119 struct inode *inode = dentry->d_inode;
120 mode_t mode = inode->i_mode;
121 @@ -165,8 +165,12 @@ int notify_change(struct dentry *dentry,
122
123 if (inode->i_op && inode->i_op->setattr) {
124 error = security_inode_setattr(dentry, mnt, attr);
125 - if (!error)
126 - error = inode->i_op->setattr(dentry, attr);
127 + if (!error) {
128 + if (file && file->f_op && file->f_op->fsetattr)
129 + error = file->f_op->fsetattr(file, attr);
130 + else
131 + error = inode->i_op->setattr(dentry, attr);
132 + }
133 } else {
134 error = inode_change_ok(inode, attr);
135 if (!error)
136 @@ -188,5 +192,12 @@ int notify_change(struct dentry *dentry,
137
138 return error;
139 }
140 +EXPORT_SYMBOL_GPL(fnotify_change);
141 +
142 +int notify_change(struct dentry *dentry, struct vfsmount *mnt,
143 + struct iattr *attr)
144 +{
145 + return fnotify_change(dentry, mnt, attr, NULL);
146 +}
147
148 EXPORT_SYMBOL(notify_change);
149 --- a/fs/fuse/dir.c
150 +++ b/fs/fuse/dir.c
151 @@ -1105,21 +1105,22 @@ static int fuse_dir_fsync(struct file *f
152 return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
153 }
154
155 -static bool update_mtime(unsigned ivalid)
156 +static bool update_mtime(unsigned ivalid, bool have_file)
157 {
158 /* Always update if mtime is explicitly set */
159 if (ivalid & ATTR_MTIME_SET)
160 return true;
161
162 /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
163 - if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
164 + if ((ivalid & ATTR_SIZE) && ((ivalid & ATTR_OPEN) || have_file))
165 return false;
166
167 /* In all other cases update */
168 return true;
169 }
170
171 -static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
172 +static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg,
173 + bool have_file)
174 {
175 unsigned ivalid = iattr->ia_valid;
176
177 @@ -1138,7 +1139,7 @@ static void iattr_to_fattr(struct iattr
178 if (!(ivalid & ATTR_ATIME_SET))
179 arg->valid |= FATTR_ATIME_NOW;
180 }
181 - if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
182 + if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, have_file)) {
183 arg->valid |= FATTR_MTIME;
184 arg->mtime = iattr->ia_mtime.tv_sec;
185 arg->mtimensec = iattr->ia_mtime.tv_nsec;
186 @@ -1199,8 +1200,8 @@ void fuse_release_nowrite(struct inode *
187 * vmtruncate() doesn't allow for this case, so do the rlimit checking
188 * and the actual truncation by hand.
189 */
190 -static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
191 - struct file *file)
192 +int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
193 + struct file *file)
194 {
195 struct inode *inode = entry->d_inode;
196 struct fuse_conn *fc = get_fuse_conn(inode);
197 @@ -1244,7 +1245,7 @@ static int fuse_do_setattr(struct dentry
198
199 memset(&inarg, 0, sizeof(inarg));
200 memset(&outarg, 0, sizeof(outarg));
201 - iattr_to_fattr(attr, &inarg);
202 + iattr_to_fattr(attr, &inarg, file != NULL);
203 if (file) {
204 struct fuse_file *ff = file->private_data;
205 inarg.valid |= FATTR_FH;
206 @@ -1314,10 +1315,7 @@ error:
207
208 static int fuse_setattr(struct dentry *entry, struct iattr *attr)
209 {
210 - if (attr->ia_valid & ATTR_FILE)
211 - return fuse_do_setattr(entry, attr, attr->ia_file);
212 - else
213 - return fuse_do_setattr(entry, attr, NULL);
214 + return fuse_do_setattr(entry, attr, NULL);
215 }
216
217 static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
218 --- a/fs/fuse/file.c
219 +++ b/fs/fuse/file.c
220 @@ -1466,6 +1466,11 @@ static loff_t fuse_file_llseek(struct fi
221 return retval;
222 }
223
224 +static int fuse_fsetattr(struct file *file, struct iattr *attr)
225 +{
226 + return fuse_do_setattr(file->f_path.dentry, attr, file);
227 +}
228 +
229 static const struct file_operations fuse_file_operations = {
230 .llseek = fuse_file_llseek,
231 .read = do_sync_read,
232 @@ -1479,6 +1484,7 @@ static const struct file_operations fuse
233 .fsync = fuse_fsync,
234 .lock = fuse_file_lock,
235 .flock = fuse_file_flock,
236 + .fsetattr = fuse_fsetattr,
237 .splice_read = generic_file_splice_read,
238 };
239
240 @@ -1492,6 +1498,7 @@ static const struct file_operations fuse
241 .fsync = fuse_fsync,
242 .lock = fuse_file_lock,
243 .flock = fuse_file_flock,
244 + .fsetattr = fuse_fsetattr,
245 /* no mmap and splice_read */
246 };
247
248 --- a/fs/fuse/fuse_i.h
249 +++ b/fs/fuse/fuse_i.h
250 @@ -551,6 +551,10 @@ void fuse_truncate(struct address_space
251 */
252 int fuse_dev_init(void);
253
254 +
255 +int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
256 + struct file *file);
257 +
258 /**
259 * Cleanup the client device
260 */
261 --- a/fs/open.c
262 +++ b/fs/open.c
263 @@ -207,16 +207,12 @@ int do_truncate(struct dentry *dentry, s
264
265 newattrs.ia_size = length;
266 newattrs.ia_valid = ATTR_SIZE | time_attrs;
267 - if (filp) {
268 - newattrs.ia_file = filp;
269 - newattrs.ia_valid |= ATTR_FILE;
270 - }
271
272 /* Remove suid/sgid on truncate too */
273 newattrs.ia_valid |= should_remove_suid(dentry);
274
275 mutex_lock(&dentry->d_inode->i_mutex);
276 - err = notify_change(dentry, mnt, &newattrs);
277 + err = fnotify_change(dentry, mnt, &newattrs, filp);
278 mutex_unlock(&dentry->d_inode->i_mutex);
279 return err;
280 }
281 @@ -625,7 +621,7 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd
282 mode = inode->i_mode;
283 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
284 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
285 - err = notify_change(dentry, file->f_path.mnt, &newattrs);
286 + err = fnotify_change(dentry, file->f_path.mnt, &newattrs, file);
287 mutex_unlock(&inode->i_mutex);
288 mnt_drop_write(file->f_path.mnt);
289 out_putf:
290 @@ -669,7 +665,7 @@ SYSCALL_DEFINE2(chmod, const char __user
291 }
292
293 static int chown_common(struct dentry * dentry, struct vfsmount *mnt,
294 - uid_t user, gid_t group)
295 + uid_t user, gid_t group, struct file *file)
296 {
297 struct inode *inode = dentry->d_inode;
298 int error;
299 @@ -688,7 +684,7 @@ static int chown_common(struct dentry *
300 newattrs.ia_valid |=
301 ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
302 mutex_lock(&inode->i_mutex);
303 - error = notify_change(dentry, mnt, &newattrs);
304 + error = fnotify_change(dentry, mnt, &newattrs, file);
305 mutex_unlock(&inode->i_mutex);
306
307 return error;
308 @@ -705,7 +701,7 @@ SYSCALL_DEFINE3(chown, const char __user
309 error = mnt_want_write(path.mnt);
310 if (error)
311 goto out_release;
312 - error = chown_common(path.dentry, path.mnt, user, group);
313 + error = chown_common(path.dentry, path.mnt, user, group, NULL);
314 mnt_drop_write(path.mnt);
315 out_release:
316 path_put(&path);
317 @@ -730,7 +726,7 @@ SYSCALL_DEFINE5(fchownat, int, dfd, cons
318 error = mnt_want_write(path.mnt);
319 if (error)
320 goto out_release;
321 - error = chown_common(path.dentry, path.mnt, user, group);
322 + error = chown_common(path.dentry, path.mnt, user, group, NULL);
323 mnt_drop_write(path.mnt);
324 out_release:
325 path_put(&path);
326 @@ -749,7 +745,7 @@ SYSCALL_DEFINE3(lchown, const char __use
327 error = mnt_want_write(path.mnt);
328 if (error)
329 goto out_release;
330 - error = chown_common(path.dentry, path.mnt, user, group);
331 + error = chown_common(path.dentry, path.mnt, user, group, NULL);
332 mnt_drop_write(path.mnt);
333 out_release:
334 path_put(&path);
335 @@ -772,7 +768,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd
336 goto out_fput;
337 dentry = file->f_path.dentry;
338 audit_inode(NULL, dentry);
339 - error = chown_common(dentry, file->f_path.mnt, user, group);
340 + error = chown_common(dentry, file->f_path.mnt, user, group, file);
341 mnt_drop_write(file->f_path.mnt);
342 out_fput:
343 fput(file);
344 --- a/fs/utimes.c
345 +++ b/fs/utimes.c
346 @@ -48,7 +48,8 @@ static bool nsec_valid(long nsec)
347 return nsec >= 0 && nsec <= 999999999;
348 }
349
350 -static int utimes_common(struct path *path, struct timespec *times)
351 +static int utimes_common(struct path *path, struct timespec *times,
352 + struct file *f)
353 {
354 int error;
355 struct iattr newattrs;
356 @@ -102,7 +103,7 @@ static int utimes_common(struct path *pa
357 }
358 }
359 mutex_lock(&inode->i_mutex);
360 - error = notify_change(path->dentry, path->mnt, &newattrs);
361 + error = fnotify_change(path->dentry, path->mnt, &newattrs, f);
362 mutex_unlock(&inode->i_mutex);
363
364 mnt_drop_write_and_out:
365 @@ -149,7 +150,7 @@ long do_utimes(int dfd, char __user *fil
366 if (!file)
367 goto out;
368
369 - error = utimes_common(&file->f_path, times);
370 + error = utimes_common(&file->f_path, times, file);
371 fput(file);
372 } else {
373 struct path path;
374 @@ -162,7 +163,7 @@ long do_utimes(int dfd, char __user *fil
375 if (error)
376 goto out;
377
378 - error = utimes_common(&path, times);
379 + error = utimes_common(&path, times, NULL);
380 path_put(&path);
381 }
382
383 --- a/include/linux/fs.h
384 +++ b/include/linux/fs.h
385 @@ -367,13 +367,6 @@ struct iattr {
386 struct timespec ia_atime;
387 struct timespec ia_mtime;
388 struct timespec ia_ctime;
389 -
390 - /*
391 - * Not an attribute, but an auxilary info for filesystems wanting to
392 - * implement an ftruncate() like method. NOTE: filesystem should
393 - * check for (ia_valid & ATTR_FILE), and not for (ia_file != NULL).
394 - */
395 - struct file *ia_file;
396 };
397
398 /*
399 @@ -1280,6 +1273,7 @@ struct file_operations {
400 #define HAVE_FOP_OPEN_EXEC
401 int (*open_exec) (struct inode *);
402 int (*setlease)(struct file *, long, struct file_lock **);
403 + int (*fsetattr)(struct file *, struct iattr *);
404 };
405
406 struct inode_operations {
407 @@ -1799,6 +1793,7 @@ extern int do_remount_sb(struct super_bl
408 extern sector_t bmap(struct inode *, sector_t);
409 #endif
410 extern int notify_change(struct dentry *, struct vfsmount *, struct iattr *);
411 +extern int fnotify_change(struct dentry *, struct vfsmount *, struct iattr *, struct file *);
412 extern int inode_permission(struct inode *, int);
413 extern int generic_permission(struct inode *, int,
414 int (*check_acl)(struct inode *, int));