diff options
author | Amir Goldstein <amir73il@gmail.com> | 2017-06-21 15:28:32 +0300 |
---|---|---|
committer | Miklos Szeredi <mszeredi@redhat.com> | 2017-07-04 22:03:16 +0200 |
commit | ad0af7104dadccd55cd2b390271677fac142650f (patch) | |
tree | 1e377c42709b12efc4e01507143ebba09f389bc7 /fs/overlayfs | |
parent | 04a01ac7ed3c5cd718713ef6341249a143c96b10 (diff) | |
download | linux-stable-ad0af7104dadccd55cd2b390271677fac142650f.tar.gz linux-stable-ad0af7104dadccd55cd2b390271677fac142650f.tar.bz2 linux-stable-ad0af7104dadccd55cd2b390271677fac142650f.zip |
vfs: introduce inode 'inuse' lock
Added an i_state flag I_INUSE and helpers to set/clear/test the bit.
The 'inuse' lock is an 'advisory' inode lock, that can be used to extend
exclusive create protection beyond parent->i_mutex lock among cooperating
users.
This is going to be used by overlayfs to get exclusive ownership on upper
and work dirs among overlayfs mounts.
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/overlayfs')
-rw-r--r-- | fs/overlayfs/overlayfs.h | 2 | ||||
-rw-r--r-- | fs/overlayfs/util.c | 31 |
2 files changed, 33 insertions, 0 deletions
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index b1be3d39ac9d..5e958427463d 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -220,6 +220,8 @@ int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry, int ovl_set_impure(struct dentry *dentry, struct dentry *upperdentry); void ovl_set_flag(unsigned long flag, struct inode *inode); bool ovl_test_flag(unsigned long flag, struct inode *inode); +bool ovl_inuse_trylock(struct dentry *dentry); +void ovl_inuse_unlock(struct dentry *dentry); static inline bool ovl_is_impuredir(struct dentry *dentry) { diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index f093fcf2b4bd..adccd74162d6 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -347,3 +347,34 @@ bool ovl_test_flag(unsigned long flag, struct inode *inode) { return test_bit(flag, &OVL_I(inode)->flags); } + +/** + * Caller must hold a reference to inode to prevent it from being freed while + * it is marked inuse. + */ +bool ovl_inuse_trylock(struct dentry *dentry) +{ + struct inode *inode = d_inode(dentry); + bool locked = false; + + spin_lock(&inode->i_lock); + if (!(inode->i_state & I_OVL_INUSE)) { + inode->i_state |= I_OVL_INUSE; + locked = true; + } + spin_unlock(&inode->i_lock); + + return locked; +} + +void ovl_inuse_unlock(struct dentry *dentry) +{ + if (dentry) { + struct inode *inode = d_inode(dentry); + + spin_lock(&inode->i_lock); + WARN_ON(!(inode->i_state & I_OVL_INUSE)); + inode->i_state &= ~I_OVL_INUSE; + spin_unlock(&inode->i_lock); + } +} |