]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.31/patches.apparmor/fsetattr.diff
Add a patch to fix Intel E100 wake-on-lan problems.
[ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.apparmor / fsetattr.diff
CommitLineData
6a930a95
BS
1Subject: VFS: new fsetattr() file operation
2
3From: Miklos Szeredi <mszeredi@suse.cz>
4
5Add a new file operation: f_op->fsetattr(), that is invoked by
6ftruncate, fchmod, fchown and utimensat. Fall back to i_op->setattr()
7if it is not defined.
8
9For the reasons why we need this, see patch adding fgetattr().
10
11ftruncate() already passed the open file to the filesystem via the
12ia_file member of struct iattr. However it is cleaner to have a
13separate file operation for this, so remove ia_file, ATTR_FILE and
14convert existing users: fuse and AFS.
15
16Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> ---
17Signed-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@@ -1467,6 +1467,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@@ -1480,6 +1485,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@@ -1493,6 +1499,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));