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


   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #pragma ident   "@(#)pc_vfsops.c        1.104   07/10/25 SMI"
  27 
  28 #include <sys/param.h>
  29 #include <sys/systm.h>
  30 #include <sys/kmem.h>
  31 #include <sys/user.h>
  32 #include <sys/proc.h>
  33 #include <sys/cred.h>
  34 #include <sys/disp.h>
  35 #include <sys/buf.h>
  36 #include <sys/vfs.h>
  37 #include <sys/vfs_opreg.h>
  38 #include <sys/vnode.h>
  39 #include <sys/fdio.h>
  40 #include <sys/file.h>
  41 #include <sys/uio.h>
  42 #include <sys/conf.h>
  43 #include <sys/statvfs.h>
  44 #include <sys/mount.h>
  45 #include <sys/pathname.h>
  46 #include <sys/cmn_err.h>


 276 
 277 extern struct pcfs_args pc_tz;
 278 
 279 /*
 280  *  Define some special logical drives we use internal to this file.
 281  */
 282 #define BOOT_PARTITION_DRIVE    99
 283 #define PRIMARY_DOS_DRIVE       1
 284 #define UNPARTITIONED_DRIVE     0
 285 
 286 static int
 287 pcfs_device_identify(
 288         struct vfs *vfsp,
 289         struct mounta *uap,
 290         struct cred *cr,
 291         int *dos_ldrive,
 292         dev_t *xdev)
 293 {
 294         struct pathname special;
 295         char *c;
 296         struct vnode *bvp;

 297         int oflag, aflag;
 298         int error;
 299 
 300         /*
 301          * Resolve path name of special file being mounted.
 302          */
 303         if (error = pn_get(uap->spec, UIO_USERSPACE, &special)) {
 304                 return (error);
 305         }
 306 
 307         *dos_ldrive = -1;
 308 
 309         if (error =
 310             lookupname(special.pn_path, UIO_SYSSPACE, FOLLOW, NULLVPP, &bvp)) {
 311                 /*
 312                  * If there's no device node, the name specified most likely
 313                  * maps to a PCFS-style "partition specifier" to select a
 314                  * harddisk primary/logical partition. Disable floppy-specific
 315                  * checks in such cases unless an explicit :A or :B is
 316                  * requested.
 317                  */
 318 
 319                 /*
 320                  * Split the pathname string at the last ':' separator.
 321                  * If there's no ':' in the device name, or the ':' is the
 322                  * last character in the string, the name is invalid and
 323                  * the error from the previous lookup will be returned.
 324                  */
 325                 c = strrchr(special.pn_path, ':');
 326                 if (c == NULL || strlen(c) == 0)
 327                         goto devlookup_done;
 328 
 329                 *c++ = '\0';
 330 


 367                          *        PCMCIA pseudofloppy (sram card).
 368                          */
 369                         *c = tolower(*c);
 370                         if (*c == 'a' || *c == 'b') {
 371                                 *dos_ldrive = UNPARTITIONED_DRIVE;
 372                         } else if (*c < 'c' || *c > 'z') {
 373                                 error = ENXIO;
 374                                 goto devlookup_done;
 375                         } else {
 376                                 *dos_ldrive = 1 + *c - 'c';
 377                         }
 378                 } else {
 379                         /*
 380                          * Can't parse this - pass through previous error.
 381                          */
 382                         goto devlookup_done;
 383                 }
 384 
 385 
 386                 error = lookupname(special.pn_path, UIO_SYSSPACE, FOLLOW,
 387                     NULLVPP, &bvp);
 388         } else {
 389                 *dos_ldrive = UNPARTITIONED_DRIVE;
 390         }
 391 devlookup_done:
 392         pn_free(&special);
 393         if (error)
 394                 return (error);
 395 
 396         ASSERT(*dos_ldrive >= UNPARTITIONED_DRIVE);
 397 
 398         *xdev = bvp->v_rdev;
 399 
 400         /*
 401          * Verify caller's permission to open the device special file.
 402          */
 403         if ((vfsp->vfs_flag & VFS_RDONLY) != 0 ||
 404             ((uap->flags & MS_RDONLY) != 0)) {
 405                 oflag = FREAD;
 406                 aflag = VREAD;
 407         } else {
 408                 oflag = FREAD | FWRITE;
 409                 aflag = VREAD | VWRITE;
 410         }
 411 
 412         if (bvp->v_type != VBLK)











 413                 error = ENOTBLK;
 414         else if (getmajor(*xdev) >= devcnt)
 415                 error = ENXIO;
 416 
 417         if ((error != 0) ||
 418             (error = VOP_ACCESS(bvp, aflag, 0, cr, NULL)) != 0 ||
 419             (error = secpolicy_spec_open(cr, bvp, oflag)) != 0) {
 420                 VN_RELE(bvp);
 421                 return (error);
 422         }
 423 
 424         VN_RELE(bvp);
 425         return (0);












 426 }
 427 
 428 static int
 429 pcfs_device_ismounted(
 430         struct vfs *vfsp,
 431         int dos_ldrive,
 432         dev_t xdev,
 433         int *remounting,
 434         dev_t *pseudodev)
 435 {
 436         struct pcfs *fsp;
 437         int remount = *remounting;
 438 
 439         /*
 440          * Ensure that this logical drive isn't already mounted, unless
 441          * this is a REMOUNT request.
 442          * Note: The framework will perform this check if the "...:c"
 443          * PCFS-style "logical drive" syntax has not been used and an
 444          * actually existing physical device is backing this filesystem.
 445          * Once all block device drivers support PC-style partitioning,




   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #pragma ident   "@(#)pc_vfsops.c        1.105   08/05/07 SMI"
  27 
  28 #include <sys/param.h>
  29 #include <sys/systm.h>
  30 #include <sys/kmem.h>
  31 #include <sys/user.h>
  32 #include <sys/proc.h>
  33 #include <sys/cred.h>
  34 #include <sys/disp.h>
  35 #include <sys/buf.h>
  36 #include <sys/vfs.h>
  37 #include <sys/vfs_opreg.h>
  38 #include <sys/vnode.h>
  39 #include <sys/fdio.h>
  40 #include <sys/file.h>
  41 #include <sys/uio.h>
  42 #include <sys/conf.h>
  43 #include <sys/statvfs.h>
  44 #include <sys/mount.h>
  45 #include <sys/pathname.h>
  46 #include <sys/cmn_err.h>


 276 
 277 extern struct pcfs_args pc_tz;
 278 
 279 /*
 280  *  Define some special logical drives we use internal to this file.
 281  */
 282 #define BOOT_PARTITION_DRIVE    99
 283 #define PRIMARY_DOS_DRIVE       1
 284 #define UNPARTITIONED_DRIVE     0
 285 
 286 static int
 287 pcfs_device_identify(
 288         struct vfs *vfsp,
 289         struct mounta *uap,
 290         struct cred *cr,
 291         int *dos_ldrive,
 292         dev_t *xdev)
 293 {
 294         struct pathname special;
 295         char *c;
 296         struct vnode *svp = NULL;
 297         struct vnode *lvp = NULL;
 298         int oflag, aflag;
 299         int error;
 300 
 301         /*
 302          * Resolve path name of special file being mounted.
 303          */
 304         if (error = pn_get(uap->spec, UIO_USERSPACE, &special)) {
 305                 return (error);
 306         }
 307 
 308         *dos_ldrive = -1;
 309 
 310         if (error =
 311             lookupname(special.pn_path, UIO_SYSSPACE, FOLLOW, NULLVPP, &svp)) {
 312                 /*
 313                  * If there's no device node, the name specified most likely
 314                  * maps to a PCFS-style "partition specifier" to select a
 315                  * harddisk primary/logical partition. Disable floppy-specific
 316                  * checks in such cases unless an explicit :A or :B is
 317                  * requested.
 318                  */
 319 
 320                 /*
 321                  * Split the pathname string at the last ':' separator.
 322                  * If there's no ':' in the device name, or the ':' is the
 323                  * last character in the string, the name is invalid and
 324                  * the error from the previous lookup will be returned.
 325                  */
 326                 c = strrchr(special.pn_path, ':');
 327                 if (c == NULL || strlen(c) == 0)
 328                         goto devlookup_done;
 329 
 330                 *c++ = '\0';
 331 


 368                          *        PCMCIA pseudofloppy (sram card).
 369                          */
 370                         *c = tolower(*c);
 371                         if (*c == 'a' || *c == 'b') {
 372                                 *dos_ldrive = UNPARTITIONED_DRIVE;
 373                         } else if (*c < 'c' || *c > 'z') {
 374                                 error = ENXIO;
 375                                 goto devlookup_done;
 376                         } else {
 377                                 *dos_ldrive = 1 + *c - 'c';
 378                         }
 379                 } else {
 380                         /*
 381                          * Can't parse this - pass through previous error.
 382                          */
 383                         goto devlookup_done;
 384                 }
 385 
 386 
 387                 error = lookupname(special.pn_path, UIO_SYSSPACE, FOLLOW,
 388                     NULLVPP, &svp);
 389         } else {
 390                 *dos_ldrive = UNPARTITIONED_DRIVE;
 391         }
 392 devlookup_done:
 393         pn_free(&special);
 394         if (error)
 395                 return (error);
 396 
 397         ASSERT(*dos_ldrive >= UNPARTITIONED_DRIVE);
 398 


 399         /*
 400          * Verify caller's permission to open the device special file.
 401          */
 402         if ((vfsp->vfs_flag & VFS_RDONLY) != 0 ||
 403             ((uap->flags & MS_RDONLY) != 0)) {
 404                 oflag = FREAD;
 405                 aflag = VREAD;
 406         } else {
 407                 oflag = FREAD | FWRITE;
 408                 aflag = VREAD | VWRITE;
 409         }
 410 
 411         error = vfs_get_lofi(vfsp, &lvp);
 412 
 413         if (error > 0) {
 414                 if (error == ENOENT)
 415                         error = ENODEV;
 416                 goto out;
 417         } else if (error == 0) {
 418                 *xdev = lvp->v_rdev;
 419         } else {
 420                 *xdev = svp->v_rdev;
 421 
 422                 if (svp->v_type != VBLK)
 423                         error = ENOTBLK;


 424 
 425                 if ((error = secpolicy_spec_open(cr, svp, oflag)) != 0)
 426                         goto out;



 427         }
 428 
 429         if (getmajor(*xdev) >= devcnt) {
 430                 error = ENXIO;
 431                 goto out;
 432         }
 433 
 434         if ((error = VOP_ACCESS(svp, aflag, 0, cr, NULL)) != 0)
 435                 goto out;
 436 
 437 out:
 438         if (svp != NULL)
 439                 VN_RELE(svp);
 440         if (lvp != NULL)
 441                 VN_RELE(lvp);
 442         return (error);
 443 }
 444 
 445 static int
 446 pcfs_device_ismounted(
 447         struct vfs *vfsp,
 448         int dos_ldrive,
 449         dev_t xdev,
 450         int *remounting,
 451         dev_t *pseudodev)
 452 {
 453         struct pcfs *fsp;
 454         int remount = *remounting;
 455 
 456         /*
 457          * Ensure that this logical drive isn't already mounted, unless
 458          * this is a REMOUNT request.
 459          * Note: The framework will perform this check if the "...:c"
 460          * PCFS-style "logical drive" syntax has not been used and an
 461          * actually existing physical device is backing this filesystem.
 462          * Once all block device drivers support PC-style partitioning,