From: syl Date: Thu, 16 Jan 2014 09:31:44 +0000 (+0000) Subject: Add support for mknod in fuse. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=3a6f645655e11f1db4c3abdeac2217524bb3538a;p=openbsd Add support for mknod in fuse. OK tedu@ "it looks good to me" from guenther@ --- diff --git a/lib/libfuse/fuse_ops.c b/lib/libfuse/fuse_ops.c index 88c6bb28b5f..23e6e92d867 100644 --- a/lib/libfuse/fuse_ops.c +++ b/lib/libfuse/fuse_ops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fuse_ops.c,v 1.19 2014/01/02 15:39:12 syl Exp $ */ +/* $OpenBSD: fuse_ops.c,v 1.20 2014/01/16 09:31:44 syl Exp $ */ /* * Copyright (c) 2013 Sylvestre Gallon * @@ -809,6 +809,34 @@ ifuse_ops_reclaim(struct fuse *f, struct fusebuf *fbuf) return (0); } +static int +ifuse_ops_mknod(struct fuse *f, struct fusebuf *fbuf) +{ + struct fuse_vnode *vn; + char *realname; + uint32_t mode; + dev_t dev; + + CHECK_OPT(mknod); + + mode = fbuf->fb_io_mode; + dev = fbuf->fb_io_rdev; + vn = get_vn_by_name_and_parent(f, fbuf->fb_dat, fbuf->fb_ino); + + free(fbuf->fb_dat); + realname = build_realname(f, vn->ino); + fbuf->fb_err = f->op.mknod(realname, mode, dev); + + if (!fbuf->fb_err) { + fbuf->fb_err = update_vattr(f, &fbuf->fb_vattr, realname, vn); + fbuf->fb_io_mode = fbuf->fb_vattr.va_mode; + fbuf->fb_ino = fbuf->fb_vattr.va_fileid; + } + free(realname); + + return (0); +} + int ifuse_exec_opcode(struct fuse *f, struct fusebuf *fbuf) { @@ -887,6 +915,9 @@ ifuse_exec_opcode(struct fuse *f, struct fusebuf *fbuf) case FBT_RECLAIM: ret = ifuse_ops_reclaim(f, fbuf); break; + case FBT_MKNOD: + ret = ifuse_ops_mknod(f, fbuf); + break; default: DPRINTF("Opcode:\t%i not supported\n", fbuf->fb_type); DPRINTF("Inode:\t%llu\n", (unsigned long long)fbuf->fb_ino); diff --git a/sys/miscfs/fuse/fuse_vnops.c b/sys/miscfs/fuse/fuse_vnops.c index 420b9278a9e..6d514bb203d 100644 --- a/sys/miscfs/fuse/fuse_vnops.c +++ b/sys/miscfs/fuse/fuse_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fuse_vnops.c,v 1.12 2013/12/20 22:03:26 syl Exp $ */ +/* $OpenBSD: fuse_vnops.c,v 1.13 2014/01/16 09:31:44 syl Exp $ */ /* * Copyright (c) 2012-2013 Sylvestre Gallon * @@ -885,10 +885,72 @@ int fusefs_mknod(void *v) { struct vop_mknod_args *ap = v; + struct componentname *cnp = ap->a_cnp; + struct vnode **vpp = ap->a_vpp; + struct vnode *dvp = ap->a_dvp; + struct vattr *vap = ap->a_vap; + struct proc *p = cnp->cn_proc; + struct vnode *tdp = NULL; + struct fusefs_mnt *fmp; + struct fusefs_node *ip; + struct fusebuf *fbuf; + int error = 0; + + ip = VTOI(dvp); + fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; + if (!fmp->sess_init || (fmp->undef_op & UNDEF_MKNOD)) { + error = ENOSYS; + goto out; + } + + fbuf = fb_setup(cnp->cn_namelen + 1, ip->ufs_ino.i_number, + FBT_MKNOD, p); + + fbuf->fb_io_mode = MAKEIMODE(vap->va_type, vap->va_mode); + if (vap->va_rdev != VNOVAL) + fbuf->fb_io_rdev = vap->va_rdev; + + memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen); + fbuf->fb_dat[cnp->cn_namelen] = '\0'; + + error = fb_queue(fmp->dev, fbuf); + if (error) { + if (error == ENOSYS) + fmp->undef_op |= UNDEF_MKNOD; + + fb_delete(fbuf); + goto out; + } + + if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp))) { + fb_delete(fbuf); + goto out; + } + + tdp->v_type = IFTOVT(fbuf->fb_io_mode); + VTOI(tdp)->vtype = tdp->v_type; + + if (dvp != NULL && dvp->v_type == VDIR) + VTOI(tdp)->parent = ip->ufs_ino.i_number; + + *vpp = tdp; VN_KNOTE(ap->a_dvp, NOTE_WRITE); + fb_delete(fbuf); vput(ap->a_dvp); - return (EINVAL); + + /* Remove inode so that it will be reloaded by VFS_VGET and + * checked to see if it is an alias of an existing entry in + * the inode cache. + */ + vput(*vpp); + (*vpp)->v_type = VNON; + vgone(*vpp); + *vpp = NULL; + return (0); +out: + vput(ap->a_dvp); + return (error); } int diff --git a/sys/miscfs/fuse/fusefs.h b/sys/miscfs/fuse/fusefs.h index 60b6fa12b49..1d9c7fbac47 100644 --- a/sys/miscfs/fuse/fusefs.h +++ b/sys/miscfs/fuse/fusefs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: fusefs.h,v 1.5 2013/12/10 13:43:05 pelikan Exp $ */ +/* $OpenBSD: fusefs.h,v 1.6 2014/01/16 09:31:44 syl Exp $ */ /* * Copyright (c) 2012-2013 Sylvestre Gallon * @@ -65,6 +65,7 @@ struct fusefs_mnt { #define UNDEF_SETATTR 1<<7 #define UNDEF_RENAME 1<<8 #define UNDEF_SYMLINK 1<<9 +#define UNDEF_MKNOD 1<<10 extern struct vops fusefs_vops; extern struct pool fusefs_fbuf_pool; diff --git a/sys/sys/fusebuf.h b/sys/sys/fusebuf.h index bec298dc1ba..f2e1aa0ed61 100644 --- a/sys/sys/fusebuf.h +++ b/sys/sys/fusebuf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: fusebuf.h,v 1.8 2013/12/03 09:59:40 syl Exp $ */ +/* $OpenBSD: fusebuf.h,v 1.9 2014/01/16 09:31:44 syl Exp $ */ /* * Copyright (c) 2013 Sylvestre Gallon * Copyright (c) 2013 Martin Pieuchot @@ -43,6 +43,7 @@ struct fb_io { size_t fi_len; /* Length of data */ mode_t fi_mode; /* mode for fd */ uint32_t fi_flags; /* flags on transfer */ + dev_t fi_rdev; /* dev for mknod */ }; /* @@ -82,6 +83,7 @@ struct fusebuf { #define fb_io_len FD.FD_io.fi_len #define fb_io_mode FD.FD_io.fi_mode #define fb_io_flags FD.FD_io.fi_flags +#define fb_io_rdev FD.FD_io.fi_rdev #define fb_dat F_databuf /*