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));
|