--- old/usr/src/uts/common/fs/ufs/ufs_vfsops.c Wed May 7 11:21:44 2008 +++ new/usr/src/uts/common/fs/ufs/ufs_vfsops.c Wed May 7 11:21:44 2008 @@ -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. */ @@ -37,7 +37,7 @@ */ -#pragma ident "@(#)ufs_vfsops.c 2.275 07/10/25 SMI" +#pragma ident "@(#)ufs_vfsops.c 2.276 08/05/07 SMI" #include #include @@ -266,6 +266,8 @@ 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 +310,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,19 +330,42 @@ /* * 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) { + bvp = lvp; + } else { + bvp = svp; + + if (svp->v_type != VBLK) { + VN_RELE(svp); + pn_free(&dpn); + return (ENOTBLK); + } + + 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); + if (lvp != NULL) + VN_RELE(lvp); + if (svp != NULL) + VN_RELE(svp); return (ENXIO); } if (uap->flags & MS_REMOUNT) @@ -337,34 +372,31 @@ 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. + * 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. + * + * 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 (IS_PXFSVP(bvp)) { - VN_RELE(bvp); + ASSERT(lvp == NULL); + VN_RELE(svp); + svp = NULL; 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 - * operations. - */ - if ((vfsp->vfs_flag & VFS_RDONLY) != 0 || - (uap->flags & MS_RDONLY) != 0) { - oflag = FREAD; - aflag = VREAD; + error = VOP_ACCESS(bvp, aflag, 0, cr, NULL); } else { - oflag = FREAD | FWRITE; - aflag = VREAD | VWRITE; + error = VOP_ACCESS(svp, aflag, 0, cr, NULL); } - if ((error = VOP_ACCESS(bvp, aflag, 0, cr, NULL)) != 0 || - (error = secpolicy_spec_open(cr, bvp, oflag)) != 0) { + + if (error != 0) { pn_free(&dpn); - VN_RELE(bvp); + if (lvp != NULL) + VN_RELE(lvp); + if (svp != NULL) + VN_RELE(svp); return (error); } @@ -377,13 +409,19 @@ if ((uap->flags & MS_GLOBAL) == 0 && vfs_devmounting(dev, vfsp)) { pn_free(&dpn); - VN_RELE(bvp); + if (lvp != NULL) + VN_RELE(lvp); + if (svp != NULL) + VN_RELE(svp); return (EBUSY); } if (vfs_devismounted(dev)) { if ((uap->flags & MS_REMOUNT) == 0) { pn_free(&dpn); - VN_RELE(bvp); + if (lvp != NULL) + VN_RELE(lvp); + if (svp != NULL) + VN_RELE(svp); return (EBUSY); } } @@ -404,9 +442,20 @@ */ error = mountfs(vfsp, why, bvp, dpn.pn_path, cr, 0, &args, datalen); pn_free(&dpn); + if (error) { - VN_RELE(bvp); + if (lvp != NULL) + VN_RELE(lvp); + if (svp != NULL) + VN_RELE(svp); + } else { + /* + * If lofi, drop our reference to the original file. + */ + if (lvp != NULL) + VN_RELE(svp); } + if (error == 0) vfs_set_feature(vfsp, VFSFT_XVATTR); return (error);