On 16/10/17(Mon) 14:37, Helg Bredow wrote:
> [...]
> Patch is below.
Do you mind explaining the problem and the solution you implemented?
Some comments below:
> Index: lib/libfuse/fuse.h
> ===================================================================
> RCS file: /cvs/src/lib/libfuse/fuse.h,v
> retrieving revision 1.12
> diff -u -p -r1.12 fuse.h
> --- lib/libfuse/fuse.h 20 Jan 2014 15:01:59 -0000 1.12
> +++ lib/libfuse/fuse.h 16 Oct 2017 14:21:06 -0000
> @@ -89,6 +89,7 @@ typedef int (*fuse_fill_dir_t)(void *, c
> off_t);
>
> typedef struct fuse_dirhandle {
> + struct fuse *fuse;
Are you sure you can save this across calls?
> fuse_fill_dir_t filler;
> void *buf;
> int filled;
> Index: lib/libfuse/fuse_ops.c
> ===================================================================
> RCS file: /cvs/src/lib/libfuse/fuse_ops.c,v
> retrieving revision 1.26
> diff -u -p -r1.26 fuse_ops.c
> --- lib/libfuse/fuse_ops.c 7 Sep 2016 17:53:35 -0000 1.26
> +++ lib/libfuse/fuse_ops.c 16 Oct 2017 14:21:06 -0000
> @@ -217,17 +217,23 @@ static int
> ifuse_fill_readdir(void *dh, const char *name, const struct stat *stbuf,
> off_t off)
> {
> + struct fuse *f;
> struct fuse_dirhandle *fd = dh;
> + struct fuse_vnode *v;
> struct fusebuf *fbuf;
> struct dirent *dir;
> uint32_t namelen;
> uint32_t len;
>
> + f = fd->fuse;
> fbuf = fd->buf;
> namelen = strnlen(name, MAXNAMLEN);
> len = GENERIC_DIRSIZ(namelen);
>
> - if (fd->full || (fbuf->fb_len + len > fd->size)) {
> + if (fd->full)
> + return (0);
> +
> + if (fbuf->fb_len + len > fd->size) {
> fd->full = 1;
> return (0);
Why is this chunk necessary? Is it part of the fix?
> }
> @@ -242,13 +248,21 @@ ifuse_fill_readdir(void *dh, const char
> if (off)
> fd->filled = 0;
>
> - if (stbuf) {
> - dir->d_fileno = stbuf->st_ino;
> + /* TODO Add support for use_ino and readdir_ino */
> + v = get_vn_by_name_and_parent(f, (uint8_t *)name, fbuf->fb_ino);
> + if (v == NULL) {
> + if (strcmp(name, ".") == 0)
> + dir->d_fileno = fbuf->fb_ino;
> + else
> + dir->d_fileno = 0xffffffff;
> + } else
> + dir->d_fileno = v->ino;
> +
> + if (stbuf)
> dir->d_type = IFTODT(stbuf->st_mode);
> - } else {
> - dir->d_fileno = 0xffffffff;
> + else
> dir->d_type = DT_UNKNOWN;
> - }
> +
> dir->d_reclen = len;
> dir->d_off = off + len; /* XXX */
> strlcpy(dir->d_name, name, sizeof(dir->d_name));
> @@ -295,7 +309,7 @@ ifuse_ops_readdir(struct fuse *f, struct
> ffi.fh = fbuf->fb_io_fd;
> offset = fbuf->fb_io_off;
> size = fbuf->fb_io_len;
> - startsave = 0;
> + startsave = offset;
>
> fbuf->fb_dat = calloc(1, size);
>
> @@ -319,6 +333,8 @@ ifuse_ops_readdir(struct fuse *f, struct
> vn->fd->size = size;
> vn->fd->off = offset;
> vn->fd->idx = 0;
> + vn->fd->fuse = f;
> + vn->fd->start = offset;
> startsave = vn->fd->start;
>
> realname = build_realname(f, vn->ino);
> @@ -345,7 +361,8 @@ ifuse_ops_readdir(struct fuse *f, struct
> if (fbuf->fb_err) {
> fbuf->fb_len = 0;
> vn->fd->filled = 1;
> - }
> + } else if (vn->fd->full && fbuf->fb_len == 0)
> + fbuf->fb_err = -ENOBUFS;
>
> if (fbuf->fb_len == 0)
> free(fbuf->fb_dat);
> Index: sys/miscfs/fuse/fuse_vnops.c
> ===================================================================
> RCS file: /cvs/src/sys/miscfs/fuse/fuse_vnops.c,v
> retrieving revision 1.33
> diff -u -p -r1.33 fuse_vnops.c
> --- sys/miscfs/fuse/fuse_vnops.c 7 Sep 2016 17:53:35 -0000 1.33
> +++ sys/miscfs/fuse/fuse_vnops.c 16 Oct 2017 14:21:17 -0000
> @@ -680,7 +680,7 @@ fusefs_readdir(void *v)
> struct vnode *vp;
> struct proc *p;
> struct uio *uio;
> - int error = 0, eofflag = 0;
> + int error = 0, eofflag = 0, diropen = 0;
>
> vp = ap->a_vp;
> uio = ap->a_uio;
> @@ -695,14 +695,18 @@ fusefs_readdir(void *v)
> if (uio->uio_resid < sizeof(struct dirent))
> return (EINVAL);
>
> + if (ip->fufh[FUFH_RDONLY].fh_type == FUFH_INVALID) {
> + error = fusefs_file_open(fmp, ip, FUFH_RDONLY, O_RDONLY, 1, p);
> + if (error) {
> + fb_delete(fbuf);
> + goto out;
You can use return (error) here and remove the goto.
> + }
> + diropen = 1;
> + }
> +
> while (uio->uio_resid > 0) {
> fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_READDIR, p);
>
> - if (ip->fufh[FUFH_RDONLY].fh_type == FUFH_INVALID) {
> - /* TODO open the file */
> - fb_delete(fbuf);
> - return (error);
> - }
> fbuf->fb_io_fd = ip->fufh[FUFH_RDONLY].fh_id;
> fbuf->fb_io_off = uio->uio_offset;
> fbuf->fb_io_len = MIN(uio->uio_resid, fmp->max_read);
> @@ -710,6 +714,11 @@ fusefs_readdir(void *v)
> error = fb_queue(fmp->dev, fbuf);
>
> if (error) {
> + /* Not a real error, dirent was larger than residual
> + space left in buffer. Return as normal. */
s/Not a real error,//
s/return as normal.//
And look a style(9) for the comment formatting.
> + if (error == ENOBUFS && fbuf->fb_len == 0)
> + error = 0;
> +
> fb_delete(fbuf);
> break;
> }
> @@ -732,6 +741,10 @@ fusefs_readdir(void *v)
> if (!error && ap->a_eofflag != NULL)
> *ap->a_eofflag = eofflag;
>
> + if (diropen)
> + fusefs_file_close(fmp, ip, FUFH_RDONLY, O_RDONLY, 1, p);
> +
> +out:
> return (error);
> }
>
>
>