Print this page
PSARC 2008/290 lofi mount
6384817 Need persistent lofi based mounts and direct mount(1m) support for lofi

@@ -17,15 +17,15 @@
  * 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.
  */
 
-#pragma ident   "@(#)udf_vfsops.c       1.48    07/10/25 SMI"
+#pragma ident   "@(#)udf_vfsops.c       1.49    08/05/07 SMI"
 
 #include <sys/types.h>
 #include <sys/t_lock.h>
 #include <sys/param.h>
 #include <sys/time.h>

@@ -181,11 +181,12 @@
 static int32_t
 udf_mount(struct vfs *vfsp, struct vnode *mvp,
         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;
         int oflag, aflag;
 

@@ -211,22 +212,34 @@
         if (error = pn_get(uap->dir, UIO_USERSPACE, &dpn)) {
                 return (error);
         }
 
         /*
-         * 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 = 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,
          * unless this is a REMOUNT request
          */

@@ -280,23 +293,28 @@
                 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) {
+
+        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);
+        if (svp != NULL)
+                VN_RELE(svp);
+        if (lvp != NULL)
+                VN_RELE(lvp);
         pn_free(&dpn);
-
         return (error);
 }
 
 
 

@@ -440,13 +458,11 @@
 
         /*
          * 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);
         sp->f_flag = vf_to_stf(vfsp->vfs_flag);
         sp->f_namemax = MAXNAMLEN;

@@ -980,12 +996,12 @@
          * Verify it and get the location of
          * Main Volume Descriptor Sequence
          */
         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);
         }
         avdp = (struct anch_vol_desc_ptr *)secbp->b_un.b_addr;
         if (ud_verify_tag_and_desc(&avdp->avd_tag, UD_ANCH_VOL_DESC,

@@ -1009,12 +1025,12 @@
         vds_loc = udf_vfsp->udf_mvds_loc;
         secbp = ud_bread(dev, vds_loc << shift,
                         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);
                 if ((error = geterror(secbp)) != 0) {

@@ -1109,12 +1125,16 @@
                         struct ud_part *pnew, *pold, *part;
 
                         pdesc = (struct part_desc *)ttag;
                         pold = udf_vfsp->udf_parts;
                         for (i = 0; i < udf_vfsp->udf_npart; i++) {
-                                if (pold->udp_number ==
+                                if (pold->udp_number !=
                                         SWAP_16(pdesc->pd_pnum)) {
+                                        pold++;
+                                        continue;
+                                }
+
                                         if (SWAP_32(pdesc->pd_vdsn) >
                                                 pold->udp_seqno) {
                                                 pold->udp_seqno =
                                                         SWAP_32(pdesc->pd_vdsn);
                                                 pold->udp_access =

@@ -1124,12 +1144,10 @@
                                                 pold->udp_length =
                                                 SWAP_32(pdesc->pd_part_length);
                                         }
                                         goto loop_end;
                                 }
-                                pold ++;
-                        }
                         pold = udf_vfsp->udf_parts;
                         udf_vfsp->udf_npart++;
                         pnew = kmem_zalloc(udf_vfsp->udf_npart *
                                         sizeof (struct ud_part), KM_SLEEP);
                         udf_vfsp->udf_parts = pnew;

@@ -1262,17 +1280,17 @@
                         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);
+                            (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;
                         map->udm_vsn = SWAP_16(typ1->map1_vsn);
                         map->udm_pn = SWAP_16(typ1->map1_pn);

@@ -1289,12 +1307,11 @@
                                  * we donot
                                  */
                                 map = udf_vfsp->udf_maps;
                                 udf_vfsp->udf_maps =
                                         kmem_zalloc(sizeof (struct ud_map) *
-                                                (udf_vfsp->udf_nmaps + 1),
-                                                KM_SLEEP);
+                                    (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,