1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  22 /*        All Rights Reserved   */
  23 
  24 
  25 /*
  26  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
  27  * Copyright 2017 Joyent, Inc.
  28  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  29  */
  30 
  31 /*
  32  * Generic vnode operations.
  33  */
  34 #include <sys/types.h>
  35 #include <sys/param.h>
  36 #include <sys/systm.h>
  37 #include <sys/errno.h>
  38 #include <sys/fcntl.h>
  39 #include <sys/flock.h>
  40 #include <sys/statvfs.h>
  41 #include <sys/vfs.h>
  42 #include <sys/vnode.h>
  43 #include <sys/cred.h>
  44 #include <sys/poll.h>
  45 #include <sys/debug.h>
  46 #include <sys/cmn_err.h>
  47 #include <sys/share.h>
  48 #include <sys/file.h>
  49 #include <sys/kmem.h>
  50 #include <sys/nbmlock.h>
  51 #include <sys/acl.h>
  52 
  53 #include <acl/acl_common.h>
  54 #include <fs/fs_subr.h>
  55 
  56 /*
  57  * Tunable to limit the number of retry to recover from STALE error.
  58  */
  59 int fs_estale_retry = 5;
  60 
  61 /*
  62  * The associated operation is not supported by the file system.
  63  */
  64 int
  65 fs_nosys()
  66 {
  67         return (ENOSYS);
  68 }
  69 
  70 /*
  71  * The associated operation is invalid (on this vnode).
  72  */
  73 int
  74 fs_inval()
  75 {
  76         return (EINVAL);
  77 }
  78 
  79 /*
  80  * The associated operation is valid only for directories.
  81  */
  82 int
  83 fs_notdir()
  84 {
  85         return (ENOTDIR);
  86 }
  87 
  88 /*
  89  * Free the file system specific resources. For the file systems that
  90  * do not support the forced unmount, it will be a nop function.
  91  */
  92 
  93 /*ARGSUSED*/
  94 void
  95 fs_freevfs(vfs_t *vfsp)
  96 {
  97 }
  98 
  99 /* ARGSUSED */
 100 int
 101 fs_nosys_map(struct vnode *vp, offset_t off, struct as *as, caddr_t *addrp,
 102     size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, struct cred *cr,
 103     caller_context_t *ct)
 104 {
 105         return (ENOSYS);
 106 }
 107 
 108 /* ARGSUSED */
 109 int
 110 fs_nosys_addmap(struct vnode *vp, offset_t off, struct as *as, caddr_t addr,
 111     size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, struct cred *cr,
 112     caller_context_t *ct)
 113 {
 114         return (ENOSYS);
 115 }
 116 
 117 /* ARGSUSED */
 118 int
 119 fs_nosys_poll(vnode_t *vp, short events, int anyyet, short *reventsp,
 120     struct pollhead **phpp, caller_context_t *ct)
 121 {
 122         return (ENOSYS);
 123 }
 124 
 125 
 126 /*
 127  * The file system has nothing to sync to disk.  However, the
 128  * VFS_SYNC operation must not fail.
 129  */
 130 /* ARGSUSED */
 131 int
 132 fs_sync(struct vfs *vfspp, short flag, cred_t *cr)
 133 {
 134         return (0);
 135 }
 136 
 137 /*
 138  * Does nothing but VOP_FSYNC must not fail.
 139  */
 140 /* ARGSUSED */
 141 int
 142 fs_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct)
 143 {
 144         return (0);
 145 }
 146 
 147 /*
 148  * Does nothing but VOP_PUTPAGE must not fail.
 149  */
 150 /* ARGSUSED */
 151 int
 152 fs_putpage(vnode_t *vp, offset_t off, size_t len, int flags, cred_t *cr,
 153     caller_context_t *ctp)
 154 {
 155         return (0);
 156 }
 157 
 158 /*
 159  * Does nothing but VOP_IOCTL must not fail.
 160  */
 161 /* ARGSUSED */
 162 int
 163 fs_ioctl(vnode_t *vp, int com, intptr_t data, int flag, cred_t *cred,
 164     int *rvalp)
 165 {
 166         return (0);
 167 }
 168 
 169 /*
 170  * Read/write lock/unlock.  Does nothing.
 171  */
 172 /* ARGSUSED */
 173 int
 174 fs_rwlock(vnode_t *vp, int write_lock, caller_context_t *ctp)
 175 {
 176         return (-1);
 177 }
 178 
 179 /* ARGSUSED */
 180 void
 181 fs_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ctp)
 182 {
 183 }
 184 
 185 /*
 186  * Compare two vnodes.
 187  */
 188 /*ARGSUSED2*/
 189 int
 190 fs_cmp(vnode_t *vp1, vnode_t *vp2, caller_context_t *ct)
 191 {
 192         return (vp1 == vp2);
 193 }
 194 
 195 /*
 196  * No-op seek operation.
 197  */
 198 /* ARGSUSED */
 199 int
 200 fs_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct)
 201 {
 202         return ((*noffp < 0 || *noffp > MAXOFFSET_T) ? EINVAL : 0);
 203 }
 204 
 205 /*
 206  * File and record locking.
 207  */
 208 /* ARGSUSED */
 209 int
 210 fs_frlock(vnode_t *vp, int cmd, struct flock64 *bfp, int flag, offset_t offset,
 211     flk_callback_t *flk_cbp, cred_t *cr, caller_context_t *ct)
 212 {
 213         return (ENOSYS);
 214 }
 215 
 216 /*
 217  * Allow any flags.
 218  */
 219 /* ARGSUSED */
 220 int
 221 fs_setfl(vnode_t *vp, int oflags, int nflags, cred_t *cr, caller_context_t *ct)
 222 {
 223         return (0);
 224 }
 225 
 226 /*
 227  * Return the answer requested to poll() for non-device files.
 228  * Only POLLIN, POLLRDNORM, and POLLOUT are recognized.
 229  */
 230 struct pollhead fs_pollhd;
 231 
 232 /* ARGSUSED */
 233 int
 234 fs_poll(vnode_t *vp, short events, int anyyet, short *reventsp,
 235     struct pollhead **phpp, caller_context_t *ct)
 236 {
 237         if (events & POLLET) {
 238                 return (EPERM);
 239         }
 240 
 241         *reventsp = 0;
 242         if (events & POLLIN)
 243                 *reventsp |= POLLIN;
 244         if (events & POLLRDNORM)
 245                 *reventsp |= POLLRDNORM;
 246         if (events & POLLRDBAND)
 247                 *reventsp |= POLLRDBAND;
 248         if (events & POLLOUT)
 249                 *reventsp |= POLLOUT;
 250         if (events & POLLWRBAND)
 251                 *reventsp |= POLLWRBAND;
 252         if (*reventsp == 0 && !anyyet) {
 253                 *phpp = &fs_pollhd;
 254         }
 255         return (0);
 256 }
 257 
 258 /*
 259  * POSIX pathconf() support.
 260  */
 261 /* ARGSUSED */
 262 int
 263 fs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
 264     caller_context_t *ct)
 265 {
 266         /* not called */
 267         return (EINVAL);
 268 }
 269 
 270 /*
 271  * Dispose of a page.
 272  */
 273 /* ARGSUSED */
 274 void
 275 fs_dispose(struct vnode *vp, page_t *pp, int fl, int dn, struct cred *cr,
 276     caller_context_t *ct)
 277 {
 278 }
 279 
 280 /* ARGSUSED */
 281 void
 282 fs_nodispose(struct vnode *vp, page_t *pp, int fl, int dn, struct cred *cr,
 283     caller_context_t *ct)
 284 {
 285         cmn_err(CE_PANIC, "fs_nodispose invoked");
 286 }
 287 
 288 /*
 289  * fabricate acls for file systems that do not support acls.
 290  */
 291 /* ARGSUSED */
 292 int
 293 fs_fab_acl(vnode_t *vp, vsecattr_t *vsecattr, int flag, cred_t *cr,
 294     caller_context_t *ct)
 295 {
 296         struct vattr    vattr;
 297         int             error;
 298 
 299         vsecattr->vsa_aclcnt = 0;
 300         vsecattr->vsa_aclentsz       = 0;
 301         vsecattr->vsa_aclentp        = NULL;
 302         vsecattr->vsa_dfaclcnt       = 0;    /* Default ACLs are not fabricated */
 303         vsecattr->vsa_dfaclentp      = NULL;
 304 
 305         vattr.va_mask = AT_MODE | AT_UID | AT_GID;
 306         if (error = VOP_GETATTR(vp, &vattr, 0, cr, ct))
 307                 return (error);
 308 
 309         if (vsecattr->vsa_mask & (VSA_ACLCNT | VSA_ACL)) {
 310                 return (ENOSYS);
 311         }
 312 
 313         if (vsecattr->vsa_mask & (VSA_ACECNT | VSA_ACE)) {
 314                 VERIFY(0 == acl_trivial_create(vattr.va_mode,
 315                     (vp->v_type == VDIR), (ace_t **)&vsecattr->vsa_aclentp,
 316                     &vsecattr->vsa_aclcnt));
 317                 vsecattr->vsa_aclentsz = vsecattr->vsa_aclcnt * sizeof (ace_t);
 318         }
 319 
 320         return (error);
 321 }
 322 
 323 /*
 324  * Common code for implementing DOS share reservations
 325  */
 326 /* ARGSUSED */
 327 int
 328 fs_shrlock(struct vnode *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr,
 329     caller_context_t *ct)
 330 {
 331         return (ENOSYS);
 332 }
 333 
 334 /*ARGSUSED1*/
 335 int
 336 fs_vnevent_nosupport(vnode_t *vp, vnevent_t e, vnode_t *dvp, char *fnm,
 337     caller_context_t *ct)
 338 {
 339         ASSERT(vp != NULL);
 340         return (ENOTSUP);
 341 }
 342 
 343 /*ARGSUSED1*/
 344 int
 345 fs_vnevent_support(vnode_t *vp, vnevent_t e, vnode_t *dvp, char *fnm,
 346     caller_context_t *ct)
 347 {
 348         ASSERT(vp != NULL);
 349         return (0);
 350 }
 351 
 352 // fs_acl_nontrivial
 353 
 354 /*
 355  * Check whether we need a retry to recover from STALE error.
 356  */
 357 int
 358 fs_need_estale_retry(int retry_count)
 359 {
 360         if (retry_count < fs_estale_retry)
 361                 return (1);
 362         else
 363                 return (0);
 364 }
 365 
 366 // fs_vscan...
 367 // reparse...
 368 
 369 /*
 370  * A few things from os/flock.c
 371  */
 372 
 373 /* ARGSUSED */
 374 void
 375 cleanlocks(vnode_t *vp, pid_t pid, int sysid)
 376 {
 377 }
 378 
 379 /* ARGSUSED */
 380 void
 381 cleanshares(struct vnode *vp, pid_t pid)
 382 {
 383 }
 384 
 385 /*
 386  * convoff - converts the given data (start, whence) to the
 387  * given whence.
 388  */
 389 int
 390 convoff(struct vnode *vp, struct flock64 *lckdat, int whence, offset_t offset)
 391 {
 392         int             error;
 393         struct vattr    vattr;
 394 
 395         if ((lckdat->l_whence == 2) || (whence == 2)) {
 396                 vattr.va_mask = AT_SIZE;
 397                 if (error = VOP_GETATTR(vp, &vattr, 0, CRED(), NULL))
 398                         return (error);
 399         }
 400 
 401         switch (lckdat->l_whence) {
 402         case 1:
 403                 lckdat->l_start += offset;
 404                 break;
 405         case 2:
 406                 lckdat->l_start += vattr.va_size;
 407                 /* FALLTHRU */
 408         case 0:
 409                 break;
 410         default:
 411                 return (EINVAL);
 412         }
 413 
 414         if (lckdat->l_start < 0)
 415                 return (EINVAL);
 416 
 417         switch (whence) {
 418         case 1:
 419                 lckdat->l_start -= offset;
 420                 break;
 421         case 2:
 422                 lckdat->l_start -= vattr.va_size;
 423                 /* FALLTHRU */
 424         case 0:
 425                 break;
 426         default:
 427                 return (EINVAL);
 428         }
 429 
 430         lckdat->l_whence = (short)whence;
 431         return (0);
 432 }