Mercurial > illumos > illumos-gate
changeset 6734:d16dda992d39
PSARC/2008/290 lofi mount
6384817 Need persistent lofi based mounts and direct mount(1m) support for lofi
author | johnlev |
---|---|
date | Tue, 27 May 2008 18:25:14 -0700 |
parents | 1db40e194d28 |
children | ba4d622bb38a |
files | usr/src/cmd/devfsadm/devfsadm.c usr/src/cmd/fs.d/fslib.c usr/src/cmd/fs.d/ufs/fsck/main.c usr/src/cmd/lofiadm/main.c usr/src/cmd/zoneadm/zoneadm.c usr/src/cmd/zoneadmd/vplat.c usr/src/uts/common/fs/hsfs/hsfs_vfsops.c usr/src/uts/common/fs/pcfs/pc_vfsops.c usr/src/uts/common/fs/udfs/udf_vfsops.c usr/src/uts/common/fs/ufs/ufs_vfsops.c usr/src/uts/common/fs/vfs.c usr/src/uts/common/io/lofi.c usr/src/uts/common/sys/lofi.h usr/src/uts/common/sys/vfs.h |
diffstat | 14 files changed, 699 insertions(+), 324 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/cmd/devfsadm/devfsadm.c Tue May 27 17:27:03 2008 -0700 +++ b/usr/src/cmd/devfsadm/devfsadm.c Tue May 27 18:25:14 2008 -0700 @@ -8467,10 +8467,16 @@ if (dev_name) free(dev_name); - if (dev_name_lookup_err) - err_print(DEV_NAME_LOOKUP_FAILED, node_path); - else + if (dev_name_lookup_err) { + /* + * If a lofi mount fails, the /devices node may well have + * disappeared by the time we run, so let's not complain. + */ + if (strcmp(subclass, ESC_LOFI) != 0) + err_print(DEV_NAME_LOOKUP_FAILED, node_path); + } else { err_print(BUILD_EVENT_ATTR_FAILED, (err) ? strerror(err) : ""); + } return (NULL); }
--- a/usr/src/cmd/fs.d/fslib.c Tue May 27 17:27:03 2008 -0700 +++ b/usr/src/cmd/fs.d/fslib.c Tue May 27 18:25:14 2008 -0700 @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -174,7 +173,7 @@ resetmnttab(mfp); while ((ret = getextmntent(mfp, &mnt, sizeof (struct extmnttab))) - != -1) { + != -1) { mntlist_t *mp; if (ret != 0) /* bad entry */ @@ -216,19 +215,19 @@ * match if and only if both are equal. */ if ((strcmp(ml->mntl_mnt->mnt_mountp, - mntin->mnt_mountp) == 0) && + mntin->mnt_mountp) == 0) && (strcmp(ml->mntl_mnt->mnt_special, - mntin->mnt_special) == 0)) + mntin->mnt_special) == 0)) delete = ml; } else if (mntin->mnt_mountp) { if (strcmp(ml->mntl_mnt->mnt_mountp, - mntin->mnt_mountp) == 0) + mntin->mnt_mountp) == 0) delete = ml; } else if (mntin->mnt_special) { if (strcmp(ml->mntl_mnt->mnt_special, - mntin->mnt_special) == 0) + mntin->mnt_special) == 0) delete = ml; - } + } } return (delete); } @@ -309,7 +308,7 @@ while (*requested_opts != '\0') { (void) getsubopt(&requested_opts, empty_opt_vector, - &option_ptr); + &option_ptr); /* * Truncate any "=<value>" string from the end of @@ -322,6 +321,14 @@ continue; /* + * Whilst we don't need this option to perform a lofi + * mount, let's not be mendacious enough to complain + * about it. + */ + if (strcmp(option_ptr, "loop") == 0) + continue; + + /* * Search for the requested option in the list of options * actually supported. */ @@ -344,7 +351,7 @@ while (*actual_opt_hold != '\0') { (void) getsubopt(&actual_opt_hold, empty_opt_vector, - &actopt); + &actopt); /* Truncate the "=<value>", if any. */ if ((equalptr = strchr(actopt, '=')) != NULL) @@ -428,10 +435,10 @@ for (;;) { if (zone_list(ids, &numzones) < 0) { - perror("unable to retrieve list of zones"); - if (ids != NULL) - free(ids); - return (NULL); + perror("unable to retrieve list of zones"); + if (ids != NULL) + free(ids); + return (NULL); } if (numzones <= oldnumzones) break;
--- a/usr/src/cmd/fs.d/ufs/fsck/main.c Tue May 27 17:27:03 2008 -0700 +++ b/usr/src/cmd/fs.d/ufs/fsck/main.c Tue May 27 18:25:14 2008 -0700 @@ -696,7 +696,8 @@ int found_magic[MAGIC_LIMIT]; int magic_cnt; int is_magic = 0; - int is_block; + int is_block = 0; + int is_file = 0; (void) memset((void *)found_magic, 0, sizeof (found_magic)); @@ -706,22 +707,12 @@ exit(EXNOSTAT); } - if ((stbd.st_mode & S_IFMT) == S_IFBLK) { + if (S_ISBLK(stbd.st_mode)) { is_block = 1; - } else if ((stbd.st_mode & S_IFMT) == S_IFCHR) { + } else if (S_ISCHR(stbd.st_mode)) { is_block = 0; - } else { - /* - * In !mflag mode, we allow checking the contents - * of a file. Since this is intended primarily for - * speeding up boot-time checks and allowing for a - * file complicates the ok-input tests, we'll disallow - * that option. - */ - (void) fprintf(stderr, - "ufs fsck: sanity check failed: " - "%s not block or character device\n", filename); - exit(EXNOSTAT); + } else if (S_ISREG(stbd.st_mode)) { + is_file = 1; } /* @@ -729,7 +720,7 @@ * silently on failures. The whole point of this is to be tolerant * of the magic file systems being already mounted. */ - if ((vfstab = fopen(VFSTAB, "r")) != 0) { + if (!is_file && (vfstab = fopen(VFSTAB, "r")) != NULL) { for (magic_cnt = 0; magic_cnt < MAGIC_LIMIT; magic_cnt++) { if (magic_cnt == MAGIC_NONE) continue;
--- a/usr/src/cmd/lofiadm/main.c Tue May 27 17:27:03 2008 -0700 +++ b/usr/src/cmd/lofiadm/main.c Tue May 27 18:25:14 2008 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -304,6 +304,8 @@ struct lofi_ioctl li; li.li_force = force; + li.li_cleanup = B_FALSE; + if (devicename == NULL) { /* delete by filename */ (void) strlcpy(li.li_filename, filename,
--- a/usr/src/cmd/zoneadm/zoneadm.c Tue May 27 17:27:03 2008 -0700 +++ b/usr/src/cmd/zoneadm/zoneadm.c Tue May 27 18:25:14 2008 -0700 @@ -2437,7 +2437,7 @@ static int verify_fs_special(struct zone_fstab *fstab) { - struct stat st; + struct stat64 st; /* * This validation is really intended for standard zone administration. @@ -2450,7 +2450,7 @@ if (strcmp(fstab->zone_fs_type, MNTTYPE_ZFS) == 0) return (verify_fs_zfs(fstab)); - if (stat(fstab->zone_fs_special, &st) != 0) { + if (stat64(fstab->zone_fs_special, &st) != 0) { (void) fprintf(stderr, gettext("could not verify fs " "%s: could not access %s: %s\n"), fstab->zone_fs_dir, fstab->zone_fs_special, strerror(errno)); @@ -2474,6 +2474,17 @@ } static int +isregfile(const char *path) +{ + struct stat64 st; + + if (stat64(path, &st) == -1) + return (-1); + + return (S_ISREG(st.st_mode)); +} + +static int verify_filesystems(zone_dochandle_t handle) { int return_code = Z_OK; @@ -2529,8 +2540,10 @@ goto next_fs; } /* - * Verify /usr/lib/fs/<fstype>/fsck exists iff zone_fs_raw is - * set. + * If zone_fs_raw is set, verify that there's an fsck + * binary for it. If zone_fs_raw is not set, and it's + * not a regular file (lofi mount), and there's an fsck + * binary for it, complain. */ if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/fsck", fstab.zone_fs_type) > sizeof (cmdbuf)) { @@ -2540,14 +2553,6 @@ return_code = Z_ERR; goto next_fs; } - if (fstab.zone_fs_raw[0] == '\0' && stat(cmdbuf, &st) == 0) { - (void) fprintf(stderr, gettext("could not verify fs " - "%s: must specify 'raw' device for %s " - "file systems\n"), - fstab.zone_fs_dir, fstab.zone_fs_type); - return_code = Z_ERR; - goto next_fs; - } if (fstab.zone_fs_raw[0] != '\0' && (stat(cmdbuf, &st) != 0 || !S_ISREG(st.st_mode))) { (void) fprintf(stderr, gettext("cannot verify fs %s: " @@ -2556,6 +2561,15 @@ fstab.zone_fs_dir, fstab.zone_fs_type); return_code = Z_ERR; goto next_fs; + } else if (fstab.zone_fs_raw[0] == '\0' && + stat(cmdbuf, &st) == 0 && + isregfile(fstab.zone_fs_special) != 1) { + (void) fprintf(stderr, gettext("could not verify fs " + "%s: must specify 'raw' device for %s " + "file systems\n"), + fstab.zone_fs_dir, fstab.zone_fs_type); + return_code = Z_ERR; + goto next_fs; } /* Verify fs_special. */
--- a/usr/src/cmd/zoneadmd/vplat.c Tue May 27 17:27:03 2008 -0700 +++ b/usr/src/cmd/zoneadmd/vplat.c Tue May 27 18:25:14 2008 -0700 @@ -803,6 +803,17 @@ } static int +isregfile(const char *path) +{ + struct stat64 st; + + if (stat64(path, &st) == -1) + return (-1); + + return (S_ISREG(st.st_mode)); +} + +static int dofsck(zlog_t *zlogp, const char *fstype, const char *rawdev) { char cmdbuf[MAXPATHLEN]; @@ -819,6 +830,13 @@ return (-1); } + /* + * If it doesn't exist, that's OK: we verified this previously + * in zoneadm. + */ + if (isregfile(cmdbuf) == -1) + return (0); + argv[0] = "fsck"; argv[1] = "-m"; argv[2] = (char *)rawdev; @@ -1260,8 +1278,12 @@ * Run 'fsck -m' if there's a device to fsck. */ if (fsptr->zone_fs_raw[0] != '\0' && - dofsck(zlogp, fsptr->zone_fs_type, fsptr->zone_fs_raw) != 0) + dofsck(zlogp, fsptr->zone_fs_type, fsptr->zone_fs_raw) != 0) { return (-1); + } else if (isregfile(fsptr->zone_fs_special) == 1 && + dofsck(zlogp, fsptr->zone_fs_type, fsptr->zone_fs_special) != 0) { + return (-1); + } /* * Build up mount option string.
--- a/usr/src/uts/common/fs/hsfs/hsfs_vfsops.c Tue May 27 17:27:03 2008 -0700 +++ b/usr/src/uts/common/fs/hsfs/hsfs_vfsops.c Tue May 27 18:25:14 2008 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1343,40 +1343,57 @@ cred_t *cr) { int error; - struct vnode *vp; + struct vnode *svp = NULL; + struct vnode *lvp = NULL; + struct vnode *bvp; struct vattr vap; dev_t dev; + enum uio_seg fromspace = (flags & MS_SYSSPACE) ? + UIO_SYSSPACE : UIO_USERSPACE; /* - * Get the device to be mounted + * Look up the device/file to be mounted. */ - error = lookupname(fspec, (flags & MS_SYSSPACE) ? - UIO_SYSSPACE : UIO_USERSPACE, FOLLOW, NULLVPP, &vp); + error = lookupname(fspec, fromspace, FOLLOW, NULLVPP, &svp); if (error) { - if (error == ENOENT) { - return (ENODEV); /* needs translation */ - } - return (error); - } - if (vp->v_type != VBLK) { - VN_RELE(vp); - return (ENOTBLK); - } - /* - * Can we read from the device? - */ - if ((error = VOP_ACCESS(vp, VREAD, 0, cr, NULL)) != 0 || - (error = secpolicy_spec_open(cr, vp, FREAD)) != 0) { - VN_RELE(vp); - return (error); + if (error == ENOENT) + error = ENODEV; + goto out; } + error = vfs_get_lofi(vfsp, &lvp); + + if (error > 0) { + if (error == ENOENT) + error = ENODEV; + goto out; + } else if (error == 0) { + bvp = lvp; + } else { + bvp = svp; + + if (bvp->v_type != VBLK) { + error = ENOTBLK; + goto out; + } + + if ((error = secpolicy_spec_open(cr, bvp, FREAD)) != 0) + goto out; + } + + /* + * Can we read from the device/file ? + */ + if ((error = VOP_ACCESS(svp, VREAD, 0, cr, NULL)) != 0) + goto out; + vap.va_mask = AT_MODE; /* get protection mode */ - (void) VOP_GETATTR(vp, &vap, 0, CRED(), NULL); + (void) VOP_GETATTR(bvp, &vap, 0, CRED(), NULL); *mode = vap.va_mode; - dev = *pdev = vp->v_rdev; - VN_RELE(vp); + dev = *pdev = bvp->v_rdev; + + error = EBUSY; /* * Ensure that this device isn't already mounted, @@ -1385,14 +1402,23 @@ */ if ((flags & MS_NOCHECK) == 0) { if (vfs_devmounting(dev, vfsp)) - return (EBUSY); + goto out; if (vfs_devismounted(dev) && !(flags & MS_REMOUNT)) - return (EBUSY); + goto out; } - if (getmajor(*pdev) >= devcnt) - return (ENXIO); - return (0); + if (getmajor(*pdev) >= devcnt) { + error = ENXIO; + goto out; + } + + error = 0; +out: + if (svp != NULL) + VN_RELE(svp); + if (lvp != NULL) + VN_RELE(lvp); + return (error); } static void
--- a/usr/src/uts/common/fs/pcfs/pc_vfsops.c Tue May 27 17:27:03 2008 -0700 +++ b/usr/src/uts/common/fs/pcfs/pc_vfsops.c Tue May 27 18:25:14 2008 -0700 @@ -293,7 +293,8 @@ { struct pathname special; char *c; - struct vnode *bvp; + struct vnode *svp = NULL; + struct vnode *lvp = NULL; int oflag, aflag; int error; @@ -307,7 +308,7 @@ *dos_ldrive = -1; if (error = - lookupname(special.pn_path, UIO_SYSSPACE, FOLLOW, NULLVPP, &bvp)) { + lookupname(special.pn_path, UIO_SYSSPACE, FOLLOW, NULLVPP, &svp)) { /* * If there's no device node, the name specified most likely * maps to a PCFS-style "partition specifier" to select a @@ -384,7 +385,7 @@ error = lookupname(special.pn_path, UIO_SYSSPACE, FOLLOW, - NULLVPP, &bvp); + NULLVPP, &svp); } else { *dos_ldrive = UNPARTITIONED_DRIVE; } @@ -395,8 +396,6 @@ ASSERT(*dos_ldrive >= UNPARTITIONED_DRIVE); - *xdev = bvp->v_rdev; - /* * Verify caller's permission to open the device special file. */ @@ -409,20 +408,38 @@ aflag = VREAD | VWRITE; } - if (bvp->v_type != VBLK) - error = ENOTBLK; - else if (getmajor(*xdev) >= devcnt) - error = ENXIO; + error = vfs_get_lofi(vfsp, &lvp); - if ((error != 0) || - (error = VOP_ACCESS(bvp, aflag, 0, cr, NULL)) != 0 || - (error = secpolicy_spec_open(cr, bvp, oflag)) != 0) { - VN_RELE(bvp); - return (error); + if (error > 0) { + if (error == ENOENT) + error = ENODEV; + goto out; + } else if (error == 0) { + *xdev = lvp->v_rdev; + } else { + *xdev = svp->v_rdev; + + if (svp->v_type != VBLK) + error = ENOTBLK; + + if ((error = secpolicy_spec_open(cr, svp, oflag)) != 0) + goto out; } - VN_RELE(bvp); - return (0); + if (getmajor(*xdev) >= devcnt) { + error = ENXIO; + goto out; + } + + if ((error = VOP_ACCESS(svp, aflag, 0, cr, NULL)) != 0) + goto out; + +out: + if (svp != NULL) + VN_RELE(svp); + if (lvp != NULL) + VN_RELE(lvp); + return (error); } static int
--- a/usr/src/uts/common/fs/udfs/udf_vfsops.c Tue May 27 17:27:03 2008 -0700 +++ b/usr/src/uts/common/fs/udfs/udf_vfsops.c Tue May 27 18:25:14 2008 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -91,22 +91,22 @@ extern kmutex_t ud_sync_busy; static int32_t ud_mountfs(struct vfs *, - enum whymountroot, dev_t, char *, struct cred *, int32_t); + enum whymountroot, dev_t, char *, struct cred *, int32_t); static struct udf_vfs *ud_validate_and_fill_superblock(dev_t, - int32_t, uint32_t); + int32_t, uint32_t); void ud_destroy_fsp(struct udf_vfs *); void ud_convert_to_superblock(struct udf_vfs *, - struct log_vol_int_desc *); + struct log_vol_int_desc *); void ud_update_superblock(struct vfs *); int32_t ud_get_last_block(dev_t, daddr_t *); static int32_t ud_val_get_vat(struct udf_vfs *, - dev_t, daddr_t, struct ud_map *); + dev_t, daddr_t, struct ud_map *); int32_t ud_read_sparing_tbls(struct udf_vfs *, - dev_t, struct ud_map *, struct pmap_typ2 *); + dev_t, struct ud_map *, struct pmap_typ2 *); uint32_t ud_get_lbsize(dev_t, uint32_t *); static int32_t udf_mount(struct vfs *, - struct vnode *, struct mounta *, struct cred *); + struct vnode *, struct mounta *, struct cred *); static int32_t udf_unmount(struct vfs *, int, struct cred *); static int32_t udf_root(struct vfs *, struct vnode **); static int32_t udf_statvfs(struct vfs *, struct statvfs64 *); @@ -183,7 +183,8 @@ struct mounta *uap, struct cred *cr) { dev_t dev; - struct vnode *bvp; + struct vnode *lvp = NULL; + struct vnode *svp = NULL; struct pathname dpn; int32_t error; enum whymountroot why; @@ -202,9 +203,9 @@ mutex_enter(&mvp->v_lock); if ((uap->flags & MS_REMOUNT) == 0 && (uap->flags & MS_OVERLAY) == 0 && - (mvp->v_count != 1 || (mvp->v_flag & VROOT))) { - mutex_exit(&mvp->v_lock); - return (EBUSY); + (mvp->v_count != 1 || (mvp->v_flag & VROOT))) { + mutex_exit(&mvp->v_lock); + return (EBUSY); } mutex_exit(&mvp->v_lock); @@ -213,18 +214,30 @@ } /* - * Resolve path name of special file being mounted. + * Resolve path name of the file being mounted. */ if (error = lookupname(uap->spec, UIO_USERSPACE, FOLLOW, NULLVPP, - &bvp)) { + &svp)) { pn_free(&dpn); return (error); } - if (bvp->v_type != VBLK) { - error = ENOTBLK; + + error = vfs_get_lofi(vfsp, &lvp); + + if (error > 0) { + if (error == ENOENT) + error = ENODEV; goto out; + } else if (error == 0) { + dev = lvp->v_rdev; + } else { + dev = svp->v_rdev; + + if (svp->v_type != VBLK) { + error = ENOTBLK; + goto out; + } } - dev = bvp->v_rdev; /* * Ensure that this device isn't already mounted, @@ -282,19 +295,23 @@ oflag = FREAD | FWRITE; aflag = VREAD | VWRITE; } - if ((error = VOP_ACCESS(bvp, aflag, 0, cr, NULL)) != 0 || - (error = secpolicy_spec_open(cr, bvp, oflag)) != 0) { + + if (lvp == NULL && + (error = secpolicy_spec_open(cr, svp, oflag)) != 0) goto out; - } + + if ((error = VOP_ACCESS(svp, aflag, 0, cr, NULL)) != 0) + goto out; /* * Mount the filesystem. */ error = ud_mountfs(vfsp, why, dev, dpn.pn_path, cr, 0); out: - VN_RELE(bvp); + VN_RELE(svp); + if (lvp != NULL) + VN_RELE(lvp); pn_free(&dpn); - return (error); } @@ -436,15 +453,13 @@ * 38(over head each dent) + MAXNAMLEN / 2 + inode_size(==block size) */ sp->f_ffree = sp->f_favail = - (sp->f_bavail * sp->f_bsize) / (146 + sp->f_bsize); + (sp->f_bavail * sp->f_bsize) / (146 + sp->f_bsize); /* * The total number of inodes is * the sum of files + directories + free inodes */ - sp->f_files = sp->f_ffree + - udf_vfsp->udf_nfiles + - udf_vfsp->udf_ndirs; + sp->f_files = sp->f_ffree + udf_vfsp->udf_nfiles + udf_vfsp->udf_ndirs; (void) cmpldev(&d32, vfsp->vfs_dev); sp->f_fsid = d32; (void) strcpy(sp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name); @@ -495,14 +510,14 @@ udfid = (struct udf_fid *)fidp; if ((error = ud_iget(vfsp, udfid->udfid_prn, - udfid->udfid_icb_lbn, &ip, NULL, CRED())) != 0) { + udfid->udfid_icb_lbn, &ip, NULL, CRED())) != 0) { *vpp = NULL; return (error); } rw_enter(&ip->i_contents, RW_READER); if ((udfid->udfid_uinq_lo != (ip->i_uniqid & 0xffffffff)) || - (udfid->udfid_prn != ip->i_icb_prn)) { + (udfid->udfid_prn != ip->i_icb_prn)) { rw_exit(&ip->i_contents); VN_RELE(ITOV(ip)); *vpp = NULL; @@ -555,7 +570,7 @@ (void) dnlc_purge_vfsp(vfsp, 0); vp = common_specvp(vp); (void) VOP_PUTPAGE(vp, (offset_t)0, - (uint32_t)0, B_INVAL, CRED(), NULL); + (uint32_t)0, B_INVAL, CRED(), NULL); binval(vfsp->vfs_dev); ovflags = vfsp->vfs_flag; @@ -566,7 +581,7 @@ ud_update(0); vp = ((struct udf_vfs *)vfsp->vfs_data)->udf_devvp; (void) VOP_CLOSE(vp, FREAD|FWRITE, 1, - (offset_t)0, CRED(), NULL); + (offset_t)0, CRED(), NULL); return (0); } @@ -589,7 +604,7 @@ if (why == ROOT_INIT) { vfs_add((struct vnode *)0, vfsp, - (vfsp->vfs_flag & VFS_RDONLY) ? MS_RDONLY : 0); + (vfsp->vfs_flag & VFS_RDONLY) ? MS_RDONLY : 0); } vfs_unlock(vfsp); return (0); @@ -678,7 +693,7 @@ if (udf_vfsp->udf_flags & UDF_FL_RDONLY) { (void) dnlc_purge_vfsp(vfsp, 0); (void) VOP_PUTPAGE(devvp, (offset_t)0, (uint_t)0, - B_INVAL, CRED(), NULL); + B_INVAL, CRED(), NULL); (void) ud_iflush(vfsp); bflush(dev); binval(dev); @@ -689,7 +704,7 @@ * disallow mount of any highier version */ if ((udf_vfsp->udf_miread > UDF_150) || - (udf_vfsp->udf_miwrite > UDF_150)) { + (udf_vfsp->udf_miwrite > UDF_150)) { error = EINVAL; goto remountout; } @@ -715,8 +730,8 @@ * mount in rw mode */ tpt = ud_bread(vfsp->vfs_dev, - udf_vfsp->udf_iseq_loc << udf_vfsp->udf_l2d_shift, - udf_vfsp->udf_iseq_len); + udf_vfsp->udf_iseq_loc << udf_vfsp->udf_l2d_shift, + udf_vfsp->udf_iseq_len); if (tpt->b_flags & B_ERROR) { error = EIO; goto remountout; @@ -735,7 +750,7 @@ lvid = (struct log_vol_int_desc *)ttag; if (SWAP_32(lvid->lvid_int_type) != - LOG_VOL_CLOSE_INT) { + LOG_VOL_CLOSE_INT) { error = EINVAL; goto remountout; } @@ -744,7 +759,7 @@ * Copy new data to old data */ bcopy(udf_vfsp->udf_iseq->b_un.b_addr, - tpt->b_un.b_addr, udf_vfsp->udf_iseq_len); + tpt->b_un.b_addr, udf_vfsp->udf_iseq_len); break; } } @@ -846,7 +861,7 @@ * disallow mount of any highier version */ if ((udf_vfsp->udf_miread > UDF_150) || - (udf_vfsp->udf_miwrite > UDF_150)) { + (udf_vfsp->udf_miwrite > UDF_150)) { error = EINVAL; goto out; } @@ -904,7 +919,7 @@ _NOTE(COMPETING_THREADS_NOW); #endif if (error = ud_iget(vfsp, udf_vfsp->udf_ricb_prn, - udf_vfsp->udf_ricb_loc, &rip, NULL, cr)) { + udf_vfsp->udf_ricb_loc, &rip, NULL, cr)) { mutex_destroy(&udf_vfsp->udf_lock); goto out; } @@ -937,7 +952,7 @@ ud_destroy_fsp(udf_vfsp); if (needclose) { (void) VOP_CLOSE(devvp, (vfsp->vfs_flag & VFS_RDONLY) ? - FREAD : FREAD|FWRITE, 1, (offset_t)0, cr, NULL); + FREAD : FREAD|FWRITE, 1, (offset_t)0, cr, NULL); bflush(dev); binval(dev); } @@ -982,8 +997,8 @@ */ secbp = ud_bread(dev, avd_loc << shift, ANCHOR_VOL_DESC_LEN); if ((error = geterror(secbp)) != 0) { - cmn_err(CE_NOTE, - "udfs : Could not read Anchor Volume Desc %x", error); + cmn_err(CE_NOTE, "udfs : Could not read Anchor Volume Desc %x", + error); brelse(secbp); return (NULL); } @@ -994,7 +1009,7 @@ return (NULL); } udf_vfsp = (struct udf_vfs *) - kmem_zalloc(sizeof (struct udf_vfs), KM_SLEEP); + kmem_zalloc(sizeof (struct udf_vfs), KM_SLEEP); udf_vfsp->udf_mvds_loc = SWAP_32(avdp->avd_main_vdse.ext_loc); udf_vfsp->udf_mvds_len = SWAP_32(avdp->avd_main_vdse.ext_len); udf_vfsp->udf_rvds_loc = SWAP_32(avdp->avd_res_vdse.ext_loc); @@ -1008,15 +1023,15 @@ */ vds_loc = udf_vfsp->udf_mvds_loc; secbp = ud_bread(dev, vds_loc << shift, - udf_vfsp->udf_mvds_len); + udf_vfsp->udf_mvds_len); if ((error = geterror(secbp)) != 0) { brelse(secbp); - cmn_err(CE_NOTE, - "udfs : Could not read Main Volume Desc %x", error); + cmn_err(CE_NOTE, "udfs : Could not read Main Volume Desc %x", + error); vds_loc = udf_vfsp->udf_rvds_loc; secbp = ud_bread(dev, vds_loc << shift, - udf_vfsp->udf_rvds_len); + udf_vfsp->udf_rvds_len); if ((error = geterror(secbp)) != 0) { brelse(secbp); cmn_err(CE_NOTE, @@ -1046,7 +1061,7 @@ 1, desc_len) == 0) { if (udf_vfsp->udf_pvd == NULL) { udf_vfsp->udf_pvd = - (struct pri_vol_desc *)ttag; + (struct pri_vol_desc *)ttag; } else { struct pri_vol_desc *opvd, *npvd; @@ -1054,15 +1069,15 @@ npvd = (struct pri_vol_desc *)ttag; if ((strncmp(opvd->pvd_vsi, - npvd->pvd_vsi, 128) == 0) && - (strncmp(opvd->pvd_vol_id, - npvd->pvd_vol_id, 32) == 0) && - (strncmp((caddr_t)&opvd->pvd_desc_cs, - (caddr_t)&npvd->pvd_desc_cs, - sizeof (charspec_t)) == 0)) { + npvd->pvd_vsi, 128) == 0) && + (strncmp(opvd->pvd_vol_id, + npvd->pvd_vol_id, 32) == 0) && + (strncmp((caddr_t)&opvd->pvd_desc_cs, + (caddr_t)&npvd->pvd_desc_cs, + sizeof (charspec_t)) == 0)) { if (SWAP_32(opvd->pvd_vdsn) < - SWAP_32(npvd->pvd_vdsn)) { + SWAP_32(npvd->pvd_vdsn)) { udf_vfsp->udf_pvd = npvd; } } else { @@ -1076,7 +1091,7 @@ lvd = (struct log_vol_desc *)ttag; if (strncmp(lvd->lvd_dom_id.reg_id, - UDF_DOMAIN_NAME, 23) != 0) { + UDF_DOMAIN_NAME, 23) != 0) { printf("Domain ID in lvd is not valid\n"); goto out; } @@ -1088,12 +1103,12 @@ olvd = udf_vfsp->udf_lvd; if ((strncmp((caddr_t)&olvd->lvd_desc_cs, - (caddr_t)&lvd->lvd_desc_cs, - sizeof (charspec_t)) == 0) && - (strncmp(olvd->lvd_lvid, - lvd->lvd_lvid, 128) == 0)) { + (caddr_t)&lvd->lvd_desc_cs, + sizeof (charspec_t)) == 0) && + (strncmp(olvd->lvd_lvid, + lvd->lvd_lvid, 128) == 0)) { if (SWAP_32(olvd->lvd_vdsn) < - SWAP_32(lvd->lvd_vdsn)) { + SWAP_32(lvd->lvd_vdsn)) { udf_vfsp->udf_lvd = lvd; } } else { @@ -1111,35 +1126,37 @@ pdesc = (struct part_desc *)ttag; pold = udf_vfsp->udf_parts; for (i = 0; i < udf_vfsp->udf_npart; i++) { - if (pold->udp_number == - SWAP_16(pdesc->pd_pnum)) { - if (SWAP_32(pdesc->pd_vdsn) > - pold->udp_seqno) { - pold->udp_seqno = - SWAP_32(pdesc->pd_vdsn); - pold->udp_access = - SWAP_32(pdesc->pd_acc_type); - pold->udp_start = - SWAP_32(pdesc->pd_part_start); - pold->udp_length = - SWAP_32(pdesc->pd_part_length); - } - goto loop_end; + if (pold->udp_number != + SWAP_16(pdesc->pd_pnum)) { + pold++; + continue; } - pold ++; + + if (SWAP_32(pdesc->pd_vdsn) > + pold->udp_seqno) { + pold->udp_seqno = + SWAP_32(pdesc->pd_vdsn); + pold->udp_access = + SWAP_32(pdesc->pd_acc_type); + pold->udp_start = + SWAP_32(pdesc->pd_part_start); + pold->udp_length = + SWAP_32(pdesc->pd_part_length); + } + goto loop_end; } pold = udf_vfsp->udf_parts; udf_vfsp->udf_npart++; pnew = kmem_zalloc(udf_vfsp->udf_npart * - sizeof (struct ud_part), KM_SLEEP); + sizeof (struct ud_part), KM_SLEEP); udf_vfsp->udf_parts = pnew; if (pold) { bcopy(pold, pnew, - sizeof (struct ud_part) * - (udf_vfsp->udf_npart - 1)); + sizeof (struct ud_part) * + (udf_vfsp->udf_npart - 1)); kmem_free(pold, - sizeof (struct ud_part) * - (udf_vfsp->udf_npart - 1)); + sizeof (struct ud_part) * + (udf_vfsp->udf_npart - 1)); } part = pnew + (udf_vfsp->udf_npart - 1); part->udp_number = SWAP_16(pdesc->pd_pnum); @@ -1157,23 +1174,23 @@ if (hdr->phdr_ust.sad_ext_len) { part->udp_flags = UDP_SPACETBLS; part->udp_unall_loc = - SWAP_32(hdr->phdr_ust.sad_ext_loc); + SWAP_32(hdr->phdr_ust.sad_ext_loc); part->udp_unall_len = - SWAP_32(hdr->phdr_ust.sad_ext_len); + SWAP_32(hdr->phdr_ust.sad_ext_len); part->udp_freed_loc = - SWAP_32(hdr->phdr_fst.sad_ext_loc); + SWAP_32(hdr->phdr_fst.sad_ext_loc); part->udp_freed_len = - SWAP_32(hdr->phdr_fst.sad_ext_len); + SWAP_32(hdr->phdr_fst.sad_ext_len); } else { part->udp_flags = UDP_BITMAPS; part->udp_unall_loc = - SWAP_32(hdr->phdr_usb.sad_ext_loc); + SWAP_32(hdr->phdr_usb.sad_ext_loc); part->udp_unall_len = - SWAP_32(hdr->phdr_usb.sad_ext_len); + SWAP_32(hdr->phdr_usb.sad_ext_len); part->udp_freed_loc = - SWAP_32(hdr->phdr_fsb.sad_ext_loc); + SWAP_32(hdr->phdr_fsb.sad_ext_loc); part->udp_freed_len = - SWAP_32(hdr->phdr_fsb.sad_ext_len); + SWAP_32(hdr->phdr_fsb.sad_ext_len); } } else if (ud_verify_tag_and_desc(ttag, UD_TERM_DESC, vds_loc + (index >> shift), @@ -1185,8 +1202,8 @@ ; } if ((udf_vfsp->udf_pvd == NULL) || - (udf_vfsp->udf_lvd == NULL) || - (udf_vfsp->udf_parts == NULL)) { + (udf_vfsp->udf_lvd == NULL) || + (udf_vfsp->udf_parts == NULL)) { goto out; } @@ -1201,7 +1218,7 @@ * Process Logical Volume Descriptor */ udf_vfsp->udf_lbsize = - SWAP_32(udf_vfsp->udf_lvd->lvd_log_bsize); + SWAP_32(udf_vfsp->udf_lvd->lvd_log_bsize); udf_vfsp->udf_lbmask = udf_vfsp->udf_lbsize - 1; udf_vfsp->udf_l2d_shift = shift; udf_vfsp->udf_l2b_shift = shift + DEV_BSHIFT; @@ -1211,7 +1228,7 @@ * proper domain. */ if (strcmp(udf_vfsp->udf_lvd->lvd_dom_id.reg_id, - UDF_DOMAIN_NAME) != 0) { + UDF_DOMAIN_NAME) != 0) { goto out; } @@ -1224,16 +1241,16 @@ } udf_vfsp->udf_iseq_loc = - SWAP_32(udf_vfsp->udf_lvd->lvd_int_seq_ext.ext_loc); + SWAP_32(udf_vfsp->udf_lvd->lvd_int_seq_ext.ext_loc); udf_vfsp->udf_iseq_len = - SWAP_32(udf_vfsp->udf_lvd->lvd_int_seq_ext.ext_len); + SWAP_32(udf_vfsp->udf_lvd->lvd_int_seq_ext.ext_len); udf_vfsp->udf_fsd_prn = - SWAP_16(udf_vfsp->udf_lvd->lvd_lvcu.lad_ext_prn); + SWAP_16(udf_vfsp->udf_lvd->lvd_lvcu.lad_ext_prn); udf_vfsp->udf_fsd_loc = - SWAP_32(udf_vfsp->udf_lvd->lvd_lvcu.lad_ext_loc); + SWAP_32(udf_vfsp->udf_lvd->lvd_lvcu.lad_ext_loc); udf_vfsp->udf_fsd_len = - SWAP_32(udf_vfsp->udf_lvd->lvd_lvcu.lad_ext_len); + SWAP_32(udf_vfsp->udf_lvd->lvd_lvcu.lad_ext_len); /* @@ -1242,13 +1259,13 @@ udf_vfsp->udf_mtype = udf_vfsp->udf_parts[0].udp_access; for (index = 0; index < udf_vfsp->udf_npart; index ++) { if (udf_vfsp->udf_parts[index].udp_access < - udf_vfsp->udf_mtype) { + udf_vfsp->udf_mtype) { udf_vfsp->udf_mtype = - udf_vfsp->udf_parts[index].udp_access; + udf_vfsp->udf_parts[index].udp_access; } } if ((udf_vfsp->udf_mtype < UDF_MT_RO) || - (udf_vfsp->udf_mtype > UDF_MT_OW)) { + (udf_vfsp->udf_mtype > UDF_MT_OW)) { udf_vfsp->udf_mtype = UDF_MT_RO; } @@ -1258,19 +1275,19 @@ for (index = 0; index < count; index++) { if ((hdr->maph_type == MAP_TYPE1) && - (hdr->maph_length == MAP_TYPE1_LEN)) { + (hdr->maph_length == MAP_TYPE1_LEN)) { typ1 = (struct pmap_typ1 *)hdr; map = udf_vfsp->udf_maps; udf_vfsp->udf_maps = - kmem_zalloc(sizeof (struct ud_map) * - (udf_vfsp->udf_nmaps + 1), - KM_SLEEP); + kmem_zalloc(sizeof (struct ud_map) * + (udf_vfsp->udf_nmaps + 1), KM_SLEEP); if (map != NULL) { bcopy(map, udf_vfsp->udf_maps, - sizeof (struct ud_map) * udf_vfsp->udf_nmaps); - kmem_free(map, - sizeof (struct ud_map) * udf_vfsp->udf_nmaps); + sizeof (struct ud_map) * + udf_vfsp->udf_nmaps); + kmem_free(map, sizeof (struct ud_map) * + udf_vfsp->udf_nmaps); } map = udf_vfsp->udf_maps + udf_vfsp->udf_nmaps; map->udm_flags = UDM_MAP_NORM; @@ -1278,11 +1295,11 @@ map->udm_pn = SWAP_16(typ1->map1_pn); udf_vfsp->udf_nmaps ++; } else if ((hdr->maph_type == MAP_TYPE2) && - (hdr->maph_length == MAP_TYPE2_LEN)) { + (hdr->maph_length == MAP_TYPE2_LEN)) { typ2 = (struct pmap_typ2 *)hdr; if (strncmp(typ2->map2_pti.reg_id, - UDF_VIRT_PART, 23) == 0) { + UDF_VIRT_PART, 23) == 0) { /* * Add this to the normal * partition table so that @@ -1290,16 +1307,15 @@ */ map = udf_vfsp->udf_maps; udf_vfsp->udf_maps = - kmem_zalloc(sizeof (struct ud_map) * - (udf_vfsp->udf_nmaps + 1), - KM_SLEEP); + kmem_zalloc(sizeof (struct ud_map) * + (udf_vfsp->udf_nmaps + 1), KM_SLEEP); if (map != NULL) { bcopy(map, udf_vfsp->udf_maps, - sizeof (struct ud_map) * - udf_vfsp->udf_nmaps); + sizeof (struct ud_map) * + udf_vfsp->udf_nmaps); kmem_free(map, - sizeof (struct ud_map) * - udf_vfsp->udf_nmaps); + sizeof (struct ud_map) * + udf_vfsp->udf_nmaps); } map = udf_vfsp->udf_maps + udf_vfsp->udf_nmaps; map->udm_flags = UDM_MAP_VPM; @@ -1310,34 +1326,34 @@ goto out; } if (error = ud_val_get_vat(udf_vfsp, dev, - lblkno, map)) { + lblkno, map)) { goto out; } } else if (strncmp(typ2->map2_pti.reg_id, - UDF_SPAR_PART, 23) == 0) { + UDF_SPAR_PART, 23) == 0) { if (SWAP_16(typ2->map2_pl) != 32) { printf( - "Packet Length is not valid %x\n", - SWAP_16(typ2->map2_pl)); + "Packet Length is not valid %x\n", + SWAP_16(typ2->map2_pl)); goto out; } if ((typ2->map2_nst < 1) || - (typ2->map2_nst > 4)) { + (typ2->map2_nst > 4)) { goto out; } map = udf_vfsp->udf_maps; udf_vfsp->udf_maps = - kmem_zalloc(sizeof (struct ud_map) * - (udf_vfsp->udf_nmaps + 1), - KM_SLEEP); + kmem_zalloc(sizeof (struct ud_map) * + (udf_vfsp->udf_nmaps + 1), + KM_SLEEP); if (map != NULL) { bcopy(map, udf_vfsp->udf_maps, - sizeof (struct ud_map) * - udf_vfsp->udf_nmaps); + sizeof (struct ud_map) * + udf_vfsp->udf_nmaps); kmem_free(map, - sizeof (struct ud_map) * - udf_vfsp->udf_nmaps); + sizeof (struct ud_map) * + udf_vfsp->udf_nmaps); } map = udf_vfsp->udf_maps + udf_vfsp->udf_nmaps; map->udm_flags = UDM_MAP_SPM; @@ -1347,7 +1363,7 @@ udf_vfsp->udf_nmaps ++; if (error = ud_read_sparing_tbls(udf_vfsp, - dev, map, typ2)) { + dev, map, typ2)) { goto out; } } else { @@ -1373,11 +1389,11 @@ * and process it */ secbp = ud_bread(dev, udf_vfsp->udf_iseq_loc << shift, - udf_vfsp->udf_iseq_len); + udf_vfsp->udf_iseq_len); if ((error = geterror(secbp)) != 0) { cmn_err(CE_NOTE, "udfs : Could not read Logical Volume Integrity Sequence %x", - error); + error); brelse(secbp); goto out; } @@ -1424,8 +1440,8 @@ } if ((blkno = ud_xlate_to_daddr(udf_vfsp, - udf_vfsp->udf_fsd_prn, udf_vfsp->udf_fsd_loc, - 1, &dummy)) == 0) { + udf_vfsp->udf_fsd_prn, udf_vfsp->udf_fsd_loc, + 1, &dummy)) == 0) { goto out; } secbp = ud_bread(dev, blkno << shift, udf_vfsp->udf_fsd_len); @@ -1449,8 +1465,8 @@ secbp->b_flags = B_AGE | B_STALE; brelse(secbp); udf_vfsp->udf_root_blkno = ud_xlate_to_daddr(udf_vfsp, - udf_vfsp->udf_ricb_prn, udf_vfsp->udf_ricb_loc, - 1, &dummy); + udf_vfsp->udf_ricb_prn, udf_vfsp->udf_ricb_loc, + 1, &dummy); return (udf_vfsp); out: @@ -1603,7 +1619,7 @@ int32_t rval, error; if ((error = cdev_ioctl(dev, DKIOCGVTOC, (intptr_t)&vtoc, - FKIOCTL|FREAD|FNATIVE, CRED(), &rval)) != 0) { + FKIOCTL|FREAD|FNATIVE, CRED(), &rval)) != 0) { cmn_err(CE_NOTE, "Could not get the vtoc information"); return (error); } @@ -1612,7 +1628,7 @@ return (EINVAL); } if ((error = cdev_ioctl(dev, DKIOCINFO, (intptr_t)&dki_info, - FKIOCTL|FREAD|FNATIVE, CRED(), &rval)) != 0) { + FKIOCTL|FREAD|FNATIVE, CRED(), &rval)) != 0) { cmn_err(CE_NOTE, "Could not get the slice information"); return (error); } @@ -1656,8 +1672,8 @@ udm->udm_vat_icb = end_loc - ud_sub_blks[i]; secbp = ud_bread(dev, - udm->udm_vat_icb << udf_vfsp->udf_l2d_shift, - udf_vfsp->udf_lbsize); + udm->udm_vat_icb << udf_vfsp->udf_l2d_shift, + udf_vfsp->udf_lbsize); ASSERT(secbp->b_un.b_addr); fe = (struct file_entry *)secbp->b_un.b_addr; @@ -1683,10 +1699,10 @@ udm->udm_nent = 1; } else if (ad_type == ICB_FLAG_SHORT_AD) { udm->udm_nent = - SWAP_32(fe->fe_len_adesc) / sizeof (struct short_ad); + SWAP_32(fe->fe_len_adesc) / sizeof (struct short_ad); } else if (ad_type == ICB_FLAG_LONG_AD) { udm->udm_nent = - SWAP_32(fe->fe_len_adesc) / sizeof (struct long_ad); + SWAP_32(fe->fe_len_adesc) / sizeof (struct long_ad); } else { err = EINVAL; goto end; @@ -1701,22 +1717,22 @@ if (ad_type == ICB_FLAG_ONE_AD) { udm->udm_count[0] = (SWAP_64(fe->fe_info_len) - 36) / - sizeof (uint32_t); + sizeof (uint32_t); udm->udm_bp[0] = secbp; udm->udm_addr[0] = (uint32_t *) - &fe->fe_spec[SWAP_32(fe->fe_len_ear)]; + &fe->fe_spec[SWAP_32(fe->fe_len_ear)]; return (0); } for (i = 0; i < udm->udm_nent; i++) { if (ad_type == ICB_FLAG_SHORT_AD) { sad = (struct short_ad *) - (fe->fe_spec + SWAP_32(fe->fe_len_ear)); + (fe->fe_spec + SWAP_32(fe->fe_len_ear)); sad += i; count = SWAP_32(sad->sad_ext_len); blk = SWAP_32(sad->sad_ext_loc); } else { lad = (struct long_ad *) - (fe->fe_spec + SWAP_32(fe->fe_len_ear)); + (fe->fe_spec + SWAP_32(fe->fe_len_ear)); lad += i; count = SWAP_32(lad->lad_ext_len); blk = SWAP_32(lad->lad_ext_loc); @@ -1744,9 +1760,9 @@ count = (count + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1); udm->udm_bp[i] = ud_bread(dev, - blk << udf_vfsp->udf_l2d_shift, count); + blk << udf_vfsp->udf_l2d_shift, count); if ((udm->udm_bp[i]->b_error != 0) || - (udm->udm_bp[i]->b_resid)) { + (udm->udm_bp[i]->b_resid)) { err = EINVAL; break; } @@ -1782,7 +1798,7 @@ map->udm_loc[index] = SWAP_32(typ2->map2_st[index]); bp = ud_bread(dev, - map->udm_loc[index] << udf_vfsp->udf_l2d_shift, sz); + map->udm_loc[index] << udf_vfsp->udf_l2d_shift, sz); if ((bp->b_error != 0) || (bp->b_resid)) { brelse(bp); continue; @@ -1840,23 +1856,23 @@ } if (cdev_ioctl(dev, CDROMREADOFFSET, (intptr_t)&session_offset, - FKIOCTL|FREAD|FNATIVE, CRED(), &rval) != 0) { + FKIOCTL|FREAD|FNATIVE, CRED(), &rval) != 0) { session_offset = 0; } for (index = 0; index < end_index; index++) { for (bsize = DEV_BSIZE, shift = 0; - bsize <= MAXBSIZE; bsize <<= 1, shift++) { + bsize <= MAXBSIZE; bsize <<= 1, shift++) { if (index == 0) { avd_loc = 256; if (bsize <= 2048) { avd_loc += - session_offset * 2048 / bsize; + session_offset * 2048 / bsize; } else { avd_loc += - session_offset / (bsize / 2048); + session_offset / (bsize / 2048); } } else if (index == 1) { avd_loc = last_block - (1 << shift); @@ -1865,7 +1881,7 @@ } bp = ud_bread(dev, avd_loc << shift, - ANCHOR_VOL_DESC_LEN); + ANCHOR_VOL_DESC_LEN); if (geterror(bp) != 0) { brelse(bp); continue;
--- a/usr/src/uts/common/fs/ufs/ufs_vfsops.c Tue May 27 17:27:03 2008 -0700 +++ b/usr/src/uts/common/fs/ufs/ufs_vfsops.c Tue May 27 18:25:14 2008 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -265,7 +265,8 @@ char *data = uap->dataptr; int datalen = uap->datalen; dev_t dev; - struct vnode *bvp; + struct vnode *lvp = NULL; + struct vnode *svp = NULL; struct pathname dpn; int error; enum whymountroot why = ROOT_INIT; @@ -308,6 +309,16 @@ } else { datalen = 0; } + + if ((vfsp->vfs_flag & VFS_RDONLY) != 0 || + (uap->flags & MS_RDONLY) != 0) { + oflag = FREAD; + aflag = VREAD; + } else { + oflag = FREAD | FWRITE; + aflag = VREAD | VWRITE; + } + /* * Read in the mount point pathname * (so we can record the directory the file system was last mounted on). @@ -318,55 +329,67 @@ /* * Resolve path name of special file being mounted. */ - if (error = lookupname(uap->spec, fromspace, FOLLOW, NULL, &bvp)) { + if (error = lookupname(uap->spec, fromspace, FOLLOW, NULL, &svp)) { pn_free(&dpn); return (error); } - if (bvp->v_type != VBLK) { - VN_RELE(bvp); + + error = vfs_get_lofi(vfsp, &lvp); + + if (error > 0) { + VN_RELE(svp); pn_free(&dpn); - return (ENOTBLK); + return (error); + } else if (error == 0) { + dev = lvp->v_rdev; + + if (getmajor(dev) >= devcnt) { + error = ENXIO; + goto out; + } + } else { + dev = svp->v_rdev; + + if (svp->v_type != VBLK) { + VN_RELE(svp); + pn_free(&dpn); + return (ENOTBLK); + } + + if (getmajor(dev) >= devcnt) { + error = ENXIO; + goto out; + } + + /* + * In SunCluster, requests to a global device are + * satisfied by a local device. We substitute the global + * pxfs node with a local spec node here. + */ + if (IS_PXFSVP(svp)) { + ASSERT(lvp == NULL); + VN_RELE(svp); + svp = makespecvp(dev, VBLK); + } + + if ((error = secpolicy_spec_open(cr, svp, oflag)) != 0) { + VN_RELE(svp); + pn_free(&dpn); + return (error); + } } - dev = bvp->v_rdev; - if (getmajor(dev) >= devcnt) { - pn_free(&dpn); - VN_RELE(bvp); - return (ENXIO); - } + if (uap->flags & MS_REMOUNT) why = ROOT_REMOUNT; /* - * In SunCluster, requests to a global device are satisfied by - * a local device. We substitute the global pxfs node with a - * local spec node here. - */ - if (IS_PXFSVP(bvp)) { - VN_RELE(bvp); - bvp = makespecvp(dev, VBLK); - } - - /* - * Open block device mounted on. We need this to - * check whether the caller has sufficient rights to - * access the device in question. - * When bio is fixed for vnodes this can all be vnode + * Open device/file mounted on. We need this to check whether + * the caller has sufficient rights to access the resource in + * question. When bio is fixed for vnodes this can all be vnode * operations. */ - if ((vfsp->vfs_flag & VFS_RDONLY) != 0 || - (uap->flags & MS_RDONLY) != 0) { - oflag = FREAD; - aflag = VREAD; - } else { - oflag = FREAD | FWRITE; - aflag = VREAD | VWRITE; - } - if ((error = VOP_ACCESS(bvp, aflag, 0, cr, NULL)) != 0 || - (error = secpolicy_spec_open(cr, bvp, oflag)) != 0) { - pn_free(&dpn); - VN_RELE(bvp); - return (error); - } + if ((error = VOP_ACCESS(svp, aflag, 0, cr, NULL)) != 0) + goto out; /* * Ensure that this device isn't already mounted or in progress on a @@ -376,15 +399,13 @@ if ((uap->flags & MS_NOCHECK) == 0) { if ((uap->flags & MS_GLOBAL) == 0 && vfs_devmounting(dev, vfsp)) { - pn_free(&dpn); - VN_RELE(bvp); - return (EBUSY); + error = EBUSY; + goto out; } if (vfs_devismounted(dev)) { if ((uap->flags & MS_REMOUNT) == 0) { - pn_free(&dpn); - VN_RELE(bvp); - return (EBUSY); + error = EBUSY; + goto out; } } } @@ -402,15 +423,31 @@ /* * Mount the filesystem, free the device vnode on error. */ - error = mountfs(vfsp, why, bvp, dpn.pn_path, cr, 0, &args, datalen); + error = mountfs(vfsp, why, lvp != NULL ? lvp : svp, + dpn.pn_path, cr, 0, &args, datalen); + + if (error == 0) { + vfs_set_feature(vfsp, VFSFT_XVATTR); + + /* + * If lofi, drop our reference to the original file. + */ + if (lvp != NULL) + VN_RELE(svp); + } + +out: pn_free(&dpn); + if (error) { - VN_RELE(bvp); + if (lvp != NULL) + VN_RELE(lvp); + if (svp != NULL) + VN_RELE(svp); } - if (error == 0) - vfs_set_feature(vfsp, VFSFT_XVATTR); return (error); } + /* * Mount root file system. * "why" is ROOT_INIT on initial call ROOT_REMOUNT if called to
--- a/usr/src/uts/common/fs/vfs.c Tue May 27 17:27:03 2008 -0700 +++ b/usr/src/uts/common/fs/vfs.c Tue May 27 18:25:14 2008 -0700 @@ -85,6 +85,7 @@ #include <sys/reboot.h> #include <sys/attr.h> #include <sys/spa.h> +#include <sys/lofi.h> #include <vm/page.h> @@ -525,6 +526,7 @@ vfsp->vfs_prev = vfsp; vfsp->vfs_zone_next = vfsp; vfsp->vfs_zone_prev = vfsp; + vfsp->vfs_lofi_minor = 0; sema_init(&vfsp->vfs_reflock, 1, NULL, SEMA_DEFAULT, NULL); vfsimpl_setup(vfsp); vfsp->vfs_data = (data); @@ -982,6 +984,129 @@ } /* + * Check to see if our "block device" is actually a file. If so, + * automatically add a lofi device, and keep track of this fact. + */ +static int +lofi_add(const char *fsname, struct vfs *vfsp, + mntopts_t *mntopts, struct mounta *uap) +{ + int fromspace = (uap->flags & MS_SYSSPACE) ? + UIO_SYSSPACE : UIO_USERSPACE; + struct lofi_ioctl *li = NULL; + struct vnode *vp = NULL; + struct pathname pn = { NULL }; + ldi_ident_t ldi_id; + ldi_handle_t ldi_hdl; + int minor; + int err = 0; + + if (fsname == NULL) + return (0); + if (strcmp(fsname, "mntfs") == 0 || strcmp(fsname, "lofs") == 0) + return (0); + + if (pn_get(uap->spec, fromspace, &pn) != 0) + return (0); + + if (lookupname(uap->spec, fromspace, FOLLOW, NULL, &vp) != 0) + goto out; + + if (vp->v_type != VREG) + goto out; + + /* OK, this is a lofi mount. */ + + if ((uap->flags & (MS_REMOUNT|MS_GLOBAL)) || + vfs_optionisset_nolock(mntopts, MNTOPT_SUID, NULL) || + vfs_optionisset_nolock(mntopts, MNTOPT_SETUID, NULL) || + vfs_optionisset_nolock(mntopts, MNTOPT_DEVICES, NULL)) { + err = EINVAL; + goto out; + } + + ldi_id = ldi_ident_from_anon(); + li = kmem_zalloc(sizeof (*li), KM_SLEEP); + (void) strlcpy(li->li_filename, pn.pn_path, MAXPATHLEN + 1); + + /* + * 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; + } + + if (err) + goto out2; + + err = ldi_ioctl(ldi_hdl, LOFI_MAP_FILE, (intptr_t)li, + FREAD | FWRITE | FEXCL | FKIOCTL, kcred, &minor); + + (void) ldi_close(ldi_hdl, FREAD | FWRITE | FEXCL, kcred); + + if (!err) + vfsp->vfs_lofi_minor = minor; + +out2: + ldi_ident_release(ldi_id); +out: + if (li != NULL) + kmem_free(li, sizeof (*li)); + if (vp != NULL) + VN_RELE(vp); + pn_free(&pn); + return (err); +} + +static void +lofi_remove(struct vfs *vfsp) +{ + struct lofi_ioctl *li = NULL; + ldi_ident_t ldi_id; + ldi_handle_t ldi_hdl; + int err; + + if (vfsp->vfs_lofi_minor == 0) + return; + + ldi_id = ldi_ident_from_anon(); + + li = kmem_zalloc(sizeof (*li), KM_SLEEP); + 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); + + if (err) + goto out; + + err = ldi_ioctl(ldi_hdl, LOFI_UNMAP_FILE_MINOR, (intptr_t)li, + FREAD | FWRITE | FEXCL | FKIOCTL, kcred, NULL); + + (void) ldi_close(ldi_hdl, FREAD | FWRITE | FEXCL, kcred); + + if (!err) + vfsp->vfs_lofi_minor = 0; + +out: + ldi_ident_release(ldi_id); + if (li != NULL) + kmem_free(li, sizeof (*li)); +} + +/* * Common mount code. Called from the system call entry point, from autofs, * nfsv4 trigger mounts, and from pxfs. * @@ -1029,6 +1154,7 @@ refstr_t *oldresource, *oldmntpt; struct pathname pn, rpn; vsk_anchor_t *vskap; + char fstname[FSTYPSZ]; /* * The v_flag value for the mount point vp is permanently set @@ -1069,7 +1195,8 @@ } else if (uap->flags & (MS_OPTIONSTR | MS_DATA | MS_FSS)) { size_t n; uint_t fstype; - char name[FSTYPSZ]; + + fsname = fstname; if ((fstype = (uintptr_t)uap->fstype) < 256) { RLOCK_VFSSW(); @@ -1078,19 +1205,19 @@ RUNLOCK_VFSSW(); return (EINVAL); } - (void) strcpy(name, vfssw[fstype].vsw_name); + (void) strcpy(fsname, vfssw[fstype].vsw_name); RUNLOCK_VFSSW(); - if ((vswp = vfs_getvfssw(name)) == NULL) + if ((vswp = vfs_getvfssw(fsname)) == NULL) return (EINVAL); } else { /* * Handle either kernel or user address space. */ if (uap->flags & MS_SYSSPACE) { - error = copystr(uap->fstype, name, + error = copystr(uap->fstype, fsname, FSTYPSZ, &n); } else { - error = copyinstr(uap->fstype, name, + error = copyinstr(uap->fstype, fsname, FSTYPSZ, &n); } if (error) { @@ -1098,7 +1225,7 @@ return (EINVAL); return (error); } - if ((vswp = vfs_getvfssw(name)) == NULL) + if ((vswp = vfs_getvfssw(fsname)) == NULL) return (EINVAL); } } else { @@ -1354,6 +1481,26 @@ VFS_HOLD(vfsp); + if ((error = lofi_add(fsname, vfsp, &mnt_mntopts, uap)) != 0) { + if (!remount) { + if (splice) + vn_vfsunlock(vp); + vfs_free(vfsp); + } else { + vn_vfsunlock(vp); + VFS_RELE(vfsp); + } + goto errout; + } + + /* + * PRIV_SYS_MOUNT doesn't mean you can become root. + */ + if (vfsp->vfs_lofi_minor != 0) { + uap->flags |= MS_NOSUID; + vfs_setmntopt_nolock(&mnt_mntopts, MNTOPT_NOSUID, NULL, 0, 0); + } + /* * The vfs_reflock is not used anymore the code below explicitly * holds it preventing others accesing it directly. @@ -1373,6 +1520,9 @@ if (!remount) { if (error = vfs_lock(vfsp)) { vfsp->vfs_flag = ovflags; + + lofi_remove(vfsp); + if (splice) vn_vfsunlock(vp); vfs_free(vfsp); @@ -1397,8 +1547,32 @@ } if (addmip) { - bdev = bvp->v_rdev; - VN_RELE(bvp); + vnode_t *lvp = NULL; + + error = vfs_get_lofi(vfsp, &lvp); + if (error > 0) { + lofi_remove(vfsp); + + if (splice) + vn_vfsunlock(vp); + vfs_unlock(vfsp); + + if (remount) { + VFS_RELE(vfsp); + } else { + vfs_free(vfsp); + } + + goto errout; + } else if (error == -1) { + bdev = bvp->v_rdev; + VN_RELE(bvp); + } else { + bdev = lvp->v_rdev; + VN_RELE(lvp); + VN_RELE(bvp); + } + vfs_addmip(bdev, vfsp); addmip = 0; delmip = 1; @@ -1478,6 +1652,8 @@ vfs_setmntopt(vfsp, MNTOPT_GLOBAL, NULL, 0); if (error) { + lofi_remove(vfsp); + if (remount) { /* put back pre-remount options */ vfs_swapopttbl(&mnt_mntopts, &vfsp->vfs_mntopts); @@ -1648,6 +1824,7 @@ if (inargs != opts) kmem_free(inargs, MAX_MNTOPT_STR); if (copyout_error) { + lofi_remove(vfsp); VFS_RELE(vfsp); error = copyout_error; } @@ -4137,6 +4314,7 @@ ASSERT(vfsp->vfs_count != 0); if (atomic_add_32_nv(&vfsp->vfs_count, -1) == 0) { VFS_FREEVFS(vfsp); + lofi_remove(vfsp); if (vfsp->vfs_zone) zone_rele(vfsp->vfs_zone); vfs_freemnttab(vfsp); @@ -4483,3 +4661,35 @@ to->vfs_featureset[i] = from->vfs_featureset[i]; } } + +#define LOFICTL_PATH "/devices/pseudo/lofi@0:%d" + +/* + * Return the vnode for the lofi node if there's a lofi mount in place. + * Returns -1 when there's no lofi node, 0 on success, and > 0 on + * failure. + */ +int +vfs_get_lofi(vfs_t *vfsp, vnode_t **vpp) +{ + char *path = NULL; + int strsize; + int err; + + if (vfsp->vfs_lofi_minor == 0) { + *vpp = NULL; + return (-1); + } + + strsize = snprintf(NULL, 0, LOFICTL_PATH, vfsp->vfs_lofi_minor); + path = kmem_alloc(strsize + 1, KM_SLEEP); + (void) snprintf(path, strsize + 1, LOFICTL_PATH, vfsp->vfs_lofi_minor); + + err = lookupname(path, UIO_SYSSPACE, FOLLOW, NULLVPP, vpp); + + if (err) + *vpp = NULL; + + kmem_free(path, strsize + 1); + return (err); +}
--- a/usr/src/uts/common/io/lofi.c Tue May 27 17:27:03 2008 -0700 +++ b/usr/src/uts/common/io/lofi.c Tue May 27 18:25:14 2008 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -325,11 +325,14 @@ mark_closed(lsp, otyp); /* - * If we have forcibly closed the underlying device, and this is the - * last close, then tear down the rest of the device. + * If we forcibly closed the underlying device (li_force), or + * asked for cleanup (li_cleanup), finish up if we're the last + * out of the door. */ - if (minor != 0 && lsp->ls_vp == NULL && !is_opened(lsp)) + if (minor != 0 && !is_opened(lsp) && + (lsp->ls_cleanup || lsp->ls_vp == NULL)) lofi_free_handle(dev, minor, lsp, credp); + mutex_exit(&lofi_lock); return (0); } @@ -1403,21 +1406,28 @@ return (ENXIO); } + /* + * If it's still held open, we'll do one of three things: + * + * If no flag is set, just return EBUSY. + * + * If the 'cleanup' flag is set, unmap and remove the device when + * the last user finishes. + * + * If the 'force' flag is set, then we forcibly close the underlying + * file. Subsequent operations will fail, and the DKIOCSTATE ioctl + * will return DKIO_DEV_GONE. When the device is last closed, the + * device will be cleaned up appropriately. + * + * This is complicated by the fact that we may have outstanding + * dispatched I/Os. Rather than having a single mutex to serialize all + * I/O, we keep a count of the number of outstanding I/O requests, as + * well as a flag to indicate that no new I/Os should be dispatched. + * We set the flag, wait for the number of outstanding I/Os to reach 0, + * and then close the underlying vnode. + */ + if (is_opened(lsp)) { - /* - * If the 'force' flag is set, then we forcibly close the - * underlying file. Subsequent operations will fail, and the - * DKIOCSTATE ioctl will return DKIO_DEV_GONE. When the device - * is last closed, the device will be cleaned up appropriately. - * - * This is complicated by the fact that we may have outstanding - * dispatched I/Os. Rather than having a single mutex to - * serialize all I/O, we keep a count of the number of - * outstanding I/O requests, as well as a flag to indicate that - * no new I/Os should be dispatched. We set the flag, wait for - * the number of outstanding I/Os to reach 0, and then close the - * underlying vnode. - */ if (klip->li_force) { mutex_enter(&lsp->ls_vp_lock); lsp->ls_vp_closereq = B_TRUE; @@ -1434,7 +1444,13 @@ (void) copy_out_lofi_ioctl(klip, ulip, ioctl_flag); free_lofi_ioctl(klip); return (0); + } else if (klip->li_cleanup) { + lsp->ls_cleanup = 1; + mutex_exit(&lofi_lock); + free_lofi_ioctl(klip); + return (0); } + mutex_exit(&lofi_lock); free_lofi_ioctl(klip); return (EBUSY);
--- a/usr/src/uts/common/sys/lofi.h Tue May 27 17:27:03 2008 -0700 +++ b/usr/src/uts/common/sys/lofi.h Tue May 27 18:25:14 2008 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -106,6 +106,11 @@ * removed, so the DKIOCSTATE ioctl will return DKIO_DEV_GONE. When the device * is last closed, it will be torn down. * + * If the 'li_cleanup' flag is set for any of the LOFI_UNMAP_* commands, then + * if the device is busy, it is marked for removal at the next time it is + * no longer held open by anybody. When the device is last closed, it will be + * torn down. + * * Oh, and last but not least: these ioctls are totally private and only * for use by lofiadm(1M). * @@ -114,6 +119,7 @@ struct lofi_ioctl { uint32_t li_minor; boolean_t li_force; + boolean_t li_cleanup; char li_filename[MAXPATHLEN + 1]; char li_algorithm[MAXALGLEN]; }; @@ -163,6 +169,7 @@ uint32_t ls_chr_open; uint32_t ls_lyr_open_count; int ls_openflag; + boolean_t ls_cleanup; /* cleanup on close */ taskq_t *ls_taskq; kstat_t *ls_kstat; kmutex_t ls_kstat_lock;
--- a/usr/src/uts/common/sys/vfs.h Tue May 27 17:27:03 2008 -0700 +++ b/usr/src/uts/common/sys/vfs.h Tue May 27 18:25:14 2008 -0700 @@ -251,7 +251,9 @@ struct zone *vfs_zone; /* zone that owns the mount */ struct vfs *vfs_zone_next; /* next VFS visible in zone */ struct vfs *vfs_zone_prev; /* prev VFS visible in zone */ + struct fem_head *vfs_femhead; /* fs monitoring */ + minor_t vfs_lofi_minor; /* minor if lofi mount */ } vfs_t; #define vfs_featureset vfs_implp->vi_featureset @@ -535,6 +537,8 @@ int vfs_zone_change_safe(vfs_t *); +int vfs_get_lofi(vfs_t *, vnode_t **); + #define VFSHASH(maj, min) (((int)((maj)+(min))) & (vfshsz - 1)) #define VFS_ON_LIST(vfsp) \ ((vfsp)->vfs_next != (vfsp) && (vfsp)->vfs_next != NULL)