Merge pull request #89 from giuseppe/perf-improvements-2

fuse-overlayfs: different performance tweaks continuation of #88
This commit is contained in:
Daniel J Walsh 2019-07-24 06:56:29 -04:00 committed by GitHub
commit bd9eb8d5cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 176 additions and 116 deletions

265
main.c
View File

@ -210,10 +210,10 @@ struct ovl_node
int lookups;
int hidden_dirfd;
int nlinks;
ino_t ino;
mode_t mode;
size_t name_hash;
ino_t ino;
unsigned int present_lowerdir : 1;
unsigned int do_unlink : 1;
unsigned int do_rmdir : 1;
unsigned int hidden : 1;
@ -759,15 +759,24 @@ hide_node (struct ovl_data *lo, struct ovl_node *node, bool unlink_src)
assert (node->layer == get_upper_layer (lo));
/* Might be leftover from a previous run. */
unlinkat (lo->workdir_fd, newpath, 0);
unlinkat (lo->workdir_fd, newpath, AT_REMOVEDIR);
if (unlink_src)
{
bool moved = false;
bool whiteout_created = false;
bool needs_whiteout;
needs_whiteout = node->parent && node->parent->last_layer != get_upper_layer (lo);
if (needs_whiteout)
{
/* If the atomic rename+mknod failed, then fallback into doing it in two steps. */
if (syscall (SYS_renameat2, node_dirfd (node), node->path, lo->workdir_fd,
newpath, RENAME_WHITEOUT) < 0)
if (can_mknod && syscall (SYS_renameat2, node_dirfd (node), node->path, lo->workdir_fd, newpath, RENAME_WHITEOUT) == 0)
{
whiteout_created = true;
moved = true;
}
if (!whiteout_created)
{
if (node->parent)
{
@ -777,19 +786,15 @@ hide_node (struct ovl_data *lo, struct ovl_node *node, bool unlink_src)
if (create_whiteout (lo, node->parent, node->name, true, false) < 0)
return -1;
}
if (renameat (node_dirfd (node), node->path, lo->workdir_fd, newpath) < 0)
{
if (node->parent)
{
char whpath[PATH_MAX];
}
}
strconcat3 (whpath, PATH_MAX, node->parent->path, "/.wh.", node->name);
unlinkat (get_upper_layer (lo)->fd, whpath, 0);
}
if (!moved)
{
if (renameat (node_dirfd (node), node->path, lo->workdir_fd, newpath) < 0)
return -1;
}
}
}
else
{
if (node_dirp (node))
@ -852,12 +857,14 @@ get_gid (struct ovl_data *data, gid_t id)
}
static int
rpl_stat (fuse_req_t req, struct ovl_node *node, int fd, const char *path, struct stat *st)
rpl_stat (fuse_req_t req, struct ovl_node *node, int fd, const char *path, struct stat *st_in, struct stat *st)
{
int ret;
int ret = 0;
struct ovl_data *data = ovl_data (req);
if (fd >= 0)
if (st_in)
memcpy (st, st_in, sizeof (* st));
else if (fd >= 0)
ret = fstat (fd, st);
else if (path != NULL)
ret = stat (path, st);
@ -882,6 +889,7 @@ rpl_stat (fuse_req_t req, struct ovl_node *node, int fd, const char *path, struc
st->st_nlink++;
}
node->nlinks = st->st_nlink;
node->mode = st->st_mode;
}
return ret;
@ -958,7 +966,7 @@ ovl_forget (fuse_req_t req, fuse_ino_t ino, uint64_t nlookup)
{
cleanup_lock int l = enter_big_lock ();
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_forget(ino=%" PRIu64 ", nlookup=%lu)\n",
ino, nlookup);
do_forget (ino, nlookup);
@ -971,7 +979,7 @@ ovl_forget_multi (fuse_req_t req, size_t count, struct fuse_forget_data *forgets
size_t i;
cleanup_lock int l = enter_big_lock ();
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_forget_multi(count=%zu, forgets=%p)\n",
count, forgets);
@ -1149,7 +1157,10 @@ make_ovl_node (const char *path, struct ovl_layer *layer, const char *name, ino_
continue;
if (fstat (fd, &st) == 0)
{
ret->ino = st.st_ino;
ret->last_layer = it;
}
s = safe_read_xattr (&val, fd, PRIVILEGED_ORIGIN_XATTR, PATH_MAX);
if (s > 0)
@ -1322,18 +1333,16 @@ load_dir (struct ovl_data *lo, struct ovl_node *n, struct ovl_layer *layer, char
child = hash_lookup (n->children, &key);
if (child)
{
if (child->whiteout && it == upper_layer)
child->last_layer = it;
if (!child->whiteout || it != upper_layer)
continue;
else
{
hash_delete (n->children, child);
node_free (child);
child = NULL;
}
else
{
if (it->low)
child->present_lowerdir = 1;
continue;
}
if (lo->fast_ino_check)
continue;
}
@ -1386,13 +1395,13 @@ load_dir (struct ovl_data *lo, struct ovl_node *n, struct ovl_layer *layer, char
}
else
{
child = make_ovl_node (node_path, it, dent->d_name, 0, dirp, n, lo->fast_ino_check);
if (child == NULL)
{
errno = ENOMEM;
return NULL;
}
child->last_layer = it;
}
}
@ -1569,8 +1578,7 @@ do_lookup_file (struct ovl_data *lo, fuse_ino_t parent, const char *name)
if (node)
{
node->ino = st.st_ino;
if (it->low)
node->present_lowerdir = 1;
node->last_layer = it;
continue;
}
@ -1613,11 +1621,9 @@ insert_node:
errno = ENOMEM;
return NULL;
}
if (node->last_layer)
break;
if (pnode && pnode->last_layer == it)
break;
if (lo->fast_ino_check)
break;
}
@ -1640,7 +1646,7 @@ ovl_lookup (fuse_req_t req, fuse_ino_t parent, const char *name)
struct ovl_data *lo = ovl_data (req);
struct ovl_node *node;
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_lookup(parent=%" PRIu64 ", name=%s)\n",
parent, name);
@ -1656,7 +1662,7 @@ ovl_lookup (fuse_req_t req, fuse_ino_t parent, const char *name)
return;
}
err = rpl_stat (req, node, -1, NULL, &e.attr);
err = rpl_stat (req, node, -1, NULL, NULL, &e.attr);
if (err)
{
fuse_reply_err (req, errno);
@ -1695,7 +1701,7 @@ ovl_opendir (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
struct ovl_dirp *d = calloc (1, sizeof (struct ovl_dirp));
cleanup_lock int l = enter_big_lock ();
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_opendir(ino=%" PRIu64 ")\n", ino);
if (d == NULL)
@ -1858,7 +1864,7 @@ ovl_do_readdir (fuse_req_t req, fuse_ino_t ino, size_t size,
char *p;
cleanup_free char *buffer = NULL;
buffer = calloc (size, 1);
buffer = malloc (size);
if (buffer == NULL)
{
fuse_reply_err (req, ENOMEM);
@ -1869,20 +1875,14 @@ ovl_do_readdir (fuse_req_t req, fuse_ino_t ino, size_t size,
{
int ret;
size_t entsize;
struct stat st;
const char *name;
struct ovl_node *node = d->tbl[offset];
struct fuse_entry_param e;
struct stat *st = &e.attr;
if (node == NULL || node->whiteout || node->hidden)
continue;
ret = rpl_stat (req, node, -1, NULL, &st);
if (ret < 0)
{
fuse_reply_err (req, errno);
return;
}
if (offset == 0)
name = ".";
else if (offset == 1)
@ -1895,17 +1895,28 @@ ovl_do_readdir (fuse_req_t req, fuse_ino_t ino, size_t size,
}
if (!plus)
entsize = fuse_add_direntry (req, p, remaining, name, &st, offset + 1);
{
/* From the 'stbuf' argument the st_ino field and bits 12-15 of the
* st_mode field are used. The other fields are ignored.
*/
st->st_ino = node->ino;
st->st_mode = node->mode;
entsize = fuse_add_direntry (req, p, remaining, name, st, offset + 1);
}
else
{
struct fuse_entry_param e;
memset (&e, 0, sizeof (e));
ret = rpl_stat (req, node, -1, NULL, NULL, st);
if (ret < 0)
{
fuse_reply_err (req, errno);
return;
}
e.attr_timeout = get_timeout (lo);
e.entry_timeout = get_timeout (lo);
e.ino = NODE_TO_INODE (node);
memcpy (&e.attr, &st, sizeof (st));
entsize = fuse_add_direntry_plus (req, p, remaining, name, &e, offset + 1);
if (entsize <= remaining)
{
@ -1929,7 +1940,7 @@ ovl_readdir (fuse_req_t req, fuse_ino_t ino, size_t size,
off_t offset, struct fuse_file_info *fi)
{
cleanup_lock int l = enter_big_lock ();
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_readdir(ino=%" PRIu64 ", size=%zu, offset=%llo)\n", ino, size, offset);
ovl_do_readdir (req, ino, size, offset, fi, 0);
}
@ -1939,7 +1950,7 @@ ovl_readdirplus (fuse_req_t req, fuse_ino_t ino, size_t size,
off_t offset, struct fuse_file_info *fi)
{
cleanup_lock int l = enter_big_lock ();
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_readdirplus(ino=%" PRIu64 ", size=%zu, offset=%llo)\n", ino, size, offset);
ovl_do_readdir (req, ino, size, offset, fi, 1);
}
@ -1951,7 +1962,7 @@ ovl_releasedir (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
size_t s;
struct ovl_dirp *d = ovl_dirp (fi);
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_releasedir(ino=%" PRIu64 ")\n", ino);
for (s = 2; s < d->tbl_size; s++)
@ -1977,7 +1988,7 @@ ovl_listxattr (fuse_req_t req, fuse_ino_t ino, size_t size)
char path[PATH_MAX];
int ret;
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_listxattr(ino=%" PRIu64 ", size=%zu)\n", ino, size);
if (lo->disable_xattrs)
@ -2039,7 +2050,7 @@ ovl_getxattr (fuse_req_t req, fuse_ino_t ino, const char *name, size_t size)
bool is_security_capability = false;
int ret;
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_getxattr(ino=%" PRIu64 ", name=%s, size=%zu)\n", ino, name, size);
if (lo->disable_xattrs)
@ -2108,12 +2119,14 @@ ovl_access (fuse_req_t req, fuse_ino_t ino, int mask)
struct ovl_data *lo = ovl_data (req);
struct ovl_node *n = do_lookup_file (lo, ino, NULL);
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_access(ino=%" PRIu64 ", mask=%d)\n",
ino, mask);
ret = faccessat (node_dirfd (n), n->path, mask, AT_SYMLINK_NOFOLLOW);
fuse_reply_err (req, ret < 0 ? errno : 0);
if (mask & n->mode == mask)
fuse_reply_err (req, 0);
else
fuse_reply_err (req, EPERM);
}
static int
@ -2147,7 +2160,7 @@ static int create_node_directory (struct ovl_data *lo, struct ovl_node *src);
static int
create_directory (struct ovl_data *lo, int dirfd, const char *name, const struct timespec *times,
struct ovl_node *parent, int xattr_sfd, uid_t uid, gid_t gid, mode_t mode)
struct ovl_node *parent, int xattr_sfd, uid_t uid, gid_t gid, mode_t mode, struct stat *st_out)
{
int ret;
cleanup_close int dfd = -1;
@ -2190,11 +2203,18 @@ create_directory (struct ovl_data *lo, int dirfd, const char *name, const struct
goto out;
}
unlinkat (dirfd, name, 0);
if (st_out)
{
ret = fstat (dfd, st_out);
if (ret < 0)
goto out;
}
ret = renameat (lo->workdir_fd, wd_tmp_file_name, dirfd, name);
if (ret < 0)
{
if (errno == ENOTDIR)
unlinkat (dirfd, name, 0);
if (errno == ENOENT && parent)
{
ret = create_node_directory (lo, parent);
@ -2236,7 +2256,7 @@ create_node_directory (struct ovl_data *lo, struct ovl_node *src)
times[0] = st.st_atim;
times[1] = st.st_mtim;
ret = create_directory (lo, get_upper_layer (lo)->fd, src->path, times, src->parent, sfd, st.st_uid, st.st_gid, st.st_mode);
ret = create_directory (lo, get_upper_layer (lo)->fd, src->path, times, src->parent, sfd, st.st_uid, st.st_gid, st.st_mode, NULL);
if (ret == 0)
{
src->layer = get_upper_layer (lo);
@ -2560,6 +2580,7 @@ do_rm (fuse_req_t req, fuse_ino_t parent, const char *name, bool dirp)
struct ovl_data *lo = ovl_data (req);
struct ovl_node *pnode;
int ret = 0;
size_t whiteouts = 0;
struct ovl_node key, *rm;
node = do_lookup_file (lo, parent, name);
@ -2581,7 +2602,7 @@ do_rm (fuse_req_t req, fuse_ino_t parent, const char *name, bool dirp)
return;
}
c = count_dir_entries (node, NULL);
c = count_dir_entries (node, &whiteouts);
if (c)
{
fuse_reply_err (req, ENOTEMPTY);
@ -2596,12 +2617,15 @@ do_rm (fuse_req_t req, fuse_ino_t parent, const char *name, bool dirp)
if (! dirp)
node->do_unlink = 1;
else
{
if (whiteouts > 0)
{
if (empty_dir (lo, node) < 0)
{
fuse_reply_err (req, errno);
return;
}
}
node->do_rmdir = 1;
}
@ -2653,7 +2677,7 @@ static void
ovl_unlink (fuse_req_t req, fuse_ino_t parent, const char *name)
{
cleanup_lock int l = enter_big_lock ();
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_unlink(parent=%" PRIu64 ", name=%s)\n",
parent, name);
do_rm (req, parent, name, false);
@ -2663,7 +2687,7 @@ static void
ovl_rmdir (fuse_req_t req, fuse_ino_t parent, const char *name)
{
cleanup_lock int l = enter_big_lock ();
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_rmdir(parent=%" PRIu64 ", name=%s)\n",
parent, name);
do_rm (req, parent, name, true);
@ -2681,7 +2705,7 @@ ovl_setxattr (fuse_req_t req, fuse_ino_t ino, const char *name,
char path[PATH_MAX];
int ret;
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_setxattr(ino=%" PRIu64 "s, name=%s, value=%s, size=%zu, flags=%d)\n", ino, name,
value, size, flags);
@ -2747,7 +2771,7 @@ ovl_removexattr (fuse_req_t req, fuse_ino_t ino, const char *name)
char path[PATH_MAX];
int ret;
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_removexattr(ino=%" PRIu64 "s, name=%s)\n", ino, name);
node = do_lookup_file (lo, ino, NULL);
@ -2919,7 +2943,7 @@ ovl_read (fuse_req_t req, fuse_ino_t ino, size_t size,
off_t offset, struct fuse_file_info *fi)
{
struct fuse_bufvec buf = FUSE_BUFVEC_INIT (size);
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_read(ino=%" PRIu64 ", size=%zd, "
"off=%lu)\n", ino, size, (unsigned long) offset);
buf.buf[0].flags = FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK;
@ -2940,7 +2964,7 @@ ovl_write_buf (fuse_req_t req, fuse_ino_t ino,
out_buf.buf[0].fd = fi->fh;
out_buf.buf[0].pos = off;
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_write_buf(ino=%" PRIu64 ", size=%zd, off=%lu, fd=%d)\n",
ino, out_buf.buf[0].size, (unsigned long) off, (int) fi->fh);
@ -2958,7 +2982,7 @@ ovl_release (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
int ret;
(void) ino;
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_release(ino=%" PRIu64 ")\n", ino);
ret = close (fi->fh);
@ -2973,7 +2997,7 @@ do_getattr (fuse_req_t req, struct fuse_entry_param *e, struct ovl_node *node, i
memset (e, 0, sizeof (*e));
err = rpl_stat (req, node, fd, path, &e->attr);
err = rpl_stat (req, node, fd, path, NULL, &e->attr);
if (err < 0)
return err;
@ -2994,7 +3018,7 @@ ovl_create (fuse_req_t req, fuse_ino_t parent, const char *name,
struct ovl_data *lo = ovl_data (req);
struct ovl_node *node;
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_create(parent=%" PRIu64 ", name=%s)\n",
parent, name);
@ -3027,7 +3051,7 @@ ovl_open (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
cleanup_lock int l = enter_big_lock ();
cleanup_close int fd = -1;
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_open(ino=%" PRIu64 "s)\n", ino);
fd = ovl_do_open (req, ino, NULL, fi->flags, 0700);
@ -3051,7 +3075,7 @@ ovl_getattr (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
struct ovl_node *node;
struct fuse_entry_param e;
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_getattr(ino=%" PRIu64 "s)\n", ino);
node = do_lookup_file (lo, ino, NULL);
@ -3085,7 +3109,7 @@ ovl_setattr (fuse_req_t req, fuse_ino_t ino, struct stat *attr, int to_set, stru
int fd;
char proc_path[PATH_MAX];
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_setattr(ino=%" PRIu64 "s, to_set=%d)\n", ino, to_set);
node = do_lookup_file (lo, ino, NULL);
@ -3240,7 +3264,7 @@ ovl_link (fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent, const char *newn
struct fuse_entry_param e;
char wd_tmp_file_name[32];
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_link(ino=%" PRIu64 "s, newparent=%" PRIu64 "s, newname=%s)\n", ino, newparent, newname);
node = do_lookup_file (lo, ino, NULL);
@ -3347,7 +3371,7 @@ ovl_link (fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent, const char *newn
memset (&e, 0, sizeof (e));
ret = rpl_stat (req, node, -1, NULL, &e.attr);
ret = rpl_stat (req, node, -1, NULL, NULL, &e.attr);
if (ret)
{
fuse_reply_err (req, errno);
@ -3372,8 +3396,9 @@ ovl_symlink (fuse_req_t req, const char *link, fuse_ino_t parent, const char *na
struct fuse_entry_param e;
const struct fuse_ctx *ctx = fuse_req_ctx (req);
char wd_tmp_file_name[32];
bool need_delete_whiteout = true;
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_symlink(link=%s, ino=%" PRIu64 "s, name=%s)\n", link, parent, name);
pnode = do_lookup_file (lo, parent, NULL);
@ -3397,6 +3422,9 @@ ovl_symlink (fuse_req_t req, const char *link, fuse_ino_t parent, const char *na
return;
}
if (pnode->loaded && node == NULL)
need_delete_whiteout = false;
sprintf (wd_tmp_file_name, "%lu", get_next_wd_counter ());
unlinkat (lo->workdir_fd, wd_tmp_file_name, 0);
@ -3414,7 +3442,7 @@ ovl_symlink (fuse_req_t req, const char *link, fuse_ino_t parent, const char *na
return;
}
if (delete_whiteout (lo, -1, pnode, name) < 0)
if (need_delete_whiteout && delete_whiteout (lo, -1, pnode, name) < 0)
{
unlinkat (lo->workdir_fd, wd_tmp_file_name, 0);
fuse_reply_err (req, errno);
@ -3451,7 +3479,7 @@ ovl_symlink (fuse_req_t req, const char *link, fuse_ino_t parent, const char *na
memset (&e, 0, sizeof (e));
ret = rpl_stat (req, node, -1, NULL, &e.attr);
ret = rpl_stat (req, node, -1, NULL, NULL, &e.attr);
if (ret)
{
fuse_reply_err (req, errno);
@ -3495,7 +3523,7 @@ ovl_rename_exchange (fuse_req_t req, fuse_ino_t parent, const char *name,
return;
}
if (node->layer != get_upper_layer (lo) || node->present_lowerdir)
if (node->layer != get_upper_layer (lo) || node->last_layer != get_upper_layer (lo))
{
fuse_reply_err (req, EXDEV);
return;
@ -3535,7 +3563,7 @@ ovl_rename_exchange (fuse_req_t req, fuse_ino_t parent, const char *name,
errno = ENOENT;
goto error;
}
if (node_dirp (node) && destnode->present_lowerdir)
if (node_dirp (node) && destnode->last_layer != get_upper_layer (lo))
{
fuse_reply_err (req, EXDEV);
return;
@ -3627,7 +3655,7 @@ ovl_rename_direct (fuse_req_t req, fuse_ino_t parent, const char *name,
return;
}
if (node->layer != get_upper_layer (lo) || node->present_lowerdir)
if (node->layer != get_upper_layer (lo) || node->last_layer != get_upper_layer (lo))
{
fuse_reply_err (req, EXDEV);
return;
@ -3798,7 +3826,7 @@ ovl_rename (fuse_req_t req, fuse_ino_t parent, const char *name,
unsigned int flags)
{
cleanup_lock int l = enter_big_lock ();
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_rename(ino=%" PRIu64 "s, name=%s , ino=%" PRIu64 "s, name=%s)\n", parent, name, newparent, newname);
if (flags & RENAME_EXCHANGE)
@ -3814,7 +3842,7 @@ ovl_statfs (fuse_req_t req, fuse_ino_t ino)
struct statvfs sfs;
struct ovl_data *lo = ovl_data (req);
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_statfs(ino=%" PRIu64 "s)\n", ino);
ret = fstatvfs (get_upper_layer (lo)->fd, &sfs);
@ -3836,7 +3864,7 @@ ovl_readlink (fuse_req_t req, fuse_ino_t ino)
size_t current_size;
int ret = 0;
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_readlink(ino=%" PRIu64 "s)\n", ino);
node = do_lookup_file (lo, ino, NULL);
@ -3930,7 +3958,7 @@ ovl_mknod (fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode, dev
const struct fuse_ctx *ctx = fuse_req_ctx (req);
char wd_tmp_file_name[32];
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_mknod(ino=%" PRIu64 ", name=%s, mode=%d, rdev=%lu)\n",
parent, name, mode, rdev);
@ -4007,7 +4035,7 @@ ovl_mknod (fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode, dev
memset (&e, 0, sizeof (e));
ret = rpl_stat (req, node, -1, NULL, &e.attr);
ret = rpl_stat (req, node, -1, NULL, NULL, &e.attr);
if (ret)
{
fuse_reply_err (req, errno);
@ -4024,16 +4052,20 @@ ovl_mknod (fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode, dev
static void
ovl_mkdir (fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode)
{
cleanup_lock int l = enter_big_lock ();
struct ovl_node *node;
const struct fuse_ctx *ctx = fuse_req_ctx (req);
struct ovl_data *lo = ovl_data (req);
struct fuse_entry_param e;
bool parent_upperdir_only;
struct ovl_node *pnode;
struct ovl_node *node;
struct stat st;
ino_t ino = 0;
int ret = 0;
char *path;
struct fuse_entry_param e;
const struct fuse_ctx *ctx = fuse_req_ctx (req);
bool need_delete_whiteout = true;
cleanup_lock int l = enter_big_lock ();
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_mkdir(ino=%" PRIu64 ", name=%s, mode=%d)\n",
parent, name, mode);
@ -4057,6 +4089,12 @@ ovl_mkdir (fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode)
fuse_reply_err (req, errno);
return;
}
if (pnode->loaded && node == NULL)
need_delete_whiteout = false;
parent_upperdir_only = pnode->last_layer == get_upper_layer (lo);
ret = asprintf (&path, "%s/%s", pnode->path, name);
if (ret < 0)
{
@ -4065,14 +4103,19 @@ ovl_mkdir (fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode)
}
ret = create_directory (lo, get_upper_layer (lo)->fd, path, NULL, pnode, -1,
get_uid (lo, ctx->uid), get_gid (lo, ctx->gid), mode & ~ctx->umask);
get_uid (lo, ctx->uid), get_gid (lo, ctx->gid), mode & ~ctx->umask,
parent_upperdir_only ? &st : NULL);
if (ret < 0)
{
fuse_reply_err (req, errno);
return;
}
node = make_ovl_node (path, get_upper_layer (lo), name, 0, true, pnode, lo->fast_ino_check);
/* if the parent is on the upper layer, it doesn't need to lookup the ino in the lower layers. */
if (parent_upperdir_only)
ino = st.st_ino;
node = make_ovl_node (path, get_upper_layer (lo), name, ino, true, pnode, lo->fast_ino_check);
if (node == NULL)
{
fuse_reply_err (req, ENOMEM);
@ -4085,14 +4128,24 @@ ovl_mkdir (fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode)
fuse_reply_err (req, ENOMEM);
return;
}
if (parent_upperdir_only)
{
node->last_layer = pnode->last_layer;
node->loaded = 1;
node->no_security_capability = 1;
}
else
{
ret = hide_all (lo, node);
if (ret < 0)
{
fuse_reply_err (req, errno);
return;
}
}
if (delete_whiteout (lo, -1, pnode, name) < 0)
if (need_delete_whiteout && delete_whiteout (lo, -1, pnode, name) < 0)
{
fuse_reply_err (req, errno);
return;
@ -4100,7 +4153,7 @@ ovl_mkdir (fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode)
memset (&e, 0, sizeof (e));
ret = rpl_stat (req, node, -1, NULL, &e.attr);
ret = rpl_stat (req, node, -1, NULL, parent_upperdir_only ? &st : NULL, &e.attr);
if (ret)
{
fuse_reply_err (req, errno);
@ -4127,7 +4180,7 @@ do_fsync (fuse_req_t req, fuse_ino_t ino, int datasync, int fd)
if (!lo->fsync)
{
fuse_reply_err (req, 0);
fuse_reply_err (req, ENOSYS);
return;
}
@ -4168,7 +4221,7 @@ do_fsync (fuse_req_t req, fuse_ino_t ino, int datasync, int fd)
static void
ovl_fsync (fuse_req_t req, fuse_ino_t ino, int datasync, struct fuse_file_info *fi)
{
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_fsync(ino=%" PRIu64 ", datasync=%d, fi=%p)\n",
ino, datasync, fi);
@ -4178,7 +4231,7 @@ ovl_fsync (fuse_req_t req, fuse_ino_t ino, int datasync, struct fuse_file_info *
static void
ovl_fsyncdir (fuse_req_t req, fuse_ino_t ino, int datasync, struct fuse_file_info *fi)
{
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_fsyncdir(ino=%" PRIu64 ", datasync=%d, fi=%p)\n",
ino, datasync, fi);
@ -4203,7 +4256,7 @@ ovl_ioctl (fuse_req_t req, fuse_ino_t ino, unsigned int cmd, void *arg,
return;
}
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_ioctl(ino=%" PRIu64 ", cmd=%d, arg=%p, fi=%p, flags=%d, buf=%p, in_bufsz=%zu, out_bufsz=%zu)\n",
ino, cmd, arg, fi, flags, in_buf, in_bufsz, out_bufsz);
@ -4266,7 +4319,7 @@ ovl_fallocate (fuse_req_t req, fuse_ino_t ino, int mode, off_t offset, off_t len
struct ovl_node *node;
int ret;
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_fallocate(ino=%" PRIu64 ", mode=%d, offset=%llo, length=%llu, fi=%p)\n",
ino, mode, offset, length, fi);
@ -4308,7 +4361,7 @@ ovl_copy_file_range (fuse_req_t req, fuse_ino_t ino_in, off_t off_in, struct fus
cleanup_close int fd = -1;
ssize_t ret;
if (ovl_debug (req))
if (UNLIKELY (ovl_debug (req)))
fprintf (stderr, "ovl_copy_file_range(ino_in=%" PRIu64 ", off_in=%llo, fi_in=%p), ino_out=%" PRIu64 ", off_out=%llo, fi_out=%p, size=%zu, flags=%d)\n",
ino_in, off_in, fi_in, ino_out, off_out, fi_out, len, flags);
@ -4436,6 +4489,10 @@ fuse_opt_proc (void *data, const char *arg, int key, struct fuse_args *outargs)
return 1;
if (strcmp (arg, "noexec") == 0)
return 1;
if (strcmp (arg, "atime") == 0)
return 1;
if (strcmp (arg, "noatime") == 0)
return 1;
if (strcmp (arg, "splice_write") == 0)
return 1;
if (strcmp (arg, "splice_read") == 0)

View File

@ -54,4 +54,7 @@ cleanup_dirp (DIR **p)
# define cleanup_close __attribute__((cleanup (cleanup_closep)))
# define cleanup_dir __attribute__((cleanup (cleanup_dirp)))
# define LIKELY(x) __builtin_expect((x),1)
# define UNLIKELY(x) __builtin_expect((x),0)
#endif