summaryrefslogtreecommitdiffstats
path: root/fs/overlayfs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/overlayfs/inode.c')
-rw-r--r--fs/overlayfs/inode.c78
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
16static 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
39out_dput_parent:
40 dput(parent);
41 return err;
42}
43
44int ovl_setattr(struct dentry *dentry, struct iattr *attr) 16int 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 }
102out_drop_write:
103 ovl_drop_write(dentry); 54 ovl_drop_write(dentry);
104out: 55out:
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
357static void ovl_fill_inode(struct inode *inode, umode_t mode) 305static 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
391struct inode *ovl_new_inode(struct super_block *sb, umode_t mode) 335struct 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 }