main: Add option static_nlink to set st_nlink to 1 for all directories

Skips calculation of st_nlink for directories, which can be
expensive on higher latency file systems such as NFS.

Signed-off-by: David Hedberg <david.hedberg@gmail.com>
This commit is contained in:
David Hedberg 2021-03-14 13:42:22 +01:00
parent 1f1377d880
commit 5ec356b29e
4 changed files with 36 additions and 10 deletions

View File

@ -116,6 +116,16 @@ Every file and directory is owned by the specified uid or gid.
.PP
It has higher precedence over \fBsquash\_to\_root\fP\&.
.PP
\fB\-o static\_nlink\fP
Set st\_nlink to the static value 1 for all directories.
.PP
This can be useful for higher latency file systems such as NFS, where
counting the number of hard links for a directory with many files can
be a slow operation. With this option enabled, the number of hard
links reported when running stat for any directory is 1.
.SH SEE ALSO
.PP

View File

@ -93,6 +93,14 @@ Every file and directory is owned by the specified uid or gid.
It has higher precedence over **squash_to_root**.
**-o static_nlink**
Set st_nlink to the static value 1 for all directories.
This can be useful for higher latency file systems such as NFS, where
counting the number of hard links for a directory with many files can
be a slow operation. With this option enabled, the number of hard
links reported when running stat for any directory is 1.
# SEE ALSO
**fuse**(8), **mount**(8), **user_namespaces**(7)

View File

@ -99,6 +99,7 @@ struct ovl_data
int squash_to_root;
int squash_to_uid;
int squash_to_gid;
int static_nlink;
/* current uid/gid*/
uid_t uid;

13
main.c
View File

@ -223,6 +223,8 @@ static const struct fuse_opt ovl_opts[] = {
offsetof (struct ovl_data, squash_to_uid), 1},
{"squash_to_gid=%d",
offsetof (struct ovl_data, squash_to_gid), 1},
{"static_nlink",
offsetof (struct ovl_data, static_nlink), 1},
{"volatile", /* native overlay supports "volatile" to mean fsync=0. */
offsetof (struct ovl_data, fsync), 0},
FUSE_OPT_END
@ -898,6 +900,8 @@ rpl_stat (fuse_req_t req, struct ovl_node *node, int fd, const char *path, struc
st->st_ino = node->tmp_ino;
st->st_dev = node->tmp_dev;
if (ret == 0 && node_dirp (node))
{
if (!data->static_nlink)
{
struct ovl_node *it;
@ -909,6 +913,9 @@ rpl_stat (fuse_req_t req, struct ovl_node *node, int fd, const char *path, struc
st->st_nlink++;
}
}
else
st->st_nlink = 1;
}
return ret;
}
@ -2105,7 +2112,7 @@ ovl_lookup (fuse_req_t req, fuse_ino_t parent, const char *name)
return;
}
if (node_dirp (node))
if (!lo->static_nlink && node_dirp (node))
{
node = reload_dir (lo, node);
if (node == NULL)
@ -2355,7 +2362,7 @@ ovl_do_readdir (fuse_req_t req, fuse_ino_t ino, size_t size,
}
else
{
if (node_dirp (node))
if (!lo->static_nlink && node_dirp (node))
{
node = reload_dir (lo, node);
if (node == NULL)
@ -2364,7 +2371,6 @@ ovl_do_readdir (fuse_req_t req, fuse_ino_t ino, size_t size,
return;
}
}
memset (&e, 0, sizeof (e));
ret = rpl_stat (req, node, -1, NULL, NULL, st);
if (ret < 0)
@ -5468,6 +5474,7 @@ main (int argc, char *argv[])
.fsync = 1,
.squash_to_uid = -1,
.squash_to_gid = -1,
.static_nlink = 0,
.xattr_permissions = 0,
.timeout = 1000000000.0,
.timeout_str = NULL,