Skip to content

Commit

Permalink
Merge branch 'for-linus-2' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/git/viro/vfs

Pull more vfs updates from Al Viro:
 "Assorted cleanups and fixes.

  In the "trivial API change" department - ->d_compare() losing 'parent'
  argument"

* 'for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  cachefiles: Fix race between inactivating and culling a cache object
  9p: use clone_fid()
  9p: fix braino introduced in "9p: new helper - v9fs_parent_fid()"
  vfs: make dentry_needs_remove_privs() internal
  vfs: remove file_needs_remove_privs()
  vfs: fix deadlock in file_remove_privs() on overlayfs
  get rid of 'parent' argument of ->d_compare()
  cifs, msdos, vfat, hfs+: don't bother with parent in ->d_compare()
  affs ->d_compare(): don't bother with ->d_inode
  fold _d_rehash() and __d_rehash() together
  fold dentry_rcuwalk_invalidate() into its only remaining caller
  • Loading branch information
torvalds committed Aug 7, 2016
2 parents 0cbbc42 + db20a89 commit fe64f32
Show file tree
Hide file tree
Showing 32 changed files with 82 additions and 130 deletions.
2 changes: 1 addition & 1 deletion Documentation/filesystems/Locking
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ prototypes:
int (*d_revalidate)(struct dentry *, unsigned int);
int (*d_weak_revalidate)(struct dentry *, unsigned int);
int (*d_hash)(const struct dentry *, struct qstr *);
int (*d_compare)(const struct dentry *, const struct dentry *,
int (*d_compare)(const struct dentry *,
unsigned int, const char *, const struct qstr *);
int (*d_delete)(struct dentry *);
int (*d_init)(struct dentry *);
Expand Down
7 changes: 7 additions & 0 deletions Documentation/filesystems/porting
Original file line number Diff line number Diff line change
Expand Up @@ -585,3 +585,10 @@ in your dentry operations instead.
in the instances. Rationale: !@#!@# security_d_instantiate() needs to be
called before we attach dentry to inode and !@#!@##!@$!$#!@#$!@$!@$ smack
->d_instantiate() uses not just ->getxattr() but ->setxattr() as well.
--
[mandatory]
->d_compare() doesn't get parent as a separate argument anymore. If you
used it for finding the struct super_block involved, dentry->d_sb will
work just as well; if it's something more complicated, use dentry->d_parent.
Just be careful not to assume that fetching it more than once will yield
the same value - in RCU mode it could change under you.
2 changes: 1 addition & 1 deletion Documentation/filesystems/vfs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -931,7 +931,7 @@ struct dentry_operations {
int (*d_revalidate)(struct dentry *, unsigned int);
int (*d_weak_revalidate)(struct dentry *, unsigned int);
int (*d_hash)(const struct dentry *, struct qstr *);
int (*d_compare)(const struct dentry *, const struct dentry *,
int (*d_compare)(const struct dentry *,
unsigned int, const char *, const struct qstr *);
int (*d_delete)(const struct dentry *);
int (*d_init)(struct dentry *);
Expand Down
2 changes: 1 addition & 1 deletion drivers/staging/lustre/lustre/llite/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ static void ll_release(struct dentry *de)
* INVALID) so d_lookup() matches it, but we have no lock on it (so
* lock_match() fails) and we spin around real_lookup().
*/
static int ll_dcompare(const struct dentry *parent, const struct dentry *dentry,
static int ll_dcompare(const struct dentry *dentry,
unsigned int len, const char *str,
const struct qstr *name)
{
Expand Down
26 changes: 1 addition & 25 deletions fs/9p/fid.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,36 +257,12 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
return v9fs_fid_lookup_with_uid(dentry, uid, any);
}

struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
{
struct p9_fid *fid, *ret;

fid = v9fs_fid_lookup(dentry);
if (IS_ERR(fid))
return fid;

ret = p9_client_walk(fid, 0, NULL, 1);
return ret;
}

static struct p9_fid *v9fs_fid_clone_with_uid(struct dentry *dentry, kuid_t uid)
{
struct p9_fid *fid, *ret;

fid = v9fs_fid_lookup_with_uid(dentry, uid, 0);
if (IS_ERR(fid))
return fid;

ret = p9_client_walk(fid, 0, NULL, 1);
return ret;
}

struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
{
int err;
struct p9_fid *fid;

fid = v9fs_fid_clone_with_uid(dentry, GLOBAL_ROOT_UID);
fid = clone_fid(v9fs_fid_lookup_with_uid(dentry, GLOBAL_ROOT_UID, 0));
if (IS_ERR(fid))
goto error_out;
/*
Expand Down
9 changes: 8 additions & 1 deletion fs/9p/fid.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,14 @@ static inline struct p9_fid *v9fs_parent_fid(struct dentry *dentry)
{
return v9fs_fid_lookup(dentry->d_parent);
}
struct p9_fid *v9fs_fid_clone(struct dentry *dentry);
void v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid);
struct p9_fid *v9fs_writeback_fid(struct dentry *dentry);
static inline struct p9_fid *clone_fid(struct p9_fid *fid)
{
return IS_ERR(fid) ? fid : p9_client_walk(fid, 0, NULL, 1);
}
static inline struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
{
return clone_fid(v9fs_fid_lookup(dentry));
}
#endif
6 changes: 3 additions & 3 deletions fs/9p/vfs_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
}

/* clone a fid to use for creation */
ofid = p9_client_walk(dfid, 0, NULL, 1);
ofid = clone_fid(dfid);
if (IS_ERR(ofid)) {
err = PTR_ERR(ofid);
p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
Expand Down Expand Up @@ -975,13 +975,13 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (IS_ERR(oldfid))
return PTR_ERR(oldfid);

olddirfid = v9fs_parent_fid(old_dentry);
olddirfid = clone_fid(v9fs_parent_fid(old_dentry));
if (IS_ERR(olddirfid)) {
retval = PTR_ERR(olddirfid);
goto done;
}

newdirfid = v9fs_parent_fid(new_dentry);
newdirfid = clone_fid(v9fs_parent_fid(new_dentry));
if (IS_ERR(newdirfid)) {
retval = PTR_ERR(newdirfid);
goto clunk_olddir;
Expand Down
2 changes: 1 addition & 1 deletion fs/9p/vfs_inode_dotl.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
}

/* clone a fid to use for creation */
ofid = p9_client_walk(dfid, 0, NULL, 1);
ofid = clone_fid(dfid);
if (IS_ERR(ofid)) {
err = PTR_ERR(ofid);
p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
Expand Down
4 changes: 1 addition & 3 deletions fs/9p/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,6 @@ int v9fs_xattr_set(struct dentry *dentry, const char *name,
const void *value, size_t value_len, int flags)
{
struct p9_fid *fid = v9fs_fid_lookup(dentry);
if (IS_ERR(fid))
return PTR_ERR(fid);
return v9fs_fid_xattr_set(fid, name, value, value_len, flags);
}

Expand All @@ -115,7 +113,7 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name,
name, value_len, flags);

/* Clone it */
fid = p9_client_walk(fid, 0, NULL, 1);
fid = clone_fid(fid);
if (IS_ERR(fid))
return PTR_ERR(fid);

Expand Down
2 changes: 1 addition & 1 deletion fs/adfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ adfs_hash(const struct dentry *parent, struct qstr *qstr)
* requirements of the underlying filesystem.
*/
static int
adfs_compare(const struct dentry *parent, const struct dentry *dentry,
adfs_compare(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
int i;
Expand Down
4 changes: 1 addition & 3 deletions fs/affs/amigaffs.c
Original file line number Diff line number Diff line change
Expand Up @@ -472,9 +472,7 @@ affs_warning(struct super_block *sb, const char *function, const char *fmt, ...)
bool
affs_nofilenametruncate(const struct dentry *dentry)
{
struct inode *inode = d_inode(dentry);

return affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_NO_TRUNCATE);
return affs_test_opt(AFFS_SB(dentry->d_sb)->s_flags, SF_NO_TRUNCATE);
}

/* Check if the name is valid for a affs object. */
Expand Down
12 changes: 6 additions & 6 deletions fs/affs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ typedef int (*toupper_t)(int);

static int affs_toupper(int ch);
static int affs_hash_dentry(const struct dentry *, struct qstr *);
static int affs_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
static int affs_compare_dentry(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name);
static int affs_intl_toupper(int ch);
static int affs_intl_hash_dentry(const struct dentry *, struct qstr *);
static int affs_intl_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
static int affs_intl_compare_dentry(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name);

const struct dentry_operations affs_dentry_operations = {
Expand Down Expand Up @@ -131,20 +131,20 @@ static inline int __affs_compare_dentry(unsigned int len,
}

static int
affs_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
affs_compare_dentry(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{

return __affs_compare_dentry(len, str, name, affs_toupper,
affs_nofilenametruncate(parent));
affs_nofilenametruncate(dentry));
}

static int
affs_intl_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
affs_intl_compare_dentry(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
return __affs_compare_dentry(len, str, name, affs_intl_toupper,
affs_nofilenametruncate(parent));
affs_nofilenametruncate(dentry));

}

Expand Down
5 changes: 3 additions & 2 deletions fs/cachefiles/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,8 @@ static int cachefiles_mark_object_active(struct cachefiles_cache *cache,
void cachefiles_mark_object_inactive(struct cachefiles_cache *cache,
struct cachefiles_object *object)
{
blkcnt_t i_blocks = d_backing_inode(object->dentry)->i_blocks;

write_lock(&cache->active_lock);
rb_erase(&object->active_node, &cache->active_nodes);
clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags);
Expand All @@ -273,8 +275,7 @@ void cachefiles_mark_object_inactive(struct cachefiles_cache *cache,
/* This object can now be culled, so we need to let the daemon know
* that there is something it can remove if it needs to.
*/
atomic_long_add(d_backing_inode(object->dentry)->i_blocks,
&cache->b_released);
atomic_long_add(i_blocks, &cache->b_released);
if (atomic_inc_return(&cache->f_released))
cachefiles_state_changed(cache);
}
Expand Down
4 changes: 2 additions & 2 deletions fs/cifs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -903,10 +903,10 @@ static int cifs_ci_hash(const struct dentry *dentry, struct qstr *q)
return 0;
}

static int cifs_ci_compare(const struct dentry *parent, const struct dentry *dentry,
static int cifs_ci_compare(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
struct nls_table *codepage = CIFS_SB(parent->d_sb)->local_nls;
struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls;
wchar_t c1, c2;
int i, l1, l2;

Expand Down
55 changes: 15 additions & 40 deletions fs/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,20 +316,6 @@ static void dentry_free(struct dentry *dentry)
call_rcu(&dentry->d_u.d_rcu, __d_free);
}

/**
* dentry_rcuwalk_invalidate - invalidate in-progress rcu-walk lookups
* @dentry: the target dentry
* After this call, in-progress rcu-walk path lookup will fail. This
* should be called after unhashing, and after changing d_inode (if
* the dentry has not already been unhashed).
*/
static inline void dentry_rcuwalk_invalidate(struct dentry *dentry)
{
lockdep_assert_held(&dentry->d_lock);
/* Go through am invalidation barrier */
write_seqcount_invalidate(&dentry->d_seq);
}

/*
* Release the dentry's inode, using the filesystem
* d_iput() operation if defined.
Expand Down Expand Up @@ -468,7 +454,8 @@ void __d_drop(struct dentry *dentry)
__hlist_bl_del(&dentry->d_hash);
dentry->d_hash.pprev = NULL;
hlist_bl_unlock(b);
dentry_rcuwalk_invalidate(dentry);
/* After this call, in-progress rcu-walk path lookup will fail. */
write_seqcount_invalidate(&dentry->d_seq);
}
}
EXPORT_SYMBOL(__d_drop);
Expand Down Expand Up @@ -2060,7 +2047,7 @@ static inline bool d_same_name(const struct dentry *dentry,
return false;
return dentry_cmp(dentry, name->name, name->len) == 0;
}
return parent->d_op->d_compare(parent, dentry,
return parent->d_op->d_compare(dentry,
dentry->d_name.len, dentry->d_name.name,
name) == 0;
}
Expand Down Expand Up @@ -2163,7 +2150,7 @@ struct dentry *__d_lookup_rcu(const struct dentry *parent,
cpu_relax();
goto seqretry;
}
if (parent->d_op->d_compare(parent, dentry,
if (parent->d_op->d_compare(dentry,
tlen, tname, name) != 0)
continue;
} else {
Expand Down Expand Up @@ -2352,19 +2339,15 @@ void d_delete(struct dentry * dentry)
}
EXPORT_SYMBOL(d_delete);

static void __d_rehash(struct dentry * entry, struct hlist_bl_head *b)
static void __d_rehash(struct dentry *entry)
{
struct hlist_bl_head *b = d_hash(entry->d_name.hash);
BUG_ON(!d_unhashed(entry));
hlist_bl_lock(b);
hlist_bl_add_head_rcu(&entry->d_hash, b);
hlist_bl_unlock(b);
}

static void _d_rehash(struct dentry * entry)
{
__d_rehash(entry, d_hash(entry->d_name.hash));
}

/**
* d_rehash - add an entry back to the hash
* @entry: dentry to add to the hash
Expand All @@ -2375,7 +2358,7 @@ static void _d_rehash(struct dentry * entry)
void d_rehash(struct dentry * entry)
{
spin_lock(&entry->d_lock);
_d_rehash(entry);
__d_rehash(entry);
spin_unlock(&entry->d_lock);
}
EXPORT_SYMBOL(d_rehash);
Expand Down Expand Up @@ -2549,7 +2532,7 @@ static inline void __d_add(struct dentry *dentry, struct inode *inode)
raw_write_seqcount_end(&dentry->d_seq);
fsnotify_update_flags(dentry);
}
_d_rehash(dentry);
__d_rehash(dentry);
if (dir)
end_dir_add(dir, n);
spin_unlock(&dentry->d_lock);
Expand Down Expand Up @@ -2611,7 +2594,7 @@ struct dentry *d_exact_alias(struct dentry *entry, struct inode *inode)
alias = NULL;
} else {
__dget_dlock(alias);
_d_rehash(alias);
__d_rehash(alias);
spin_unlock(&alias->d_lock);
}
spin_unlock(&inode->i_lock);
Expand Down Expand Up @@ -2795,30 +2778,22 @@ static void __d_move(struct dentry *dentry, struct dentry *target,
write_seqcount_begin(&dentry->d_seq);
write_seqcount_begin_nested(&target->d_seq, DENTRY_D_LOCK_NESTED);

/* unhash both */
/* __d_drop does write_seqcount_barrier, but they're OK to nest. */

/*
* Move the dentry to the target hash queue. Don't bother checking
* for the same hash queue because of how unlikely it is.
*/
__d_drop(dentry);
__d_rehash(dentry, d_hash(target->d_name.hash));

/*
* Unhash the target (d_delete() is not usable here). If exchanging
* the two dentries, then rehash onto the other's hash queue.
*/
__d_drop(target);
if (exchange) {
__d_rehash(target, d_hash(dentry->d_name.hash));
}

/* Switch the names.. */
if (exchange)
swap_names(dentry, target);
else
copy_name(dentry, target);

/* rehash in new place(s) */
__d_rehash(dentry);
if (exchange)
__d_rehash(target);

/* ... and switch them in the tree */
if (IS_ROOT(dentry)) {
/* splicing a tree */
Expand Down
3 changes: 1 addition & 2 deletions fs/efivarfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ static struct super_block *efivarfs_sb;
* So we need to perform a case-sensitive match on part 1 and a
* case-insensitive match on part 2.
*/
static int efivarfs_d_compare(const struct dentry *parent,
const struct dentry *dentry,
static int efivarfs_d_compare(const struct dentry *dentry,
unsigned int len, const char *str,
const struct qstr *name)
{
Expand Down
4 changes: 2 additions & 2 deletions fs/fat/namei_msdos.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,10 @@ static int msdos_hash(const struct dentry *dentry, struct qstr *qstr)
* Compare two msdos names. If either of the names are invalid,
* we fall back to doing the standard name comparison.
*/
static int msdos_cmp(const struct dentry *parent, const struct dentry *dentry,
static int msdos_cmp(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
struct fat_mount_options *options = &MSDOS_SB(parent->d_sb)->options;
struct fat_mount_options *options = &MSDOS_SB(dentry->d_sb)->options;
unsigned char a_msdos_name[MSDOS_NAME], b_msdos_name[MSDOS_NAME];
int error;

Expand Down
Loading

0 comments on commit fe64f32

Please sign in to comment.