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>

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/smbsrv/libfksmbsrv/common/fake_vop.c
          +++ new/usr/src/lib/smbsrv/libfksmbsrv/common/fake_vop.c
↓ open down ↓ 2 lines elided ↑ open up ↑
   3    3   * Common Development and Distribution License ("CDDL"), version 1.0.
   4    4   * You may only use this file in accordance with the terms of version
   5    5   * 1.0 of the CDDL.
   6    6   *
   7    7   * A full copy of the text of the CDDL should have accompanied this
   8    8   * source.  A copy of the CDDL is also available via the Internet at
   9    9   * http://www.illumos.org/license/CDDL.
  10   10   */
  11   11  
  12   12  /*
  13      - * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
       13 + * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  14   14   */
  15   15  
  16   16  #include <sys/types.h>
  17   17  #include <sys/param.h>
       18 +#include <sys/systm.h>
  18   19  #include <sys/t_lock.h>
  19   20  #include <sys/errno.h>
  20   21  #include <sys/cred.h>
  21   22  #include <sys/user.h>
  22   23  #include <sys/uio.h>
  23   24  #include <sys/file.h>
  24   25  #include <sys/pathname.h>
  25   26  #include <sys/vfs.h>
  26   27  #include <sys/vnode.h>
  27   28  #include <sys/stat.h>
  28   29  #include <sys/mode.h>
  29   30  #include <sys/kmem.h>
       31 +#include <sys/cmn_err.h>
  30   32  #include <sys/debug.h>
  31   33  #include <sys/atomic.h>
  32   34  #include <sys/acl.h>
       35 +#include <sys/filio.h>
  33   36  #include <sys/flock.h>
  34   37  #include <sys/nbmlock.h>
  35   38  #include <sys/fcntl.h>
  36   39  #include <sys/poll.h>
  37   40  #include <sys/time.h>
  38   41  
  39   42  #include <errno.h>
  40   43  #include <fcntl.h>
  41   44  #include <unistd.h>
  42   45  
  43   46  #include "vncache.h"
  44   47  
  45   48  #define O_RWMASK        (O_WRONLY | O_RDWR) /* == 3 */
  46   49  
  47   50  int fop_shrlock_enable = 0;
  48   51  
  49   52  int stat_to_vattr(const struct stat *, vattr_t *);
  50   53  int fop__getxvattr(vnode_t *, xvattr_t *);
  51   54  int fop__setxvattr(vnode_t *, xvattr_t *);
  52   55  
       56 +static void fake_inactive_xattrdir(vnode_t *);
  53   57  
  54   58  /* ARGSUSED */
  55   59  int
  56   60  fop_open(
  57   61          vnode_t **vpp,
  58   62          int mode,
  59   63          cred_t *cr,
  60   64          caller_context_t *ct)
  61   65  {
  62   66  
↓ open down ↓ 144 lines elided ↑ open up ↑
 207  211  int
 208  212  fop_ioctl(
 209  213          vnode_t *vp,
 210  214          int cmd,
 211  215          intptr_t arg,
 212  216          int flag,
 213  217          cred_t *cr,
 214  218          int *rvalp,
 215  219          caller_context_t *ct)
 216  220  {
 217      -        return (ENOSYS);
      221 +        off64_t off;
      222 +        int rv, whence;
      223 +
      224 +        switch (cmd) {
      225 +        case _FIO_SEEK_DATA:
      226 +        case _FIO_SEEK_HOLE:
      227 +                whence = (cmd == _FIO_SEEK_DATA) ? SEEK_DATA : SEEK_HOLE;
      228 +                bcopy((void *)arg, &off, sizeof (off));
      229 +                off = lseek(vp->v_fd, off, whence);
      230 +                if (off == (off64_t)-1) {
      231 +                        rv = errno;
      232 +                } else {
      233 +                        bcopy(&off, (void *)arg, sizeof (off));
      234 +                        rv = 0;
      235 +                }
      236 +                break;
      237 +
      238 +        default:
      239 +                rv = ENOTTY;
      240 +                break;
      241 +        }
      242 +
      243 +        return (rv);
 218  244  }
 219  245  
 220  246  /* ARGSUSED */
 221  247  int
 222  248  fop_setfl(
 223  249          vnode_t *vp,
 224  250          int oflags,
 225  251          int nflags,
 226  252          cred_t *cr,
 227  253          caller_context_t *ct)
↓ open down ↓ 27 lines elided ↑ open up ↑
 255  281  /* ARGSUSED */
 256  282  int
 257  283  fop_setattr(
 258  284          vnode_t *vp,
 259  285          vattr_t *vap,
 260  286          int flags,
 261  287          cred_t *cr,
 262  288          caller_context_t *ct)
 263  289  {
 264  290          timespec_t times[2];
      291 +        int err;
 265  292  
 266  293          if (vap->va_mask & AT_SIZE) {
 267      -                if (ftruncate(vp->v_fd, vap->va_size) == -1)
 268      -                        return (errno);
      294 +                if (ftruncate(vp->v_fd, vap->va_size) == -1) {
      295 +                        err = errno;
      296 +                        if (err == EBADF)
      297 +                                err = EACCES;
      298 +                        return (err);
      299 +                }
 269  300          }
 270  301  
 271  302          /* AT_MODE or anything else? */
 272  303  
 273  304          if (vap->va_mask & AT_XVATTR)
 274  305                  (void) fop__setxvattr(vp, (xvattr_t *)vap);
 275  306  
 276  307          if (vap->va_mask & (AT_ATIME | AT_MTIME)) {
 277  308                  if (vap->va_mask & AT_ATIME) {
 278  309                          times[0] = vap->va_atime;
↓ open down ↓ 19 lines elided ↑ open up ↑
 298  329  fop_access(
 299  330          vnode_t *vp,
 300  331          int mode,
 301  332          int flags,
 302  333          cred_t *cr,
 303  334          caller_context_t *ct)
 304  335  {
 305  336          return (0);
 306  337  }
 307  338  
      339 +/*
      340 + * Conceptually like xattr_dir_lookup()
      341 + */
      342 +static int
      343 +fake_lookup_xattrdir(
      344 +        vnode_t *dvp,
      345 +        vnode_t **vpp)
      346 +{
      347 +        int len, fd;
      348 +        int omode = O_RDWR | O_NOFOLLOW;
      349 +        vnode_t *vp;
      350 +
      351 +        *vpp = NULL;
      352 +
      353 +        if (dvp->v_type != VDIR && dvp->v_type != VREG)
      354 +                return (EINVAL);
      355 +
      356 +        /*
      357 +         * If we're already in sysattr space, don't allow creation
      358 +         * of another level of sysattrs.
      359 +         */
      360 +        if (dvp->v_flag & V_SYSATTR)
      361 +                return (EINVAL);
      362 +
      363 +        mutex_enter(&dvp->v_lock);
      364 +        if (dvp->v_xattrdir != NULL) {
      365 +                *vpp = dvp->v_xattrdir;
      366 +                VN_HOLD(*vpp);
      367 +                mutex_exit(&dvp->v_lock);
      368 +                return (0);
      369 +        }
      370 +        mutex_exit(&dvp->v_lock);
      371 +
      372 +        omode = O_RDONLY|O_XATTR;
      373 +        fd = openat(dvp->v_fd, ".", omode);
      374 +        if (fd < 0)
      375 +                return (errno);
      376 +
      377 +        vp = vn_alloc(KM_SLEEP);
      378 +        vp->v_fd = fd;
      379 +        vp->v_flag = V_XATTRDIR|V_SYSATTR;
      380 +        vp->v_type = VDIR;
      381 +        vp->v_vfsp = dvp->v_vfsp;
      382 +
      383 +        /* Set v_path to parent path + "/@" (like NFS) */
      384 +        len = strlen(dvp->v_path) + 3;
      385 +        vp->v_path = kmem_alloc(len, KM_SLEEP);
      386 +        (void) snprintf(vp->v_path, len, "%s/@", dvp->v_path);
      387 +
      388 +        /*
      389 +         * Keep a pointer to the parent and a hold on it.
      390 +         * Both are cleaned up in fake_inactive_xattrdir
      391 +         */
      392 +        vp->v_data = dvp;
      393 +        vn_hold(dvp);
      394 +
      395 +        mutex_enter(&dvp->v_lock);
      396 +        if (dvp->v_xattrdir == NULL) {
      397 +                *vpp = dvp->v_xattrdir = vp;
      398 +                mutex_exit(&dvp->v_lock);
      399 +        } else {
      400 +                *vpp = dvp->v_xattrdir;
      401 +                mutex_exit(&dvp->v_lock);
      402 +                fake_inactive_xattrdir(vp);
      403 +        }
      404 +
      405 +        return (0);
      406 +}
      407 +
 308  408  /* ARGSUSED */
 309  409  int
 310  410  fop_lookup(
 311  411          vnode_t *dvp,
 312  412          char *name,
 313  413          vnode_t **vpp,
 314  414          pathname_t *pnp,
 315  415          int flags,
 316  416          vnode_t *rdir,
 317  417          cred_t *cr,
 318  418          caller_context_t *ct,
 319  419          int *deflags,           /* Returned per-dirent flags */
 320  420          pathname_t *ppnp)       /* Returned case-preserved name in directory */
 321  421  {
 322  422          int fd;
 323  423          int omode = O_RDWR | O_NOFOLLOW;
 324  424          vnode_t *vp;
 325  425          struct stat st;
 326  426  
 327  427          if (flags & LOOKUP_XATTR)
 328      -                return (ENOENT);
      428 +                return (fake_lookup_xattrdir(dvp, vpp));
 329  429  
 330  430          /*
 331  431           * If lookup is for "", just return dvp.
 332  432           */
 333  433          if (name[0] == '\0') {
 334  434                  vn_hold(dvp);
 335  435                  *vpp = dvp;
 336  436                  return (0);
 337  437          }
 338  438  
↓ open down ↓ 335 lines elided ↑ open up ↑
 674  774          return (0);
 675  775  }
 676  776  
 677  777  /* ARGSUSED */
 678  778  void
 679  779  fop_inactive(
 680  780          vnode_t *vp,
 681  781          cred_t *cr,
 682  782          caller_context_t *ct)
 683  783  {
 684      -        vncache_inactive(vp);
      784 +        if (vp->v_flag & V_XATTRDIR) {
      785 +                fake_inactive_xattrdir(vp);
      786 +        } else {
      787 +                vncache_inactive(vp);
      788 +        }
 685  789  }
 686  790  
      791 +/*
      792 + * The special xattr directories are not in the vncache AVL, but
      793 + * hang off the parent's v_xattrdir field.  When vn_rele finds
      794 + * an xattr dir at v_count == 1 it calls here, but until we
      795 + * take locks on both the parent and the xattrdir, we don't
      796 + * know if we're really at the last reference.  So in here we
      797 + * take both locks, re-check the count, and either bail out
      798 + * or proceed with "inactive" vnode cleanup.  Part of that
      799 + * cleanup includes releasing the hold on the parent and
      800 + * clearing the parent's v_xattrdir field, which were
      801 + * setup in fake_lookup_xattrdir()
      802 + */
      803 +static void
      804 +fake_inactive_xattrdir(vnode_t *vp)
      805 +{
      806 +        vnode_t *dvp = vp->v_data; /* parent */
      807 +        mutex_enter(&dvp->v_lock);
      808 +        mutex_enter(&vp->v_lock);
      809 +        if (vp->v_count > 1) {
      810 +                /* new ref. via v_xattrdir */
      811 +                mutex_exit(&vp->v_lock);
      812 +                mutex_exit(&dvp->v_lock);
      813 +                return;
      814 +        }
      815 +        ASSERT(dvp->v_xattrdir == vp);
      816 +        dvp->v_xattrdir = NULL;
      817 +        mutex_exit(&vp->v_lock);
      818 +        mutex_exit(&dvp->v_lock);
      819 +        vn_rele(dvp);
      820 +        vn_free(vp);
      821 +}
      822 +
 687  823  /* ARGSUSED */
 688  824  int
 689  825  fop_fid(
 690  826          vnode_t *vp,
 691  827          fid_t *fidp,
 692  828          caller_context_t *ct)
 693  829  {
 694  830          return (ENOSYS);
 695  831  }
 696  832  
↓ open down ↓ 45 lines elided ↑ open up ↑
 742  878  fop_frlock(
 743  879          vnode_t *vp,
 744  880          int cmd,
 745  881          flock64_t *bfp,
 746  882          int flag,
 747  883          offset_t offset,
 748  884          struct flk_callback *flk_cbp,
 749  885          cred_t *cr,
 750  886          caller_context_t *ct)
 751  887  {
      888 +#if defined(_LP64)
      889 +        offset_t maxoffset = INT64_MAX;
      890 +#elif defined(_ILP32)
      891 +        /*
      892 +         * Sadly, the fcntl API enforces 32-bit offsets,
      893 +         * even though we have _FILE_OFFSET_BITS=64
      894 +         */
      895 +        offset_t maxoffset = INT32_MAX;
      896 +#else
      897 +#error "unsupported env."
      898 +#endif
      899 +
 752  900          /* See fs_frlock */
 753  901  
 754  902          switch (cmd) {
 755  903          case F_GETLK:
 756  904          case F_SETLK_NBMAND:
 757  905          case F_SETLK:
 758  906          case F_SETLKW:
 759  907                  break;
 760  908          default:
 761  909                  return (EINVAL);
 762  910          }
 763  911  
      912 +        /* We only get SEEK_SET ranges here. */
      913 +        if (bfp->l_whence != 0)
      914 +                return (EINVAL);
      915 +
      916 +        /*
      917 +         * One limitation of using fcntl(2) F_SETLK etc is that
      918 +         * the real kernel limits the offsets we can use.
      919 +         * (Maybe the fcntl API should loosen that up?)
      920 +         * See syscall/fcntl.c:flock_check()
      921 +         *
      922 +         * Here in libfksmbsrv we can just ignore such locks,
      923 +         * or ignore the part that extends beyond maxoffset.
      924 +         * The SMB layer still keeps track of such locks for
      925 +         * conflict detection, so not reflecting such locks
      926 +         * into the real FS layer is OK.  Note: this may
      927 +         * modify the pased bfp->l_len.
      928 +         */
      929 +        if (bfp->l_start < 0 || bfp->l_start > maxoffset)
      930 +                return (0);
      931 +        if (bfp->l_len < 0 || bfp->l_len > maxoffset)
      932 +                return (0);
      933 +        if (bfp->l_len > (maxoffset - bfp->l_start + 1))
      934 +                bfp->l_len = (maxoffset - bfp->l_start + 1);
      935 +
 764  936          if (fcntl(vp->v_fd, cmd, bfp) == -1)
 765  937                  return (errno);
 766  938  
 767  939          return (0);
 768  940  }
 769  941  
 770  942  /* ARGSUSED */
 771  943  int
 772  944  fop_space(
 773  945          vnode_t *vp,
↓ open down ↓ 202 lines elided ↑ open up ↑
 976 1148  
 977 1149          case _PC_CHOWN_RESTRICTED:
 978 1150                  val = 1; /* chown restricted enabled */
 979 1151                  break;
 980 1152  
 981 1153          case _PC_FILESIZEBITS:
 982 1154                  val = (ulong_t)-1;    /* large file support */
 983 1155                  break;
 984 1156  
 985 1157          case _PC_ACL_ENABLED:
 986      -                val = 0;
     1158 +                val = _ACL_ACE_ENABLED;
 987 1159                  break;
 988 1160  
 989 1161          case _PC_CASE_BEHAVIOR:
 990 1162                  val = _CASE_SENSITIVE;
 991 1163                  break;
 992 1164  
 993 1165          case _PC_SATTR_ENABLED:
 994 1166          case _PC_SATTR_EXISTS:
 995 1167                  val = 0;
 996 1168                  break;
↓ open down ↓ 263 lines elided ↑ open up ↑
1260 1432          mutex_exit(&vp->v_lock);
1261 1433  }
1262 1434  
1263 1435  void
1264 1436  vn_rele(vnode_t *vp)
1265 1437  {
1266 1438          VERIFY3U(vp->v_count, !=, 0);
1267 1439          mutex_enter(&vp->v_lock);
1268 1440          if (vp->v_count == 1) {
1269 1441                  mutex_exit(&vp->v_lock);
1270      -                vncache_inactive(vp);
     1442 +                fop_inactive(vp, NULL, NULL);
1271 1443          } else {
1272 1444                  vp->v_count--;
1273 1445                  mutex_exit(&vp->v_lock);
1274 1446          }
1275 1447  }
1276 1448  
1277 1449  int
1278 1450  vn_has_other_opens(
1279 1451          vnode_t *vp,
1280 1452          v_mode_t mode)
↓ open down ↓ 72 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX