aboutsummaryrefslogtreecommitdiffstats
path: root/fs/overlayfs/inode.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-12-16 10:58:12 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2016-12-16 10:58:12 -0800
commitff0f962ca3c38239b299a70e7eea27abfbb979c3 (patch)
treeab37876cf2e8af4900f11f44ac4b96cb0f15e548 /fs/overlayfs/inode.c
parentMerge branch 'for-linus-4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs (diff)
parentovl: fix reStructuredText syntax errors in documentation (diff)
downloadlinux-dev-ff0f962ca3c38239b299a70e7eea27abfbb979c3.tar.xz
linux-dev-ff0f962ca3c38239b299a70e7eea27abfbb979c3.zip
Merge branch 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs
Pull overlayfs updates from Miklos Szeredi: "This update contains: - try to clone on copy-up - allow renaming a directory - split source into managable chunks - misc cleanups and fixes It does not contain the read-only fd data inconsistency fix, which Al didn't like. I'll leave that to the next year..." * 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs: (36 commits) ovl: fix reStructuredText syntax errors in documentation ovl: fix return value of ovl_fill_super ovl: clean up kstat usage ovl: fold ovl_copy_up_truncate() into ovl_copy_up() ovl: create directories inside merged parent opaque ovl: opaque cleanup ovl: show redirect_dir mount option ovl: allow setting max size of redirect ovl: allow redirect_dir to default to "on" ovl: check for emptiness of redirect dir ovl: redirect on rename-dir ovl: lookup redirects ovl: consolidate lookup for underlying layers ovl: fix nested overlayfs mount ovl: check namelen ovl: split super.c ovl: use d_is_dir() ovl: simplify lookup ovl: check lower existence of rename target ovl: rename: simplify handling of lower/merged directory ...
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 @@
#include <linux/posix_acl.h>
#include "overlayfs.h"
-static int ovl_copy_up_truncate(struct dentry *dentry)
-{
- int err;
- struct dentry *parent;
- struct kstat stat;
- struct path lowerpath;
- const struct cred *old_cred;
-
- parent = dget_parent(dentry);
- err = ovl_copy_up(parent);
- if (err)
- goto out_dput_parent;
-
- ovl_path_lower(dentry, &lowerpath);
-
- old_cred = ovl_override_creds(dentry->d_sb);
- err = vfs_getattr(&lowerpath, &stat);
- if (!err) {
- stat.size = 0;
- err = ovl_copy_up_one(parent, dentry, &lowerpath, &stat);
- }
- revert_creds(old_cred);
-
-out_dput_parent:
- dput(parent);
- return err;
-}
-
int ovl_setattr(struct dentry *dentry, struct iattr *attr)
{
int err;
@@ -64,27 +36,10 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
if (err)
goto out;
- if (attr->ia_valid & ATTR_SIZE) {
- struct inode *realinode = d_inode(ovl_dentry_real(dentry));
-
- err = -ETXTBSY;
- if (atomic_read(&realinode->i_writecount) < 0)
- goto out_drop_write;
- }
-
err = ovl_copy_up(dentry);
if (!err) {
- struct inode *winode = NULL;
-
upperdentry = ovl_dentry_upper(dentry);
- if (attr->ia_valid & ATTR_SIZE) {
- winode = d_inode(upperdentry);
- err = get_write_access(winode);
- if (err)
- goto out_drop_write;
- }
-
if (attr->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
attr->ia_valid &= ~ATTR_MODE;
@@ -95,11 +50,7 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
if (!err)
ovl_copyattr(upperdentry->d_inode, dentry->d_inode);
inode_unlock(upperdentry->d_inode);
-
- if (winode)
- put_write_access(winode);
}
-out_drop_write:
ovl_drop_write(dentry);
out:
return err;
@@ -302,10 +253,7 @@ int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags)
if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) {
err = ovl_want_write(dentry);
if (!err) {
- if (file_flags & O_TRUNC)
- err = ovl_copy_up_truncate(dentry);
- else
- err = ovl_copy_up(dentry);
+ err = ovl_copy_up_flags(dentry, file_flags);
ovl_drop_write(dentry);
}
}
@@ -354,7 +302,7 @@ static const struct inode_operations ovl_symlink_inode_operations = {
.update_time = ovl_update_time,
};
-static void ovl_fill_inode(struct inode *inode, umode_t mode)
+static void ovl_fill_inode(struct inode *inode, umode_t mode, dev_t rdev)
{
inode->i_ino = get_next_ino();
inode->i_mode = mode;
@@ -363,8 +311,11 @@ static void ovl_fill_inode(struct inode *inode, umode_t mode)
inode->i_acl = inode->i_default_acl = ACL_DONT_CACHE;
#endif
- mode &= S_IFMT;
- switch (mode) {
+ switch (mode & S_IFMT) {
+ case S_IFREG:
+ inode->i_op = &ovl_file_inode_operations;
+ break;
+
case S_IFDIR:
inode->i_op = &ovl_dir_inode_operations;
inode->i_fop = &ovl_dir_operations;
@@ -375,26 +326,19 @@ static void ovl_fill_inode(struct inode *inode, umode_t mode)
break;
default:
- WARN(1, "illegal file type: %i\n", mode);
- /* Fall through */
-
- case S_IFREG:
- case S_IFSOCK:
- case S_IFBLK:
- case S_IFCHR:
- case S_IFIFO:
inode->i_op = &ovl_file_inode_operations;
+ init_special_inode(inode, mode, rdev);
break;
}
}
-struct inode *ovl_new_inode(struct super_block *sb, umode_t mode)
+struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, dev_t rdev)
{
struct inode *inode;
inode = new_inode(sb);
if (inode)
- ovl_fill_inode(inode, mode);
+ ovl_fill_inode(inode, mode, rdev);
return inode;
}
@@ -418,7 +362,7 @@ struct inode *ovl_get_inode(struct super_block *sb, struct inode *realinode)
inode = iget5_locked(sb, (unsigned long) realinode,
ovl_inode_test, ovl_inode_set, realinode);
if (inode && inode->i_state & I_NEW) {
- ovl_fill_inode(inode, realinode->i_mode);
+ ovl_fill_inode(inode, realinode->i_mode, realinode->i_rdev);
set_nlink(inode, realinode->i_nlink);
unlock_new_inode(inode);
}