Commit 119009db authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'vfs-6.15-rc3.fixes.2' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull vfs fixes from Christian Brauner:

 - Revert the hfs{plus} deprecation warning that's also included in this
   pull request. The commit introducing the deprecation warning resides
   rather early in this branch. So simply dropping it would've rebased
   all other commits which I decided to avoid. Hence the revert in the
   same branch

   [ Background - the deprecation warning discussion resulted in people
     stepping up, and so hfs{plus} will have a maintainer taking care of
     it after all..   - Linus ]

 - Switch CONFIG_SYSFS_SYCALL default to n and decouple from
   CONFIG_EXPERT

 - Fix an audit bug caused by changes to our kernel path lookup helpers
   this cycle. Audit needs the parent path even if the dentry it tried
   to look up is negative

 - Ensure that the kernel path lookup helpers leave the passed in path
   argument clean when they return an error. This is consistent with all
   our other helpers

 - Ensure that vfs_getattr_nosec() calls bdev_statx() so the relevant
   information is available to kernel consumers as well

 - Don't set a timer and call schedule() if the timer will expire
   immediately in epoll

 - Make netfs lookup tables with __nonstring

* tag 'vfs-6.15-rc3.fixes.2' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
  Revert "hfs{plus}: add deprecation warning"
  fs: move the bdex_statx call to vfs_getattr_nosec
  netfs: Mark __nonstring lookup tables
  eventpoll: Set epoll timeout if it's in the future
  fs: ensure that *path_locked*() helpers leave passed path pristine
  fs: add kern_path_locked_negative()
  hfs{plus}: add deprecation warning
  Kconfig: switch CONFIG_SYSFS_SYCALL default to n
parents 6fe81317 408e4504
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -1272,8 +1272,7 @@ void sync_bdevs(bool wait)
/*
 * Handle STATX_{DIOALIGN, WRITE_ATOMIC} for block devices.
 */
void bdev_statx(struct path *path, struct kstat *stat,
		u32 request_mask)
void bdev_statx(const struct path *path, struct kstat *stat, u32 request_mask)
{
	struct inode *backing_inode;
	struct block_device *bdev;
+9 −1
Original line number Diff line number Diff line
@@ -1996,6 +1996,14 @@ static int ep_try_send_events(struct eventpoll *ep,
	return res;
}

static int ep_schedule_timeout(ktime_t *to)
{
	if (to)
		return ktime_after(*to, ktime_get());
	else
		return 1;
}

/**
 * ep_poll - Retrieves ready events, and delivers them to the caller-supplied
 *           event buffer.
@@ -2103,7 +2111,7 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,

		write_unlock_irq(&ep->lock);

		if (!eavail)
		if (!eavail && ep_schedule_timeout(to))
			timed_out = !schedule_hrtimeout_range(to, slack,
							      HRTIMER_MODE_ABS);
		__set_current_state(TASK_RUNNING);
+58 −23
Original line number Diff line number Diff line
@@ -1665,27 +1665,20 @@ static struct dentry *lookup_dcache(const struct qstr *name,
	return dentry;
}

/*
 * Parent directory has inode locked exclusive.  This is one
 * and only case when ->lookup() gets called on non in-lookup
 * dentries - as the matter of fact, this only gets called
 * when directory is guaranteed to have no in-lookup children
 * at all.
 * Will return -ENOENT if name isn't found and LOOKUP_CREATE wasn't passed.
 * Will return -EEXIST if name is found and LOOKUP_EXCL was passed.
 */
struct dentry *lookup_one_qstr_excl(const struct qstr *name,
static struct dentry *lookup_one_qstr_excl_raw(const struct qstr *name,
					       struct dentry *base,
					       unsigned int flags)
{
	struct dentry *dentry = lookup_dcache(name, base, flags);
	struct dentry *dentry;
	struct dentry *old;
	struct inode *dir = base->d_inode;
	struct inode *dir;

	dentry = lookup_dcache(name, base, flags);
	if (dentry)
		goto found;
		return dentry;

	/* Don't create child dentry for a dead directory. */
	dir = base->d_inode;
	if (unlikely(IS_DEADDIR(dir)))
		return ERR_PTR(-ENOENT);

@@ -1698,7 +1691,24 @@ struct dentry *lookup_one_qstr_excl(const struct qstr *name,
		dput(dentry);
		dentry = old;
	}
found:
	return dentry;
}

/*
 * Parent directory has inode locked exclusive.  This is one
 * and only case when ->lookup() gets called on non in-lookup
 * dentries - as the matter of fact, this only gets called
 * when directory is guaranteed to have no in-lookup children
 * at all.
 * Will return -ENOENT if name isn't found and LOOKUP_CREATE wasn't passed.
 * Will return -EEXIST if name is found and LOOKUP_EXCL was passed.
 */
struct dentry *lookup_one_qstr_excl(const struct qstr *name,
				    struct dentry *base, unsigned int flags)
{
	struct dentry *dentry;

	dentry = lookup_one_qstr_excl_raw(name, base, flags);
	if (IS_ERR(dentry))
		return dentry;
	if (d_is_negative(dentry) && !(flags & LOOKUP_CREATE)) {
@@ -2742,23 +2752,48 @@ static int filename_parentat(int dfd, struct filename *name,
/* does lookup, returns the object with parent locked */
static struct dentry *__kern_path_locked(int dfd, struct filename *name, struct path *path)
{
	struct path parent_path __free(path_put) = {};
	struct dentry *d;
	struct qstr last;
	int type, error;

	error = filename_parentat(dfd, name, 0, path, &last, &type);
	error = filename_parentat(dfd, name, 0, &parent_path, &last, &type);
	if (error)
		return ERR_PTR(error);
	if (unlikely(type != LAST_NORM)) {
		path_put(path);
	if (unlikely(type != LAST_NORM))
		return ERR_PTR(-EINVAL);
	inode_lock_nested(parent_path.dentry->d_inode, I_MUTEX_PARENT);
	d = lookup_one_qstr_excl(&last, parent_path.dentry, 0);
	if (IS_ERR(d)) {
		inode_unlock(parent_path.dentry->d_inode);
		return d;
	}
	inode_lock_nested(path->dentry->d_inode, I_MUTEX_PARENT);
	d = lookup_one_qstr_excl(&last, path->dentry, 0);
	path->dentry = no_free_ptr(parent_path.dentry);
	path->mnt = no_free_ptr(parent_path.mnt);
	return d;
}

struct dentry *kern_path_locked_negative(const char *name, struct path *path)
{
	struct path parent_path __free(path_put) = {};
	struct filename *filename __free(putname) = getname_kernel(name);
	struct dentry *d;
	struct qstr last;
	int type, error;

	error = filename_parentat(AT_FDCWD, filename, 0, &parent_path, &last, &type);
	if (error)
		return ERR_PTR(error);
	if (unlikely(type != LAST_NORM))
		return ERR_PTR(-EINVAL);
	inode_lock_nested(parent_path.dentry->d_inode, I_MUTEX_PARENT);
	d = lookup_one_qstr_excl_raw(&last, parent_path.dentry, 0);
	if (IS_ERR(d)) {
		inode_unlock(path->dentry->d_inode);
		path_put(path);
		inode_unlock(parent_path.dentry->d_inode);
		return d;
	}
	path->dentry = no_free_ptr(parent_path.dentry);
	path->mnt = no_free_ptr(parent_path.mnt);
	return d;
}

+1 −1
Original line number Diff line number Diff line
@@ -372,7 +372,7 @@ void fscache_withdraw_cache(struct fscache_cache *cache)
EXPORT_SYMBOL(fscache_withdraw_cache);

#ifdef CONFIG_PROC_FS
static const char fscache_cache_states[NR__FSCACHE_CACHE_STATE] = "-PAEW";
static const char fscache_cache_states[NR__FSCACHE_CACHE_STATE] __nonstring = "-PAEW";

/*
 * Generate a list of caches in /proc/fs/fscache/caches
+1 −1
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@ static LIST_HEAD(fscache_cookie_lru);
static DEFINE_SPINLOCK(fscache_cookie_lru_lock);
DEFINE_TIMER(fscache_cookie_lru_timer, fscache_cookie_lru_timed_out);
static DECLARE_WORK(fscache_cookie_lru_work, fscache_cookie_lru_worker);
static const char fscache_cookie_states[FSCACHE_COOKIE_STATE__NR] = "-LCAIFUWRD";
static const char fscache_cookie_states[FSCACHE_COOKIE_STATE__NR] __nonstring = "-LCAIFUWRD";
static unsigned int fscache_lru_cookie_timeout = 10 * HZ;

void fscache_print_cookie(struct fscache_cookie *cookie, char prefix)
Loading