On Mon, May 05, 2014 at 08:40:10PM +0800, Helg wrote:
> This patch fixes a bug where fusefs_link does not return an error on
> subsequent invocations if a fuse filesystem does not implement hard
> links.
> 
> As an aside, returning ENOSYS in this case is contrary to the link(2)
> man page (and different again to the Open Group) but consistent with
> the fuse implementation on Linux.
> 
> -- 
> Helg <xx...@msn.com>
> 
> 
> Index: fuse_vnops.c
> ===================================================================
> RCS file: /cvs/src/sys/miscfs/fuse/fuse_vnops.c,v
> retrieving revision 1.16
> diff -u -p -r1.16 fuse_vnops.c
> --- fuse_vnops.c        18 Mar 2014 08:51:53 -0000      1.16
> +++ fuse_vnops.c        4 May 2014 06:32:50 -0000
> @@ -540,8 +540,10 @@ fusefs_link(void *v)
>         dip = VTOI(dvp);
>         fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
>  
> -       if (!fmp->sess_init || (fmp->undef_op & UNDEF_LINK))
> +       if (!fmp->sess_init || (fmp->undef_op & UNDEF_LINK)) {
> +               error = ENOSYS;
>                 goto out1;
> +       }
>  
>         fbuf = fb_setup(cnp->cn_namelen + 1, dip->ufs_ino.i_number,
>             FBT_LINK, p);
> 

Hi,

Thanks for your diff. Here is an updated version that adds some
consistency on fuse error handling. We need to return ENXIO when
the fuse communication channel is broken and ENOSYS when the libfuse
callback does not exist.

I've also modified some vnops to be sure that the checks for active
fuse communication channel and for libfuse callbacks presence are 
done first...

Any OK ?

Cheers,

Index: fuse_vnops.c
===================================================================
RCS file: /cvs/src/sys/miscfs/fuse/fuse_vnops.c,v
retrieving revision 1.16
diff -u -p -u -p -r1.16 fuse_vnops.c
--- fuse_vnops.c        18 Mar 2014 08:51:53 -0000      1.16
+++ fuse_vnops.c        7 May 2014 08:17:57 -0000
@@ -202,7 +202,7 @@ fusefs_open(void *v)
        fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
 
        if (!fmp->sess_init)
-               return (0);
+               return (ENXIO);
 
        isdir = 0;
        if (ip->vtype == VDIR)
@@ -293,7 +293,10 @@ fusefs_access(void *v)
        ip = VTOI(ap->a_vp);
        fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
 
-       if (!fmp->sess_init || (fmp->undef_op & UNDEF_ACCESS))
+       if (!fmp->sess_init)
+               return (ENXIO);
+
+       if (fmp->undef_op & UNDEF_ACCESS)
                goto system_check;
 
        if (ap->a_vp->v_type == VLNK)
@@ -358,7 +361,7 @@ fusefs_getattr(void *v)
        fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
 
        if (!fmp->sess_init)
-               goto fake;
+               return (ENXIO);
 
        fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_GETATTR, p);
 
@@ -372,10 +375,6 @@ fusefs_getattr(void *v)
        memcpy(vap, &fbuf->fb_vattr, sizeof(*vap));
        fb_delete(fbuf);
        return (error);
-fake:
-       bzero(vap, sizeof(*vap));
-       vap->va_type = vp->v_type;
-       return (0);
 }
 
 int
@@ -401,9 +400,12 @@ fusefs_setattr(void *v)
            ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL))
                return (EINVAL);
 
-       if (!fmp->sess_init || (fmp->undef_op & UNDEF_SETATTR))
+       if (!fmp->sess_init)
                return (ENXIO);
 
+       if (fmp->undef_op & UNDEF_SETATTR)
+               return (ENOSYS);
+
        fbuf = fb_setup(sizeof(*io), ip->ufs_ino.i_number, FBT_SETATTR, p);
        io = fbtod(fbuf, struct fb_io *);
        io->fi_flags = 0;
@@ -521,6 +523,20 @@ fusefs_link(void *v)
        struct fusebuf *fbuf;
        int error = 0;
 
+       ip = VTOI(vp);
+       dip = VTOI(dvp);
+       fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
+
+       if (!fmp->sess_init) {
+               VOP_ABORTOP(dvp, cnp);
+               error = ENXIO;
+               goto out2;
+       }
+       if (fmp->undef_op & UNDEF_LINK) {
+               VOP_ABORTOP(dvp, cnp);
+               error = ENOSYS;
+               goto out2;
+       }
        if (vp->v_type == VDIR) {
                VOP_ABORTOP(dvp, cnp);
                error = EISDIR;
@@ -536,13 +552,6 @@ fusefs_link(void *v)
                goto out2;
        }
 
-       ip = VTOI(vp);
-       dip = VTOI(dvp);
-       fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
-
-       if (!fmp->sess_init || (fmp->undef_op & UNDEF_LINK))
-               goto out1;
-
        fbuf = fb_setup(cnp->cn_namelen + 1, dip->ufs_ino.i_number,
            FBT_LINK, p);
 
@@ -591,7 +600,12 @@ fusefs_symlink(void *v)
        dp = VTOI(dvp);
        fmp = (struct fusefs_mnt *)dp->ufs_ino.i_ump;
 
-       if (!fmp->sess_init  || (fmp->undef_op & UNDEF_SYMLINK)) {
+       if (!fmp->sess_init) {
+               error = ENXIO;
+               goto bad;
+       }
+
+       if (fmp->undef_op & UNDEF_SYMLINK) {
                error = ENOSYS;
                goto bad;
        }
@@ -652,7 +666,7 @@ fusefs_readdir(void *v)
        fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
 
        if (!fmp->sess_init)
-               return (0);
+               return (ENXIO);
 
        if (uio->uio_resid < sizeof(struct dirent))
                return (EINVAL);
@@ -743,10 +757,11 @@ fusefs_readlink(void *v)
        uio = ap->a_uio;
        p = uio->uio_procp;
 
-       if (!fmp->sess_init || (fmp->undef_op & UNDEF_READLINK)) {
-               error = ENOSYS;
-               goto out;
-       }
+       if (!fmp->sess_init)
+               return (ENXIO);
+
+       if (fmp->undef_op & UNDEF_READLINK)
+               return (ENOSYS);
 
        fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_READLINK, p);
 
@@ -757,12 +772,12 @@ fusefs_readlink(void *v)
                        fmp->undef_op |= UNDEF_READLINK;
 
                fb_delete(fbuf);
-               goto out;
+               return (error);
        }
 
        error = uiomove(fbuf->fb_dat, fbuf->fb_len, uio);
        fb_delete(fbuf);
-out:
+
        return (error);
 }
 
@@ -849,7 +864,12 @@ fusefs_create(void *v)
        fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
        mode = MAKEIMODE(vap->va_type, vap->va_mode);
 
-       if (!fmp->sess_init || (fmp->undef_op & UNDEF_CREATE)) {
+       if (!fmp->sess_init) {
+               error = ENXIO;
+               goto out;
+       }
+
+       if (fmp->undef_op & UNDEF_CREATE) {
                error = ENOSYS;
                goto out;
        }
@@ -909,7 +929,12 @@ fusefs_mknod(void *v)
        ip = VTOI(dvp);
        fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
 
-       if (!fmp->sess_init || (fmp->undef_op & UNDEF_MKNOD)) {
+       if (!fmp->sess_init) {
+               error = ENXIO;
+               goto out;
+       }
+
+       if (fmp->undef_op & UNDEF_MKNOD) {
                error = ENOSYS;
                goto out;
        }
@@ -1167,7 +1192,13 @@ abortit:
        }
        VN_KNOTE(fdvp, NOTE_WRITE);     /* XXX right place? */
 
-       if (!fmp->sess_init || (fmp->undef_op & UNDEF_RENAME)) {
+       if (!fmp->sess_init) {
+               error = ENXIO;
+               VOP_UNLOCK(fvp, 0, p);
+               goto abortit;
+       }
+
+       if (fmp->undef_op & UNDEF_RENAME) {
                error = ENOSYS;
                VOP_UNLOCK(fvp, 0, p);
                goto abortit;
@@ -1228,7 +1259,12 @@ fusefs_mkdir(void *v)
        fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
 
 
-       if (!fmp->sess_init || (fmp->undef_op & UNDEF_MKDIR)) {
+       if (!fmp->sess_init) {
+               error = ENXIO;
+               goto out;
+       }
+
+       if (fmp->undef_op & UNDEF_MKDIR) {
                error = ENOSYS;
                goto out;
        }
@@ -1285,6 +1321,16 @@ fusefs_rmdir(void *v)
        dp = VTOI(dvp);
        fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
 
+       if (!fmp->sess_init) {
+               error = ENXIO;
+               goto out;
+       }
+
+       if (fmp->undef_op & UNDEF_RMDIR) {
+               error = ENOSYS;
+               goto out;
+       }
+
        /*
         * No rmdir "." please.
         */
@@ -1294,11 +1340,6 @@ fusefs_rmdir(void *v)
                return (EINVAL);
        }
 
-       if (!fmp->sess_init || (fmp->undef_op & UNDEF_RMDIR)) {
-               error = ENOSYS;
-               goto out;
-       }
-
        VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
 
        fbuf = fb_setup(cnp->cn_namelen + 1, dp->ufs_ino.i_number,
@@ -1350,7 +1391,12 @@ fusefs_remove(void *v)
        dp = VTOI(dvp);
        fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
 
-       if (!fmp->sess_init || (fmp->undef_op & UNDEF_REMOVE)) {
+       if (!fmp->sess_init) {
+               error = ENXIO;
+               goto out;
+       }
+
+       if (fmp->undef_op & UNDEF_REMOVE) {
                error = ENOSYS;
                goto out;
        }

Reply via email to