Commit 27992ef8 authored by Bernd Schubert's avatar Bernd Schubert Committed by Miklos Szeredi
Browse files

fuse: Increase FUSE_NAME_MAX to PATH_MAX

Our file system has a translation capability for S3-to-posix.
The current value of 1kiB is enough to cover S3 keys, but
does not allow encoding of %xx escape characters.
The limit is increased to (PATH_MAX - 1), as we need
3 x 1024 and that is close to PATH_MAX (4kB) already.
-1 is used as the terminating null is not included in the
length calculation.

Testing large file names was hard with libfuse/example file systems,
so I created a new memfs that does not have a 255 file name length
limitation.
https://github.com/libfuse/libfuse/pull/1077



The connection is initialized with FUSE_NAME_LOW_MAX, which
is set to the previous value of FUSE_NAME_MAX of 1024. With
FUSE_MIN_READ_BUFFER of 8192 that is enough for two file names
+ fuse headers.
When FUSE_INIT reply sets max_pages to a value > 1 we know
that fuse daemon supports request buffers of at least 2 pages
(+ header) and can therefore hold 2 x PATH_MAX file names - operations
like rename or link that need two file names are no issue then.

Signed-off-by: default avatarBernd Schubert <bschubert@ddn.com>
Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent 2412085d
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -1657,7 +1657,7 @@ static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size,
		goto err;

	err = -ENAMETOOLONG;
	if (outarg.namelen > FUSE_NAME_MAX)
	if (outarg.namelen > fc->name_max)
		goto err;

	err = -EINVAL;
@@ -1706,7 +1706,7 @@ static int fuse_notify_delete(struct fuse_conn *fc, unsigned int size,
		goto err;

	err = -ENAMETOOLONG;
	if (outarg.namelen > FUSE_NAME_MAX)
	if (outarg.namelen > fc->name_max)
		goto err;

	err = -EINVAL;
+1 −1
Original line number Diff line number Diff line
@@ -370,7 +370,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name

	*inode = NULL;
	err = -ENAMETOOLONG;
	if (name->len > FUSE_NAME_MAX)
	if (name->len > fm->fc->name_max)
		goto out;


+9 −2
Original line number Diff line number Diff line
@@ -38,8 +38,12 @@
/** Bias for fi->writectr, meaning new writepages must not be sent */
#define FUSE_NOWRITE INT_MIN

/** It could be as large as PATH_MAX, but would that have any uses? */
#define FUSE_NAME_MAX 1024
/** Maximum length of a filename, not including terminating null */

/* maximum, small enough for FUSE_MIN_READ_BUFFER*/
#define FUSE_NAME_LOW_MAX 1024
/* maximum, but needs a request buffer > FUSE_MIN_READ_BUFFER */
#define FUSE_NAME_MAX (PATH_MAX - 1)

/** Number of dentries for each connection in the control filesystem */
#define FUSE_CTL_NUM_DENTRIES 5
@@ -924,6 +928,9 @@ struct fuse_conn {
	/** Version counter for evict inode */
	atomic64_t evict_ctr;

	/* maximum file name length */
	u32 name_max;

	/** Called on final put */
	void (*release)(struct fuse_conn *);

+8 −0
Original line number Diff line number Diff line
@@ -982,6 +982,7 @@ void fuse_conn_init(struct fuse_conn *fc, struct fuse_mount *fm,
	fc->user_ns = get_user_ns(user_ns);
	fc->max_pages = FUSE_DEFAULT_MAX_PAGES_PER_REQ;
	fc->max_pages_limit = fuse_max_pages_limit;
	fc->name_max = FUSE_NAME_LOW_MAX;
	fc->timeout.req_timeout = 0;

	if (IS_ENABLED(CONFIG_FUSE_PASSTHROUGH))
@@ -1373,6 +1374,13 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args,
				fc->max_pages =
					min_t(unsigned int, fc->max_pages_limit,
					max_t(unsigned int, arg->max_pages, 1));

				/*
				 * PATH_MAX file names might need two pages for
				 * ops like rename
				 */
				if (fc->max_pages > 1)
					fc->name_max = FUSE_NAME_MAX;
			}
			if (IS_ENABLED(CONFIG_FUSE_DAX)) {
				if (flags & FUSE_MAP_ALIGNMENT &&