From 513ca7d7b3b0b74c9f4482fb7f9b20550535c9af Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Tue, 5 Feb 2008 20:52:01 +0000 Subject: [PATCH] Implement NFS support and export control for HAMMER. --- sys/vfs/hammer/hammer.h | 9 ++- sys/vfs/hammer/hammer_inode.c | 28 +------ sys/vfs/hammer/hammer_mount.h | 4 +- sys/vfs/hammer/hammer_vfsops.c | 132 +++++++++++++++++++++++++++++++-- sys/vfs/hammer/hammer_vnops.c | 29 +++++++- 5 files changed, 164 insertions(+), 38 deletions(-) diff --git a/sys/vfs/hammer/hammer.h b/sys/vfs/hammer/hammer.h index 65ee397a7c..a06ce334ef 100644 --- a/sys/vfs/hammer/hammer.h +++ b/sys/vfs/hammer/hammer.h @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer.h,v 1.32 2008/02/05 07:58:43 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer.h,v 1.33 2008/02/05 20:52:01 dillon Exp $ */ /* * This header file contains structures used internally by the HAMMERFS @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -69,7 +70,7 @@ struct hammer_mount; * the function hammer_ino_rb_tree_RB_LOOKUP_INFO(root, info). */ typedef struct hammer_inode_info { - u_int64_t obj_id; /* (key) object identifier */ + int64_t obj_id; /* (key) object identifier */ hammer_tid_t obj_asof; /* (key) snapshot transid or 0 */ } *hammer_inode_info_t; @@ -455,6 +456,7 @@ struct hammer_mount { udev_t fsid_udev; hammer_tid_t asof; u_int32_t namekey_iterator; + struct netexport export; }; typedef struct hammer_mount *hammer_mount_t; @@ -496,7 +498,6 @@ extern int hammer_count_spikes; int hammer_vop_inactive(struct vop_inactive_args *); int hammer_vop_reclaim(struct vop_reclaim_args *); -int hammer_vfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp); int hammer_get_vnode(struct hammer_inode *ip, int lktype, struct vnode **vpp); struct hammer_inode *hammer_get_inode(hammer_mount_t hmp, @@ -615,6 +616,8 @@ void hammer_rel_supercl(hammer_supercl_t supercl, int flush); void hammer_rel_cluster(hammer_cluster_t cluster, int flush); void hammer_rel_buffer(hammer_buffer_t buffer, int flush); +int hammer_vfs_export(struct mount *mp, int op, + const struct export_args *export); hammer_node_t hammer_get_node(hammer_cluster_t cluster, int32_t node_offset, int *errorp); int hammer_ref_node(hammer_node_t node); diff --git a/sys/vfs/hammer/hammer_inode.c b/sys/vfs/hammer/hammer_inode.c index c1524d9e72..e92da9d847 100644 --- a/sys/vfs/hammer/hammer_inode.c +++ b/sys/vfs/hammer/hammer_inode.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer_inode.c,v 1.26 2008/02/05 07:58:43 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_inode.c,v 1.27 2008/02/05 20:52:01 dillon Exp $ */ #include "hammer.h" @@ -91,32 +91,6 @@ hammer_vop_reclaim(struct vop_reclaim_args *ap) return(0); } -/* - * Obtain a vnode for the specified inode number. An exclusively locked - * vnode is returned. - */ -int -hammer_vfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) -{ - struct hammer_mount *hmp = (void *)mp->mnt_data; - struct hammer_inode *ip; - int error; - - /* - * Get/allocate the hammer_inode structure. The structure must be - * unlocked while we manipulate the related vnode to avoid a - * deadlock. - */ - ip = hammer_get_inode(hmp, NULL, ino, hmp->asof, 0, &error); - if (ip == NULL) { - *vpp = NULL; - return(error); - } - error = hammer_get_vnode(ip, LK_EXCLUSIVE, vpp); - hammer_rel_inode(ip, 0); - return (error); -} - /* * Return a locked vnode for the specified inode. The inode must be * referenced but NOT LOCKED on entry and will remain referenced on diff --git a/sys/vfs/hammer/hammer_mount.h b/sys/vfs/hammer/hammer_mount.h index 51c82f074e..dd0298d2bc 100644 --- a/sys/vfs/hammer/hammer_mount.h +++ b/sys/vfs/hammer/hammer_mount.h @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer_mount.h,v 1.3 2007/11/30 00:16:56 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_mount.h,v 1.4 2008/02/05 20:52:01 dillon Exp $ */ #ifndef _SYS_TYPES_H_ @@ -51,8 +51,10 @@ struct hammer_mount_info { int hflags; /* extended hammer mount flags */ int unused01; u_int64_t asof; /* asof - HAMMER_MAX_TID is current */ + struct export_args export; /* export arguments */ u_int64_t reserved[15]; }; #define HMNT_NOHISTORY 0x00000001 +#define HMNT_EXPORTREQ 0x00000002 diff --git a/sys/vfs/hammer/hammer_vfsops.c b/sys/vfs/hammer/hammer_vfsops.c index 5cd4b2d3e8..2b785e278d 100644 --- a/sys/vfs/hammer/hammer_vfsops.c +++ b/sys/vfs/hammer/hammer_vfsops.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer_vfsops.c,v 1.16 2008/01/25 10:36:04 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_vfsops.c,v 1.17 2008/02/05 20:52:01 dillon Exp $ */ #include @@ -104,7 +104,15 @@ static int hammer_vfs_root(struct mount *mp, struct vnode **vpp); static int hammer_vfs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred); static int hammer_vfs_sync(struct mount *mp, int waitfor); +static int hammer_vfs_vget(struct mount *mp, ino_t ino, + struct vnode **vpp); static int hammer_vfs_init(struct vfsconf *conf); +static int hammer_vfs_fhtovp(struct mount *mp, struct fid *fhp, + struct vnode **vpp); +static int hammer_vfs_vptofh(struct vnode *vp, struct fid *fhp); +static int hammer_vfs_checkexp(struct mount *mp, struct sockaddr *nam, + int *exflagsp, struct ucred **credanonp); + static struct vfsops hammer_vfsops = { .vfs_mount = hammer_vfs_mount, @@ -113,7 +121,10 @@ static struct vfsops hammer_vfsops = { .vfs_statfs = hammer_vfs_statfs, .vfs_sync = hammer_vfs_sync, .vfs_vget = hammer_vfs_vget, - .vfs_init = hammer_vfs_init + .vfs_init = hammer_vfs_init, + .vfs_vptofh = hammer_vfs_vptofh, + .vfs_fhtovp = hammer_vfs_fhtovp, + .vfs_checkexp = hammer_vfs_checkexp }; MALLOC_DEFINE(M_HAMMER, "hammer-mount", "hammer mount"); @@ -224,8 +235,6 @@ hammer_vfs_mount(struct mount *mp, char *mntpt, caddr_t data, */ mp->mnt_iosize_max = MAXPHYS; mp->mnt_kern_flag |= MNTK_FSMID; - mp->mnt_stat.f_fsid.val[0] = 0; /* XXX */ - mp->mnt_stat.f_fsid.val[1] = 0; /* XXX */ /* * note: f_iosize is used by vnode_pager_haspage() when constructing @@ -233,7 +242,6 @@ hammer_vfs_mount(struct mount *mp, char *mntpt, caddr_t data, */ mp->mnt_stat.f_iosize = HAMMER_BUFSIZE; mp->mnt_stat.f_bsize = HAMMER_BUFSIZE; - vfs_getnewfsid(mp); /* XXX */ mp->mnt_maxsymlinklen = 255; mp->mnt_flag |= MNT_LOCAL; @@ -251,6 +259,10 @@ hammer_vfs_mount(struct mount *mp, char *mntpt, caddr_t data, ksnprintf(mp->mnt_stat.f_mntfromname, sizeof(mp->mnt_stat.f_mntfromname), "%s", rootvol->ondisk->vol_name); + mp->mnt_stat.f_fsid.val[0] = + crc32((char *)&rootvol->ondisk->vol_fsid + 0, 8); + mp->mnt_stat.f_fsid.val[1] = + crc32((char *)&rootvol->ondisk->vol_fsid + 8, 8); hammer_rel_volume(rootvol, 0); /* @@ -339,6 +351,32 @@ hammer_free_hmp(struct mount *mp) kfree(hmp, M_HAMMER); } +/* + * Obtain a vnode for the specified inode number. An exclusively locked + * vnode is returned. + */ +int +hammer_vfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) +{ + struct hammer_mount *hmp = (void *)mp->mnt_data; + struct hammer_inode *ip; + int error; + + /* + * Get/allocate the hammer_inode structure. The structure must be + * unlocked while we manipulate the related vnode to avoid a + * deadlock. + */ + ip = hammer_get_inode(hmp, NULL, ino, hmp->asof, 0, &error); + if (ip == NULL) { + *vpp = NULL; + return(error); + } + error = hammer_get_vnode(ip, LK_EXCLUSIVE, vpp); + hammer_rel_inode(ip, 0); + return (error); +} + /* * Return the root vnode for the filesystem. * @@ -410,3 +448,87 @@ hammer_vfs_sync(struct mount *mp, int waitfor) return(error); } +/* + * Convert a vnode to a file handle. + */ +static int +hammer_vfs_vptofh(struct vnode *vp, struct fid *fhp) +{ + hammer_inode_t ip; + + KKASSERT(MAXFIDSZ >= 16); + ip = VTOI(vp); + fhp->fid_len = offsetof(struct fid, fid_data[16]); + fhp->fid_reserved = 0; + bcopy(&ip->obj_id, fhp->fid_data + 0, sizeof(ip->obj_id)); + bcopy(&ip->obj_asof, fhp->fid_data + 8, sizeof(ip->obj_asof)); + return(0); +} + + +/* + * Convert a file handle back to a vnode. + */ +static int +hammer_vfs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) +{ + struct hammer_mount *hmp = (void *)mp->mnt_data; + struct hammer_inode *ip; + struct hammer_inode_info info; + int error; + + bcopy(fhp->fid_data + 0, &info.obj_id, sizeof(info.obj_id)); + bcopy(fhp->fid_data + 8, &info.obj_asof, sizeof(info.obj_asof)); + + /* + * Get/allocate the hammer_inode structure. The structure must be + * unlocked while we manipulate the related vnode to avoid a + * deadlock. + */ + ip = hammer_get_inode(hmp, NULL, info.obj_id, info.obj_asof, 0, &error); + if (ip == NULL) { + *vpp = NULL; + return(error); + } + error = hammer_get_vnode(ip, LK_EXCLUSIVE, vpp); + hammer_rel_inode(ip, 0); + return (error); +} + +static int +hammer_vfs_checkexp(struct mount *mp, struct sockaddr *nam, + int *exflagsp, struct ucred **credanonp) +{ + hammer_mount_t hmp = (void *)mp->mnt_data; + struct netcred *np; + int error; + + np = vfs_export_lookup(mp, &hmp->export, nam); + if (np) { + *exflagsp = np->netc_exflags; + *credanonp = &np->netc_anon; + error = 0; + } else { + error = EACCES; + } + return (error); + +} + +int +hammer_vfs_export(struct mount *mp, int op, const struct export_args *export) +{ + hammer_mount_t hmp = (void *)mp->mnt_data; + int error; + + switch(op) { + case MOUNTCTL_SET_EXPORT: + error = vfs_export(mp, &hmp->export, export); + break; + default: + error = EOPNOTSUPP; + break; + } + return(error); +} + diff --git a/sys/vfs/hammer/hammer_vnops.c b/sys/vfs/hammer/hammer_vnops.c index 07097c7244..ae07554167 100644 --- a/sys/vfs/hammer/hammer_vnops.c +++ b/sys/vfs/hammer/hammer_vnops.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer_vnops.c,v 1.26 2008/02/05 07:58:43 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_vnops.c,v 1.27 2008/02/05 20:52:01 dillon Exp $ */ #include @@ -78,6 +78,7 @@ static int hammer_vop_strategy(struct vop_strategy_args *); static int hammer_vop_nsymlink(struct vop_nsymlink_args *); static int hammer_vop_nwhiteout(struct vop_nwhiteout_args *); static int hammer_vop_ioctl(struct vop_ioctl_args *); +static int hammer_vop_mountctl(struct vop_mountctl_args *); static int hammer_vop_fifoclose (struct vop_close_args *); static int hammer_vop_fiforead (struct vop_read_args *); @@ -118,7 +119,8 @@ struct vop_ops hammer_vnode_vops = { .vop_strategy = hammer_vop_strategy, .vop_nsymlink = hammer_vop_nsymlink, .vop_nwhiteout = hammer_vop_nwhiteout, - .vop_ioctl = hammer_vop_ioctl + .vop_ioctl = hammer_vop_ioctl, + .vop_mountctl = hammer_vop_mountctl }; struct vop_ops hammer_spec_vops = { @@ -1511,6 +1513,29 @@ hammer_vop_ioctl(struct vop_ioctl_args *ap) ap->a_fflag, ap->a_cred)); } +static +int +hammer_vop_mountctl(struct vop_mountctl_args *ap) +{ + struct mount *mp; + int error; + + mp = ap->a_head.a_ops->head.vv_mount; + + switch(ap->a_op) { + case MOUNTCTL_SET_EXPORT: + if (ap->a_ctllen != sizeof(struct export_args)) + error = EINVAL; + error = hammer_vfs_export(mp, ap->a_op, + (const struct export_args *)ap->a_ctl); + break; + default: + error = journal_mountctl(ap); + break; + } + return(error); +} + /* * hammer_vop_strategy { vp, bio } * -- 2.41.0