Print this page
NEX-15069 smtorture smb2.create.blob is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15069 smtorture smb2.create.blob is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-6276 SMB sparse file support
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5844 want SMB2 ioctl FSCTL_SRV_COPYCHUNK
NEX-6124 smb_fsop_read/write should allow file != sr->fid_ofile
NEX-6125 smbtorture invalid response with smb2.ioctl
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-6041 Should pass the smbtorture lock tests
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-5312 delete_on_close should be acted on earlier
Reviewed by: Gordon Ross <gwr@nexenta.com>
NEX-4239 smbtorture create failures re. allocation size
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-4083 Upstream changes from illumos 5917 and 5995
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-2831 panic in smb_make_link
NEX-2442 regression with smbtorture test raw.sfileinfo.rename
SMB-122 smbd core dumps in smbd_dc_update / smb_log
SMB-117 Win7 fails to open security properties
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)
SMB-50 User-mode SMB server
 Includes work by these authors:
 Thomas Keiser <thomas.keiser@nexenta.com>
 Albert Lee <trisk@nexenta.com>

*** 8,22 **** * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* ! * Copyright 2015 Nexenta Systems, Inc. All rights reserved. */ #include <sys/types.h> #include <sys/param.h> #include <sys/t_lock.h> #include <sys/errno.h> #include <sys/cred.h> #include <sys/user.h> #include <sys/uio.h> --- 8,23 ---- * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* ! * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #include <sys/types.h> #include <sys/param.h> + #include <sys/systm.h> #include <sys/t_lock.h> #include <sys/errno.h> #include <sys/cred.h> #include <sys/user.h> #include <sys/uio.h>
*** 25,37 **** --- 26,40 ---- #include <sys/vfs.h> #include <sys/vnode.h> #include <sys/stat.h> #include <sys/mode.h> #include <sys/kmem.h> + #include <sys/cmn_err.h> #include <sys/debug.h> #include <sys/atomic.h> #include <sys/acl.h> + #include <sys/filio.h> #include <sys/flock.h> #include <sys/nbmlock.h> #include <sys/fcntl.h> #include <sys/poll.h> #include <sys/time.h>
*** 48,57 **** --- 51,61 ---- 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 fop_open( vnode_t **vpp,
*** 212,222 **** int flag, cred_t *cr, int *rvalp, caller_context_t *ct) { ! return (ENOSYS); } /* ARGSUSED */ int fop_setfl( --- 216,248 ---- int flag, cred_t *cr, int *rvalp, caller_context_t *ct) { ! off64_t off; ! int rv, whence; ! ! switch (cmd) { ! case _FIO_SEEK_DATA: ! case _FIO_SEEK_HOLE: ! whence = (cmd == _FIO_SEEK_DATA) ? SEEK_DATA : SEEK_HOLE; ! bcopy((void *)arg, &off, sizeof (off)); ! off = lseek(vp->v_fd, off, whence); ! if (off == (off64_t)-1) { ! rv = errno; ! } else { ! bcopy(&off, (void *)arg, sizeof (off)); ! rv = 0; ! } ! break; ! ! default: ! rv = ENOTTY; ! break; ! } ! ! return (rv); } /* ARGSUSED */ int fop_setfl(
*** 260,274 **** int flags, cred_t *cr, caller_context_t *ct) { timespec_t times[2]; if (vap->va_mask & AT_SIZE) { ! if (ftruncate(vp->v_fd, vap->va_size) == -1) ! return (errno); } /* AT_MODE or anything else? */ if (vap->va_mask & AT_XVATTR) (void) fop__setxvattr(vp, (xvattr_t *)vap); --- 286,305 ---- int flags, cred_t *cr, caller_context_t *ct) { timespec_t times[2]; + int err; if (vap->va_mask & AT_SIZE) { ! if (ftruncate(vp->v_fd, vap->va_size) == -1) { ! err = errno; ! if (err == EBADF) ! err = EACCES; ! return (err); } + } /* AT_MODE or anything else? */ if (vap->va_mask & AT_XVATTR) (void) fop__setxvattr(vp, (xvattr_t *)vap);
*** 303,312 **** --- 334,412 ---- caller_context_t *ct) { 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( vnode_t *dvp, char *name,
*** 323,333 **** int omode = O_RDWR | O_NOFOLLOW; vnode_t *vp; struct stat st; if (flags & LOOKUP_XATTR) ! return (ENOENT); /* * If lookup is for "", just return dvp. */ if (name[0] == '\0') { --- 423,433 ---- int omode = O_RDWR | O_NOFOLLOW; vnode_t *vp; struct stat st; if (flags & LOOKUP_XATTR) ! return (fake_lookup_xattrdir(dvp, vpp)); /* * If lookup is for "", just return dvp. */ if (name[0] == '\0') {
*** 679,691 **** --- 779,827 ---- fop_inactive( vnode_t *vp, cred_t *cr, caller_context_t *ct) { + 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 */ int fop_fid( vnode_t *vp, fid_t *fidp,
*** 747,756 **** --- 883,904 ---- offset_t offset, struct flk_callback *flk_cbp, cred_t *cr, caller_context_t *ct) { + #if defined(_LP64) + offset_t maxoffset = INT64_MAX; + #elif defined(_ILP32) + /* + * Sadly, the fcntl API enforces 32-bit offsets, + * even though we have _FILE_OFFSET_BITS=64 + */ + offset_t maxoffset = INT32_MAX; + #else + #error "unsupported env." + #endif + /* See fs_frlock */ switch (cmd) { case F_GETLK: case F_SETLK_NBMAND:
*** 759,768 **** --- 907,940 ---- break; default: return (EINVAL); } + /* We only get SEEK_SET ranges here. */ + if (bfp->l_whence != 0) + return (EINVAL); + + /* + * One limitation of using fcntl(2) F_SETLK etc is that + * the real kernel limits the offsets we can use. + * (Maybe the fcntl API should loosen that up?) + * See syscall/fcntl.c:flock_check() + * + * Here in libfksmbsrv we can just ignore such locks, + * or ignore the part that extends beyond maxoffset. + * The SMB layer still keeps track of such locks for + * conflict detection, so not reflecting such locks + * into the real FS layer is OK. Note: this may + * modify the pased bfp->l_len. + */ + if (bfp->l_start < 0 || bfp->l_start > maxoffset) + return (0); + if (bfp->l_len < 0 || bfp->l_len > maxoffset) + return (0); + if (bfp->l_len > (maxoffset - bfp->l_start + 1)) + bfp->l_len = (maxoffset - bfp->l_start + 1); + if (fcntl(vp->v_fd, cmd, bfp) == -1) return (errno); return (0); }
*** 981,991 **** case _PC_FILESIZEBITS: val = (ulong_t)-1; /* large file support */ break; case _PC_ACL_ENABLED: ! val = 0; break; case _PC_CASE_BEHAVIOR: val = _CASE_SENSITIVE; break; --- 1153,1163 ---- case _PC_FILESIZEBITS: val = (ulong_t)-1; /* large file support */ break; case _PC_ACL_ENABLED: ! val = _ACL_ACE_ENABLED; break; case _PC_CASE_BEHAVIOR: val = _CASE_SENSITIVE; break;
*** 1265,1275 **** { VERIFY3U(vp->v_count, !=, 0); mutex_enter(&vp->v_lock); if (vp->v_count == 1) { mutex_exit(&vp->v_lock); ! vncache_inactive(vp); } else { vp->v_count--; mutex_exit(&vp->v_lock); } } --- 1437,1447 ---- { VERIFY3U(vp->v_count, !=, 0); mutex_enter(&vp->v_lock); if (vp->v_count == 1) { mutex_exit(&vp->v_lock); ! fop_inactive(vp, NULL, NULL); } else { vp->v_count--; mutex_exit(&vp->v_lock); } }