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
   1    1  /*
   2    2   * This file and its contents are supplied under the terms of the
  
    | 
      ↓ 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  
  63   67          if ((*vpp)->v_type == VREG) {
  64   68                  if (mode & FREAD)
  65   69                          atomic_add_32(&((*vpp)->v_rdcnt), 1);
  66   70                  if (mode & FWRITE)
  67   71                          atomic_add_32(&((*vpp)->v_wrcnt), 1);
  68   72          }
  69   73  
  70   74          /* call to ->vop_open was here */
  71   75  
  72   76          return (0);
  73   77  }
  74   78  
  75   79  /* ARGSUSED */
  76   80  int
  77   81  fop_close(
  78   82          vnode_t *vp,
  79   83          int flag,
  80   84          int count,
  81   85          offset_t offset,
  82   86          cred_t *cr,
  83   87          caller_context_t *ct)
  84   88  {
  85   89  
  86   90          /* call to ->vop_close was here */
  87   91  
  88   92          /*
  89   93           * Check passed in count to handle possible dups. Vnode counts are only
  90   94           * kept on regular files
  91   95           */
  92   96          if ((vp->v_type == VREG) && (count == 1))  {
  93   97                  if (flag & FREAD) {
  94   98                          ASSERT(vp->v_rdcnt > 0);
  95   99                          atomic_add_32(&(vp->v_rdcnt), -1);
  96  100                  }
  97  101                  if (flag & FWRITE) {
  98  102                          ASSERT(vp->v_wrcnt > 0);
  99  103                          atomic_add_32(&(vp->v_wrcnt), -1);
 100  104                  }
 101  105          }
 102  106          return (0);
 103  107  }
 104  108  
 105  109  /* ARGSUSED */
 106  110  int
 107  111  fop_read(
 108  112          vnode_t *vp,
 109  113          uio_t *uio,
 110  114          int ioflag,
 111  115          cred_t *cr,
 112  116          caller_context_t *ct)
 113  117  {
 114  118          struct stat st;
 115  119          struct iovec *iov;
 116  120          ssize_t resid;
 117  121          size_t cnt;
 118  122          int n;
 119  123  
 120  124          /*
 121  125           * If that caller asks for read beyond end of file,
 122  126           * that causes the pread call to block.  (Ugh!)
 123  127           * Get the file size and return what we can.
 124  128           */
 125  129          (void) fstat(vp->v_fd, &st);
 126  130          resid = uio->uio_resid;
 127  131          if ((uio->uio_loffset + resid) > st.st_size)
 128  132                  resid = st.st_size - uio->uio_loffset;
 129  133  
 130  134          while (resid > 0) {
 131  135  
 132  136                  ASSERT(uio->uio_iovcnt > 0);
 133  137                  iov = uio->uio_iov;
 134  138  
 135  139                  if (iov->iov_len == 0) {
 136  140                          uio->uio_iov++;
 137  141                          uio->uio_iovcnt--;
 138  142                          continue;
 139  143                  }
 140  144                  cnt = iov->iov_len;
 141  145                  if (cnt > resid)
 142  146                          cnt = resid;
 143  147  
 144  148                  n = pread(vp->v_fd, iov->iov_base, cnt, uio->uio_loffset);
 145  149                  if (n < 0)
 146  150                          return (errno);
 147  151  
 148  152                  iov->iov_base += n;
 149  153                  iov->iov_len -= n;
 150  154  
 151  155                  uio->uio_resid -= n;
 152  156                  uio->uio_loffset += n;
 153  157  
 154  158                  resid -= n;
 155  159          }
 156  160  
 157  161          return (0);
 158  162  }
 159  163  
 160  164  /* ARGSUSED */
 161  165  int
 162  166  fop_write(
 163  167          vnode_t *vp,
 164  168          uio_t *uio,
 165  169          int ioflag,
 166  170          cred_t *cr,
 167  171          caller_context_t *ct)
 168  172  {
 169  173          struct iovec *iov;
 170  174          size_t cnt;
 171  175          int n;
 172  176  
 173  177          while (uio->uio_resid > 0) {
 174  178  
 175  179                  ASSERT(uio->uio_iovcnt > 0);
 176  180                  iov = uio->uio_iov;
 177  181  
 178  182                  if (iov->iov_len == 0) {
 179  183                          uio->uio_iov++;
 180  184                          uio->uio_iovcnt--;
 181  185                          continue;
 182  186                  }
 183  187                  cnt = iov->iov_len;
 184  188                  if (cnt > uio->uio_resid)
 185  189                          cnt = uio->uio_resid;
 186  190  
 187  191                  n = pwrite(vp->v_fd, iov->iov_base, iov->iov_len,
 188  192                      uio->uio_loffset);
 189  193                  if (n < 0)
 190  194                          return (errno);
 191  195  
 192  196                  iov->iov_base += n;
 193  197                  iov->iov_len -= n;
 194  198  
 195  199                  uio->uio_resid -= n;
 196  200                  uio->uio_loffset += n;
 197  201          }
 198  202  
 199  203          if (ioflag == FSYNC) {
 200  204                  (void) fsync(vp->v_fd);
 201  205          }
 202  206  
 203  207          return (0);
 204  208  }
 205  209  
 206  210  /* ARGSUSED */
  
    | 
      ↓ 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)
 228  254  {
 229  255          /* allow any flags? See fs_setfl */
 230  256          return (0);
 231  257  }
 232  258  
 233  259  /* ARGSUSED */
 234  260  int
 235  261  fop_getattr(
 236  262          vnode_t *vp,
 237  263          vattr_t *vap,
 238  264          int flags,
 239  265          cred_t *cr,
 240  266          caller_context_t *ct)
 241  267  {
 242  268          int error;
 243  269          struct stat st;
 244  270  
 245  271          if (fstat(vp->v_fd, &st) == -1)
 246  272                  return (errno);
 247  273          error = stat_to_vattr(&st, vap);
 248  274  
 249  275          if (vap->va_mask & AT_XVATTR)
 250  276                  (void) fop__getxvattr(vp, (xvattr_t *)vap);
 251  277  
 252  278          return (error);
 253  279  }
 254  280  
  
    | 
      ↓ 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;
 279  310                  } else {
 280  311                          times[0].tv_sec = 0;
 281  312                          times[0].tv_nsec = UTIME_OMIT;
 282  313                  }
 283  314                  if (vap->va_mask & AT_MTIME) {
 284  315                          times[1] = vap->va_mtime;
 285  316                  } else {
 286  317                          times[1].tv_sec = 0;
 287  318                          times[1].tv_nsec = UTIME_OMIT;
 288  319                  }
 289  320  
 290  321                  (void) futimens(vp->v_fd, times);
 291  322          }
 292  323  
 293  324          return (0);
 294  325  }
 295  326  
 296  327  /* ARGSUSED */
 297  328  int
  
    | 
      ↓ 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  
 339  439          if (fstatat(dvp->v_fd, name, &st, AT_SYMLINK_NOFOLLOW) == -1)
 340  440                  return (errno);
 341  441  
 342  442          vp = vncache_lookup(&st);
 343  443          if (vp != NULL) {
 344  444                  /* lookup gave us a hold */
 345  445                  *vpp = vp;
 346  446                  return (0);
 347  447          }
 348  448  
 349  449          if (S_ISDIR(st.st_mode))
 350  450                  omode = O_RDONLY | O_NOFOLLOW;
 351  451  
 352  452  again:
 353  453          fd = openat(dvp->v_fd, name, omode, 0);
 354  454          if (fd < 0) {
 355  455                  if ((omode & O_RWMASK) == O_RDWR) {
 356  456                          omode &= ~O_RWMASK;
 357  457                          omode |= O_RDONLY;
 358  458                          goto again;
 359  459                  }
 360  460                  return (errno);
 361  461          }
 362  462  
 363  463          if (fstat(fd, &st) == -1) {
 364  464                  (void) close(fd);
 365  465                  return (errno);
 366  466          }
 367  467  
 368  468          vp = vncache_enter(&st, dvp, name, fd);
 369  469  
 370  470          *vpp = vp;
 371  471          return (0);
 372  472  }
 373  473  
 374  474  /* ARGSUSED */
 375  475  int
 376  476  fop_create(
 377  477          vnode_t *dvp,
 378  478          char *name,
 379  479          vattr_t *vap,
 380  480          vcexcl_t excl,
 381  481          int mode,
 382  482          vnode_t **vpp,
 383  483          cred_t *cr,
 384  484          int flags,
 385  485          caller_context_t *ct,
 386  486          vsecattr_t *vsecp)      /* ACL to set during create */
 387  487  {
 388  488          struct stat st;
 389  489          vnode_t *vp;
 390  490          int err, fd, omode;
 391  491  
 392  492          /*
 393  493           * If creating "", just return dvp.
 394  494           */
 395  495          if (name[0] == '\0') {
 396  496                  vn_hold(dvp);
 397  497                  *vpp = dvp;
 398  498                  return (0);
 399  499          }
 400  500  
 401  501          err = fstatat(dvp->v_fd, name, &st, AT_SYMLINK_NOFOLLOW);
 402  502          if (err != 0)
 403  503                  err = errno;
 404  504  
 405  505          vp = NULL;
 406  506          if (err == 0) {
 407  507                  /* The file already exists. */
 408  508                  if (excl == EXCL)
 409  509                          return (EEXIST);
 410  510  
 411  511                  vp = vncache_lookup(&st);
 412  512                  /* vp gained a hold */
 413  513          }
 414  514  
 415  515          if (vp == NULL) {
 416  516                  /*
 417  517                   * Open it. (may or may not exist)
 418  518                   */
 419  519                  omode = O_RDWR | O_CREAT | O_NOFOLLOW;
 420  520                  if (excl == EXCL)
 421  521                          omode |= O_EXCL;
 422  522          open_again:
 423  523                  fd = openat(dvp->v_fd, name, omode, mode);
 424  524                  if (fd < 0) {
 425  525                          if ((omode & O_RWMASK) == O_RDWR) {
 426  526                                  omode &= ~O_RWMASK;
 427  527                                  omode |= O_RDONLY;
 428  528                                  goto open_again;
 429  529                          }
 430  530                          return (errno);
 431  531                  }
 432  532                  (void) fstat(fd, &st);
 433  533  
 434  534                  vp = vncache_enter(&st, dvp, name, fd);
 435  535                  /* vp has its initial hold */
 436  536          }
 437  537  
 438  538          /* Should have the vp now. */
 439  539          if (vp == NULL)
 440  540                  return (EFAULT);
 441  541  
 442  542          if (vp->v_type == VDIR && vap->va_type != VDIR) {
 443  543                  vn_rele(vp);
 444  544                  return (EISDIR);
 445  545          }
 446  546          if (vp->v_type != VDIR && vap->va_type == VDIR) {
 447  547                  vn_rele(vp);
 448  548                  return (ENOTDIR);
 449  549          }
 450  550  
 451  551          /*
 452  552           * Might need to set attributes.
 453  553           */
 454  554          (void) fop_setattr(vp, vap, 0, cr, ct);
 455  555  
 456  556          *vpp = vp;
 457  557          return (0);
 458  558  }
 459  559  
 460  560  /* ARGSUSED */
 461  561  int
 462  562  fop_remove(
 463  563          vnode_t *dvp,
 464  564          char *name,
 465  565          cred_t *cr,
 466  566          caller_context_t *ct,
 467  567          int flags)
 468  568  {
 469  569  
 470  570          if (unlinkat(dvp->v_fd, name, 0))
 471  571                  return (errno);
 472  572  
 473  573          return (0);
 474  574  }
 475  575  
 476  576  /* ARGSUSED */
 477  577  int
 478  578  fop_link(
 479  579          vnode_t *to_dvp,
 480  580          vnode_t *fr_vp,
 481  581          char *to_name,
 482  582          cred_t *cr,
 483  583          caller_context_t *ct,
 484  584          int flags)
 485  585  {
 486  586          int err;
 487  587  
 488  588          /*
 489  589           * Would prefer to specify "from" as the combination:
 490  590           * (fr_vp->v_fd, NULL) but linkat does not permit it.
 491  591           */
 492  592          err = linkat(AT_FDCWD, fr_vp->v_path, to_dvp->v_fd, to_name,
 493  593              AT_SYMLINK_FOLLOW);
 494  594          if (err == -1)
 495  595                  err = errno;
 496  596  
 497  597          return (err);
 498  598  }
 499  599  
 500  600  /* ARGSUSED */
 501  601  int
 502  602  fop_rename(
 503  603          vnode_t *from_dvp,
 504  604          char *from_name,
 505  605          vnode_t *to_dvp,
 506  606          char *to_name,
 507  607          cred_t *cr,
 508  608          caller_context_t *ct,
 509  609          int flags)
 510  610  {
 511  611          struct stat st;
 512  612          vnode_t *vp;
 513  613          int err;
 514  614  
 515  615          if (fstatat(from_dvp->v_fd, from_name, &st,
 516  616              AT_SYMLINK_NOFOLLOW) == -1)
 517  617                  return (errno);
 518  618  
 519  619          vp = vncache_lookup(&st);
 520  620          if (vp == NULL)
 521  621                  return (ENOENT);
 522  622  
 523  623          err = renameat(from_dvp->v_fd, from_name, to_dvp->v_fd, to_name);
 524  624          if (err == -1)
 525  625                  err = errno;
 526  626          else
 527  627                  vncache_renamed(vp, to_dvp, to_name);
 528  628  
 529  629          vn_rele(vp);
 530  630  
 531  631          return (err);
 532  632  }
 533  633  
 534  634  /* ARGSUSED */
 535  635  int
 536  636  fop_mkdir(
 537  637          vnode_t *dvp,
 538  638          char *name,
 539  639          vattr_t *vap,
 540  640          vnode_t **vpp,
 541  641          cred_t *cr,
 542  642          caller_context_t *ct,
 543  643          int flags,
 544  644          vsecattr_t *vsecp)      /* ACL to set during create */
 545  645  {
 546  646          struct stat st;
 547  647          int err, fd;
 548  648  
 549  649          mode_t mode = vap->va_mode & 0777;
 550  650  
 551  651          if (mkdirat(dvp->v_fd, name, mode) == -1)
 552  652                  return (errno);
 553  653  
 554  654          if ((fd = openat(dvp->v_fd, name, O_RDONLY)) == -1)
 555  655                  return (errno);
 556  656          if (fstat(fd, &st) == -1) {
 557  657                  err = errno;
 558  658                  (void) close(fd);
 559  659                  return (err);
 560  660          }
 561  661  
 562  662          *vpp = vncache_enter(&st, dvp, name, fd);
 563  663  
 564  664          /*
 565  665           * Might need to set attributes.
 566  666           */
 567  667          (void) fop_setattr(*vpp, vap, 0, cr, ct);
 568  668  
 569  669          return (0);
 570  670  }
 571  671  
 572  672  /* ARGSUSED */
 573  673  int
 574  674  fop_rmdir(
 575  675          vnode_t *dvp,
 576  676          char *name,
 577  677          vnode_t *cdir,
 578  678          cred_t *cr,
 579  679          caller_context_t *ct,
 580  680          int flags)
 581  681  {
 582  682  
 583  683          if (unlinkat(dvp->v_fd, name, AT_REMOVEDIR) == -1)
 584  684                  return (errno);
 585  685  
 586  686          return (0);
 587  687  }
 588  688  
 589  689  /* ARGSUSED */
 590  690  int
 591  691  fop_readdir(
 592  692          vnode_t *vp,
 593  693          uio_t *uiop,
 594  694          cred_t *cr,
 595  695          int *eofp,
 596  696          caller_context_t *ct,
 597  697          int flags)
 598  698  {
 599  699          struct iovec *iov;
 600  700          int cnt;
 601  701          int error = 0;
 602  702          int fd = vp->v_fd;
 603  703  
 604  704          if (eofp) {
 605  705                  *eofp = 0;
 606  706          }
 607  707  
 608  708          error = lseek(fd, uiop->uio_loffset, SEEK_SET);
 609  709          if (error == -1)
 610  710                  return (errno);
 611  711  
 612  712          ASSERT(uiop->uio_iovcnt > 0);
 613  713          iov = uiop->uio_iov;
 614  714          if (iov->iov_len < sizeof (struct dirent))
 615  715                  return (EINVAL);
 616  716  
 617  717          /* LINTED E_BAD_PTR_CAST_ALIGN */
 618  718          cnt = getdents(fd, (struct dirent *)(uiop->uio_iov->iov_base),
 619  719              uiop->uio_resid);
 620  720          if (cnt == -1)
 621  721                  return (errno);
 622  722          if (cnt == 0) {
 623  723                  if (eofp) {
 624  724                          *eofp = 1;
 625  725                  }
 626  726                  return (ENOENT);
 627  727          }
 628  728  
 629  729          iov->iov_base += cnt;
 630  730          iov->iov_len  -= cnt;
 631  731          uiop->uio_resid -= cnt;
 632  732          uiop->uio_loffset = lseek(fd, 0LL, SEEK_CUR);
 633  733  
 634  734          return (0);
 635  735  }
 636  736  
 637  737  /* ARGSUSED */
 638  738  int
 639  739  fop_symlink(
 640  740          vnode_t *dvp,
 641  741          char *linkname,
 642  742          vattr_t *vap,
 643  743          char *target,
 644  744          cred_t *cr,
 645  745          caller_context_t *ct,
 646  746          int flags)
 647  747  {
 648  748          return (ENOSYS);
 649  749  }
 650  750  
 651  751  /* ARGSUSED */
 652  752  int
 653  753  fop_readlink(
 654  754          vnode_t *vp,
 655  755          uio_t *uiop,
 656  756          cred_t *cr,
 657  757          caller_context_t *ct)
 658  758  {
 659  759          return (ENOSYS);
 660  760  }
 661  761  
 662  762  /* ARGSUSED */
 663  763  int
 664  764  fop_fsync(
 665  765          vnode_t *vp,
 666  766          int syncflag,
 667  767          cred_t *cr,
 668  768          caller_context_t *ct)
 669  769  {
 670  770  
 671  771          if (fsync(vp->v_fd) == -1)
 672  772                  return (errno);
 673  773  
  
    | 
      ↓ 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  
 697  833  /* ARGSUSED */
 698  834  int
 699  835  fop_rwlock(
 700  836          vnode_t *vp,
 701  837          int write_lock,
 702  838          caller_context_t *ct)
 703  839  {
 704  840          /* See: fs_rwlock */
 705  841          return (-1);
 706  842  }
 707  843  
 708  844  /* ARGSUSED */
 709  845  void
 710  846  fop_rwunlock(
 711  847          vnode_t *vp,
 712  848          int write_lock,
 713  849          caller_context_t *ct)
 714  850  {
 715  851          /* See: fs_rwunlock */
 716  852  }
 717  853  
 718  854  /* ARGSUSED */
 719  855  int
 720  856  fop_seek(
 721  857          vnode_t *vp,
 722  858          offset_t ooff,
 723  859          offset_t *noffp,
 724  860          caller_context_t *ct)
 725  861  {
 726  862          return (ENOSYS);
 727  863  }
 728  864  
 729  865  /* ARGSUSED */
 730  866  int
 731  867  fop_cmp(
 732  868          vnode_t *vp1,
 733  869          vnode_t *vp2,
 734  870          caller_context_t *ct)
 735  871  {
 736  872          /* See fs_cmp */
 737  873          return (vncache_cmp(vp1, vp2));
 738  874  }
 739  875  
 740  876  /* ARGSUSED */
 741  877  int
  
    | 
      ↓ 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,
 774  946          int cmd,
 775  947          flock64_t *bfp,
 776  948          int flag,
 777  949          offset_t offset,
 778  950          cred_t *cr,
 779  951          caller_context_t *ct)
 780  952  {
 781  953          /* See fs_frlock */
 782  954  
 783  955          switch (cmd) {
 784  956          case F_ALLOCSP:
 785  957          case F_FREESP:
 786  958                  break;
 787  959          default:
 788  960                  return (EINVAL);
 789  961          }
 790  962  
 791  963          if (fcntl(vp->v_fd, cmd, bfp) == -1)
 792  964                  return (errno);
 793  965  
 794  966          return (0);
 795  967  }
 796  968  
 797  969  /* ARGSUSED */
 798  970  int
 799  971  fop_realvp(
 800  972          vnode_t *vp,
 801  973          vnode_t **vpp,
 802  974          caller_context_t *ct)
 803  975  {
 804  976          return (ENOSYS);
 805  977  }
 806  978  
 807  979  /* ARGSUSED */
 808  980  int
 809  981  fop_getpage(
 810  982          vnode_t *vp,
 811  983          offset_t off,
 812  984          size_t len,
 813  985          uint_t *protp,
 814  986          struct page **plarr,
 815  987          size_t plsz,
 816  988          struct seg *seg,
 817  989          caddr_t addr,
 818  990          enum seg_rw rw,
 819  991          cred_t *cr,
 820  992          caller_context_t *ct)
 821  993  {
 822  994          return (ENOSYS);
 823  995  }
 824  996  
 825  997  /* ARGSUSED */
 826  998  int
 827  999  fop_putpage(
 828 1000          vnode_t *vp,
 829 1001          offset_t off,
 830 1002          size_t len,
 831 1003          int flags,
 832 1004          cred_t *cr,
 833 1005          caller_context_t *ct)
 834 1006  {
 835 1007          return (ENOSYS);
 836 1008  }
 837 1009  
 838 1010  /* ARGSUSED */
 839 1011  int
 840 1012  fop_map(
 841 1013          vnode_t *vp,
 842 1014          offset_t off,
 843 1015          struct as *as,
 844 1016          caddr_t *addrp,
 845 1017          size_t len,
 846 1018          uchar_t prot,
 847 1019          uchar_t maxprot,
 848 1020          uint_t flags,
 849 1021          cred_t *cr,
 850 1022          caller_context_t *ct)
 851 1023  {
 852 1024          return (ENOSYS);
 853 1025  }
 854 1026  
 855 1027  /* ARGSUSED */
 856 1028  int
 857 1029  fop_addmap(
 858 1030          vnode_t *vp,
 859 1031          offset_t off,
 860 1032          struct as *as,
 861 1033          caddr_t addr,
 862 1034          size_t len,
 863 1035          uchar_t prot,
 864 1036          uchar_t maxprot,
 865 1037          uint_t flags,
 866 1038          cred_t *cr,
 867 1039          caller_context_t *ct)
 868 1040  {
 869 1041          return (ENOSYS);
 870 1042  }
 871 1043  
 872 1044  /* ARGSUSED */
 873 1045  int
 874 1046  fop_delmap(
 875 1047          vnode_t *vp,
 876 1048          offset_t off,
 877 1049          struct as *as,
 878 1050          caddr_t addr,
 879 1051          size_t len,
 880 1052          uint_t prot,
 881 1053          uint_t maxprot,
 882 1054          uint_t flags,
 883 1055          cred_t *cr,
 884 1056          caller_context_t *ct)
 885 1057  {
 886 1058          return (ENOSYS);
 887 1059  }
 888 1060  
 889 1061  /* ARGSUSED */
 890 1062  int
 891 1063  fop_poll(
 892 1064          vnode_t *vp,
 893 1065          short events,
 894 1066          int anyyet,
 895 1067          short *reventsp,
 896 1068          struct pollhead **phpp,
 897 1069          caller_context_t *ct)
 898 1070  {
 899 1071          *reventsp = 0;
 900 1072          if (events & POLLIN)
 901 1073                  *reventsp |= POLLIN;
 902 1074          if (events & POLLRDNORM)
 903 1075                  *reventsp |= POLLRDNORM;
 904 1076          if (events & POLLRDBAND)
 905 1077                  *reventsp |= POLLRDBAND;
 906 1078          if (events & POLLOUT)
 907 1079                  *reventsp |= POLLOUT;
 908 1080          if (events & POLLWRBAND)
 909 1081                  *reventsp |= POLLWRBAND;
 910 1082          *phpp = NULL; /* or fake_pollhead? */
 911 1083  
 912 1084          return (0);
 913 1085  }
 914 1086  
 915 1087  /* ARGSUSED */
 916 1088  int
 917 1089  fop_dump(
 918 1090          vnode_t *vp,
 919 1091          caddr_t addr,
 920 1092          offset_t lbdn,
 921 1093          offset_t dblks,
 922 1094          caller_context_t *ct)
 923 1095  {
 924 1096          return (ENOSYS);
 925 1097  }
 926 1098  
 927 1099  /*
 928 1100   * See fs_pathconf
 929 1101   */
 930 1102  /* ARGSUSED */
 931 1103  int
 932 1104  fop_pathconf(
 933 1105          vnode_t *vp,
 934 1106          int cmd,
 935 1107          ulong_t *valp,
 936 1108          cred_t *cr,
 937 1109          caller_context_t *ct)
 938 1110  {
 939 1111          register ulong_t val;
 940 1112          register int error = 0;
 941 1113  
 942 1114          switch (cmd) {
 943 1115  
 944 1116          case _PC_LINK_MAX:
 945 1117                  val = MAXLINK;
 946 1118                  break;
 947 1119  
 948 1120          case _PC_MAX_CANON:
 949 1121                  val = MAX_CANON;
 950 1122                  break;
 951 1123  
 952 1124          case _PC_MAX_INPUT:
 953 1125                  val = MAX_INPUT;
 954 1126                  break;
 955 1127  
 956 1128          case _PC_NAME_MAX:
 957 1129                  val = MAXNAMELEN;
 958 1130                  break;
 959 1131  
 960 1132          case _PC_PATH_MAX:
 961 1133          case _PC_SYMLINK_MAX:
 962 1134                  val = MAXPATHLEN;
 963 1135                  break;
 964 1136  
 965 1137          case _PC_PIPE_BUF:
 966 1138                  val = PIPE_BUF;
 967 1139                  break;
 968 1140  
 969 1141          case _PC_NO_TRUNC:
 970 1142                  val = (ulong_t)-1;
 971 1143                  break;
 972 1144  
 973 1145          case _PC_VDISABLE:
 974 1146                  val = _POSIX_VDISABLE;
 975 1147                  break;
  
    | 
      ↓ 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;
 997 1169  
 998 1170          case _PC_ACCESS_FILTERING:
 999 1171                  val = 0;
1000 1172                  break;
1001 1173  
1002 1174          default:
1003 1175                  error = EINVAL;
1004 1176                  break;
1005 1177          }
1006 1178  
1007 1179          if (error == 0)
1008 1180                  *valp = val;
1009 1181          return (error);
1010 1182  }
1011 1183  
1012 1184  /* ARGSUSED */
1013 1185  int
1014 1186  fop_pageio(
1015 1187          vnode_t *vp,
1016 1188          struct page *pp,
1017 1189          u_offset_t io_off,
1018 1190          size_t io_len,
1019 1191          int flags,
1020 1192          cred_t *cr,
1021 1193          caller_context_t *ct)
1022 1194  {
1023 1195          return (ENOSYS);
1024 1196  }
1025 1197  
1026 1198  /* ARGSUSED */
1027 1199  int
1028 1200  fop_dumpctl(
1029 1201          vnode_t *vp,
1030 1202          int action,
1031 1203          offset_t *blkp,
1032 1204          caller_context_t *ct)
1033 1205  {
1034 1206          return (ENOSYS);
1035 1207  }
1036 1208  
1037 1209  /* ARGSUSED */
1038 1210  void
1039 1211  fop_dispose(
1040 1212          vnode_t *vp,
1041 1213          struct page *pp,
1042 1214          int flag,
1043 1215          int dn,
1044 1216          cred_t *cr,
1045 1217          caller_context_t *ct)
1046 1218  {
1047 1219  }
1048 1220  
1049 1221  /* ARGSUSED */
1050 1222  int
1051 1223  fop_setsecattr(
1052 1224          vnode_t *vp,
1053 1225          vsecattr_t *vsap,
1054 1226          int flag,
1055 1227          cred_t *cr,
1056 1228          caller_context_t *ct)
1057 1229  {
1058 1230          return (0);
1059 1231  }
1060 1232  
1061 1233  /*
1062 1234   * Fake up just enough of this so we can test get/set SDs.
1063 1235   */
1064 1236  /* ARGSUSED */
1065 1237  int
1066 1238  fop_getsecattr(
1067 1239          vnode_t *vp,
1068 1240          vsecattr_t *vsecattr,
1069 1241          int flag,
1070 1242          cred_t *cr,
1071 1243          caller_context_t *ct)
1072 1244  {
1073 1245  
1074 1246          vsecattr->vsa_aclcnt    = 0;
1075 1247          vsecattr->vsa_aclentsz  = 0;
1076 1248          vsecattr->vsa_aclentp   = NULL;
1077 1249          vsecattr->vsa_dfaclcnt  = 0;    /* Default ACLs are not fabricated */
1078 1250          vsecattr->vsa_dfaclentp = NULL;
1079 1251  
1080 1252          if (vsecattr->vsa_mask & (VSA_ACLCNT | VSA_ACL)) {
1081 1253                  aclent_t *aclentp;
1082 1254                  size_t aclsize;
1083 1255  
1084 1256                  aclsize = sizeof (aclent_t);
1085 1257                  vsecattr->vsa_aclcnt = 1;
1086 1258                  vsecattr->vsa_aclentp = kmem_zalloc(aclsize, KM_SLEEP);
1087 1259                  aclentp = vsecattr->vsa_aclentp;
1088 1260  
1089 1261                  aclentp->a_type = OTHER_OBJ;
1090 1262                  aclentp->a_perm = 0777;
1091 1263                  aclentp->a_id = (gid_t)-1;
1092 1264                  aclentp++;
1093 1265          } else if (vsecattr->vsa_mask & (VSA_ACECNT | VSA_ACE)) {
1094 1266                  ace_t *acl;
1095 1267  
1096 1268                  acl = kmem_alloc(sizeof (ace_t), KM_SLEEP);
1097 1269                  acl->a_who = (uint32_t)-1;
1098 1270                  acl->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
1099 1271                  acl->a_flags = ACE_EVERYONE;
1100 1272                  acl->a_access_mask  = ACE_MODIFY_PERMS;
1101 1273  
1102 1274                  vsecattr->vsa_aclentp = (void *)acl;
1103 1275                  vsecattr->vsa_aclcnt = 1;
1104 1276                  vsecattr->vsa_aclentsz = sizeof (ace_t);
1105 1277          }
1106 1278  
1107 1279          return (0);
1108 1280  }
1109 1281  
1110 1282  /* ARGSUSED */
1111 1283  int
1112 1284  fop_shrlock(
1113 1285          vnode_t *vp,
1114 1286          int cmd,
1115 1287          struct shrlock *shr,
1116 1288          int flag,
1117 1289          cred_t *cr,
1118 1290          caller_context_t *ct)
1119 1291  {
1120 1292  
1121 1293          switch (cmd) {
1122 1294          case F_SHARE:
1123 1295          case F_SHARE_NBMAND:
1124 1296          case F_UNSHARE:
1125 1297                  break;
1126 1298          default:
1127 1299                  return (EINVAL);
1128 1300          }
1129 1301  
1130 1302          if (!fop_shrlock_enable)
1131 1303                  return (0);
1132 1304  
1133 1305          if (fcntl(vp->v_fd, cmd, shr) == -1)
1134 1306                  return (errno);
1135 1307  
1136 1308          return (0);
1137 1309  }
1138 1310  
1139 1311  /* ARGSUSED */
1140 1312  int
1141 1313  fop_vnevent(vnode_t *vp, vnevent_t vnevent, vnode_t *dvp, char *fnm,
1142 1314      caller_context_t *ct)
1143 1315  {
1144 1316          return (ENOSYS);
1145 1317  }
1146 1318  
1147 1319  /* ARGSUSED */
1148 1320  int
1149 1321  fop_reqzcbuf(vnode_t *vp, enum uio_rw ioflag, xuio_t *uiop, cred_t *cr,
1150 1322      caller_context_t *ct)
1151 1323  {
1152 1324          return (ENOSYS);
1153 1325  }
1154 1326  
1155 1327  /* ARGSUSED */
1156 1328  int
1157 1329  fop_retzcbuf(vnode_t *vp, xuio_t *uiop, cred_t *cr, caller_context_t *ct)
1158 1330  {
1159 1331          return (ENOSYS);
1160 1332  }
1161 1333  
1162 1334  
1163 1335  /*
1164 1336   * ***************************************************************
1165 1337   * other VOP support
1166 1338   */
1167 1339  
1168 1340  /*
1169 1341   * Convert stat(2) formats to vnode types and vice versa.  (Knows about
1170 1342   * numerical order of S_IFMT and vnode types.)
1171 1343   */
1172 1344  enum vtype iftovt_tab[] = {
1173 1345          VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
1174 1346          VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VNON
1175 1347  };
1176 1348  
1177 1349  ushort_t vttoif_tab[] = {
1178 1350          0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, S_IFIFO,
1179 1351          S_IFDOOR, 0, S_IFSOCK, S_IFPORT, 0
1180 1352  };
1181 1353  
1182 1354  /*
1183 1355   * stat_to_vattr()
1184 1356   *
1185 1357   * Convert from a stat structure to an vattr structure
1186 1358   * Note: only set fields according to va_mask
1187 1359   */
1188 1360  
1189 1361  int
1190 1362  stat_to_vattr(const struct stat *st, vattr_t *vap)
1191 1363  {
1192 1364  
1193 1365          if (vap->va_mask & AT_TYPE)
1194 1366                  vap->va_type = IFTOVT(st->st_mode);
1195 1367  
1196 1368          if (vap->va_mask & AT_MODE)
1197 1369                  vap->va_mode = st->st_mode;
1198 1370  
1199 1371          if (vap->va_mask & AT_UID)
1200 1372                  vap->va_uid = st->st_uid;
1201 1373  
1202 1374          if (vap->va_mask & AT_GID)
1203 1375                  vap->va_gid = st->st_gid;
1204 1376  
1205 1377          if (vap->va_mask & AT_FSID)
1206 1378                  vap->va_fsid = st->st_dev;
1207 1379  
1208 1380          if (vap->va_mask & AT_NODEID)
1209 1381                  vap->va_nodeid = st->st_ino;
1210 1382  
1211 1383          if (vap->va_mask & AT_NLINK)
1212 1384                  vap->va_nlink = st->st_nlink;
1213 1385  
1214 1386          if (vap->va_mask & AT_SIZE)
1215 1387                  vap->va_size = (u_offset_t)st->st_size;
1216 1388  
1217 1389          if (vap->va_mask & AT_ATIME) {
1218 1390                  vap->va_atime.tv_sec  = st->st_atim.tv_sec;
1219 1391                  vap->va_atime.tv_nsec = st->st_atim.tv_nsec;
1220 1392          }
1221 1393  
1222 1394          if (vap->va_mask & AT_MTIME) {
1223 1395                  vap->va_mtime.tv_sec  = st->st_mtim.tv_sec;
1224 1396                  vap->va_mtime.tv_nsec = st->st_mtim.tv_nsec;
1225 1397          }
1226 1398  
1227 1399          if (vap->va_mask & AT_CTIME) {
1228 1400                  vap->va_ctime.tv_sec  = st->st_ctim.tv_sec;
1229 1401                  vap->va_ctime.tv_nsec = st->st_ctim.tv_nsec;
1230 1402          }
1231 1403  
1232 1404          if (vap->va_mask & AT_RDEV)
1233 1405                  vap->va_rdev = st->st_rdev;
1234 1406  
1235 1407          if (vap->va_mask & AT_BLKSIZE)
1236 1408                  vap->va_blksize = (uint_t)st->st_blksize;
1237 1409  
1238 1410  
1239 1411          if (vap->va_mask & AT_NBLOCKS)
1240 1412                  vap->va_nblocks = (u_longlong_t)st->st_blocks;
1241 1413  
1242 1414          if (vap->va_mask & AT_SEQ)
1243 1415                  vap->va_seq = 0;
1244 1416  
1245 1417          return (0);
1246 1418  }
1247 1419  
1248 1420  /* ARGSUSED */
1249 1421  void
1250 1422  flk_init_callback(flk_callback_t *flk_cb,
1251 1423          callb_cpr_t *(*cb_fcn)(flk_cb_when_t, void *), void *cbdata)
1252 1424  {
1253 1425  }
1254 1426  
1255 1427  void
1256 1428  vn_hold(vnode_t *vp)
1257 1429  {
1258 1430          mutex_enter(&vp->v_lock);
1259 1431          vp->v_count++;
  
    | 
      ↓ 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)
1281 1453  {
1282 1454  
1283 1455          switch (mode) {
1284 1456          case V_WRITE:
1285 1457                  if (vp->v_wrcnt > 1)
1286 1458                          return (V_TRUE);
1287 1459                  break;
1288 1460          case V_RDORWR:
1289 1461                  if ((vp->v_rdcnt > 1) || (vp->v_wrcnt > 1))
1290 1462                          return (V_TRUE);
1291 1463                  break;
1292 1464          case V_RDANDWR:
1293 1465                  if ((vp->v_rdcnt > 1) && (vp->v_wrcnt > 1))
1294 1466                          return (V_TRUE);
1295 1467                  break;
1296 1468          case V_READ:
1297 1469                  if (vp->v_rdcnt > 1)
1298 1470                          return (V_TRUE);
1299 1471                  break;
1300 1472          }
1301 1473  
1302 1474          return (V_FALSE);
1303 1475  }
1304 1476  
1305 1477  /*
1306 1478   * vn_is_opened() checks whether a particular file is opened and
1307 1479   * whether the open is for read and/or write.
1308 1480   *
1309 1481   * Vnode counts are only kept on regular files (v_type=VREG).
1310 1482   */
1311 1483  int
1312 1484  vn_is_opened(
1313 1485          vnode_t *vp,
1314 1486          v_mode_t mode)
1315 1487  {
1316 1488  
1317 1489          ASSERT(vp != NULL);
1318 1490  
1319 1491          switch (mode) {
1320 1492          case V_WRITE:
1321 1493                  if (vp->v_wrcnt)
1322 1494                          return (V_TRUE);
1323 1495                  break;
1324 1496          case V_RDANDWR:
1325 1497                  if (vp->v_rdcnt && vp->v_wrcnt)
1326 1498                          return (V_TRUE);
1327 1499                  break;
1328 1500          case V_RDORWR:
1329 1501                  if (vp->v_rdcnt || vp->v_wrcnt)
1330 1502                          return (V_TRUE);
1331 1503                  break;
1332 1504          case V_READ:
1333 1505                  if (vp->v_rdcnt)
1334 1506                          return (V_TRUE);
1335 1507                  break;
1336 1508          }
1337 1509  
1338 1510          return (V_FALSE);
1339 1511  }
1340 1512  
1341 1513  /*
1342 1514   * vn_is_mapped() checks whether a particular file is mapped and whether
1343 1515   * the file is mapped read and/or write.
1344 1516   */
1345 1517  /* ARGSUSED */
1346 1518  int
1347 1519  vn_is_mapped(
1348 1520          vnode_t *vp,
1349 1521          v_mode_t mode)
1350 1522  {
1351 1523          return (V_FALSE);
1352 1524  }
  
    | 
      ↓ open down ↓ | 
    72 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX