diff options
| author | John Levon <john.levon@sun.com> | 2010-06-16 10:02:44 -0700 |
|---|---|---|
| committer | John Levon <john.levon@sun.com> | 2010-06-16 10:02:44 -0700 |
| commit | 0fbb751d81ab0a7c7ddfd8d4e447e075a9f7024f (patch) | |
| tree | 547ed35c638d3c30c437e212b458d74268e35afa /usr/src/uts/common/fs/vfs.c | |
| parent | ded9341448cd6e2573619c7f6fe98909bdd35ec6 (diff) | |
| download | illumos-joyent-0fbb751d81ab0a7c7ddfd8d4e447e075a9f7024f.tar.gz | |
PSARC 2010/144 lofi(7D) in non global zones
6354954 lofi support in non-global zones
6942891 prof_lookup_globaldev() leaks rootdir refs
6945005 lofiadm -a /dev/lofi/1: recursive mutex enter
6946486 lofi_ioctl() shouldn't allow disk ioctl()s on /dev/lofictl
Diffstat (limited to 'usr/src/uts/common/fs/vfs.c')
| -rw-r--r-- | usr/src/uts/common/fs/vfs.c | 64 |
1 files changed, 33 insertions, 31 deletions
diff --git a/usr/src/uts/common/fs/vfs.c b/usr/src/uts/common/fs/vfs.c index d5d254a20d..2bfe3908f0 100644 --- a/usr/src/uts/common/fs/vfs.c +++ b/usr/src/uts/common/fs/vfs.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ @@ -1014,8 +1013,7 @@ lofi_add(const char *fsname, struct vfs *vfsp, int minor; int err = 0; - if (fsname == NULL || - (vfssw = vfs_getvfssw(fsname)) == NULL) + if ((vfssw = vfs_getvfssw(fsname)) == NULL) return (0); if (!(vfssw->vsw_flag & VSW_CANLOFI)) { @@ -1049,29 +1047,16 @@ lofi_add(const char *fsname, struct vfs *vfsp, li = kmem_zalloc(sizeof (*li), KM_SLEEP); (void) strlcpy(li->li_filename, pn.pn_path, MAXPATHLEN); - /* - * The lofi control node is currently exclusive-open. We'd like - * to improve this, but in the meantime, we'll loop waiting for - * access. - */ - for (;;) { - err = ldi_open_by_name("/dev/lofictl", FREAD | FWRITE | FEXCL, - kcred, &ldi_hdl, ldi_id); - - if (err != EBUSY) - break; - - if ((err = delay_sig(hz / 8)) == EINTR) - break; - } + err = ldi_open_by_name("/dev/lofictl", FREAD | FWRITE, kcred, + &ldi_hdl, ldi_id); if (err) goto out2; err = ldi_ioctl(ldi_hdl, LOFI_MAP_FILE, (intptr_t)li, - FREAD | FWRITE | FEXCL | FKIOCTL, kcred, &minor); + FREAD | FWRITE | FKIOCTL, kcred, &minor); - (void) ldi_close(ldi_hdl, FREAD | FWRITE | FEXCL, kcred); + (void) ldi_close(ldi_hdl, FREAD | FWRITE, kcred); if (!err) vfsp->vfs_lofi_minor = minor; @@ -1104,18 +1089,16 @@ lofi_remove(struct vfs *vfsp) li->li_minor = vfsp->vfs_lofi_minor; li->li_cleanup = B_TRUE; - do { - err = ldi_open_by_name("/dev/lofictl", FREAD | FWRITE | FEXCL, - kcred, &ldi_hdl, ldi_id); - } while (err == EBUSY); + err = ldi_open_by_name("/dev/lofictl", FREAD | FWRITE, kcred, + &ldi_hdl, ldi_id); if (err) goto out; err = ldi_ioctl(ldi_hdl, LOFI_UNMAP_FILE_MINOR, (intptr_t)li, - FREAD | FWRITE | FEXCL | FKIOCTL, kcred, NULL); + FREAD | FWRITE | FKIOCTL, kcred, NULL); - (void) ldi_close(ldi_hdl, FREAD | FWRITE | FEXCL, kcred); + (void) ldi_close(ldi_hdl, FREAD | FWRITE, kcred); if (!err) vfsp->vfs_lofi_minor = 0; @@ -1251,9 +1234,16 @@ domount(char *fsname, struct mounta *uap, vnode_t *vp, struct cred *credp, } else { if ((vswp = vfs_getvfsswbyvfsops(vfs_getops(rootvfs))) == NULL) return (EINVAL); + fsname = vswp->vsw_name; } if (!VFS_INSTALLED(vswp)) return (EINVAL); + + if ((error = secpolicy_fs_allowed_mount(fsname)) != 0) { + vfs_unrefvfssw(vswp); + return (error); + } + vfsops = &vswp->vsw_vfsops; vfs_copyopttbl(&vswp->vsw_optproto, &mnt_mntopts); @@ -4782,7 +4772,7 @@ vfs_propagate_features(vfs_t *from, vfs_t *to) } } -#define LOFICTL_PATH "/devices/pseudo/lofi@0:%d" +#define LOFINODE_PATH "/dev/lofi/%d" /* * Return the vnode for the lofi node if there's a lofi mount in place. @@ -4801,11 +4791,23 @@ vfs_get_lofi(vfs_t *vfsp, vnode_t **vpp) return (-1); } - strsize = snprintf(NULL, 0, LOFICTL_PATH, vfsp->vfs_lofi_minor); + strsize = snprintf(NULL, 0, LOFINODE_PATH, vfsp->vfs_lofi_minor); path = kmem_alloc(strsize + 1, KM_SLEEP); - (void) snprintf(path, strsize + 1, LOFICTL_PATH, vfsp->vfs_lofi_minor); + (void) snprintf(path, strsize + 1, LOFINODE_PATH, vfsp->vfs_lofi_minor); + + /* + * We may be inside a zone, so we need to use the /dev path, but + * it's created asynchronously, so we wait here. + */ + for (;;) { + err = lookupname(path, UIO_SYSSPACE, FOLLOW, NULLVPP, vpp); + + if (err != ENOENT) + break; - err = lookupname(path, UIO_SYSSPACE, FOLLOW, NULLVPP, vpp); + if ((err = delay_sig(hz / 8)) == EINTR) + break; + } if (err) *vpp = NULL; |
