mirror of
https://github.com/containers/fuse-overlayfs.git
synced 2025-09-14 09:46:33 -04:00
Merge pull request #89 from giuseppe/perf-improvements-2
fuse-overlayfs: different performance tweaks continuation of #88
This commit is contained in:
commit
bd9eb8d5cd
289
main.c
289
main.c
@ -210,10 +210,10 @@ struct ovl_node
|
|||||||
int lookups;
|
int lookups;
|
||||||
int hidden_dirfd;
|
int hidden_dirfd;
|
||||||
int nlinks;
|
int nlinks;
|
||||||
ino_t ino;
|
mode_t mode;
|
||||||
size_t name_hash;
|
size_t name_hash;
|
||||||
|
ino_t ino;
|
||||||
|
|
||||||
unsigned int present_lowerdir : 1;
|
|
||||||
unsigned int do_unlink : 1;
|
unsigned int do_unlink : 1;
|
||||||
unsigned int do_rmdir : 1;
|
unsigned int do_rmdir : 1;
|
||||||
unsigned int hidden : 1;
|
unsigned int hidden : 1;
|
||||||
@ -759,36 +759,41 @@ hide_node (struct ovl_data *lo, struct ovl_node *node, bool unlink_src)
|
|||||||
|
|
||||||
assert (node->layer == get_upper_layer (lo));
|
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)
|
if (unlink_src)
|
||||||
{
|
{
|
||||||
/* If the atomic rename+mknod failed, then fallback into doing it in two steps. */
|
bool moved = false;
|
||||||
if (syscall (SYS_renameat2, node_dirfd (node), node->path, lo->workdir_fd,
|
bool whiteout_created = false;
|
||||||
newpath, RENAME_WHITEOUT) < 0)
|
bool needs_whiteout;
|
||||||
|
|
||||||
|
needs_whiteout = node->parent && node->parent->last_layer != get_upper_layer (lo);
|
||||||
|
|
||||||
|
if (needs_whiteout)
|
||||||
{
|
{
|
||||||
if (node->parent)
|
/* If the atomic rename+mknod failed, then fallback into doing it in two steps. */
|
||||||
|
if (can_mknod && syscall (SYS_renameat2, node_dirfd (node), node->path, lo->workdir_fd, newpath, RENAME_WHITEOUT) == 0)
|
||||||
{
|
{
|
||||||
/* If we are here, it means we have no permissions to use mknod. Also
|
whiteout_created = true;
|
||||||
since the file is not yet moved, creating a whiteout would fail on
|
moved = true;
|
||||||
the mknodat call. */
|
|
||||||
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 (!whiteout_created)
|
||||||
{
|
{
|
||||||
if (node->parent)
|
if (node->parent)
|
||||||
{
|
{
|
||||||
char whpath[PATH_MAX];
|
/* If we are here, it means we have no permissions to use mknod. Also
|
||||||
|
since the file is not yet moved, creating a whiteout would fail on
|
||||||
strconcat3 (whpath, PATH_MAX, node->parent->path, "/.wh.", node->name);
|
the mknodat call. */
|
||||||
unlinkat (get_upper_layer (lo)->fd, whpath, 0);
|
if (create_whiteout (lo, node->parent, node->name, true, false) < 0)
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!moved)
|
||||||
|
{
|
||||||
|
if (renameat (node_dirfd (node), node->path, lo->workdir_fd, newpath) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -852,12 +857,14 @@ get_gid (struct ovl_data *data, gid_t id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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);
|
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);
|
ret = fstat (fd, st);
|
||||||
else if (path != NULL)
|
else if (path != NULL)
|
||||||
ret = stat (path, st);
|
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++;
|
st->st_nlink++;
|
||||||
}
|
}
|
||||||
node->nlinks = st->st_nlink;
|
node->nlinks = st->st_nlink;
|
||||||
|
node->mode = st->st_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
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 ();
|
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",
|
fprintf (stderr, "ovl_forget(ino=%" PRIu64 ", nlookup=%lu)\n",
|
||||||
ino, nlookup);
|
ino, nlookup);
|
||||||
do_forget (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;
|
size_t i;
|
||||||
cleanup_lock int l = enter_big_lock ();
|
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",
|
fprintf (stderr, "ovl_forget_multi(count=%zu, forgets=%p)\n",
|
||||||
count, forgets);
|
count, forgets);
|
||||||
|
|
||||||
@ -1149,7 +1157,10 @@ make_ovl_node (const char *path, struct ovl_layer *layer, const char *name, ino_
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (fstat (fd, &st) == 0)
|
if (fstat (fd, &st) == 0)
|
||||||
ret->ino = st.st_ino;
|
{
|
||||||
|
ret->ino = st.st_ino;
|
||||||
|
ret->last_layer = it;
|
||||||
|
}
|
||||||
|
|
||||||
s = safe_read_xattr (&val, fd, PRIVILEGED_ORIGIN_XATTR, PATH_MAX);
|
s = safe_read_xattr (&val, fd, PRIVILEGED_ORIGIN_XATTR, PATH_MAX);
|
||||||
if (s > 0)
|
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);
|
child = hash_lookup (n->children, &key);
|
||||||
if (child)
|
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);
|
hash_delete (n->children, child);
|
||||||
node_free (child);
|
node_free (child);
|
||||||
child = NULL;
|
child = NULL;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
if (it->low)
|
|
||||||
child->present_lowerdir = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (lo->fast_ino_check)
|
if (lo->fast_ino_check)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1386,13 +1395,13 @@ load_dir (struct ovl_data *lo, struct ovl_node *n, struct ovl_layer *layer, char
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
child = make_ovl_node (node_path, it, dent->d_name, 0, dirp, n, lo->fast_ino_check);
|
child = make_ovl_node (node_path, it, dent->d_name, 0, dirp, n, lo->fast_ino_check);
|
||||||
if (child == NULL)
|
if (child == NULL)
|
||||||
{
|
{
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return NULL;
|
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)
|
if (node)
|
||||||
{
|
{
|
||||||
node->ino = st.st_ino;
|
node->ino = st.st_ino;
|
||||||
if (it->low)
|
node->last_layer = it;
|
||||||
node->present_lowerdir = 1;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1613,11 +1621,9 @@ insert_node:
|
|||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (node->last_layer)
|
|
||||||
break;
|
|
||||||
if (pnode && pnode->last_layer == it)
|
if (pnode && pnode->last_layer == it)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (lo->fast_ino_check)
|
if (lo->fast_ino_check)
|
||||||
break;
|
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_data *lo = ovl_data (req);
|
||||||
struct ovl_node *node;
|
struct ovl_node *node;
|
||||||
|
|
||||||
if (ovl_debug (req))
|
if (UNLIKELY (ovl_debug (req)))
|
||||||
fprintf (stderr, "ovl_lookup(parent=%" PRIu64 ", name=%s)\n",
|
fprintf (stderr, "ovl_lookup(parent=%" PRIu64 ", name=%s)\n",
|
||||||
parent, name);
|
parent, name);
|
||||||
|
|
||||||
@ -1656,7 +1662,7 @@ ovl_lookup (fuse_req_t req, fuse_ino_t parent, const char *name)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = rpl_stat (req, node, -1, NULL, &e.attr);
|
err = rpl_stat (req, node, -1, NULL, NULL, &e.attr);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
fuse_reply_err (req, errno);
|
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));
|
struct ovl_dirp *d = calloc (1, sizeof (struct ovl_dirp));
|
||||||
cleanup_lock int l = enter_big_lock ();
|
cleanup_lock int l = enter_big_lock ();
|
||||||
|
|
||||||
if (ovl_debug (req))
|
if (UNLIKELY (ovl_debug (req)))
|
||||||
fprintf (stderr, "ovl_opendir(ino=%" PRIu64 ")\n", ino);
|
fprintf (stderr, "ovl_opendir(ino=%" PRIu64 ")\n", ino);
|
||||||
|
|
||||||
if (d == NULL)
|
if (d == NULL)
|
||||||
@ -1858,7 +1864,7 @@ ovl_do_readdir (fuse_req_t req, fuse_ino_t ino, size_t size,
|
|||||||
char *p;
|
char *p;
|
||||||
cleanup_free char *buffer = NULL;
|
cleanup_free char *buffer = NULL;
|
||||||
|
|
||||||
buffer = calloc (size, 1);
|
buffer = malloc (size);
|
||||||
if (buffer == NULL)
|
if (buffer == NULL)
|
||||||
{
|
{
|
||||||
fuse_reply_err (req, ENOMEM);
|
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;
|
int ret;
|
||||||
size_t entsize;
|
size_t entsize;
|
||||||
struct stat st;
|
|
||||||
const char *name;
|
const char *name;
|
||||||
struct ovl_node *node = d->tbl[offset];
|
struct ovl_node *node = d->tbl[offset];
|
||||||
|
struct fuse_entry_param e;
|
||||||
|
struct stat *st = &e.attr;
|
||||||
|
|
||||||
if (node == NULL || node->whiteout || node->hidden)
|
if (node == NULL || node->whiteout || node->hidden)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ret = rpl_stat (req, node, -1, NULL, &st);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
fuse_reply_err (req, errno);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset == 0)
|
if (offset == 0)
|
||||||
name = ".";
|
name = ".";
|
||||||
else if (offset == 1)
|
else if (offset == 1)
|
||||||
@ -1895,17 +1895,28 @@ ovl_do_readdir (fuse_req_t req, fuse_ino_t ino, size_t size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!plus)
|
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
|
else
|
||||||
{
|
{
|
||||||
struct fuse_entry_param e;
|
|
||||||
|
|
||||||
memset (&e, 0, sizeof (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.attr_timeout = get_timeout (lo);
|
||||||
e.entry_timeout = get_timeout (lo);
|
e.entry_timeout = get_timeout (lo);
|
||||||
e.ino = NODE_TO_INODE (node);
|
e.ino = NODE_TO_INODE (node);
|
||||||
memcpy (&e.attr, &st, sizeof (st));
|
|
||||||
|
|
||||||
entsize = fuse_add_direntry_plus (req, p, remaining, name, &e, offset + 1);
|
entsize = fuse_add_direntry_plus (req, p, remaining, name, &e, offset + 1);
|
||||||
if (entsize <= remaining)
|
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)
|
off_t offset, struct fuse_file_info *fi)
|
||||||
{
|
{
|
||||||
cleanup_lock int l = enter_big_lock ();
|
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);
|
fprintf (stderr, "ovl_readdir(ino=%" PRIu64 ", size=%zu, offset=%llo)\n", ino, size, offset);
|
||||||
ovl_do_readdir (req, ino, size, offset, fi, 0);
|
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)
|
off_t offset, struct fuse_file_info *fi)
|
||||||
{
|
{
|
||||||
cleanup_lock int l = enter_big_lock ();
|
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);
|
fprintf (stderr, "ovl_readdirplus(ino=%" PRIu64 ", size=%zu, offset=%llo)\n", ino, size, offset);
|
||||||
ovl_do_readdir (req, ino, size, offset, fi, 1);
|
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;
|
size_t s;
|
||||||
struct ovl_dirp *d = ovl_dirp (fi);
|
struct ovl_dirp *d = ovl_dirp (fi);
|
||||||
|
|
||||||
if (ovl_debug (req))
|
if (UNLIKELY (ovl_debug (req)))
|
||||||
fprintf (stderr, "ovl_releasedir(ino=%" PRIu64 ")\n", ino);
|
fprintf (stderr, "ovl_releasedir(ino=%" PRIu64 ")\n", ino);
|
||||||
|
|
||||||
for (s = 2; s < d->tbl_size; s++)
|
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];
|
char path[PATH_MAX];
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (ovl_debug (req))
|
if (UNLIKELY (ovl_debug (req)))
|
||||||
fprintf (stderr, "ovl_listxattr(ino=%" PRIu64 ", size=%zu)\n", ino, size);
|
fprintf (stderr, "ovl_listxattr(ino=%" PRIu64 ", size=%zu)\n", ino, size);
|
||||||
|
|
||||||
if (lo->disable_xattrs)
|
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;
|
bool is_security_capability = false;
|
||||||
int ret;
|
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);
|
fprintf (stderr, "ovl_getxattr(ino=%" PRIu64 ", name=%s, size=%zu)\n", ino, name, size);
|
||||||
|
|
||||||
if (lo->disable_xattrs)
|
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_data *lo = ovl_data (req);
|
||||||
struct ovl_node *n = do_lookup_file (lo, ino, NULL);
|
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",
|
fprintf (stderr, "ovl_access(ino=%" PRIu64 ", mask=%d)\n",
|
||||||
ino, mask);
|
ino, mask);
|
||||||
|
|
||||||
ret = faccessat (node_dirfd (n), n->path, mask, AT_SYMLINK_NOFOLLOW);
|
if (mask & n->mode == mask)
|
||||||
fuse_reply_err (req, ret < 0 ? errno : 0);
|
fuse_reply_err (req, 0);
|
||||||
|
else
|
||||||
|
fuse_reply_err (req, EPERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -2147,7 +2160,7 @@ static int create_node_directory (struct ovl_data *lo, struct ovl_node *src);
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
create_directory (struct ovl_data *lo, int dirfd, const char *name, const struct timespec *times,
|
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;
|
int ret;
|
||||||
cleanup_close int dfd = -1;
|
cleanup_close int dfd = -1;
|
||||||
@ -2190,11 +2203,18 @@ create_directory (struct ovl_data *lo, int dirfd, const char *name, const struct
|
|||||||
goto out;
|
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);
|
ret = renameat (lo->workdir_fd, wd_tmp_file_name, dirfd, name);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
|
if (errno == ENOTDIR)
|
||||||
|
unlinkat (dirfd, name, 0);
|
||||||
if (errno == ENOENT && parent)
|
if (errno == ENOENT && parent)
|
||||||
{
|
{
|
||||||
ret = create_node_directory (lo, 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[0] = st.st_atim;
|
||||||
times[1] = st.st_mtim;
|
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)
|
if (ret == 0)
|
||||||
{
|
{
|
||||||
src->layer = get_upper_layer (lo);
|
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_data *lo = ovl_data (req);
|
||||||
struct ovl_node *pnode;
|
struct ovl_node *pnode;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
size_t whiteouts = 0;
|
||||||
struct ovl_node key, *rm;
|
struct ovl_node key, *rm;
|
||||||
|
|
||||||
node = do_lookup_file (lo, parent, name);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = count_dir_entries (node, NULL);
|
c = count_dir_entries (node, &whiteouts);
|
||||||
if (c)
|
if (c)
|
||||||
{
|
{
|
||||||
fuse_reply_err (req, ENOTEMPTY);
|
fuse_reply_err (req, ENOTEMPTY);
|
||||||
@ -2597,10 +2618,13 @@ do_rm (fuse_req_t req, fuse_ino_t parent, const char *name, bool dirp)
|
|||||||
node->do_unlink = 1;
|
node->do_unlink = 1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (empty_dir (lo, node) < 0)
|
if (whiteouts > 0)
|
||||||
{
|
{
|
||||||
fuse_reply_err (req, errno);
|
if (empty_dir (lo, node) < 0)
|
||||||
return;
|
{
|
||||||
|
fuse_reply_err (req, errno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
node->do_rmdir = 1;
|
node->do_rmdir = 1;
|
||||||
@ -2653,7 +2677,7 @@ static void
|
|||||||
ovl_unlink (fuse_req_t req, fuse_ino_t parent, const char *name)
|
ovl_unlink (fuse_req_t req, fuse_ino_t parent, const char *name)
|
||||||
{
|
{
|
||||||
cleanup_lock int l = enter_big_lock ();
|
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",
|
fprintf (stderr, "ovl_unlink(parent=%" PRIu64 ", name=%s)\n",
|
||||||
parent, name);
|
parent, name);
|
||||||
do_rm (req, parent, name, false);
|
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)
|
ovl_rmdir (fuse_req_t req, fuse_ino_t parent, const char *name)
|
||||||
{
|
{
|
||||||
cleanup_lock int l = enter_big_lock ();
|
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",
|
fprintf (stderr, "ovl_rmdir(parent=%" PRIu64 ", name=%s)\n",
|
||||||
parent, name);
|
parent, name);
|
||||||
do_rm (req, parent, name, true);
|
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];
|
char path[PATH_MAX];
|
||||||
int ret;
|
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,
|
fprintf (stderr, "ovl_setxattr(ino=%" PRIu64 "s, name=%s, value=%s, size=%zu, flags=%d)\n", ino, name,
|
||||||
value, size, flags);
|
value, size, flags);
|
||||||
|
|
||||||
@ -2747,7 +2771,7 @@ ovl_removexattr (fuse_req_t req, fuse_ino_t ino, const char *name)
|
|||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (ovl_debug (req))
|
if (UNLIKELY (ovl_debug (req)))
|
||||||
fprintf (stderr, "ovl_removexattr(ino=%" PRIu64 "s, name=%s)\n", ino, name);
|
fprintf (stderr, "ovl_removexattr(ino=%" PRIu64 "s, name=%s)\n", ino, name);
|
||||||
|
|
||||||
node = do_lookup_file (lo, ino, NULL);
|
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)
|
off_t offset, struct fuse_file_info *fi)
|
||||||
{
|
{
|
||||||
struct fuse_bufvec buf = FUSE_BUFVEC_INIT (size);
|
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, "
|
fprintf (stderr, "ovl_read(ino=%" PRIu64 ", size=%zd, "
|
||||||
"off=%lu)\n", ino, size, (unsigned long) offset);
|
"off=%lu)\n", ino, size, (unsigned long) offset);
|
||||||
buf.buf[0].flags = FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK;
|
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].fd = fi->fh;
|
||||||
out_buf.buf[0].pos = off;
|
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",
|
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);
|
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;
|
int ret;
|
||||||
(void) ino;
|
(void) ino;
|
||||||
|
|
||||||
if (ovl_debug (req))
|
if (UNLIKELY (ovl_debug (req)))
|
||||||
fprintf (stderr, "ovl_release(ino=%" PRIu64 ")\n", ino);
|
fprintf (stderr, "ovl_release(ino=%" PRIu64 ")\n", ino);
|
||||||
|
|
||||||
ret = close (fi->fh);
|
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));
|
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)
|
if (err < 0)
|
||||||
return err;
|
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_data *lo = ovl_data (req);
|
||||||
struct ovl_node *node;
|
struct ovl_node *node;
|
||||||
|
|
||||||
if (ovl_debug (req))
|
if (UNLIKELY (ovl_debug (req)))
|
||||||
fprintf (stderr, "ovl_create(parent=%" PRIu64 ", name=%s)\n",
|
fprintf (stderr, "ovl_create(parent=%" PRIu64 ", name=%s)\n",
|
||||||
parent, name);
|
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_lock int l = enter_big_lock ();
|
||||||
cleanup_close int fd = -1;
|
cleanup_close int fd = -1;
|
||||||
|
|
||||||
if (ovl_debug (req))
|
if (UNLIKELY (ovl_debug (req)))
|
||||||
fprintf (stderr, "ovl_open(ino=%" PRIu64 "s)\n", ino);
|
fprintf (stderr, "ovl_open(ino=%" PRIu64 "s)\n", ino);
|
||||||
|
|
||||||
fd = ovl_do_open (req, ino, NULL, fi->flags, 0700);
|
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 ovl_node *node;
|
||||||
struct fuse_entry_param e;
|
struct fuse_entry_param e;
|
||||||
|
|
||||||
if (ovl_debug (req))
|
if (UNLIKELY (ovl_debug (req)))
|
||||||
fprintf (stderr, "ovl_getattr(ino=%" PRIu64 "s)\n", ino);
|
fprintf (stderr, "ovl_getattr(ino=%" PRIu64 "s)\n", ino);
|
||||||
|
|
||||||
node = do_lookup_file (lo, ino, NULL);
|
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;
|
int fd;
|
||||||
char proc_path[PATH_MAX];
|
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);
|
fprintf (stderr, "ovl_setattr(ino=%" PRIu64 "s, to_set=%d)\n", ino, to_set);
|
||||||
|
|
||||||
node = do_lookup_file (lo, ino, NULL);
|
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;
|
struct fuse_entry_param e;
|
||||||
char wd_tmp_file_name[32];
|
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);
|
fprintf (stderr, "ovl_link(ino=%" PRIu64 "s, newparent=%" PRIu64 "s, newname=%s)\n", ino, newparent, newname);
|
||||||
|
|
||||||
node = do_lookup_file (lo, ino, NULL);
|
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));
|
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)
|
if (ret)
|
||||||
{
|
{
|
||||||
fuse_reply_err (req, errno);
|
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;
|
struct fuse_entry_param e;
|
||||||
const struct fuse_ctx *ctx = fuse_req_ctx (req);
|
const struct fuse_ctx *ctx = fuse_req_ctx (req);
|
||||||
char wd_tmp_file_name[32];
|
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);
|
fprintf (stderr, "ovl_symlink(link=%s, ino=%" PRIu64 "s, name=%s)\n", link, parent, name);
|
||||||
|
|
||||||
pnode = do_lookup_file (lo, parent, NULL);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pnode->loaded && node == NULL)
|
||||||
|
need_delete_whiteout = false;
|
||||||
|
|
||||||
sprintf (wd_tmp_file_name, "%lu", get_next_wd_counter ());
|
sprintf (wd_tmp_file_name, "%lu", get_next_wd_counter ());
|
||||||
|
|
||||||
unlinkat (lo->workdir_fd, wd_tmp_file_name, 0);
|
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;
|
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);
|
unlinkat (lo->workdir_fd, wd_tmp_file_name, 0);
|
||||||
fuse_reply_err (req, errno);
|
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));
|
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)
|
if (ret)
|
||||||
{
|
{
|
||||||
fuse_reply_err (req, errno);
|
fuse_reply_err (req, errno);
|
||||||
@ -3495,7 +3523,7 @@ ovl_rename_exchange (fuse_req_t req, fuse_ino_t parent, const char *name,
|
|||||||
return;
|
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);
|
fuse_reply_err (req, EXDEV);
|
||||||
return;
|
return;
|
||||||
@ -3535,7 +3563,7 @@ ovl_rename_exchange (fuse_req_t req, fuse_ino_t parent, const char *name,
|
|||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
goto error;
|
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);
|
fuse_reply_err (req, EXDEV);
|
||||||
return;
|
return;
|
||||||
@ -3627,7 +3655,7 @@ ovl_rename_direct (fuse_req_t req, fuse_ino_t parent, const char *name,
|
|||||||
return;
|
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);
|
fuse_reply_err (req, EXDEV);
|
||||||
return;
|
return;
|
||||||
@ -3798,7 +3826,7 @@ ovl_rename (fuse_req_t req, fuse_ino_t parent, const char *name,
|
|||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
cleanup_lock int l = enter_big_lock ();
|
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);
|
fprintf (stderr, "ovl_rename(ino=%" PRIu64 "s, name=%s , ino=%" PRIu64 "s, name=%s)\n", parent, name, newparent, newname);
|
||||||
|
|
||||||
if (flags & RENAME_EXCHANGE)
|
if (flags & RENAME_EXCHANGE)
|
||||||
@ -3814,7 +3842,7 @@ ovl_statfs (fuse_req_t req, fuse_ino_t ino)
|
|||||||
struct statvfs sfs;
|
struct statvfs sfs;
|
||||||
struct ovl_data *lo = ovl_data (req);
|
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);
|
fprintf (stderr, "ovl_statfs(ino=%" PRIu64 "s)\n", ino);
|
||||||
|
|
||||||
ret = fstatvfs (get_upper_layer (lo)->fd, &sfs);
|
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;
|
size_t current_size;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (ovl_debug (req))
|
if (UNLIKELY (ovl_debug (req)))
|
||||||
fprintf (stderr, "ovl_readlink(ino=%" PRIu64 "s)\n", ino);
|
fprintf (stderr, "ovl_readlink(ino=%" PRIu64 "s)\n", ino);
|
||||||
|
|
||||||
node = do_lookup_file (lo, ino, NULL);
|
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);
|
const struct fuse_ctx *ctx = fuse_req_ctx (req);
|
||||||
char wd_tmp_file_name[32];
|
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",
|
fprintf (stderr, "ovl_mknod(ino=%" PRIu64 ", name=%s, mode=%d, rdev=%lu)\n",
|
||||||
parent, name, mode, rdev);
|
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));
|
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)
|
if (ret)
|
||||||
{
|
{
|
||||||
fuse_reply_err (req, errno);
|
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
|
static void
|
||||||
ovl_mkdir (fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode)
|
ovl_mkdir (fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode)
|
||||||
{
|
{
|
||||||
cleanup_lock int l = enter_big_lock ();
|
const struct fuse_ctx *ctx = fuse_req_ctx (req);
|
||||||
struct ovl_node *node;
|
|
||||||
struct ovl_data *lo = ovl_data (req);
|
struct ovl_data *lo = ovl_data (req);
|
||||||
|
struct fuse_entry_param e;
|
||||||
|
bool parent_upperdir_only;
|
||||||
struct ovl_node *pnode;
|
struct ovl_node *pnode;
|
||||||
|
struct ovl_node *node;
|
||||||
|
struct stat st;
|
||||||
|
ino_t ino = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
char *path;
|
char *path;
|
||||||
struct fuse_entry_param e;
|
bool need_delete_whiteout = true;
|
||||||
const struct fuse_ctx *ctx = fuse_req_ctx (req);
|
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",
|
fprintf (stderr, "ovl_mkdir(ino=%" PRIu64 ", name=%s, mode=%d)\n",
|
||||||
parent, name, mode);
|
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);
|
fuse_reply_err (req, errno);
|
||||||
return;
|
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);
|
ret = asprintf (&path, "%s/%s", pnode->path, name);
|
||||||
if (ret < 0)
|
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,
|
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)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
fuse_reply_err (req, errno);
|
fuse_reply_err (req, errno);
|
||||||
return;
|
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)
|
if (node == NULL)
|
||||||
{
|
{
|
||||||
fuse_reply_err (req, ENOMEM);
|
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);
|
fuse_reply_err (req, ENOMEM);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ret = hide_all (lo, node);
|
|
||||||
if (ret < 0)
|
if (parent_upperdir_only)
|
||||||
{
|
{
|
||||||
fuse_reply_err (req, errno);
|
node->last_layer = pnode->last_layer;
|
||||||
return;
|
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);
|
fuse_reply_err (req, errno);
|
||||||
return;
|
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));
|
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)
|
if (ret)
|
||||||
{
|
{
|
||||||
fuse_reply_err (req, errno);
|
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)
|
if (!lo->fsync)
|
||||||
{
|
{
|
||||||
fuse_reply_err (req, 0);
|
fuse_reply_err (req, ENOSYS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4168,7 +4221,7 @@ do_fsync (fuse_req_t req, fuse_ino_t ino, int datasync, int fd)
|
|||||||
static void
|
static void
|
||||||
ovl_fsync (fuse_req_t req, fuse_ino_t ino, int datasync, struct fuse_file_info *fi)
|
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",
|
fprintf (stderr, "ovl_fsync(ino=%" PRIu64 ", datasync=%d, fi=%p)\n",
|
||||||
ino, datasync, fi);
|
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
|
static void
|
||||||
ovl_fsyncdir (fuse_req_t req, fuse_ino_t ino, int datasync, struct fuse_file_info *fi)
|
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",
|
fprintf (stderr, "ovl_fsyncdir(ino=%" PRIu64 ", datasync=%d, fi=%p)\n",
|
||||||
ino, datasync, fi);
|
ino, datasync, fi);
|
||||||
|
|
||||||
@ -4203,7 +4256,7 @@ ovl_ioctl (fuse_req_t req, fuse_ino_t ino, unsigned int cmd, void *arg,
|
|||||||
return;
|
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",
|
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);
|
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;
|
struct ovl_node *node;
|
||||||
int ret;
|
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",
|
fprintf (stderr, "ovl_fallocate(ino=%" PRIu64 ", mode=%d, offset=%llo, length=%llu, fi=%p)\n",
|
||||||
ino, mode, offset, length, fi);
|
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;
|
cleanup_close int fd = -1;
|
||||||
ssize_t ret;
|
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",
|
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);
|
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;
|
return 1;
|
||||||
if (strcmp (arg, "noexec") == 0)
|
if (strcmp (arg, "noexec") == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
if (strcmp (arg, "atime") == 0)
|
||||||
|
return 1;
|
||||||
|
if (strcmp (arg, "noatime") == 0)
|
||||||
|
return 1;
|
||||||
if (strcmp (arg, "splice_write") == 0)
|
if (strcmp (arg, "splice_write") == 0)
|
||||||
return 1;
|
return 1;
|
||||||
if (strcmp (arg, "splice_read") == 0)
|
if (strcmp (arg, "splice_read") == 0)
|
||||||
|
3
utils.h
3
utils.h
@ -54,4 +54,7 @@ cleanup_dirp (DIR **p)
|
|||||||
# define cleanup_close __attribute__((cleanup (cleanup_closep)))
|
# define cleanup_close __attribute__((cleanup (cleanup_closep)))
|
||||||
# define cleanup_dir __attribute__((cleanup (cleanup_dirp)))
|
# define cleanup_dir __attribute__((cleanup (cleanup_dirp)))
|
||||||
|
|
||||||
|
# define LIKELY(x) __builtin_expect((x),1)
|
||||||
|
# define UNLIKELY(x) __builtin_expect((x),0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user