Print this page
PSARC 2008/290 lofi mount
6384817 Need persistent lofi based mounts and direct mount(1m) support for lofi
@@ -17,11 +17,11 @@
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* 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.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
@@ -35,11 +35,11 @@
* software developed by the University of California, Berkeley, and its
* contributors.
*/
-#pragma ident "@(#)ufs_vfsops.c 2.275 07/10/25 SMI"
+#pragma ident "@(#)ufs_vfsops.c 2.276 08/05/07 SMI"
#include <sys/types.h>
#include <sys/t_lock.h>
#include <sys/param.h>
#include <sys/systm.h>
@@ -264,10 +264,12 @@
{
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;
struct ufs_args args;
int oflag, aflag;
@@ -306,10 +308,20 @@
return (EFAULT);
datalen = sizeof (struct ufs_args);
} 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).
*/
if (error = pn_get(uap->dir, fromspace, &dpn))
@@ -316,57 +328,77 @@
return (error);
/*
* 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 (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)
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);
}
/*
* Ensure that this device isn't already mounted or in progress on a
@@ -375,17 +407,23 @@
*/
if ((uap->flags & MS_NOCHECK) == 0) {
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);
}
}
}
@@ -402,13 +440,24 @@
/*
* Mount the filesystem, free the device vnode on error.
*/
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);
}
/*