Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libukfs Add what is essentially disklabel support. All ...



details:   https://anonhg.NetBSD.org/src/rev/c9af44aa6489
branches:  trunk
changeset: 747980:c9af44aa6489
user:      pooka <pooka%NetBSD.org@localhost>
date:      Wed Oct 07 20:51:00 2009 +0000

description:
Add what is essentially disklabel support.  All disk-based file
systems should be mounted with ukfs_mount_disk() from now on.  The
partition argument specifies which label is being mounted (or the
entire image).  E.g. partition 4 should be label 'e'.

diffstat:

 lib/libukfs/Makefile             |    5 +-
 lib/libukfs/ukfs.c               |  206 +++++++++++++++++++++++++++++---------
 lib/libukfs/ukfs.h               |   24 +++-
 lib/libukfs/ukfs_disklabel.c     |  124 +++++++++++++++++++++++
 lib/libukfs/ukfs_int_disklabel.h |  157 +++++++++++++++++++++++++++++
 5 files changed, 462 insertions(+), 54 deletions(-)

diffs (truncated from 617 to 300 lines):

diff -r f302194a3df5 -r c9af44aa6489 lib/libukfs/Makefile
--- a/lib/libukfs/Makefile      Wed Oct 07 20:42:09 2009 +0000
+++ b/lib/libukfs/Makefile      Wed Oct 07 20:51:00 2009 +0000
@@ -1,14 +1,15 @@
-#      $NetBSD: Makefile,v 1.2 2008/11/27 16:14:46 pooka Exp $
+#      $NetBSD: Makefile,v 1.3 2009/10/07 20:51:00 pooka Exp $
 #
 
 LIB=           ukfs
 LIBDPLIBS+=    rump    ${.CURDIR}/../librump           \
                rumpvfs ${.CURDIR}/../librumpvfs
+CPPFLAGS+=     -I${.CURDIR}
 
 INCS=          ukfs.h
 INCSDIR=       /usr/include/rump
 
-SRCS=          ukfs.c
+SRCS=          ukfs.c ukfs_disklabel.c
 MAN=           ukfs.3
 
 .include <bsd.lib.mk>
diff -r f302194a3df5 -r c9af44aa6489 lib/libukfs/ukfs.c
--- a/lib/libukfs/ukfs.c        Wed Oct 07 20:42:09 2009 +0000
+++ b/lib/libukfs/ukfs.c        Wed Oct 07 20:51:00 2009 +0000
@@ -1,7 +1,7 @@
-/*     $NetBSD: ukfs.c,v 1.37 2009/10/02 09:32:01 pooka Exp $  */
+/*     $NetBSD: ukfs.c,v 1.38 2009/10/07 20:51:00 pooka Exp $  */
 
 /*
- * Copyright (c) 2007, 2008  Antti Kantee.  All Rights Reserved.
+ * Copyright (c) 2007, 2008, 2009  Antti Kantee.  All Rights Reserved.
  *
  * Development of this software was supported by the
  * Finnish Cultural Foundation.
@@ -63,6 +63,8 @@
 #include <rump/rump.h>
 #include <rump/rump_syscalls.h>
 
+#include "ukfs_int_disklabel.h"
+
 #define UKFS_MODE_DEFAULT 0555
 
 struct ukfs {
@@ -187,63 +189,149 @@
        return rump_sys_mkdir(path, mode);
 }
 
-struct ukfs *
-ukfs_mount(const char *vfsname, const char *devpath, const char *mountpath,
-       int mntflags, void *arg, size_t alen)
+int
+ukfs_partition_probe(char *devpath, int *partition)
 {
-       struct stat sb;
-       struct ukfs *fs = NULL;
-       int rv = 0, devfd = -1, rdonly;
-       int mounted = 0;
-       int regged = 0;
-       int doreg = 0;
+       char *p;
+       int rv = 0;
 
        /*
-        * Try open and lock the device.  if we can't open it, assume
-        * it's a file system which doesn't use a real device and let
-        * it slide.  The mount will fail anyway if the fs requires a
-        * device.
-        *
-        * XXX: strictly speaking this is not 100% correct, as virtual
-        * file systems can use a device path which does exist and can
-        * be opened.  E.g. tmpfs should be mountable multiple times
-        * with "device" path "/swap", but now isn't.  But I think the
-        * chances are so low that it's currently acceptable to let
-        * this one slip.
+        * Check for disklabel magic in pathname:
+        * /regularpath%PART:<char>%\0
         */
-       rdonly = mntflags & MNT_RDONLY;
+#define MAGICADJ(p, n) (p+sizeof(UKFS_PARTITION_SCANMAGIC)-1+n)
+       if ((p = strstr(devpath, UKFS_PARTITION_SCANMAGIC)) != NULL
+           && strlen(p) == UKFS_PARTITION_MAGICLEN
+           && *(MAGICADJ(p,1)) == '%') {
+               if (*(MAGICADJ(p,0)) >= 'a' &&
+                   *(MAGICADJ(p,0)) < 'a' + UKFS_MAXPARTITIONS) {
+                       *partition = *(MAGICADJ(p,0)) - 'a';
+                       *p = '\0';
+               } else {
+                       rv = EINVAL;
+               }
+       } else {
+               *partition = UKFS_PARTITION_NONE;
+       }
+
+       return rv;
+}
+
+/*
+ * Open the disk file and flock it.  Also, if we are operation on
+ * an embedded partition, find the partition offset and size from
+ * the disklabel.
+ *
+ * We hard-fail only in two cases:
+ *  1) we failed to get the partition info out (don't know what offset
+ *     to mount from)
+ *  2) we failed to flock the source device (i.e. flock() fails,
+ *     not e.g. open() before it)
+ *
+ * Otherwise we let the code proceed to mount and let the file system
+ * throw the proper error.  The only questionable bit is that if we
+ * soft-fail before flock() and mount does succeed...
+ *
+ * Returns: -1 error (errno reports error code)
+ *           0 success
+ *
+ * dfdp: -1  device is not open
+ *        n  device is open
+ */
+static int
+process_diskdevice(const char *devpath, int partition, int rdonly,
+       int *dfdp, uint64_t *devoff, uint64_t *devsize)
+{
+       char buf[65536];
+       struct stat sb;
+       struct ukfs_disklabel dl;
+       struct ukfs_partition *pp;
+       int rv = 0, devfd;
+
+       /* defaults */
+       *devoff = 0;
+       *devsize = RUMP_ETFS_SIZE_ENDOFF;
+       *dfdp = -1;
+
        devfd = open(devpath, rdonly ? O_RDONLY : O_RDWR);
-       if (devfd != -1) {
-               if (fstat(devfd, &sb) == -1) {
-                       close(devfd);
-                       devfd = -1;
+       if (devfd == -1) {
+               if (UKFS_USEPARTITION(partition))
+                       rv = errno;
+               goto out;
+       }
+
+       /*
+        * Locate the disklabel and find the partition in question.
+        */
+       if (UKFS_USEPARTITION(partition)) {
+               if (pread(devfd, buf, sizeof(buf), 0) == -1) {
                        rv = errno;
                        goto out;
                }
 
-               /*
-                * We do this only for non-block device since the
-                * (NetBSD) kernel allows block device open only once.
-                */
-               if (!S_ISBLK(sb.st_mode)) {
-                       if (flock(devfd, LOCK_NB | (rdonly ? LOCK_SH:LOCK_EX))
-                           == -1) {
-                               warnx("ukfs_mount: cannot get %s lock on "
-                                   "device", rdonly ? "shared" : "exclusive");
-                               close(devfd);
-                               devfd = -1;
-                               rv = errno;
-                               goto out;
-                       }
-               } else {
+               if (ukfs_disklabel_scan(&dl, buf, sizeof(buf)) != 0) {
+                       rv = ENOENT;
+                       goto out;
+               }
+
+               if (dl.d_npartitions < partition) {
+                       rv = ENOENT;
+                       goto out;
+               }
+
+               pp = &dl.d_partitions[partition];
+               *devoff = pp->p_offset << DEV_BSHIFT;
+               *devsize = pp->p_size << DEV_BSHIFT;
+       }
+
+       if (fstat(devfd, &sb) == -1) {
+               rv = errno;
+               goto out;
+       }
+
+       /*
+        * We do this only for non-block device since the
+        * (NetBSD) kernel allows block device open only once.
+        * We also need to close the device for fairly obvious reasons.
+        */
+       if (!S_ISBLK(sb.st_mode)) {
+               if (flock(devfd, LOCK_NB | (rdonly ? LOCK_SH:LOCK_EX)) == -1) {
+                       warnx("ukfs_mount: cannot get %s lock on "
+                           "device", rdonly ? "shared" : "exclusive");
+                       rv = errno;
+                       goto out;
+               }
+       } else {
+               close(devfd);
+               devfd = -1;
+       }
+       *dfdp = devfd;
+
+ out:
+       if (rv) {
+               if (devfd != -1)
                        close(devfd);
-                       devfd = -1;
-               }
-               doreg = 1;
-       } else if (errno != ENOENT) {
-               doreg = 1;
+               errno = rv;
+               rv = -1;
        }
 
+       return rv;
+}
+
+static struct ukfs *
+doukfsmount(const char *vfsname, const char *devpath, int partition,
+       const char *mountpath, int mntflags, void *arg, size_t alen)
+{
+       struct ukfs *fs = NULL;
+       int rv = 0, devfd;
+       uint64_t devoff, devsize;
+       int mounted = 0;
+       int regged = 0;
+
+       if (partition != UKFS_PARTITION_NA)
+               process_diskdevice(devpath, partition, mntflags & MNT_RDONLY,
+                   &devfd, &devoff, &devsize);
+
        fs = malloc(sizeof(struct ukfs));
        if (fs == NULL) {
                rv = ENOMEM;
@@ -259,13 +347,15 @@
                }
        }
 
-       if (doreg) {
-               rv = rump_etfs_register(devpath, devpath, RUMP_ETFS_BLK);
+       if (partition != UKFS_PARTITION_NA) {
+               rv = rump_etfs_register_withsize(devpath, devpath,
+                   RUMP_ETFS_BLK, devoff, devsize);
                if (rv) {
                        goto out;
                }
                regged = 1;
        }
+
        rv = rump_sys_mount(vfsname, mountpath, mntflags, arg, alen);
        if (rv) {
                rv = errno;
@@ -312,6 +402,24 @@
        return fs;
 }
 
+struct ukfs *
+ukfs_mount(const char *vfsname, const char *devpath,
+       const char *mountpath, int mntflags, void *arg, size_t alen)
+{
+
+       return doukfsmount(vfsname, devpath, UKFS_PARTITION_NA,
+           mountpath, mntflags, arg, alen);
+}
+
+struct ukfs *
+ukfs_mount_disk(const char *vfsname, const char *devpath, int partition,
+       const char *mountpath, int mntflags, void *arg, size_t alen)
+{
+
+       return doukfsmount(vfsname, devpath, partition,
+           mountpath, mntflags, arg, alen);
+}
+
 int
 ukfs_release(struct ukfs *fs, int flags)
 {
diff -r f302194a3df5 -r c9af44aa6489 lib/libukfs/ukfs.h
--- a/lib/libukfs/ukfs.h        Wed Oct 07 20:42:09 2009 +0000
+++ b/lib/libukfs/ukfs.h        Wed Oct 07 20:51:00 2009 +0000
@@ -1,7 +1,7 @@
-/*     $NetBSD: ukfs.h,v 1.10 2009/10/02 09:32:01 pooka Exp $  */
+/*     $NetBSD: ukfs.h,v 1.11 2009/10/07 20:51:00 pooka Exp $  */
 
 /*
- * Copyright (c) 2007, 2008  Antti Kantee.  All Rights Reserved.
+ * Copyright (c) 2007, 2008, 2009  Antti Kantee.  All Rights Reserved.
  *
  * Development of this software was supported by the
  * Finnish Cultural Foundation.
@@ -55,7 +55,9 @@
 
 int            _ukfs_init(int);
 struct ukfs    *ukfs_mount(const char *, const char *, const char *,
-                         int, void *, size_t);
+                           int, void *, size_t);



Home | Main Index | Thread Index | Old Index