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 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * This is the /dev (hence, the sdev_ prefix) filesystem. 28 */ 29 30 #include <sys/types.h> 31 #include <sys/param.h> 32 #include <sys/sysmacros.h> 33 #include <sys/systm.h> 34 #include <sys/kmem.h> 35 #include <sys/time.h> 36 #include <sys/pathname.h> 37 #include <sys/vfs.h> 38 #include <sys/vfs_opreg.h> 39 #include <sys/vnode.h> 40 #include <sys/file.h> 41 #include <sys/stat.h> 42 #include <sys/uio.h> 43 #include <sys/stat.h> 44 #include <sys/errno.h> 45 #include <sys/cmn_err.h> 46 #include <sys/cred.h> 47 #include <sys/statvfs.h> 48 #include <sys/policy.h> 49 #include <sys/mount.h> 50 #include <sys/debug.h> 51 #include <sys/modctl.h> 52 #include <sys/mkdev.h> 53 #include <fs/fs_subr.h> 54 #include <sys/fs/sdev_impl.h> 55 #include <sys/fs/snode.h> 56 #include <sys/fs/dv_node.h> 57 #include <sys/sunndi.h> 58 #include <sys/mntent.h> 59 60 /* 61 * /dev vfs operations. 62 */ 63 64 /* 65 * globals 66 */ 67 struct sdev_data *sdev_origins; /* mount info for origins under /dev */ 68 kmutex_t sdev_lock; /* used for mount/unmount/rename synchronization */ 69 70 /* 71 * static 72 */ 73 static major_t devmajor; /* the fictitious major we live on */ 74 static major_t devminor; /* the fictitious minor of this instance */ 75 static struct sdev_data *sdev_mntinfo = NULL; /* linked list of instances */ 76 77 /* LINTED E_STATIC_UNUSED */ /* useful for debugging */ 78 static struct vnode *sdev_stale_attrvp; /* stale root attrvp after remount */ 79 80 static int sdev_mount(struct vfs *, struct vnode *, struct mounta *, 81 struct cred *); 82 static int sdev_unmount(struct vfs *, int, struct cred *); 83 static int sdev_root(struct vfs *, struct vnode **); 84 static int sdev_statvfs(struct vfs *, struct statvfs64 *); 85 static void sdev_insert_mntinfo(struct sdev_data *); 86 static int devinit(int, char *); 87 88 static vfsdef_t sdev_vfssw = { 89 VFSDEF_VERSION, 90 "dev", /* type name string */ 91 devinit, /* init routine */ 92 VSW_CANREMOUNT, /* flags */ 93 NULL /* mount options table prototype */ 94 }; 95 96 97 /* 98 * Module linkage information 99 */ 100 static struct modlfs modlfs = { 101 &mod_fsops, "/dev filesystem", &sdev_vfssw 102 }; 103 104 static struct modlinkage modlinkage = { 105 MODREV_1, (void *)&modlfs, NULL 106 }; 107 108 int 109 _init(void) 110 { 111 int e; 112 113 mutex_init(&sdev_lock, NULL, MUTEX_DEFAULT, NULL); 114 sdev_node_cache_init(); 115 sdev_devfsadm_lockinit(); 116 if ((e = mod_install(&modlinkage)) != 0) { 117 sdev_devfsadm_lockdestroy(); 118 sdev_node_cache_fini(); 119 mutex_destroy(&sdev_lock); 120 return (e); 121 } 122 return (0); 123 } 124 125 /* 126 * dev module remained loaded for the global /dev instance 127 */ 128 int 129 _fini(void) 130 { 131 return (EBUSY); 132 } 133 134 int 135 _info(struct modinfo *modinfop) 136 { 137 return (mod_info(&modlinkage, modinfop)); 138 } 139 140 /*ARGSUSED*/ 141 static int 142 devinit(int fstype, char *name) 143 { 144 static const fs_operation_def_t dev_vfsops_tbl[] = { 145 VFSNAME_MOUNT, { .vfs_mount = sdev_mount }, 146 VFSNAME_UNMOUNT, { .vfs_unmount = sdev_unmount }, 147 VFSNAME_ROOT, { .vfs_root = sdev_root }, 148 VFSNAME_STATVFS, { .vfs_statvfs = sdev_statvfs }, 149 NULL, NULL 150 }; 151 152 int error; 153 extern major_t getudev(void); 154 155 devtype = fstype; 156 157 error = vfs_setfsops(fstype, dev_vfsops_tbl, NULL); 158 if (error != 0) { 159 cmn_err(CE_WARN, "devinit: bad vfs ops tbl"); 160 return (error); 161 } 162 163 error = vn_make_ops("dev", sdev_vnodeops_tbl, &sdev_vnodeops); 164 if (error != 0) { 165 (void) vfs_freevfsops_by_type(fstype); 166 cmn_err(CE_WARN, "devinit: bad vnode ops tbl"); 167 return (error); 168 } 169 170 if ((devmajor = getudev()) == (major_t)-1) { 171 cmn_err(CE_WARN, "%s: can't get unique dev", sdev_vfssw.name); 172 return (1); 173 } 174 175 /* initialize negative cache */ 176 sdev_ncache_init(); 177 178 return (0); 179 } 180 181 /* 182 * Both mount point and backing store directory name are 183 * passed in from userland 184 */ 185 static int 186 sdev_mount(struct vfs *vfsp, struct vnode *mvp, struct mounta *uap, 187 struct cred *cr) 188 { 189 struct sdev_data *sdev_data; 190 struct vnode *avp; 191 struct sdev_node *dv; 192 struct sdev_mountargs *args = NULL; 193 int error = 0; 194 dev_t devdev; 195 196 /* 197 * security check 198 */ 199 if ((secpolicy_fs_mount(cr, mvp, vfsp) != 0) || 200 (secpolicy_sys_devices(cr) != 0)) 201 return (EPERM); 202 203 /* 204 * Sanity check the mount point 205 */ 206 if (mvp->v_type != VDIR) 207 return (ENOTDIR); 208 209 /* 210 * Sanity Check for overlay mount. 211 */ 212 mutex_enter(&mvp->v_lock); 213 if ((uap->flags & MS_OVERLAY) == 0 && 214 (uap->flags & MS_REMOUNT) == 0 && 215 (mvp->v_count > 1 || (mvp->v_flag & VROOT))) { 216 mutex_exit(&mvp->v_lock); 217 return (EBUSY); 218 } 219 mutex_exit(&mvp->v_lock); 220 221 args = kmem_zalloc(sizeof (*args), KM_SLEEP); 222 223 if ((uap->flags & MS_DATA) && 224 (uap->datalen != 0 && uap->dataptr != NULL)) { 225 /* copy in the arguments */ 226 if (error = sdev_copyin_mountargs(uap, args)) 227 goto cleanup; 228 } 229 230 /* 231 * Sanity check the backing store 232 */ 233 if (args->sdev_attrdir) { 234 /* user supplied an attribute store */ 235 if (error = lookupname((char *)(uintptr_t)args->sdev_attrdir, 236 UIO_USERSPACE, FOLLOW, NULLVPP, &avp)) { 237 cmn_err(CE_NOTE, "/dev fs: lookup on attribute " 238 "directory %s failed", 239 (char *)(uintptr_t)args->sdev_attrdir); 240 goto cleanup; 241 } 242 243 if (avp->v_type != VDIR) { 244 VN_RELE(avp); 245 error = ENOTDIR; 246 goto cleanup; 247 } 248 } else { 249 /* use mountp as the attribute store */ 250 avp = mvp; 251 VN_HOLD(avp); 252 } 253 254 mutex_enter(&sdev_lock); 255 256 /* 257 * handling installation 258 */ 259 if (uap->flags & MS_REMOUNT) { 260 sdev_data = (struct sdev_data *)vfsp->vfs_data; 261 ASSERT(sdev_data); 262 263 dv = sdev_data->sdev_root; 264 ASSERT(dv == dv->sdev_dotdot); 265 266 /* 267 * mark all existing sdev_nodes (except root node) stale 268 */ 269 sdev_stale(dv); 270 271 /* Reset previous mountargs */ 272 if (sdev_data->sdev_mountargs) { 273 kmem_free(sdev_data->sdev_mountargs, 274 sizeof (struct sdev_mountargs)); 275 } 276 sdev_data->sdev_mountargs = args; 277 args = NULL; /* so it won't be freed below */ 278 279 sdev_stale_attrvp = dv->sdev_attrvp; 280 dv->sdev_attrvp = avp; 281 vfsp->vfs_mtime = ddi_get_time(); 282 283 mutex_exit(&sdev_lock); 284 goto cleanup; /* we're done */ 285 } 286 287 /* 288 * Create and initialize the vfs-private data. 289 */ 290 devdev = makedevice(devmajor, devminor); 291 while (vfs_devismounted(devdev)) { 292 devminor = (devminor + 1) & MAXMIN32; 293 294 /* 295 * All the minor numbers are used up. 296 */ 297 if (devminor == 0) { 298 mutex_exit(&sdev_lock); 299 VN_RELE(avp); 300 error = ENODEV; 301 goto cleanup; 302 } 303 304 devdev = makedevice(devmajor, devminor); 305 } 306 307 dv = sdev_mkroot(vfsp, devdev, mvp, avp, cr); 308 sdev_data = kmem_zalloc(sizeof (struct sdev_data), KM_SLEEP); 309 vfsp->vfs_dev = devdev; 310 vfsp->vfs_data = (caddr_t)sdev_data; 311 vfsp->vfs_fstype = devtype; 312 vfsp->vfs_bsize = DEV_BSIZE; 313 vfsp->vfs_mtime = ddi_get_time(); 314 vfs_make_fsid(&vfsp->vfs_fsid, vfsp->vfs_dev, devtype); 315 316 ASSERT(dv == dv->sdev_dotdot); 317 318 sdev_data->sdev_vfsp = vfsp; 319 sdev_data->sdev_root = dv; 320 sdev_data->sdev_mountargs = args; 321 322 /* get acl flavor from attribute dir */ 323 if (VOP_PATHCONF(avp, _PC_ACL_ENABLED, &sdev_data->sdev_acl_flavor, 324 kcred, NULL) != 0 || sdev_data->sdev_acl_flavor == 0) 325 sdev_data->sdev_acl_flavor = _ACL_ACLENT_ENABLED; 326 327 args = NULL; /* so it won't be freed below */ 328 sdev_insert_mntinfo(sdev_data); 329 mutex_exit(&sdev_lock); 330 331 if (!SDEV_IS_GLOBAL(dv)) { 332 ASSERT(sdev_origins); 333 dv->sdev_flags &= ~SDEV_GLOBAL; 334 dv->sdev_origin = sdev_origins->sdev_root; 335 } else { 336 sdev_ncache_setup(); 337 rw_enter(&dv->sdev_contents, RW_WRITER); 338 sdev_filldir_dynamic(dv); 339 rw_exit(&dv->sdev_contents); 340 } 341 342 sdev_update_timestamps(dv->sdev_attrvp, 343 cr, AT_CTIME|AT_MTIME|AT_ATIME); 344 345 cleanup: 346 if (args) 347 kmem_free(args, sizeof (*args)); 348 return (error); 349 } 350 351 /* 352 * unmounting the non-global /dev instances, e.g. when deleting a Kevlar zone. 353 */ 354 static int 355 sdev_unmount(struct vfs *vfsp, int flag, struct cred *cr) 356 { 357 struct sdev_node *dv; 358 int error; 359 struct sdev_data *sdev_data, *prev, *next; 360 361 /* 362 * enforce the security policies 363 */ 364 if ((secpolicy_fs_unmount(cr, vfsp) != 0) || 365 (secpolicy_sys_devices(cr) != 0)) 366 return (EPERM); 367 368 if (flag & MS_FORCE) 369 return (ENOTSUP); 370 371 mutex_enter(&sdev_lock); 372 dv = VFSTOSDEVFS(vfsp)->sdev_root; 373 ASSERT(dv == dv->sdev_dotdot); 374 if (SDEVTOV(dv)->v_count > 1) { 375 mutex_exit(&sdev_lock); 376 return (EBUSY); 377 } 378 379 /* 380 * global instance remains mounted 381 */ 382 if (SDEV_IS_GLOBAL(dv)) { 383 mutex_exit(&sdev_lock); 384 return (EBUSY); 385 } 386 mutex_exit(&sdev_lock); 387 388 /* verify the v_count */ 389 if ((error = sdev_cleandir(dv, NULL, 0)) != 0) { 390 return (error); 391 } 392 ASSERT(SDEVTOV(dv)->v_count == 1); 393 394 /* release hold on root node and destroy it */ 395 SDEV_RELE(dv); 396 dv->sdev_nlink -= 2; 397 sdev_nodedestroy(dv, 0); 398 399 sdev_data = (struct sdev_data *)vfsp->vfs_data; 400 vfsp->vfs_data = (caddr_t)0; 401 402 /* 403 * XXX separate it into sdev_delete_mntinfo() if useful 404 */ 405 mutex_enter(&sdev_lock); 406 prev = sdev_data->sdev_prev; 407 next = sdev_data->sdev_next; 408 if (prev) 409 prev->sdev_next = next; 410 else 411 sdev_mntinfo = next; 412 if (next) 413 next->sdev_prev = prev; 414 mutex_exit(&sdev_lock); 415 416 if (sdev_data->sdev_mountargs) { 417 kmem_free(sdev_data->sdev_mountargs, 418 sizeof (struct sdev_mountargs)); 419 } 420 kmem_free(sdev_data, sizeof (struct sdev_data)); 421 return (0); 422 } 423 424 /* 425 * return root vnode for given vfs 426 */ 427 static int 428 sdev_root(struct vfs *vfsp, struct vnode **vpp) 429 { 430 *vpp = SDEVTOV(VFSTOSDEVFS(vfsp)->sdev_root); 431 VN_HOLD(*vpp); 432 return (0); 433 } 434 435 /* 436 * return 'generic superblock' information to userland. 437 * 438 * not much that we can usefully admit to here 439 */ 440 static int 441 sdev_statvfs(struct vfs *vfsp, struct statvfs64 *sbp) 442 { 443 dev32_t d32; 444 445 bzero(sbp, sizeof (*sbp)); 446 sbp->f_frsize = sbp->f_bsize = vfsp->vfs_bsize; 447 sbp->f_files = kmem_cache_stat(sdev_node_cache, "alloc"); 448 449 /* no illusions that free/avail files is relevant to dev */ 450 sbp->f_ffree = 0; 451 sbp->f_favail = 0; 452 453 /* no illusions that blocks are relevant to devfs */ 454 sbp->f_bfree = 0; 455 sbp->f_bavail = 0; 456 sbp->f_blocks = 0; 457 458 (void) cmpldev(&d32, vfsp->vfs_dev); 459 sbp->f_fsid = d32; 460 (void) strcpy(sbp->f_basetype, vfssw[devtype].vsw_name); 461 sbp->f_flag = vf_to_stf(vfsp->vfs_flag); 462 sbp->f_namemax = MAXNAMELEN - 1; 463 (void) strcpy(sbp->f_fstr, "dev"); 464 465 return (0); 466 } 467 468 static void 469 sdev_insert_mntinfo(struct sdev_data *data) 470 { 471 ASSERT(mutex_owned(&sdev_lock)); 472 data->sdev_next = sdev_mntinfo; 473 data->sdev_prev = NULL; 474 if (sdev_mntinfo) { 475 sdev_mntinfo->sdev_prev = data; 476 } else { 477 sdev_origins = data; 478 } 479 sdev_mntinfo = data; 480 } 481 482 struct sdev_data * 483 sdev_find_mntinfo(char *mntpt) 484 { 485 struct sdev_data *mntinfo; 486 487 mutex_enter(&sdev_lock); 488 mntinfo = sdev_mntinfo; 489 while (mntinfo) { 490 if (strcmp(mntpt, mntinfo->sdev_root->sdev_name) == 0) { 491 SDEVTOV(mntinfo->sdev_root)->v_count++; 492 break; 493 } 494 mntinfo = mntinfo->sdev_next; 495 } 496 mutex_exit(&sdev_lock); 497 return (mntinfo); 498 } 499 500 void 501 sdev_mntinfo_rele(struct sdev_data *mntinfo) 502 { 503 mutex_enter(&sdev_lock); 504 SDEVTOV(mntinfo->sdev_root)->v_count--; 505 mutex_exit(&sdev_lock); 506 } 507