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>
   1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  14  */
  15 
  16 #include <sys/types.h>
  17 #include <sys/param.h>

  18 #include <sys/t_lock.h>
  19 #include <sys/errno.h>
  20 #include <sys/cred.h>
  21 #include <sys/user.h>
  22 #include <sys/uio.h>
  23 #include <sys/file.h>
  24 #include <sys/pathname.h>
  25 #include <sys/vfs.h>
  26 #include <sys/vnode.h>
  27 #include <sys/stat.h>
  28 #include <sys/mode.h>
  29 #include <sys/kmem.h>

  30 #include <sys/debug.h>
  31 #include <sys/atomic.h>
  32 #include <sys/acl.h>

  33 #include <sys/flock.h>
  34 #include <sys/nbmlock.h>
  35 #include <sys/fcntl.h>
  36 #include <sys/poll.h>
  37 #include <sys/time.h>
  38 
  39 #include <errno.h>
  40 #include <fcntl.h>
  41 #include <unistd.h>
  42 
  43 #include "vncache.h"
  44 
  45 #define O_RWMASK        (O_WRONLY | O_RDWR) /* == 3 */
  46 
  47 int fop_shrlock_enable = 0;
  48 
  49 int stat_to_vattr(const struct stat *, vattr_t *);
  50 int fop__getxvattr(vnode_t *, xvattr_t *);
  51 int fop__setxvattr(vnode_t *, xvattr_t *);
  52 

  53 
  54 /* ARGSUSED */
  55 int
  56 fop_open(
  57         vnode_t **vpp,
  58         int mode,
  59         cred_t *cr,
  60         caller_context_t *ct)
  61 {
  62 
  63         if ((*vpp)->v_type == VREG) {
  64                 if (mode & FREAD)
  65                         atomic_add_32(&((*vpp)->v_rdcnt), 1);
  66                 if (mode & FWRITE)
  67                         atomic_add_32(&((*vpp)->v_wrcnt), 1);
  68         }
  69 
  70         /* call to ->vop_open was here */
  71 
  72         return (0);


 197         }
 198 
 199         if (ioflag == FSYNC) {
 200                 (void) fsync(vp->v_fd);
 201         }
 202 
 203         return (0);
 204 }
 205 
 206 /* ARGSUSED */
 207 int
 208 fop_ioctl(
 209         vnode_t *vp,
 210         int cmd,
 211         intptr_t arg,
 212         int flag,
 213         cred_t *cr,
 214         int *rvalp,
 215         caller_context_t *ct)
 216 {
 217         return (ENOSYS);






















 218 }
 219 
 220 /* ARGSUSED */
 221 int
 222 fop_setfl(
 223         vnode_t *vp,
 224         int oflags,
 225         int nflags,
 226         cred_t *cr,
 227         caller_context_t *ct)
 228 {
 229         /* allow any flags? See fs_setfl */
 230         return (0);
 231 }
 232 
 233 /* ARGSUSED */
 234 int
 235 fop_getattr(
 236         vnode_t *vp,
 237         vattr_t *vap,


 245         if (fstat(vp->v_fd, &st) == -1)
 246                 return (errno);
 247         error = stat_to_vattr(&st, vap);
 248 
 249         if (vap->va_mask & AT_XVATTR)
 250                 (void) fop__getxvattr(vp, (xvattr_t *)vap);
 251 
 252         return (error);
 253 }
 254 
 255 /* ARGSUSED */
 256 int
 257 fop_setattr(
 258         vnode_t *vp,
 259         vattr_t *vap,
 260         int flags,
 261         cred_t *cr,
 262         caller_context_t *ct)
 263 {
 264         timespec_t times[2];

 265 
 266         if (vap->va_mask & AT_SIZE) {
 267                 if (ftruncate(vp->v_fd, vap->va_size) == -1)
 268                         return (errno);



 269         }

 270 
 271         /* AT_MODE or anything else? */
 272 
 273         if (vap->va_mask & AT_XVATTR)
 274                 (void) fop__setxvattr(vp, (xvattr_t *)vap);
 275 
 276         if (vap->va_mask & (AT_ATIME | AT_MTIME)) {
 277                 if (vap->va_mask & AT_ATIME) {
 278                         times[0] = vap->va_atime;
 279                 } else {
 280                         times[0].tv_sec = 0;
 281                         times[0].tv_nsec = UTIME_OMIT;
 282                 }
 283                 if (vap->va_mask & AT_MTIME) {
 284                         times[1] = vap->va_mtime;
 285                 } else {
 286                         times[1].tv_sec = 0;
 287                         times[1].tv_nsec = UTIME_OMIT;
 288                 }
 289 
 290                 (void) futimens(vp->v_fd, times);
 291         }
 292 
 293         return (0);
 294 }
 295 
 296 /* ARGSUSED */
 297 int
 298 fop_access(
 299         vnode_t *vp,
 300         int mode,
 301         int flags,
 302         cred_t *cr,
 303         caller_context_t *ct)
 304 {
 305         return (0);
 306 }
 307 





































































 308 /* ARGSUSED */
 309 int
 310 fop_lookup(
 311         vnode_t *dvp,
 312         char *name,
 313         vnode_t **vpp,
 314         pathname_t *pnp,
 315         int flags,
 316         vnode_t *rdir,
 317         cred_t *cr,
 318         caller_context_t *ct,
 319         int *deflags,           /* Returned per-dirent flags */
 320         pathname_t *ppnp)       /* Returned case-preserved name in directory */
 321 {
 322         int fd;
 323         int omode = O_RDWR | O_NOFOLLOW;
 324         vnode_t *vp;
 325         struct stat st;
 326 
 327         if (flags & LOOKUP_XATTR)
 328                 return (ENOENT);
 329 
 330         /*
 331          * If lookup is for "", just return dvp.
 332          */
 333         if (name[0] == '\0') {
 334                 vn_hold(dvp);
 335                 *vpp = dvp;
 336                 return (0);
 337         }
 338 
 339         if (fstatat(dvp->v_fd, name, &st, AT_SYMLINK_NOFOLLOW) == -1)
 340                 return (errno);
 341 
 342         vp = vncache_lookup(&st);
 343         if (vp != NULL) {
 344                 /* lookup gave us a hold */
 345                 *vpp = vp;
 346                 return (0);
 347         }
 348 


 664 fop_fsync(
 665         vnode_t *vp,
 666         int syncflag,
 667         cred_t *cr,
 668         caller_context_t *ct)
 669 {
 670 
 671         if (fsync(vp->v_fd) == -1)
 672                 return (errno);
 673 
 674         return (0);
 675 }
 676 
 677 /* ARGSUSED */
 678 void
 679 fop_inactive(
 680         vnode_t *vp,
 681         cred_t *cr,
 682         caller_context_t *ct)
 683 {



 684         vncache_inactive(vp);

 685 }
 686 
































 687 /* ARGSUSED */
 688 int
 689 fop_fid(
 690         vnode_t *vp,
 691         fid_t *fidp,
 692         caller_context_t *ct)
 693 {
 694         return (ENOSYS);
 695 }
 696 
 697 /* ARGSUSED */
 698 int
 699 fop_rwlock(
 700         vnode_t *vp,
 701         int write_lock,
 702         caller_context_t *ct)
 703 {
 704         /* See: fs_rwlock */
 705         return (-1);
 706 }


 732         vnode_t *vp1,
 733         vnode_t *vp2,
 734         caller_context_t *ct)
 735 {
 736         /* See fs_cmp */
 737         return (vncache_cmp(vp1, vp2));
 738 }
 739 
 740 /* ARGSUSED */
 741 int
 742 fop_frlock(
 743         vnode_t *vp,
 744         int cmd,
 745         flock64_t *bfp,
 746         int flag,
 747         offset_t offset,
 748         struct flk_callback *flk_cbp,
 749         cred_t *cr,
 750         caller_context_t *ct)
 751 {












 752         /* See fs_frlock */
 753 
 754         switch (cmd) {
 755         case F_GETLK:
 756         case F_SETLK_NBMAND:
 757         case F_SETLK:
 758         case F_SETLKW:
 759                 break;
 760         default:
 761                 return (EINVAL);
 762         }
 763 
























 764         if (fcntl(vp->v_fd, cmd, bfp) == -1)
 765                 return (errno);
 766 
 767         return (0);
 768 }
 769 
 770 /* ARGSUSED */
 771 int
 772 fop_space(
 773         vnode_t *vp,
 774         int cmd,
 775         flock64_t *bfp,
 776         int flag,
 777         offset_t offset,
 778         cred_t *cr,
 779         caller_context_t *ct)
 780 {
 781         /* See fs_frlock */
 782 
 783         switch (cmd) {


 966                 val = PIPE_BUF;
 967                 break;
 968 
 969         case _PC_NO_TRUNC:
 970                 val = (ulong_t)-1;
 971                 break;
 972 
 973         case _PC_VDISABLE:
 974                 val = _POSIX_VDISABLE;
 975                 break;
 976 
 977         case _PC_CHOWN_RESTRICTED:
 978                 val = 1; /* chown restricted enabled */
 979                 break;
 980 
 981         case _PC_FILESIZEBITS:
 982                 val = (ulong_t)-1;    /* large file support */
 983                 break;
 984 
 985         case _PC_ACL_ENABLED:
 986                 val = 0;
 987                 break;
 988 
 989         case _PC_CASE_BEHAVIOR:
 990                 val = _CASE_SENSITIVE;
 991                 break;
 992 
 993         case _PC_SATTR_ENABLED:
 994         case _PC_SATTR_EXISTS:
 995                 val = 0;
 996                 break;
 997 
 998         case _PC_ACCESS_FILTERING:
 999                 val = 0;
1000                 break;
1001 
1002         default:
1003                 error = EINVAL;
1004                 break;
1005         }
1006 


1250 flk_init_callback(flk_callback_t *flk_cb,
1251         callb_cpr_t *(*cb_fcn)(flk_cb_when_t, void *), void *cbdata)
1252 {
1253 }
1254 
1255 void
1256 vn_hold(vnode_t *vp)
1257 {
1258         mutex_enter(&vp->v_lock);
1259         vp->v_count++;
1260         mutex_exit(&vp->v_lock);
1261 }
1262 
1263 void
1264 vn_rele(vnode_t *vp)
1265 {
1266         VERIFY3U(vp->v_count, !=, 0);
1267         mutex_enter(&vp->v_lock);
1268         if (vp->v_count == 1) {
1269                 mutex_exit(&vp->v_lock);
1270                 vncache_inactive(vp);
1271         } else {
1272                 vp->v_count--;
1273                 mutex_exit(&vp->v_lock);
1274         }
1275 }
1276 
1277 int
1278 vn_has_other_opens(
1279         vnode_t *vp,
1280         v_mode_t mode)
1281 {
1282 
1283         switch (mode) {
1284         case V_WRITE:
1285                 if (vp->v_wrcnt > 1)
1286                         return (V_TRUE);
1287                 break;
1288         case V_RDORWR:
1289                 if ((vp->v_rdcnt > 1) || (vp->v_wrcnt > 1))
1290                         return (V_TRUE);


   1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  14  */
  15 
  16 #include <sys/types.h>
  17 #include <sys/param.h>
  18 #include <sys/systm.h>
  19 #include <sys/t_lock.h>
  20 #include <sys/errno.h>
  21 #include <sys/cred.h>
  22 #include <sys/user.h>
  23 #include <sys/uio.h>
  24 #include <sys/file.h>
  25 #include <sys/pathname.h>
  26 #include <sys/vfs.h>
  27 #include <sys/vnode.h>
  28 #include <sys/stat.h>
  29 #include <sys/mode.h>
  30 #include <sys/kmem.h>
  31 #include <sys/cmn_err.h>
  32 #include <sys/debug.h>
  33 #include <sys/atomic.h>
  34 #include <sys/acl.h>
  35 #include <sys/filio.h>
  36 #include <sys/flock.h>
  37 #include <sys/nbmlock.h>
  38 #include <sys/fcntl.h>
  39 #include <sys/poll.h>
  40 #include <sys/time.h>
  41 
  42 #include <errno.h>
  43 #include <fcntl.h>
  44 #include <unistd.h>
  45 
  46 #include "vncache.h"
  47 
  48 #define O_RWMASK        (O_WRONLY | O_RDWR) /* == 3 */
  49 
  50 int fop_shrlock_enable = 0;
  51 
  52 int stat_to_vattr(const struct stat *, vattr_t *);
  53 int fop__getxvattr(vnode_t *, xvattr_t *);
  54 int fop__setxvattr(vnode_t *, xvattr_t *);
  55 
  56 static void fake_inactive_xattrdir(vnode_t *);
  57 
  58 /* ARGSUSED */
  59 int
  60 fop_open(
  61         vnode_t **vpp,
  62         int mode,
  63         cred_t *cr,
  64         caller_context_t *ct)
  65 {
  66 
  67         if ((*vpp)->v_type == VREG) {
  68                 if (mode & FREAD)
  69                         atomic_add_32(&((*vpp)->v_rdcnt), 1);
  70                 if (mode & FWRITE)
  71                         atomic_add_32(&((*vpp)->v_wrcnt), 1);
  72         }
  73 
  74         /* call to ->vop_open was here */
  75 
  76         return (0);


 201         }
 202 
 203         if (ioflag == FSYNC) {
 204                 (void) fsync(vp->v_fd);
 205         }
 206 
 207         return (0);
 208 }
 209 
 210 /* ARGSUSED */
 211 int
 212 fop_ioctl(
 213         vnode_t *vp,
 214         int cmd,
 215         intptr_t arg,
 216         int flag,
 217         cred_t *cr,
 218         int *rvalp,
 219         caller_context_t *ct)
 220 {
 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);
 244 }
 245 
 246 /* ARGSUSED */
 247 int
 248 fop_setfl(
 249         vnode_t *vp,
 250         int oflags,
 251         int nflags,
 252         cred_t *cr,
 253         caller_context_t *ct)
 254 {
 255         /* allow any flags? See fs_setfl */
 256         return (0);
 257 }
 258 
 259 /* ARGSUSED */
 260 int
 261 fop_getattr(
 262         vnode_t *vp,
 263         vattr_t *vap,


 271         if (fstat(vp->v_fd, &st) == -1)
 272                 return (errno);
 273         error = stat_to_vattr(&st, vap);
 274 
 275         if (vap->va_mask & AT_XVATTR)
 276                 (void) fop__getxvattr(vp, (xvattr_t *)vap);
 277 
 278         return (error);
 279 }
 280 
 281 /* ARGSUSED */
 282 int
 283 fop_setattr(
 284         vnode_t *vp,
 285         vattr_t *vap,
 286         int flags,
 287         cred_t *cr,
 288         caller_context_t *ct)
 289 {
 290         timespec_t times[2];
 291         int err;
 292 
 293         if (vap->va_mask & AT_SIZE) {
 294                 if (ftruncate(vp->v_fd, vap->va_size) == -1) {
 295                         err = errno;
 296                         if (err == EBADF)
 297                                 err = EACCES;
 298                         return (err);
 299                 }
 300         }
 301 
 302         /* AT_MODE or anything else? */
 303 
 304         if (vap->va_mask & AT_XVATTR)
 305                 (void) fop__setxvattr(vp, (xvattr_t *)vap);
 306 
 307         if (vap->va_mask & (AT_ATIME | AT_MTIME)) {
 308                 if (vap->va_mask & AT_ATIME) {
 309                         times[0] = vap->va_atime;
 310                 } else {
 311                         times[0].tv_sec = 0;
 312                         times[0].tv_nsec = UTIME_OMIT;
 313                 }
 314                 if (vap->va_mask & AT_MTIME) {
 315                         times[1] = vap->va_mtime;
 316                 } else {
 317                         times[1].tv_sec = 0;
 318                         times[1].tv_nsec = UTIME_OMIT;
 319                 }
 320 
 321                 (void) futimens(vp->v_fd, times);
 322         }
 323 
 324         return (0);
 325 }
 326 
 327 /* ARGSUSED */
 328 int
 329 fop_access(
 330         vnode_t *vp,
 331         int mode,
 332         int flags,
 333         cred_t *cr,
 334         caller_context_t *ct)
 335 {
 336         return (0);
 337 }
 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 
 408 /* ARGSUSED */
 409 int
 410 fop_lookup(
 411         vnode_t *dvp,
 412         char *name,
 413         vnode_t **vpp,
 414         pathname_t *pnp,
 415         int flags,
 416         vnode_t *rdir,
 417         cred_t *cr,
 418         caller_context_t *ct,
 419         int *deflags,           /* Returned per-dirent flags */
 420         pathname_t *ppnp)       /* Returned case-preserved name in directory */
 421 {
 422         int fd;
 423         int omode = O_RDWR | O_NOFOLLOW;
 424         vnode_t *vp;
 425         struct stat st;
 426 
 427         if (flags & LOOKUP_XATTR)
 428                 return (fake_lookup_xattrdir(dvp, vpp));
 429 
 430         /*
 431          * If lookup is for "", just return dvp.
 432          */
 433         if (name[0] == '\0') {
 434                 vn_hold(dvp);
 435                 *vpp = dvp;
 436                 return (0);
 437         }
 438 
 439         if (fstatat(dvp->v_fd, name, &st, AT_SYMLINK_NOFOLLOW) == -1)
 440                 return (errno);
 441 
 442         vp = vncache_lookup(&st);
 443         if (vp != NULL) {
 444                 /* lookup gave us a hold */
 445                 *vpp = vp;
 446                 return (0);
 447         }
 448 


 764 fop_fsync(
 765         vnode_t *vp,
 766         int syncflag,
 767         cred_t *cr,
 768         caller_context_t *ct)
 769 {
 770 
 771         if (fsync(vp->v_fd) == -1)
 772                 return (errno);
 773 
 774         return (0);
 775 }
 776 
 777 /* ARGSUSED */
 778 void
 779 fop_inactive(
 780         vnode_t *vp,
 781         cred_t *cr,
 782         caller_context_t *ct)
 783 {
 784         if (vp->v_flag & V_XATTRDIR) {
 785                 fake_inactive_xattrdir(vp);
 786         } else {
 787                 vncache_inactive(vp);
 788         }
 789 }
 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 
 823 /* ARGSUSED */
 824 int
 825 fop_fid(
 826         vnode_t *vp,
 827         fid_t *fidp,
 828         caller_context_t *ct)
 829 {
 830         return (ENOSYS);
 831 }
 832 
 833 /* ARGSUSED */
 834 int
 835 fop_rwlock(
 836         vnode_t *vp,
 837         int write_lock,
 838         caller_context_t *ct)
 839 {
 840         /* See: fs_rwlock */
 841         return (-1);
 842 }


 868         vnode_t *vp1,
 869         vnode_t *vp2,
 870         caller_context_t *ct)
 871 {
 872         /* See fs_cmp */
 873         return (vncache_cmp(vp1, vp2));
 874 }
 875 
 876 /* ARGSUSED */
 877 int
 878 fop_frlock(
 879         vnode_t *vp,
 880         int cmd,
 881         flock64_t *bfp,
 882         int flag,
 883         offset_t offset,
 884         struct flk_callback *flk_cbp,
 885         cred_t *cr,
 886         caller_context_t *ct)
 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 
 900         /* See fs_frlock */
 901 
 902         switch (cmd) {
 903         case F_GETLK:
 904         case F_SETLK_NBMAND:
 905         case F_SETLK:
 906         case F_SETLKW:
 907                 break;
 908         default:
 909                 return (EINVAL);
 910         }
 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 
 936         if (fcntl(vp->v_fd, cmd, bfp) == -1)
 937                 return (errno);
 938 
 939         return (0);
 940 }
 941 
 942 /* ARGSUSED */
 943 int
 944 fop_space(
 945         vnode_t *vp,
 946         int cmd,
 947         flock64_t *bfp,
 948         int flag,
 949         offset_t offset,
 950         cred_t *cr,
 951         caller_context_t *ct)
 952 {
 953         /* See fs_frlock */
 954 
 955         switch (cmd) {


1138                 val = PIPE_BUF;
1139                 break;
1140 
1141         case _PC_NO_TRUNC:
1142                 val = (ulong_t)-1;
1143                 break;
1144 
1145         case _PC_VDISABLE:
1146                 val = _POSIX_VDISABLE;
1147                 break;
1148 
1149         case _PC_CHOWN_RESTRICTED:
1150                 val = 1; /* chown restricted enabled */
1151                 break;
1152 
1153         case _PC_FILESIZEBITS:
1154                 val = (ulong_t)-1;    /* large file support */
1155                 break;
1156 
1157         case _PC_ACL_ENABLED:
1158                 val = _ACL_ACE_ENABLED;
1159                 break;
1160 
1161         case _PC_CASE_BEHAVIOR:
1162                 val = _CASE_SENSITIVE;
1163                 break;
1164 
1165         case _PC_SATTR_ENABLED:
1166         case _PC_SATTR_EXISTS:
1167                 val = 0;
1168                 break;
1169 
1170         case _PC_ACCESS_FILTERING:
1171                 val = 0;
1172                 break;
1173 
1174         default:
1175                 error = EINVAL;
1176                 break;
1177         }
1178 


1422 flk_init_callback(flk_callback_t *flk_cb,
1423         callb_cpr_t *(*cb_fcn)(flk_cb_when_t, void *), void *cbdata)
1424 {
1425 }
1426 
1427 void
1428 vn_hold(vnode_t *vp)
1429 {
1430         mutex_enter(&vp->v_lock);
1431         vp->v_count++;
1432         mutex_exit(&vp->v_lock);
1433 }
1434 
1435 void
1436 vn_rele(vnode_t *vp)
1437 {
1438         VERIFY3U(vp->v_count, !=, 0);
1439         mutex_enter(&vp->v_lock);
1440         if (vp->v_count == 1) {
1441                 mutex_exit(&vp->v_lock);
1442                 fop_inactive(vp, NULL, NULL);
1443         } else {
1444                 vp->v_count--;
1445                 mutex_exit(&vp->v_lock);
1446         }
1447 }
1448 
1449 int
1450 vn_has_other_opens(
1451         vnode_t *vp,
1452         v_mode_t mode)
1453 {
1454 
1455         switch (mode) {
1456         case V_WRITE:
1457                 if (vp->v_wrcnt > 1)
1458                         return (V_TRUE);
1459                 break;
1460         case V_RDORWR:
1461                 if ((vp->v_rdcnt > 1) || (vp->v_wrcnt > 1))
1462                         return (V_TRUE);