Commit 18c9901d authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull fsnotify updates from Jan Kara:

 - Support for fanotify events returning file handles for filesystems
   not exportable via NFS

 - Improved error handling exportfs functions

 - Add missing FS_OPEN events when unusual open helpers are used

* tag 'fsnotify_for_v6.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  fsnotify: move fsnotify_open() hook into do_dentry_open()
  exportfs: check for error return value from exportfs_encode_*()
  fanotify: support reporting non-decodeable file handles
  exportfs: allow exporting non-decodeable file handles to userspace
  exportfs: add explicit flag to request non-decodeable file handles
  exportfs: change connectable argument to bit flags
parents 0a37714f 7b8c9d7b
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -123,7 +123,7 @@ super_block. This field must point to a "struct export_operations"
struct which has the following members:

  encode_fh (optional)
    Takes a dentry and creates a filehandle fragment which can later be used
    Takes a dentry and creates a filehandle fragment which may later be used
    to find or create a dentry for the same object.  The default
    implementation creates a filehandle fragment that encodes a 32bit inode
    and generation number for the inode encoded, and if necessary the
+0 −5
Original line number Diff line number Diff line
@@ -152,8 +152,6 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
			 path_noexec(&file->f_path)))
		goto exit;

	fsnotify_open(file);

	error = -ENOEXEC;

	read_lock(&binfmt_lock);
@@ -940,9 +938,6 @@ static struct file *do_open_execat(int fd, struct filename *name, int flags)
	if (err)
		goto exit;

	if (name->name[0] != '\0')
		fsnotify_open(file);

out:
	return file;

+29 −4
Original line number Diff line number Diff line
@@ -381,11 +381,27 @@ static int export_encode_fh(struct inode *inode, struct fid *fid,
	return type;
}

/**
 * exportfs_encode_inode_fh - encode a file handle from inode
 * @inode:   the object to encode
 * @fid:     where to store the file handle fragment
 * @max_len: maximum length to store there
 * @flags:   properties of the requested file handle
 *
 * Returns an enum fid_type or a negative errno.
 */
int exportfs_encode_inode_fh(struct inode *inode, struct fid *fid,
			     int *max_len, struct inode *parent)
			     int *max_len, struct inode *parent, int flags)
{
	const struct export_operations *nop = inode->i_sb->s_export_op;

	/*
	 * If a decodeable file handle was requested, we need to make sure that
	 * filesystem can decode file handles.
	 */
	if (nop && !(flags & EXPORT_FH_FID) && !nop->fh_to_dentry)
		return -EOPNOTSUPP;

	if (nop && nop->encode_fh)
		return nop->encode_fh(inode, fid->raw, max_len, parent);

@@ -393,14 +409,23 @@ int exportfs_encode_inode_fh(struct inode *inode, struct fid *fid,
}
EXPORT_SYMBOL_GPL(exportfs_encode_inode_fh);

/**
 * exportfs_encode_fh - encode a file handle from dentry
 * @dentry:  the object to encode
 * @fid:     where to store the file handle fragment
 * @max_len: maximum length to store there
 * @flags:   properties of the requested file handle
 *
 * Returns an enum fid_type or a negative errno.
 */
int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len,
		int connectable)
		       int flags)
{
	int error;
	struct dentry *p = NULL;
	struct inode *inode = dentry->d_inode, *parent = NULL;

	if (connectable && !S_ISDIR(inode->i_mode)) {
	if ((flags & EXPORT_FH_CONNECTABLE) && !S_ISDIR(inode->i_mode)) {
		p = dget_parent(dentry);
		/*
		 * note that while p might've ceased to be our parent already,
@@ -409,7 +434,7 @@ int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len,
		parent = p->d_inode;
	}

	error = exportfs_encode_inode_fh(inode, fid, max_len, parent);
	error = exportfs_encode_inode_fh(inode, fid, max_len, parent, flags);
	dput(p);

	return error;
+17 −11
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@

static long do_sys_name_to_handle(const struct path *path,
				  struct file_handle __user *ufh,
				  int __user *mnt_id)
				  int __user *mnt_id, int fh_flags)
{
	long retval;
	struct file_handle f_handle;
@@ -24,11 +24,14 @@ static long do_sys_name_to_handle(const struct path *path,
	struct file_handle *handle = NULL;

	/*
	 * We need to make sure whether the file system
	 * support decoding of the file handle
	 * We need to make sure whether the file system support decoding of
	 * the file handle if decodeable file handle was requested.
	 * Otherwise, even empty export_operations are sufficient to opt-in
	 * to encoding FIDs.
	 */
	if (!path->dentry->d_sb->s_export_op ||
	    !path->dentry->d_sb->s_export_op->fh_to_dentry)
	    (!(fh_flags & EXPORT_FH_FID) &&
	     !path->dentry->d_sb->s_export_op->fh_to_dentry))
		return -EOPNOTSUPP;

	if (copy_from_user(&f_handle, ufh, sizeof(struct file_handle)))
@@ -45,27 +48,28 @@ static long do_sys_name_to_handle(const struct path *path,
	/* convert handle size to multiple of sizeof(u32) */
	handle_dwords = f_handle.handle_bytes >> 2;

	/* we ask for a non connected handle */
	/* we ask for a non connectable maybe decodeable file handle */
	retval = exportfs_encode_fh(path->dentry,
				    (struct fid *)handle->f_handle,
				    &handle_dwords,  0);
				    &handle_dwords, fh_flags);
	handle->handle_type = retval;
	/* convert handle size to bytes */
	handle_bytes = handle_dwords * sizeof(u32);
	handle->handle_bytes = handle_bytes;
	if ((handle->handle_bytes > f_handle.handle_bytes) ||
	    (retval == FILEID_INVALID) || (retval == -ENOSPC)) {
	    (retval == FILEID_INVALID) || (retval < 0)) {
		/* As per old exportfs_encode_fh documentation
		 * we could return ENOSPC to indicate overflow
		 * But file system returned 255 always. So handle
		 * both the values
		 */
		if (retval == FILEID_INVALID || retval == -ENOSPC)
			retval = -EOVERFLOW;
		/*
		 * set the handle size to zero so we copy only
		 * non variable part of the file_handle
		 */
		handle_bytes = 0;
		retval = -EOVERFLOW;
	} else
		retval = 0;
	/* copy the mount id */
@@ -84,6 +88,7 @@ static long do_sys_name_to_handle(const struct path *path,
 * @handle: resulting file handle
 * @mnt_id: mount id of the file system containing the file
 * @flag: flag value to indicate whether to follow symlink or not
 *        and whether a decodable file handle is required.
 *
 * @handle->handle_size indicate the space available to store the
 * variable part of the file handle in bytes. If there is not
@@ -96,17 +101,19 @@ SYSCALL_DEFINE5(name_to_handle_at, int, dfd, const char __user *, name,
{
	struct path path;
	int lookup_flags;
	int fh_flags;
	int err;

	if ((flag & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0)
	if (flag & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH | AT_HANDLE_FID))
		return -EINVAL;

	lookup_flags = (flag & AT_SYMLINK_FOLLOW) ? LOOKUP_FOLLOW : 0;
	fh_flags = (flag & AT_HANDLE_FID) ? EXPORT_FH_FID : 0;
	if (flag & AT_EMPTY_PATH)
		lookup_flags |= LOOKUP_EMPTY;
	err = user_path_at(dfd, name, lookup_flags, &path);
	if (!err) {
		err = do_sys_name_to_handle(&path, handle, mnt_id);
		err = do_sys_name_to_handle(&path, handle, mnt_id, fh_flags);
		path_put(&path);
	}
	return err;
@@ -235,7 +242,6 @@ static long do_handle_open(int mountdirfd, struct file_handle __user *ufh,
		retval =  PTR_ERR(file);
	} else {
		retval = fd;
		fsnotify_open(file);
		fd_install(fd, file);
	}
	path_put(&path);
+5 −2
Original line number Diff line number Diff line
@@ -414,10 +414,13 @@ static void _fh_update(struct svc_fh *fhp, struct svc_export *exp,
		struct fid *fid = (struct fid *)
			(fhp->fh_handle.fh_fsid + fhp->fh_handle.fh_size/4 - 1);
		int maxsize = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4;
		int subtreecheck = !(exp->ex_flags & NFSEXP_NOSUBTREECHECK);
		int fh_flags = (exp->ex_flags & NFSEXP_NOSUBTREECHECK) ? 0 :
				EXPORT_FH_CONNECTABLE;
		int fileid_type =
			exportfs_encode_fh(dentry, fid, &maxsize, fh_flags);

		fhp->fh_handle.fh_fileid_type =
			exportfs_encode_fh(dentry, fid, &maxsize, subtreecheck);
			fileid_type > 0 ? fileid_type : FILEID_INVALID;
		fhp->fh_handle.fh_size += maxsize * 4;
	} else {
		fhp->fh_handle.fh_fileid_type = FILEID_ROOT;
Loading