The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/geom/label/g_label_ufs.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2002, 2003 Gordon Tetlow
    5  * Copyright (c) 2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD$");
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/disklabel.h>
   36 #include <sys/malloc.h>
   37 #include <sys/vnode.h>
   38 
   39 #include <ufs/ufs/dinode.h>
   40 #include <ufs/ffs/fs.h>
   41 #include <ufs/ufs/quota.h>
   42 #include <ufs/ufs/extattr.h>
   43 #include <ufs/ffs/ffs_extern.h>
   44 
   45 #include <geom/geom.h>
   46 #include <geom/geom_dbg.h>
   47 #include <geom/label/g_label.h>
   48 
   49 #define G_LABEL_UFS_VOLUME      0
   50 #define G_LABEL_UFS_ID          1
   51 
   52 /*
   53  * G_LABEL_UFS_CMP returns true if difference between provider mediasize
   54  * and filesystem size is less than G_LABEL_UFS_MAXDIFF sectors
   55  */
   56 #define G_LABEL_UFS_CMP(prov, fsys, size)                                  \
   57         ( abs( ((fsys)->size) - ( (prov)->mediasize / (fsys)->fs_fsize ))  \
   58                                 < G_LABEL_UFS_MAXDIFF )
   59 #define G_LABEL_UFS_MAXDIFF     0x100
   60 
   61 /*
   62  * For providers that look like disklabels we need to check if the file system
   63  * size is almost equal to the provider's size, because sysinstall(8) used to
   64  * bogusly put the first partition at offset 0 instead of 16, and glabel/ufs
   65  * would find a file system on the slice instead of the partition.
   66  *
   67  * In addition, media size can be a bit bigger than file system size. For
   68  * instance, mkuzip can append bytes to align data to large sector size (it
   69  * improves compression rates).
   70  */
   71 static bool
   72 g_label_ufs_ignore_bsdlabel_slice(struct g_consumer *cp,
   73     struct fs *fs)
   74 {
   75         struct g_provider *pp;
   76         u_char *buf;
   77         uint32_t magic1, magic2;
   78         int error;
   79 
   80         pp = cp->provider;
   81 
   82         /*
   83          * If the expected provider size for the filesystem matches the
   84          * real provider size then don't ignore this filesystem.
   85          */
   86         if (G_LABEL_UFS_CMP(pp, fs, fs_providersize))
   87                 return (false);
   88 
   89         /*
   90          * If the filesystem size matches the real provider size then
   91          * don't ignore this filesystem.
   92          */
   93         if (fs->fs_magic == FS_UFS1_MAGIC ?
   94             G_LABEL_UFS_CMP(pp, fs, fs_old_size) :
   95             G_LABEL_UFS_CMP(pp, fs, fs_size))
   96                 return (false);
   97 
   98         /*
   99          * Provider is bigger than expected; probe to see if there's a
  100          * disklabel. Adapted from g_part_bsd_probe.
  101          */
  102 
  103         /* Check if the superblock overlaps where the disklabel lives. */
  104         if (fs->fs_sblockloc < pp->sectorsize * 2)
  105                 return (false);
  106 
  107         /* Sanity-check the provider. */
  108         if (pp->sectorsize < sizeof(struct disklabel) ||
  109             pp->mediasize < BBSIZE)
  110                 return (false);
  111         if (BBSIZE % pp->sectorsize)
  112                 return (false);
  113 
  114         /* Check that there's a disklabel. */
  115         buf = g_read_data(cp, pp->sectorsize, pp->sectorsize, &error);
  116         if (buf == NULL)
  117                 return (false);
  118         magic1 = le32dec(buf + 0);
  119         magic2 = le32dec(buf + 132);
  120         g_free(buf);
  121         if (magic1 == DISKMAGIC && magic2 == DISKMAGIC)
  122                 return (true);
  123 
  124         return (false);
  125 }
  126 
  127 /*
  128  * Try to find a superblock on the provider. If successful, look for a volume
  129  * label and create an appropriate provider based on that.
  130  */
  131 static void
  132 g_label_ufs_taste_common(struct g_consumer *cp, char *label, size_t size, int what)
  133 {
  134         struct g_provider *pp;
  135         struct fs *fs;
  136 
  137         g_topology_assert_not();
  138         pp = cp->provider;
  139         label[0] = '\0';
  140 
  141         fs = NULL;
  142         KASSERT(pp->sectorsize != 0, ("Tasting a disk with 0 sectorsize"));
  143         if (SBLOCKSIZE % pp->sectorsize != 0 || ffs_sbget(cp, &fs, UFS_STDSB,
  144             UFS_NOHASHFAIL | UFS_NOCSUM | UFS_NOMSG, M_GEOM, g_use_g_read_data)
  145             != 0) {
  146                 KASSERT(fs == NULL,
  147                     ("g_label_ufs_taste_common: non-NULL fs %p\n", fs));
  148                 return;
  149         }
  150 
  151         /* Check for magic. */
  152         if (fs->fs_magic == FS_UFS1_MAGIC && fs->fs_fsize > 0) {
  153                 /* Valid UFS1. */
  154         } else if (fs->fs_magic == FS_UFS2_MAGIC && fs->fs_fsize > 0) {
  155                 /* Valid UFS2. */
  156         } else {
  157                 goto out;
  158         }
  159         /* Check if this should be ignored for compatibility. */
  160         if (g_label_ufs_ignore_bsdlabel_slice(cp, fs))
  161                 goto out;
  162         G_LABEL_DEBUG(1, "%s file system detected on %s.",
  163             fs->fs_magic == FS_UFS1_MAGIC ? "UFS1" : "UFS2", pp->name);
  164         switch (what) {
  165         case G_LABEL_UFS_VOLUME:
  166                 /* Check for volume label */
  167                 if (fs->fs_volname[0] != '\0')
  168                         strlcpy(label, fs->fs_volname, size);
  169                 break;
  170         case G_LABEL_UFS_ID:
  171                 if (fs->fs_id[0] != 0 || fs->fs_id[1] != 0)
  172                         snprintf(label, size, "%08x%08x", fs->fs_id[0],
  173                             fs->fs_id[1]);
  174                 break;
  175         }
  176 out:
  177         g_free(fs);
  178 }
  179 
  180 static void
  181 g_label_ufs_volume_taste(struct g_consumer *cp, char *label, size_t size)
  182 {
  183 
  184         g_label_ufs_taste_common(cp, label, size, G_LABEL_UFS_VOLUME);
  185 }
  186 
  187 static void
  188 g_label_ufs_id_taste(struct g_consumer *cp, char *label, size_t size)
  189 {
  190 
  191         g_label_ufs_taste_common(cp, label, size, G_LABEL_UFS_ID);
  192 }
  193 
  194 struct g_label_desc g_label_ufs_volume = {
  195         .ld_taste = g_label_ufs_volume_taste,
  196         .ld_dirprefix = "ufs/",
  197         .ld_enabled = 1
  198 };
  199 
  200 struct g_label_desc g_label_ufs_id = {
  201         .ld_taste = g_label_ufs_id_taste,
  202         .ld_dirprefix = "ufsid/",
  203         .ld_enabled = 1
  204 };
  205 
  206 G_LABEL_INIT(ufsid, g_label_ufs_id, "Create device nodes for UFS file system IDs");
  207 G_LABEL_INIT(ufs, g_label_ufs_volume, "Create device nodes for UFS volume names");
  208 
  209 MODULE_DEPEND(g_label, ufs, 1, 1, 1);

Cache object: 0e0a73c3a10995ad970f5b752d8f019e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.