diff options
Diffstat (limited to 'fs/overlayfs/inode.c')
-rw-r--r-- | fs/overlayfs/inode.c | 78 |
1 files changed, 11 insertions, 67 deletions
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 7fb53d055537..1ab8b0dbc237 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c | |||
@@ -13,34 +13,6 @@ | |||
13 | #include <linux/posix_acl.h> | 13 | #include <linux/posix_acl.h> |
14 | #include "overlayfs.h" | 14 | #include "overlayfs.h" |
15 | 15 | ||
16 | static int ovl_copy_up_truncate(struct dentry *dentry) | ||
17 | { | ||
18 | int err; | ||
19 | struct dentry *parent; | ||
20 | struct kstat stat; | ||
21 | struct path lowerpath; | ||
22 | const struct cred *old_cred; | ||
23 | |||
24 | parent = dget_parent(dentry); | ||
25 | err = ovl_copy_up(parent); | ||
26 | if (err) | ||
27 | goto out_dput_parent; | ||
28 | |||
29 | ovl_path_lower(dentry, &lowerpath); | ||
30 | |||
31 | old_cred = ovl_override_creds(dentry->d_sb); | ||
32 | err = vfs_getattr(&lowerpath, &stat); | ||
33 | if (!err) { | ||
34 | stat.size = 0; | ||
35 | err = ovl_copy_up_one(parent, dentry, &lowerpath, &stat); | ||
36 | } | ||
37 | revert_creds(old_cred); | ||
38 | |||
39 | out_dput_parent: | ||
40 | dput(parent); | ||
41 | return err; | ||
42 | } | ||
43 | |||
44 | int ovl_setattr(struct dentry *dentry, struct iattr *attr) | 16 | int ovl_setattr(struct dentry *dentry, struct iattr *attr) |
45 | { | 17 | { |
46 | int err; | 18 | int err; |
@@ -64,27 +36,10 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr) | |||
64 | if (err) | 36 | if (err) |
65 | goto out; | 37 | goto out; |
66 | 38 | ||
67 | if (attr->ia_valid & ATTR_SIZE) { | ||
68 | struct inode *realinode = d_inode(ovl_dentry_real(dentry)); | ||
69 | |||
70 | err = -ETXTBSY; | ||
71 | if (atomic_read(&realinode->i_writecount) < 0) | ||
72 | goto out_drop_write; | ||
73 | } | ||
74 | |||
75 | err = ovl_copy_up(dentry); | 39 | err = ovl_copy_up(dentry); |
76 | if (!err) { | 40 | if (!err) { |
77 | struct inode *winode = NULL; | ||
78 | |||
79 | upperdentry = ovl_dentry_upper(dentry); | 41 | upperdentry = ovl_dentry_upper(dentry); |
80 | 42 | ||
81 | if (attr->ia_valid & ATTR_SIZE) { | ||
82 | winode = d_inode(upperdentry); | ||
83 | err = get_write_access(winode); | ||
84 | if (err) | ||
85 | goto out_drop_write; | ||
86 | } | ||
87 | |||
88 | if (attr->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) | 43 | if (attr->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) |
89 | attr->ia_valid &= ~ATTR_MODE; | 44 | attr->ia_valid &= ~ATTR_MODE; |
90 | 45 | ||
@@ -95,11 +50,7 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr) | |||
95 | if (!err) | 50 | if (!err) |
96 | ovl_copyattr(upperdentry->d_inode, dentry->d_inode); | 51 | ovl_copyattr(upperdentry->d_inode, dentry->d_inode); |
97 | inode_unlock(upperdentry->d_inode); | 52 | inode_unlock(upperdentry->d_inode); |
98 | |||
99 | if (winode) | ||
100 | put_write_access(winode); | ||
101 | } | 53 | } |
102 | out_drop_write: | ||
103 | ovl_drop_write(dentry); | 54 | ovl_drop_write(dentry); |
104 | out: | 55 | out: |
105 | return err; | 56 | return err; |
@@ -302,10 +253,7 @@ int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags) | |||
302 | if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) { | 253 | if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) { |
303 | err = ovl_want_write(dentry); | 254 | err = ovl_want_write(dentry); |
304 | if (!err) { | 255 | if (!err) { |
305 | if (file_flags & O_TRUNC) | 256 | err = ovl_copy_up_flags(dentry, file_flags); |
306 | err = ovl_copy_up_truncate(dentry); | ||
307 | else | ||
308 | err = ovl_copy_up(dentry); | ||
309 | ovl_drop_write(dentry); | 257 | ovl_drop_write(dentry); |
310 | } | 258 | } |
311 | } | 259 | } |
@@ -354,7 +302,7 @@ static const struct inode_operations ovl_symlink_inode_operations = { | |||
354 | .update_time = ovl_update_time, | 302 | .update_time = ovl_update_time, |
355 | }; | 303 | }; |
356 | 304 | ||
357 | static void ovl_fill_inode(struct inode *inode, umode_t mode) | 305 | static void ovl_fill_inode(struct inode *inode, umode_t mode, dev_t rdev) |
358 | { | 306 | { |
359 | inode->i_ino = get_next_ino(); | 307 | inode->i_ino = get_next_ino(); |
360 | inode->i_mode = mode; | 308 | inode->i_mode = mode; |
@@ -363,8 +311,11 @@ static void ovl_fill_inode(struct inode *inode, umode_t mode) | |||
363 | inode->i_acl = inode->i_default_acl = ACL_DONT_CACHE; | 311 | inode->i_acl = inode->i_default_acl = ACL_DONT_CACHE; |
364 | #endif | 312 | #endif |
365 | 313 | ||
366 | mode &= S_IFMT; | 314 | switch (mode & S_IFMT) { |
367 | switch (mode) { | 315 | case S_IFREG: |
316 | inode->i_op = &ovl_file_inode_operations; | ||
317 | break; | ||
318 | |||
368 | case S_IFDIR: | 319 | case S_IFDIR: |
369 | inode->i_op = &ovl_dir_inode_operations; | 320 | inode->i_op = &ovl_dir_inode_operations; |
370 | inode->i_fop = &ovl_dir_operations; | 321 | inode->i_fop = &ovl_dir_operations; |
@@ -375,26 +326,19 @@ static void ovl_fill_inode(struct inode *inode, umode_t mode) | |||
375 | break; | 326 | break; |
376 | 327 | ||
377 | default: | 328 | default: |
378 | WARN(1, "illegal file type: %i\n", mode); | ||
379 | /* Fall through */ | ||
380 | |||
381 | case S_IFREG: | ||
382 | case S_IFSOCK: | ||
383 | case S_IFBLK: | ||
384 | case S_IFCHR: | ||
385 | case S_IFIFO: | ||
386 | inode->i_op = &ovl_file_inode_operations; | 329 | inode->i_op = &ovl_file_inode_operations; |
330 | init_special_inode(inode, mode, rdev); | ||
387 | break; | 331 | break; |
388 | } | 332 | } |
389 | } | 333 | } |
390 | 334 | ||
391 | struct inode *ovl_new_inode(struct super_block *sb, umode_t mode) | 335 | struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, dev_t rdev) |
392 | { | 336 | { |
393 | struct inode *inode; | 337 | struct inode *inode; |
394 | 338 | ||
395 | inode = new_inode(sb); | 339 | inode = new_inode(sb); |
396 | if (inode) | 340 | if (inode) |
397 | ovl_fill_inode(inode, mode); | 341 | ovl_fill_inode(inode, mode, rdev); |
398 | 342 | ||
399 | return inode; | 343 | return inode; |
400 | } | 344 | } |
@@ -418,7 +362,7 @@ struct inode *ovl_get_inode(struct super_block *sb, struct inode *realinode) | |||
418 | inode = iget5_locked(sb, (unsigned long) realinode, | 362 | inode = iget5_locked(sb, (unsigned long) realinode, |
419 | ovl_inode_test, ovl_inode_set, realinode); | 363 | ovl_inode_test, ovl_inode_set, realinode); |
420 | if (inode && inode->i_state & I_NEW) { | 364 | if (inode && inode->i_state & I_NEW) { |
421 | ovl_fill_inode(inode, realinode->i_mode); | 365 | ovl_fill_inode(inode, realinode->i_mode, realinode->i_rdev); |
422 | set_nlink(inode, realinode->i_nlink); | 366 | set_nlink(inode, realinode->i_nlink); |
423 | unlock_new_inode(inode); | 367 | unlock_new_inode(inode); |
424 | } | 368 | } |