From 5ec356b29ed0fa5be63f5a1c5486ff48bbcdc298 Mon Sep 17 00:00:00 2001 From: David Hedberg Date: Sun, 14 Mar 2021 13:42:22 +0100 Subject: [PATCH] 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 --- fuse-overlayfs.1 | 10 ++++++++++ fuse-overlayfs.1.md | 8 ++++++++ fuse-overlayfs.h | 1 + main.c | 27 +++++++++++++++++---------- 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/fuse-overlayfs.1 b/fuse-overlayfs.1 index cbf55e2..1227547 100644 --- a/fuse-overlayfs.1 +++ b/fuse-overlayfs.1 @@ -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 diff --git a/fuse-overlayfs.1.md b/fuse-overlayfs.1.md index 61b8418..94494c8 100644 --- a/fuse-overlayfs.1.md +++ b/fuse-overlayfs.1.md @@ -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) diff --git a/fuse-overlayfs.h b/fuse-overlayfs.h index 83d5697..ea8172c 100644 --- a/fuse-overlayfs.h +++ b/fuse-overlayfs.h @@ -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; diff --git a/main.c b/main.c index 7ca4229..b17a7ca 100644 --- a/main.c +++ b/main.c @@ -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 @@ -899,15 +901,20 @@ rpl_stat (fuse_req_t req, struct ovl_node *node, int fd, const char *path, struc st->st_dev = node->tmp_dev; if (ret == 0 && node_dirp (node)) { - struct ovl_node *it; - - st->st_nlink = 2; - - for (it = hash_get_first (node->children); it; it = hash_get_next (node->children, it)) + if (!data->static_nlink) { - if (node_dirp (it)) - st->st_nlink++; + struct ovl_node *it; + + st->st_nlink = 2; + + for (it = hash_get_first (node->children); it; it = hash_get_next (node->children, it)) + { + if (node_dirp (it)) + 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,