[Virtio-fs] [RFC 2/2] virtiofsd: Set st_rdev for sub-mount points

Dr. David Alan Gilbert dgilbert at redhat.com
Wed May 6 16:04:11 UTC 2020


* Max Reitz (mreitz at redhat.com) wrote:
> Whenever we encounter a directory with an st_dev that differs from that
> of its parent, we set st_rdev accordingly so the guest can create a
> submount for it.
> 
> Make this behavior optional, so submounts are only announced to the
> guest with the announce_submounts option.  Some users may prefer the
> current behavior, so that the guest learns nothing about the host mount
> structure.
> 
> Signed-off-by: Max Reitz <mreitz at redhat.com>

Does this need to be wired to a flag in the INIT message (like say
FUSE_ASYNC_READ) to indicate that the kernel/daemon supports this, or is
it really safe just to start sending the changed rdev?

Dave

> ---
>  tools/virtiofsd/passthrough_ll.c | 59 +++++++++++++++++++++++++++-----
>  1 file changed, 50 insertions(+), 9 deletions(-)
> 
> diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
> index 6cf471d31a..abf9d33493 100644
> --- a/tools/virtiofsd/passthrough_ll.c
> +++ b/tools/virtiofsd/passthrough_ll.c
> @@ -159,6 +159,7 @@ struct lo_data {
>      int timeout_set;
>      int readdirplus_set;
>      int readdirplus_clear;
> +    int announce_submounts;
>      struct lo_inode root;
>      GHashTable *inodes; /* protected by lo->mutex */
>      struct lo_map ino_map; /* protected by lo->mutex */
> @@ -187,6 +188,7 @@ static const struct fuse_opt lo_opts[] = {
>      { "norace", offsetof(struct lo_data, norace), 1 },
>      { "readdirplus", offsetof(struct lo_data, readdirplus_set), 1 },
>      { "no_readdirplus", offsetof(struct lo_data, readdirplus_clear), 1 },
> +    { "announce_submounts", offsetof(struct lo_data, announce_submounts), 1 },
>      FUSE_OPT_END
>  };
>  static bool use_syslog = false;
> @@ -582,17 +584,42 @@ static void lo_init(void *userdata, struct fuse_conn_info *conn)
>      }
>  }
>  
> +/**
> + * Call fstatat() and set st_rdev whenever a directory's st_dev
> + * differs from the rparent's st_dev (@parent_dev).  This will
> + * announce submounts to the FUSE client (unless @announce_submounts
> + * is false).
> + */
> +static int do_fstatat(int dirfd, const char *pathname, struct stat *statbuf,
> +                      int flags, dev_t parent_dev, bool announce_submounts)
> +{
> +    int res = fstatat(dirfd, pathname, statbuf, flags);
> +    if (res == -1) {
> +        return res;
> +    }
> +
> +    if (statbuf->st_dev != parent_dev && S_ISDIR(statbuf->st_mode) &&
> +        announce_submounts)
> +    {
> +        statbuf->st_rdev = statbuf->st_dev;
> +    }
> +
> +    return 0;
> +}
> +
>  static void lo_getattr(fuse_req_t req, fuse_ino_t ino,
>                         struct fuse_file_info *fi)
>  {
>      int res;
>      struct stat buf;
>      struct lo_data *lo = lo_data(req);
> +    struct lo_inode *inode = lo_inode(req, ino);
>  
>      (void)fi;
>  
> -    res =
> -        fstatat(lo_fd(req, ino), "", &buf, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
> +    res = do_fstatat(inode->fd, "", &buf, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW,
> +                     inode->parent_dev, lo->announce_submounts);
> +    lo_inode_put(lo, &inode);
>      if (res == -1) {
>          return (void)fuse_reply_err(req, errno);
>      }
> @@ -645,7 +672,9 @@ retry:
>          pthread_mutex_unlock(&lo->mutex);
>      } else {
>          *last = '\0';
> -        res = fstatat(AT_FDCWD, last == path ? "/" : path, &stat, 0);
> +        /* Pass parent_dev=0 because st_rdev will be ignored anyway */
> +        res = do_fstatat(AT_FDCWD, last == path ? "/" : path, &stat, 0, 0,
> +                         lo->announce_submounts);
>          if (res == -1) {
>              if (!retries) {
>                  fuse_log(FUSE_LOG_WARNING,
> @@ -663,7 +692,8 @@ retry:
>          }
>      }
>      last++;
> -    res = fstatat(p->fd, last, &stat, AT_SYMLINK_NOFOLLOW);
> +    res = do_fstatat(p->fd, last, &stat, AT_SYMLINK_NOFOLLOW, p->key.dev,
> +                     lo->announce_submounts);
>      if (res == -1) {
>          if (!retries) {
>              fuse_log(FUSE_LOG_WARNING,
> @@ -925,7 +955,8 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name,
>          goto out_err;
>      }
>  
> -    res = fstatat(newfd, "", &e->attr, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
> +    res = do_fstatat(newfd, "", &e->attr, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW,
> +                     dir->key.dev, lo->announce_submounts);
>      if (res == -1) {
>          goto out_err;
>      }
> @@ -1207,7 +1238,9 @@ static void lo_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t parent,
>          goto out_err;
>      }
>  
> -    res = fstatat(inode->fd, "", &e.attr, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
> +    res = do_fstatat(inode->fd, "", &e.attr,
> +                     AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW,
> +                     parent_inode->key.dev, lo->announce_submounts);
>      if (res == -1) {
>          goto out_err;
>      }
> @@ -1246,14 +1279,22 @@ static struct lo_inode *lookup_name(fuse_req_t req, fuse_ino_t parent,
>  {
>      int res;
>      struct stat attr;
> +    struct lo_data *lo = lo_data(req);
> +    struct lo_inode *dir = lo_inode(req, parent);
>  
> -    res = fstatat(lo_fd(req, parent), name, &attr,
> -                  AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
> +    if (!dir) {
> +        return NULL;
> +    }
> +
> +    res = do_fstatat(dir->fd, name, &attr,
> +                     AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW, dir->key.dev,
> +                     lo->announce_submounts);
> +    lo_inode_put(lo, &dir);
>      if (res == -1) {
>          return NULL;
>      }
>  
> -    return lo_find(lo_data(req), &attr);
> +    return lo_find(lo, &attr);
>  }
>  
>  static void lo_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
> -- 
> 2.26.2
> 
> _______________________________________________
> Virtio-fs mailing list
> Virtio-fs at redhat.com
> https://www.redhat.com/mailman/listinfo/virtio-fs
--
Dr. David Alan Gilbert / dgilbert at redhat.com / Manchester, UK




More information about the Virtio-fs mailing list