mirror of
https://github.com/torvalds/linux
synced 2024-07-23 03:29:48 +00:00
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:
commit
7bb5226c8a
|
@ -793,10 +793,17 @@ static inline bool fast_dput(struct dentry *dentry)
|
||||||
* a reference to the dentry and change that, but
|
* a reference to the dentry and change that, but
|
||||||
* our work is done - we can leave the dentry
|
* our work is done - we can leave the dentry
|
||||||
* around with a zero refcount.
|
* 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();
|
smp_rmb();
|
||||||
d_flags = READ_ONCE(dentry->d_flags);
|
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? */
|
/* Nothing to do? Dropping the reference was all we needed? */
|
||||||
if (d_flags == (DCACHE_REFERENCED | DCACHE_LRU_LIST) && !d_unhashed(dentry))
|
if (d_flags == (DCACHE_REFERENCED | DCACHE_LRU_LIST) && !d_unhashed(dentry))
|
||||||
|
|
|
@ -315,7 +315,7 @@ static int hostfs_open(struct inode *ino, struct file *file)
|
||||||
if (mode & FMODE_WRITE)
|
if (mode & FMODE_WRITE)
|
||||||
r = w = 1;
|
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)
|
if (name == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
|
|
@ -1624,7 +1624,9 @@ static void iput_final(struct inode *inode)
|
||||||
else
|
else
|
||||||
drop = generic_drop_inode(inode);
|
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);
|
inode_add_lru(inode);
|
||||||
spin_unlock(&inode->i_lock);
|
spin_unlock(&inode->i_lock);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -2114,8 +2114,10 @@ static int link_path_walk(const char *name, struct nameidata *nd)
|
||||||
return PTR_ERR(name);
|
return PTR_ERR(name);
|
||||||
while (*name=='/')
|
while (*name=='/')
|
||||||
name++;
|
name++;
|
||||||
if (!*name)
|
if (!*name) {
|
||||||
|
nd->dir_mode = 0; // short-circuit the 'hardening' idiocy
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* At this point we know we have a real path component. */
|
/* At this point we know we have a real path component. */
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
|
|
@ -156,10 +156,10 @@ static inline void mnt_add_count(struct mount *mnt, int n)
|
||||||
/*
|
/*
|
||||||
* vfsmount lock must be held for write
|
* 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
|
#ifdef CONFIG_SMP
|
||||||
unsigned int count = 0;
|
int count = 0;
|
||||||
int cpu;
|
int cpu;
|
||||||
|
|
||||||
for_each_possible_cpu(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)
|
static void mntput_no_expire(struct mount *mnt)
|
||||||
{
|
{
|
||||||
LIST_HEAD(list);
|
LIST_HEAD(list);
|
||||||
|
int count;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
if (likely(READ_ONCE(mnt->mnt_ns))) {
|
if (likely(READ_ONCE(mnt->mnt_ns))) {
|
||||||
|
@ -1162,7 +1163,9 @@ static void mntput_no_expire(struct mount *mnt)
|
||||||
*/
|
*/
|
||||||
smp_mb();
|
smp_mb();
|
||||||
mnt_add_count(mnt, -1);
|
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();
|
rcu_read_unlock();
|
||||||
unlock_mount_hash();
|
unlock_mount_hash();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -44,7 +44,7 @@ int propagate_mount_busy(struct mount *, int);
|
||||||
void propagate_mount_unlock(struct mount *);
|
void propagate_mount_unlock(struct mount *);
|
||||||
void mnt_release_group_id(struct mount *);
|
void mnt_release_group_id(struct mount *);
|
||||||
int get_dominating_id(struct mount *mnt, const struct path *root);
|
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 *,
|
void mnt_set_mountpoint(struct mount *, struct mountpoint *,
|
||||||
struct mount *);
|
struct mount *);
|
||||||
void mnt_change_mountpoint(struct mount *parent, struct mountpoint *mp,
|
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);
|
extern int generic_delete_inode(struct inode *inode);
|
||||||
static inline int generic_drop_inode(struct inode *inode)
|
static inline int generic_drop_inode(struct inode *inode)
|
||||||
{
|
{
|
||||||
return !inode->i_nlink || inode_unhashed(inode) ||
|
return !inode->i_nlink || inode_unhashed(inode);
|
||||||
(inode->i_state & I_DONTCACHE);
|
|
||||||
}
|
}
|
||||||
extern void d_mark_dontcache(struct inode *inode);
|
extern void d_mark_dontcache(struct inode *inode);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue