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:
Linus Torvalds 2020-12-25 10:54:29 -08:00
Родитель 71c5f03154 2e2cbaf920
Коммит 7bb5226c8a
7 изменённых файлов: 23 добавлений и 10 удалений

Просмотреть файл

@ -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);