From d082c87763acd6b9390ffaefe9062d481a085d6c Mon Sep 17 00:00:00 2001 From: Gordon Ross Date: Wed, 24 Jun 2015 13:13:00 -0400 Subject: 10975 Want SMB2 Apple extensions Reviewed by: Bayard Bell Reviewed by: Kevin Crowe Reviewed by: Matt Barden Reviewed by: Evan Layton Approved by: Dan McDonald --- usr/src/lib/smbsrv/libfksmbsrv/Makefile.com | 1 + usr/src/lib/smbsrv/libfksmbsrv/common/fake_vop.c | 117 ++++++++++++++++++++++- 2 files changed, 114 insertions(+), 4 deletions(-) (limited to 'usr/src/lib') diff --git a/usr/src/lib/smbsrv/libfksmbsrv/Makefile.com b/usr/src/lib/smbsrv/libfksmbsrv/Makefile.com index 168343801b..8512488b42 100644 --- a/usr/src/lib/smbsrv/libfksmbsrv/Makefile.com +++ b/usr/src/lib/smbsrv/libfksmbsrv/Makefile.com @@ -122,6 +122,7 @@ OBJS_FS_SMBSRV = \ smb_vss.o \ smb_write.o \ \ + smb2_aapl.o \ smb2_dispatch.o \ smb2_cancel.o \ smb2_change_notify.o \ diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/fake_vop.c b/usr/src/lib/smbsrv/libfksmbsrv/common/fake_vop.c index 41c301fbaa..fdb1d82f5c 100644 --- a/usr/src/lib/smbsrv/libfksmbsrv/common/fake_vop.c +++ b/usr/src/lib/smbsrv/libfksmbsrv/common/fake_vop.c @@ -10,11 +10,12 @@ */ /* - * Copyright 2015 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #include #include +#include #include #include #include @@ -27,9 +28,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -50,6 +53,7 @@ int stat_to_vattr(const struct stat *, vattr_t *); int fop__getxvattr(vnode_t *, xvattr_t *); int fop__setxvattr(vnode_t *, xvattr_t *); +static void fake_inactive_xattrdir(vnode_t *); /* ARGSUSED */ int @@ -305,6 +309,75 @@ fop_access( return (0); } +/* + * Conceptually like xattr_dir_lookup() + */ +static int +fake_lookup_xattrdir( + vnode_t *dvp, + vnode_t **vpp) +{ + int len, fd; + int omode = O_RDWR | O_NOFOLLOW; + vnode_t *vp; + + *vpp = NULL; + + if (dvp->v_type != VDIR && dvp->v_type != VREG) + return (EINVAL); + + /* + * If we're already in sysattr space, don't allow creation + * of another level of sysattrs. + */ + if (dvp->v_flag & V_SYSATTR) + return (EINVAL); + + mutex_enter(&dvp->v_lock); + if (dvp->v_xattrdir != NULL) { + *vpp = dvp->v_xattrdir; + VN_HOLD(*vpp); + mutex_exit(&dvp->v_lock); + return (0); + } + mutex_exit(&dvp->v_lock); + + omode = O_RDONLY|O_XATTR; + fd = openat(dvp->v_fd, ".", omode); + if (fd < 0) + return (errno); + + vp = vn_alloc(KM_SLEEP); + vp->v_fd = fd; + vp->v_flag = V_XATTRDIR|V_SYSATTR; + vp->v_type = VDIR; + vp->v_vfsp = dvp->v_vfsp; + + /* Set v_path to parent path + "/@" (like NFS) */ + len = strlen(dvp->v_path) + 3; + vp->v_path = kmem_alloc(len, KM_SLEEP); + (void) snprintf(vp->v_path, len, "%s/@", dvp->v_path); + + /* + * Keep a pointer to the parent and a hold on it. + * Both are cleaned up in fake_inactive_xattrdir + */ + vp->v_data = dvp; + vn_hold(dvp); + + mutex_enter(&dvp->v_lock); + if (dvp->v_xattrdir == NULL) { + *vpp = dvp->v_xattrdir = vp; + mutex_exit(&dvp->v_lock); + } else { + *vpp = dvp->v_xattrdir; + mutex_exit(&dvp->v_lock); + fake_inactive_xattrdir(vp); + } + + return (0); +} + /* ARGSUSED */ int fop_lookup( @@ -325,7 +398,7 @@ fop_lookup( struct stat st; if (flags & LOOKUP_XATTR) - return (ENOENT); + return (fake_lookup_xattrdir(dvp, vpp)); /* * If lookup is for "", just return dvp. @@ -681,7 +754,43 @@ fop_inactive( cred_t *cr, caller_context_t *ct) { - vncache_inactive(vp); + if (vp->v_flag & V_XATTRDIR) { + fake_inactive_xattrdir(vp); + } else { + vncache_inactive(vp); + } +} + +/* + * The special xattr directories are not in the vncache AVL, but + * hang off the parent's v_xattrdir field. When vn_rele finds + * an xattr dir at v_count == 1 it calls here, but until we + * take locks on both the parent and the xattrdir, we don't + * know if we're really at the last reference. So in here we + * take both locks, re-check the count, and either bail out + * or proceed with "inactive" vnode cleanup. Part of that + * cleanup includes releasing the hold on the parent and + * clearing the parent's v_xattrdir field, which were + * setup in fake_lookup_xattrdir() + */ +static void +fake_inactive_xattrdir(vnode_t *vp) +{ + vnode_t *dvp = vp->v_data; /* parent */ + mutex_enter(&dvp->v_lock); + mutex_enter(&vp->v_lock); + if (vp->v_count > 1) { + /* new ref. via v_xattrdir */ + mutex_exit(&vp->v_lock); + mutex_exit(&dvp->v_lock); + return; + } + ASSERT(dvp->v_xattrdir == vp); + dvp->v_xattrdir = NULL; + mutex_exit(&vp->v_lock); + mutex_exit(&dvp->v_lock); + vn_rele(dvp); + vn_free(vp); } /* ARGSUSED */ @@ -1267,7 +1376,7 @@ vn_rele(vnode_t *vp) mutex_enter(&vp->v_lock); if (vp->v_count == 1) { mutex_exit(&vp->v_lock); - vncache_inactive(vp); + fop_inactive(vp, NULL, NULL); } else { vp->v_count--; mutex_exit(&vp->v_lock); -- cgit v1.2.3