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 /*
  22  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 /*
  25  * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
  26  */
  27 
  28 /*
  29  * vnode ops for the /dev filesystem
  30  *
  31  * - VDIR, VCHR, CBLK, and VLNK are considered must supported files
  32  * - VREG and VDOOR are used for some internal implementations in
  33  *    the global zone, e.g. devname and devfsadm communication
  34  * - other file types are unusual in this namespace and
  35  *    not supported for now
  36  */
  37 
  38 /*
  39  * sdev has a few basic goals:
  40  *   o Provide /dev for the global zone as well as various non-global zones.
  41  *   o Provide the basic functionality that devfsadm might need (mknod,
  42  *     symlinks, etc.)
  43  *   o Allow persistent permissions on files in /dev.
  44  *   o Allow for dynamic directories and nodes for use by various services (pts,
  45  *     zvol, net, etc.)
 
 
 847         /*
 848          * best efforts clean up the backing store
 849          */
 850         if (bkstore) {
 851                 ASSERT(parent->sdev_attrvp);
 852                 error = VOP_REMOVE(parent->sdev_attrvp, nm, cred,
 853                     ct, flags);
 854                 /*
 855                  * do not report BUSY error
 856                  * because the backing store ref count is released
 857                  * when the last ref count on the sdev_node is
 858                  * released.
 859                  */
 860                 if (error == EBUSY) {
 861                         sdcmn_err2(("sdev_remove: device %s is still on"
 862                             "disk %s\n", nm, parent->sdev_path));
 863                         error = 0;
 864                 }
 865         }
 866 
 867         return (error);
 868 }
 869 
 870 /*
 871  * Some restrictions for this file system:
 872  *  - both oldnm and newnm are in the scope of /dev file system,
 873  *    to simply the namespace management model.
 874  */
 875 /*ARGSUSED6*/
 876 static int
 877 sdev_rename(struct vnode *odvp, char *onm, struct vnode *ndvp, char *nnm,
 878     struct cred *cred, caller_context_t *ct, int flags)
 879 {
 880         struct sdev_node        *fromparent = NULL;
 881         struct vattr            vattr;
 882         struct sdev_node        *toparent;
 883         struct sdev_node        *fromdv = NULL; /* source node */
 884         struct vnode            *ovp = NULL;    /* source vnode */
 885         struct sdev_node        *todv = NULL;   /* destination node */
 886         struct vnode            *nvp = NULL;    /* destination vnode */
 
1171         rw_enter(&parent->sdev_contents, RW_WRITER);
1172         error = sdev_mknode(parent, lnm, &self, tva, NULL, (void *)tnm,
1173             cred, SDEV_READY);
1174         if (error) {
1175                 rw_exit(&parent->sdev_contents);
1176                 sdcmn_err2(("sdev_symlink: node %s creation failed\n", lnm));
1177                 if (self)
1178                         SDEV_RELE(self);
1179 
1180                 return (error);
1181         }
1182         ASSERT(self && (self->sdev_state == SDEV_READY));
1183         rw_exit(&parent->sdev_contents);
1184 
1185         /* take care the timestamps for the node and its parent */
1186         sdev_update_timestamps(SDEVTOV(self), kcred,
1187             AT_CTIME|AT_MTIME|AT_ATIME);
1188         sdev_update_timestamps(dvp, kcred, AT_MTIME|AT_ATIME);
1189         if (SDEV_IS_GLOBAL(parent))
1190                 atomic_inc_ulong(&parent->sdev_gdir_gen);
1191 
1192         /* wake up other threads blocked on looking up this node */
1193         mutex_enter(&self->sdev_lookup_lock);
1194         SDEV_UNBLOCK_OTHERS(self, SDEV_LOOKUP);
1195         mutex_exit(&self->sdev_lookup_lock);
1196         SDEV_RELE(self);        /* don't return with vnode held */
1197         return (0);
1198 }
1199 
1200 /*ARGSUSED6*/
1201 static int
1202 sdev_mkdir(struct vnode *dvp, char *nm, struct vattr *va, struct vnode **vpp,
1203     struct cred *cred, caller_context_t *ct, int flags, vsecattr_t *vsecp)
1204 {
1205         int error;
1206         struct sdev_node *parent = (struct sdev_node *)VTOSDEV(dvp);
1207         struct sdev_node *self = NULL;
1208         struct vnode    *vp = NULL;
1209 
1210         ASSERT(parent && parent->sdev_dotdot);
 
1243 
1244         /* put it into memory */
1245         rw_enter(&parent->sdev_contents, RW_WRITER);
1246         error = sdev_mknode(parent, nm, &self,
1247             va, NULL, NULL, cred, SDEV_READY);
1248         if (error) {
1249                 rw_exit(&parent->sdev_contents);
1250                 if (self)
1251                         SDEV_RELE(self);
1252                 return (error);
1253         }
1254         ASSERT(self && (self->sdev_state == SDEV_READY));
1255         rw_exit(&parent->sdev_contents);
1256 
1257         /* take care the timestamps for the node and its parent */
1258         sdev_update_timestamps(SDEVTOV(self), kcred,
1259             AT_CTIME|AT_MTIME|AT_ATIME);
1260         sdev_update_timestamps(dvp, kcred, AT_MTIME|AT_ATIME);
1261         if (SDEV_IS_GLOBAL(parent))
1262                 atomic_inc_ulong(&parent->sdev_gdir_gen);
1263 
1264         /* wake up other threads blocked on looking up this node */
1265         mutex_enter(&self->sdev_lookup_lock);
1266         SDEV_UNBLOCK_OTHERS(self, SDEV_LOOKUP);
1267         mutex_exit(&self->sdev_lookup_lock);
1268         *vpp = SDEVTOV(self);
1269         return (0);
1270 }
1271 
1272 /*
1273  * allowing removing an empty directory under /dev
1274  */
1275 /*ARGSUSED*/
1276 static int
1277 sdev_rmdir(struct vnode *dvp, char *nm, struct vnode *cdir, struct cred *cred,
1278     caller_context_t *ct, int flags)
1279 {
1280         int error = 0;
1281         struct sdev_node *parent = (struct sdev_node *)VTOSDEV(dvp);
1282         struct sdev_node *self = NULL;
 
1358         /* unlink it from the directory cache */
1359         sdev_cache_update(parent, &self, nm, SDEV_CACHE_DELETE);
1360         rw_exit(&parent->sdev_contents);
1361         vn_vfsunlock(vp);
1362         VN_RELE(vp);
1363 
1364         /* best effort to clean up the backing store */
1365         if (SDEV_IS_PERSIST(parent)) {
1366                 ASSERT(parent->sdev_attrvp);
1367                 error = VOP_RMDIR(parent->sdev_attrvp, nm,
1368                     parent->sdev_attrvp, kcred, ct, flags);
1369 
1370                 if (error)
1371                         sdcmn_err2(("sdev_rmdir: cleaning device %s is on"
1372                             " disk error %d\n", parent->sdev_path, error));
1373                 if (error == EBUSY)
1374                         error = 0;
1375 
1376         }
1377 
1378         return (error);
1379 }
1380 
1381 /*
1382  * read the contents of a symbolic link
1383  */
1384 static int
1385 sdev_readlink(struct vnode *vp, struct uio *uiop, struct cred *cred,
1386     caller_context_t *ct)
1387 {
1388         struct sdev_node *dv;
1389         int     error = 0;
1390 
1391         ASSERT(vp->v_type == VLNK);
1392 
1393         dv = VTOSDEV(vp);
1394 
1395         if (dv->sdev_attrvp) {
1396                 /* non-NULL attrvp implys a persisted node at READY state */
1397                 return (VOP_READLINK(dv->sdev_attrvp, uiop, cred, ct));
 
 | 
 
 
   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 /*
  22  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 /*
  25  * Copyright 2016, Joyent, Inc.
  26  */
  27 
  28 /*
  29  * vnode ops for the /dev filesystem
  30  *
  31  * - VDIR, VCHR, CBLK, and VLNK are considered must supported files
  32  * - VREG and VDOOR are used for some internal implementations in
  33  *    the global zone, e.g. devname and devfsadm communication
  34  * - other file types are unusual in this namespace and
  35  *    not supported for now
  36  */
  37 
  38 /*
  39  * sdev has a few basic goals:
  40  *   o Provide /dev for the global zone as well as various non-global zones.
  41  *   o Provide the basic functionality that devfsadm might need (mknod,
  42  *     symlinks, etc.)
  43  *   o Allow persistent permissions on files in /dev.
  44  *   o Allow for dynamic directories and nodes for use by various services (pts,
  45  *     zvol, net, etc.)
 
 
 847         /*
 848          * best efforts clean up the backing store
 849          */
 850         if (bkstore) {
 851                 ASSERT(parent->sdev_attrvp);
 852                 error = VOP_REMOVE(parent->sdev_attrvp, nm, cred,
 853                     ct, flags);
 854                 /*
 855                  * do not report BUSY error
 856                  * because the backing store ref count is released
 857                  * when the last ref count on the sdev_node is
 858                  * released.
 859                  */
 860                 if (error == EBUSY) {
 861                         sdcmn_err2(("sdev_remove: device %s is still on"
 862                             "disk %s\n", nm, parent->sdev_path));
 863                         error = 0;
 864                 }
 865         }
 866 
 867         if (error == 0)
 868                 i_ddi_di_cache_invalidate();
 869 
 870         return (error);
 871 }
 872 
 873 /*
 874  * Some restrictions for this file system:
 875  *  - both oldnm and newnm are in the scope of /dev file system,
 876  *    to simply the namespace management model.
 877  */
 878 /*ARGSUSED6*/
 879 static int
 880 sdev_rename(struct vnode *odvp, char *onm, struct vnode *ndvp, char *nnm,
 881     struct cred *cred, caller_context_t *ct, int flags)
 882 {
 883         struct sdev_node        *fromparent = NULL;
 884         struct vattr            vattr;
 885         struct sdev_node        *toparent;
 886         struct sdev_node        *fromdv = NULL; /* source node */
 887         struct vnode            *ovp = NULL;    /* source vnode */
 888         struct sdev_node        *todv = NULL;   /* destination node */
 889         struct vnode            *nvp = NULL;    /* destination vnode */
 
1174         rw_enter(&parent->sdev_contents, RW_WRITER);
1175         error = sdev_mknode(parent, lnm, &self, tva, NULL, (void *)tnm,
1176             cred, SDEV_READY);
1177         if (error) {
1178                 rw_exit(&parent->sdev_contents);
1179                 sdcmn_err2(("sdev_symlink: node %s creation failed\n", lnm));
1180                 if (self)
1181                         SDEV_RELE(self);
1182 
1183                 return (error);
1184         }
1185         ASSERT(self && (self->sdev_state == SDEV_READY));
1186         rw_exit(&parent->sdev_contents);
1187 
1188         /* take care the timestamps for the node and its parent */
1189         sdev_update_timestamps(SDEVTOV(self), kcred,
1190             AT_CTIME|AT_MTIME|AT_ATIME);
1191         sdev_update_timestamps(dvp, kcred, AT_MTIME|AT_ATIME);
1192         if (SDEV_IS_GLOBAL(parent))
1193                 atomic_inc_ulong(&parent->sdev_gdir_gen);
1194         i_ddi_di_cache_invalidate();
1195 
1196         /* wake up other threads blocked on looking up this node */
1197         mutex_enter(&self->sdev_lookup_lock);
1198         SDEV_UNBLOCK_OTHERS(self, SDEV_LOOKUP);
1199         mutex_exit(&self->sdev_lookup_lock);
1200         SDEV_RELE(self);        /* don't return with vnode held */
1201         return (0);
1202 }
1203 
1204 /*ARGSUSED6*/
1205 static int
1206 sdev_mkdir(struct vnode *dvp, char *nm, struct vattr *va, struct vnode **vpp,
1207     struct cred *cred, caller_context_t *ct, int flags, vsecattr_t *vsecp)
1208 {
1209         int error;
1210         struct sdev_node *parent = (struct sdev_node *)VTOSDEV(dvp);
1211         struct sdev_node *self = NULL;
1212         struct vnode    *vp = NULL;
1213 
1214         ASSERT(parent && parent->sdev_dotdot);
 
1247 
1248         /* put it into memory */
1249         rw_enter(&parent->sdev_contents, RW_WRITER);
1250         error = sdev_mknode(parent, nm, &self,
1251             va, NULL, NULL, cred, SDEV_READY);
1252         if (error) {
1253                 rw_exit(&parent->sdev_contents);
1254                 if (self)
1255                         SDEV_RELE(self);
1256                 return (error);
1257         }
1258         ASSERT(self && (self->sdev_state == SDEV_READY));
1259         rw_exit(&parent->sdev_contents);
1260 
1261         /* take care the timestamps for the node and its parent */
1262         sdev_update_timestamps(SDEVTOV(self), kcred,
1263             AT_CTIME|AT_MTIME|AT_ATIME);
1264         sdev_update_timestamps(dvp, kcred, AT_MTIME|AT_ATIME);
1265         if (SDEV_IS_GLOBAL(parent))
1266                 atomic_inc_ulong(&parent->sdev_gdir_gen);
1267         i_ddi_di_cache_invalidate();
1268 
1269         /* wake up other threads blocked on looking up this node */
1270         mutex_enter(&self->sdev_lookup_lock);
1271         SDEV_UNBLOCK_OTHERS(self, SDEV_LOOKUP);
1272         mutex_exit(&self->sdev_lookup_lock);
1273         *vpp = SDEVTOV(self);
1274         return (0);
1275 }
1276 
1277 /*
1278  * allowing removing an empty directory under /dev
1279  */
1280 /*ARGSUSED*/
1281 static int
1282 sdev_rmdir(struct vnode *dvp, char *nm, struct vnode *cdir, struct cred *cred,
1283     caller_context_t *ct, int flags)
1284 {
1285         int error = 0;
1286         struct sdev_node *parent = (struct sdev_node *)VTOSDEV(dvp);
1287         struct sdev_node *self = NULL;
 
1363         /* unlink it from the directory cache */
1364         sdev_cache_update(parent, &self, nm, SDEV_CACHE_DELETE);
1365         rw_exit(&parent->sdev_contents);
1366         vn_vfsunlock(vp);
1367         VN_RELE(vp);
1368 
1369         /* best effort to clean up the backing store */
1370         if (SDEV_IS_PERSIST(parent)) {
1371                 ASSERT(parent->sdev_attrvp);
1372                 error = VOP_RMDIR(parent->sdev_attrvp, nm,
1373                     parent->sdev_attrvp, kcred, ct, flags);
1374 
1375                 if (error)
1376                         sdcmn_err2(("sdev_rmdir: cleaning device %s is on"
1377                             " disk error %d\n", parent->sdev_path, error));
1378                 if (error == EBUSY)
1379                         error = 0;
1380 
1381         }
1382 
1383         if (error == 0)
1384                 i_ddi_di_cache_invalidate();
1385 
1386         return (error);
1387 }
1388 
1389 /*
1390  * read the contents of a symbolic link
1391  */
1392 static int
1393 sdev_readlink(struct vnode *vp, struct uio *uiop, struct cred *cred,
1394     caller_context_t *ct)
1395 {
1396         struct sdev_node *dv;
1397         int     error = 0;
1398 
1399         ASSERT(vp->v_type == VLNK);
1400 
1401         dv = VTOSDEV(vp);
1402 
1403         if (dv->sdev_attrvp) {
1404                 /* non-NULL attrvp implys a persisted node at READY state */
1405                 return (VOP_READLINK(dv->sdev_attrvp, uiop, cred, ct));
 
 |