diff options
author | Alex Shi <alex.shi@linaro.org> | 2016-04-11 11:16:39 +0800 |
---|---|---|
committer | Alex Shi <alex.shi@linaro.org> | 2016-04-11 11:16:39 +0800 |
commit | d83731cf53fd3af7173cab5e3f573d06ebc852be (patch) | |
tree | d61002ed1d894fe2d9b26003a1230f05a61ed51b /fs/overlayfs | |
parent | bfbd381ea0ca274e4c07ea62acaaeac31829cd5d (diff) | |
parent | 017cfa86c2450b158d7d0336f2f3ea685da1230b (diff) |
Merge branch 'linux-linaro-lsk-v4.1' into linux-linaro-lsk-v4.1-rtlsk-v4.1-16.04-rt
Diffstat (limited to 'fs/overlayfs')
-rw-r--r-- | fs/overlayfs/dir.c | 10 | ||||
-rw-r--r-- | fs/overlayfs/inode.c | 2 | ||||
-rw-r--r-- | fs/overlayfs/super.c | 12 |
3 files changed, 18 insertions, 6 deletions
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index 692ceda3bc21..a2b1d7ce3e1a 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -618,7 +618,8 @@ static int ovl_remove_upper(struct dentry *dentry, bool is_dir) * sole user of this dentry. Too tricky... Just unhash for * now. */ - d_drop(dentry); + if (!err) + d_drop(dentry); mutex_unlock(&dir->i_mutex); return err; @@ -903,6 +904,13 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old, if (!overwrite && new_is_dir && !old_opaque && new_opaque) ovl_remove_opaque(newdentry); + /* + * Old dentry now lives in different location. Dentries in + * lowerstack are stale. We cannot drop them here because + * access to them is lockless. This could be only pure upper + * or opaque directory - numlower is zero. Or upper non-dir + * entry - its pureness is tracked by flag opaque. + */ if (old_opaque != new_opaque) { ovl_dentry_set_opaque(old, new_opaque); if (!overwrite) diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index a1b069e5e363..e505b44a9184 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -66,6 +66,8 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr) if (upperdentry) { mutex_lock(&upperdentry->d_inode->i_mutex); err = notify_change(upperdentry, attr, NULL); + if (!err) + ovl_copyattr(upperdentry->d_inode, dentry->d_inode); mutex_unlock(&upperdentry->d_inode->i_mutex); } else { err = ovl_copy_up_last(dentry, attr, false); diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index bd6d5c1e667d..39266655d2bd 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -76,12 +76,14 @@ enum ovl_path_type ovl_path_type(struct dentry *dentry) if (oe->__upperdentry) { type = __OVL_PATH_UPPER; - if (oe->numlower) { - if (S_ISDIR(dentry->d_inode->i_mode)) - type |= __OVL_PATH_MERGE; - } else if (!oe->opaque) { + /* + * Non-dir dentry can hold lower dentry from previous + * location. Its purity depends only on opaque flag. + */ + if (oe->numlower && S_ISDIR(dentry->d_inode->i_mode)) + type |= __OVL_PATH_MERGE; + else if (!oe->opaque) type |= __OVL_PATH_PURE; - } } else { if (oe->numlower > 1) type |= __OVL_PATH_MERGE; |