Merge branch 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull misc vfs updates from Al Viro: "Assorted patches from previous cycle(s)..." * 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: fix hostfs_open() use of ->f_path.dentry Make sure that make_create_in_sticky() never sees uninitialized value of dir_mode fs: Kill DCACHE_DONTCACHE dentry even if DCACHE_REFERENCED is set fs: Handle I_DONTCACHE in iput_final() instead of generic_drop_inode() fs/namespace.c: WARN if mnt_count has become negative
This commit is contained in:
Коммит
7bb5226c8a
|
@ -793,10 +793,17 @@ static inline bool fast_dput(struct dentry *dentry)
|
|||
* a reference to the dentry and change that, but
|
||||
* our work is done - we can leave the dentry
|
||||
* around with a zero refcount.
|
||||
*
|
||||
* Nevertheless, there are two cases that we should kill
|
||||
* the dentry anyway.
|
||||
* 1. free disconnected dentries as soon as their refcount
|
||||
* reached zero.
|
||||
* 2. free dentries if they should not be cached.
|
||||
*/
|
||||
smp_rmb();
|
||||
d_flags = READ_ONCE(dentry->d_flags);
|
||||
d_flags &= DCACHE_REFERENCED | DCACHE_LRU_LIST | DCACHE_DISCONNECTED;
|
||||
d_flags &= DCACHE_REFERENCED | DCACHE_LRU_LIST |
|
||||
DCACHE_DISCONNECTED | DCACHE_DONTCACHE;
|
||||
|
||||
/* Nothing to do? Dropping the reference was all we needed? */
|
||||
if (d_flags == (DCACHE_REFERENCED | DCACHE_LRU_LIST) && !d_unhashed(dentry))
|
||||
|
|
|
@ -315,7 +315,7 @@ retry:
|
|||
if (mode & FMODE_WRITE)
|
||||
r = w = 1;
|
||||
|
||||
name = dentry_name(file->f_path.dentry);
|
||||
name = dentry_name(d_real(file->f_path.dentry, file->f_inode));
|
||||
if (name == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
@ -1624,7 +1624,9 @@ static void iput_final(struct inode *inode)
|
|||
else
|
||||
drop = generic_drop_inode(inode);
|
||||
|
||||
if (!drop && (sb->s_flags & SB_ACTIVE)) {
|
||||
if (!drop &&
|
||||
!(inode->i_state & I_DONTCACHE) &&
|
||||
(sb->s_flags & SB_ACTIVE)) {
|
||||
inode_add_lru(inode);
|
||||
spin_unlock(&inode->i_lock);
|
||||
return;
|
||||
|
|
|
@ -2114,8 +2114,10 @@ static int link_path_walk(const char *name, struct nameidata *nd)
|
|||
return PTR_ERR(name);
|
||||
while (*name=='/')
|
||||
name++;
|
||||
if (!*name)
|
||||
if (!*name) {
|
||||
nd->dir_mode = 0; // short-circuit the 'hardening' idiocy
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* At this point we know we have a real path component. */
|
||||
for(;;) {
|
||||
|
|
|
@ -156,10 +156,10 @@ static inline void mnt_add_count(struct mount *mnt, int n)
|
|||
/*
|
||||
* vfsmount lock must be held for write
|
||||
*/
|
||||
unsigned int mnt_get_count(struct mount *mnt)
|
||||
int mnt_get_count(struct mount *mnt)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
unsigned int count = 0;
|
||||
int count = 0;
|
||||
int cpu;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
|
@ -1139,6 +1139,7 @@ static DECLARE_DELAYED_WORK(delayed_mntput_work, delayed_mntput);
|
|||
static void mntput_no_expire(struct mount *mnt)
|
||||
{
|
||||
LIST_HEAD(list);
|
||||
int count;
|
||||
|
||||
rcu_read_lock();
|
||||
if (likely(READ_ONCE(mnt->mnt_ns))) {
|
||||
|
@ -1162,7 +1163,9 @@ static void mntput_no_expire(struct mount *mnt)
|
|||
*/
|
||||
smp_mb();
|
||||
mnt_add_count(mnt, -1);
|
||||
if (mnt_get_count(mnt)) {
|
||||
count = mnt_get_count(mnt);
|
||||
if (count != 0) {
|
||||
WARN_ON(count < 0);
|
||||
rcu_read_unlock();
|
||||
unlock_mount_hash();
|
||||
return;
|
||||
|
|
|
@ -44,7 +44,7 @@ int propagate_mount_busy(struct mount *, int);
|
|||
void propagate_mount_unlock(struct mount *);
|
||||
void mnt_release_group_id(struct mount *);
|
||||
int get_dominating_id(struct mount *mnt, const struct path *root);
|
||||
unsigned int mnt_get_count(struct mount *mnt);
|
||||
int mnt_get_count(struct mount *mnt);
|
||||
void mnt_set_mountpoint(struct mount *, struct mountpoint *,
|
||||
struct mount *);
|
||||
void mnt_change_mountpoint(struct mount *parent, struct mountpoint *mp,
|
||||
|
|
|
@ -2876,8 +2876,7 @@ extern int inode_needs_sync(struct inode *inode);
|
|||
extern int generic_delete_inode(struct inode *inode);
|
||||
static inline int generic_drop_inode(struct inode *inode)
|
||||
{
|
||||
return !inode->i_nlink || inode_unhashed(inode) ||
|
||||
(inode->i_state & I_DONTCACHE);
|
||||
return !inode->i_nlink || inode_unhashed(inode);
|
||||
}
|
||||
extern void d_mark_dontcache(struct inode *inode);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче