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/boot/zfs/zfs.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  * Copyright (c) 2007 Doug Rabson
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  *      $FreeBSD: releng/8.4/sys/boot/zfs/zfs.c 242235 2012-10-28 15:54:15Z avg $
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD: releng/8.4/sys/boot/zfs/zfs.c 242235 2012-10-28 15:54:15Z avg $");
   31 
   32 /*
   33  *      Stand-alone file reading package.
   34  */
   35 
   36 #include <sys/param.h>
   37 #include <sys/disklabel.h>
   38 #include <sys/time.h>
   39 #include <sys/queue.h>
   40 #include <stddef.h>
   41 #include <stdarg.h>
   42 #include <string.h>
   43 #include <stand.h>
   44 #include <bootstrap.h>
   45 
   46 #include "libzfs.h"
   47 
   48 #include "zfsimpl.c"
   49 
   50 static int      zfs_open(const char *path, struct open_file *f);
   51 static int      zfs_write(struct open_file *f, void *buf, size_t size, size_t *resid);
   52 static int      zfs_close(struct open_file *f);
   53 static int      zfs_read(struct open_file *f, void *buf, size_t size, size_t *resid);
   54 static off_t    zfs_seek(struct open_file *f, off_t offset, int where);
   55 static int      zfs_stat(struct open_file *f, struct stat *sb);
   56 static int      zfs_readdir(struct open_file *f, struct dirent *d);
   57 
   58 struct devsw zfs_dev;
   59 
   60 struct fs_ops zfs_fsops = {
   61         "zfs",
   62         zfs_open,
   63         zfs_close,
   64         zfs_read,
   65         zfs_write,
   66         zfs_seek,
   67         zfs_stat,
   68         zfs_readdir
   69 };
   70 
   71 /*
   72  * In-core open file.
   73  */
   74 struct file {
   75         off_t           f_seekp;        /* seek pointer */
   76         dnode_phys_t    f_dnode;
   77         uint64_t        f_zap_type;     /* zap type for readdir */
   78         uint64_t        f_num_leafs;    /* number of fzap leaf blocks */
   79         zap_leaf_phys_t *f_zap_leaf;    /* zap leaf buffer */
   80 };
   81 
   82 /*
   83  * Open a file.
   84  */
   85 static int
   86 zfs_open(const char *upath, struct open_file *f)
   87 {
   88         struct zfsmount *mount = (struct zfsmount *)f->f_devdata;
   89         struct file *fp;
   90         int rc;
   91 
   92         if (f->f_dev != &zfs_dev)
   93                 return (EINVAL);
   94 
   95         /* allocate file system specific data structure */
   96         fp = malloc(sizeof(struct file));
   97         bzero(fp, sizeof(struct file));
   98         f->f_fsdata = (void *)fp;
   99 
  100         rc = zfs_lookup(mount, upath, &fp->f_dnode);
  101         fp->f_seekp = 0;
  102         if (rc) {
  103                 f->f_fsdata = NULL;
  104                 free(fp);
  105         }
  106         return (rc);
  107 }
  108 
  109 static int
  110 zfs_close(struct open_file *f)
  111 {
  112         struct file *fp = (struct file *)f->f_fsdata;
  113 
  114         dnode_cache_obj = 0;
  115         f->f_fsdata = (void *)0;
  116         if (fp == (struct file *)0)
  117                 return (0);
  118 
  119         free(fp);
  120         return (0);
  121 }
  122 
  123 /*
  124  * Copy a portion of a file into kernel memory.
  125  * Cross block boundaries when necessary.
  126  */
  127 static int
  128 zfs_read(struct open_file *f, void *start, size_t size, size_t *resid   /* out */)
  129 {
  130         const spa_t *spa = ((struct zfsmount *)f->f_devdata)->spa;
  131         struct file *fp = (struct file *)f->f_fsdata;
  132         struct stat sb;
  133         size_t n;
  134         int rc;
  135 
  136         rc = zfs_stat(f, &sb);
  137         if (rc)
  138                 return (rc);
  139         n = size;
  140         if (fp->f_seekp + n > sb.st_size)
  141                 n = sb.st_size - fp->f_seekp;
  142         
  143         rc = dnode_read(spa, &fp->f_dnode, fp->f_seekp, start, n);
  144         if (rc)
  145                 return (rc);
  146 
  147         if (0) {
  148             int i;
  149             for (i = 0; i < n; i++)
  150                 putchar(((char*) start)[i]);
  151         }
  152         fp->f_seekp += n;
  153         if (resid)
  154                 *resid = size - n;
  155 
  156         return (0);
  157 }
  158 
  159 /*
  160  * Don't be silly - the bootstrap has no business writing anything.
  161  */
  162 static int
  163 zfs_write(struct open_file *f, void *start, size_t size, size_t *resid  /* out */)
  164 {
  165 
  166         return (EROFS);
  167 }
  168 
  169 static off_t
  170 zfs_seek(struct open_file *f, off_t offset, int where)
  171 {
  172         struct file *fp = (struct file *)f->f_fsdata;
  173 
  174         switch (where) {
  175         case SEEK_SET:
  176                 fp->f_seekp = offset;
  177                 break;
  178         case SEEK_CUR:
  179                 fp->f_seekp += offset;
  180                 break;
  181         case SEEK_END:
  182             {
  183                 struct stat sb;
  184                 int error;
  185 
  186                 error = zfs_stat(f, &sb);
  187                 if (error != 0) {
  188                         errno = error;
  189                         return (-1);
  190                 }
  191                 fp->f_seekp = sb.st_size - offset;
  192                 break;
  193             }
  194         default:
  195                 errno = EINVAL;
  196                 return (-1);
  197         }
  198         return (fp->f_seekp);
  199 }
  200 
  201 static int
  202 zfs_stat(struct open_file *f, struct stat *sb)
  203 {
  204         const spa_t *spa = ((struct zfsmount *)f->f_devdata)->spa;
  205         struct file *fp = (struct file *)f->f_fsdata;
  206 
  207         return (zfs_dnode_stat(spa, &fp->f_dnode, sb));
  208 }
  209 
  210 static int
  211 zfs_readdir(struct open_file *f, struct dirent *d)
  212 {
  213         const spa_t *spa = ((struct zfsmount *)f->f_devdata)->spa;
  214         struct file *fp = (struct file *)f->f_fsdata;
  215         mzap_ent_phys_t mze;
  216         struct stat sb;
  217         size_t bsize = fp->f_dnode.dn_datablkszsec << SPA_MINBLOCKSHIFT;
  218         int rc;
  219 
  220         rc = zfs_stat(f, &sb);
  221         if (rc)
  222                 return (rc);
  223         if (!S_ISDIR(sb.st_mode))
  224                 return (ENOTDIR);
  225 
  226         /*
  227          * If this is the first read, get the zap type.
  228          */
  229         if (fp->f_seekp == 0) {
  230                 rc = dnode_read(spa, &fp->f_dnode,
  231                                 0, &fp->f_zap_type, sizeof(fp->f_zap_type));
  232                 if (rc)
  233                         return (rc);
  234 
  235                 if (fp->f_zap_type == ZBT_MICRO) {
  236                         fp->f_seekp = offsetof(mzap_phys_t, mz_chunk);
  237                 } else {
  238                         rc = dnode_read(spa, &fp->f_dnode,
  239                                         offsetof(zap_phys_t, zap_num_leafs),
  240                                         &fp->f_num_leafs,
  241                                         sizeof(fp->f_num_leafs));
  242                         if (rc)
  243                                 return (rc);
  244 
  245                         fp->f_seekp = bsize;
  246                         fp->f_zap_leaf = (zap_leaf_phys_t *)malloc(bsize);
  247                         rc = dnode_read(spa, &fp->f_dnode,
  248                                         fp->f_seekp,
  249                                         fp->f_zap_leaf,
  250                                         bsize);
  251                         if (rc)
  252                                 return (rc);
  253                 }
  254         }
  255 
  256         if (fp->f_zap_type == ZBT_MICRO) {
  257         mzap_next:
  258                 if (fp->f_seekp >= bsize)
  259                         return (ENOENT);
  260 
  261                 rc = dnode_read(spa, &fp->f_dnode,
  262                                 fp->f_seekp, &mze, sizeof(mze));
  263                 if (rc)
  264                         return (rc);
  265                 fp->f_seekp += sizeof(mze);
  266 
  267                 if (!mze.mze_name[0])
  268                         goto mzap_next;
  269 
  270                 d->d_fileno = ZFS_DIRENT_OBJ(mze.mze_value);
  271                 d->d_type = ZFS_DIRENT_TYPE(mze.mze_value);
  272                 strcpy(d->d_name, mze.mze_name);
  273                 d->d_namlen = strlen(d->d_name);
  274                 return (0);
  275         } else {
  276                 zap_leaf_t zl;
  277                 zap_leaf_chunk_t *zc, *nc;
  278                 int chunk;
  279                 size_t namelen;
  280                 char *p;
  281                 uint64_t value;
  282 
  283                 /*
  284                  * Initialise this so we can use the ZAP size
  285                  * calculating macros.
  286                  */
  287                 zl.l_bs = ilog2(bsize);
  288                 zl.l_phys = fp->f_zap_leaf;
  289 
  290                 /*
  291                  * Figure out which chunk we are currently looking at
  292                  * and consider seeking to the next leaf. We use the
  293                  * low bits of f_seekp as a simple chunk index.
  294                  */
  295         fzap_next:
  296                 chunk = fp->f_seekp & (bsize - 1);
  297                 if (chunk == ZAP_LEAF_NUMCHUNKS(&zl)) {
  298                         fp->f_seekp = (fp->f_seekp & ~(bsize - 1)) + bsize;
  299                         chunk = 0;
  300 
  301                         /*
  302                          * Check for EOF and read the new leaf.
  303                          */
  304                         if (fp->f_seekp >= bsize * fp->f_num_leafs)
  305                                 return (ENOENT);
  306 
  307                         rc = dnode_read(spa, &fp->f_dnode,
  308                                         fp->f_seekp,
  309                                         fp->f_zap_leaf,
  310                                         bsize);
  311                         if (rc)
  312                                 return (rc);
  313                 }
  314 
  315                 zc = &ZAP_LEAF_CHUNK(&zl, chunk);
  316                 fp->f_seekp++;
  317                 if (zc->l_entry.le_type != ZAP_CHUNK_ENTRY)
  318                         goto fzap_next;
  319 
  320                 namelen = zc->l_entry.le_name_numints;
  321                 if (namelen > sizeof(d->d_name))
  322                         namelen = sizeof(d->d_name);
  323 
  324                 /*
  325                  * Paste the name back together.
  326                  */
  327                 nc = &ZAP_LEAF_CHUNK(&zl, zc->l_entry.le_name_chunk);
  328                 p = d->d_name;
  329                 while (namelen > 0) {
  330                         int len;
  331                         len = namelen;
  332                         if (len > ZAP_LEAF_ARRAY_BYTES)
  333                                 len = ZAP_LEAF_ARRAY_BYTES;
  334                         memcpy(p, nc->l_array.la_array, len);
  335                         p += len;
  336                         namelen -= len;
  337                         nc = &ZAP_LEAF_CHUNK(&zl, nc->l_array.la_next);
  338                 }
  339                 d->d_name[sizeof(d->d_name) - 1] = 0;
  340 
  341                 /*
  342                  * Assume the first eight bytes of the value are
  343                  * a uint64_t.
  344                  */
  345                 value = fzap_leaf_value(&zl, zc);
  346 
  347                 d->d_fileno = ZFS_DIRENT_OBJ(value);
  348                 d->d_type = ZFS_DIRENT_TYPE(value);
  349                 d->d_namlen = strlen(d->d_name);
  350 
  351                 return (0);
  352         }
  353 }
  354 
  355 static int
  356 vdev_read(vdev_t *vdev, void *priv, off_t offset, void *buf, size_t size)
  357 {
  358         int fd;
  359 
  360         fd = (uintptr_t) priv;
  361         lseek(fd, offset, SEEK_SET);
  362         if (read(fd, buf, size) == size) {
  363                 return 0;
  364         } else {
  365                 return (EIO);
  366         }
  367 }
  368 
  369 static int
  370 zfs_dev_init(void)
  371 {
  372         spa_t *spa;
  373         spa_t *next;
  374         spa_t *prev;
  375 
  376         zfs_init();
  377         if (archsw.arch_zfs_probe == NULL)
  378                 return (ENXIO);
  379         archsw.arch_zfs_probe();
  380 
  381         prev = NULL;
  382         spa = STAILQ_FIRST(&zfs_pools);
  383         while (spa != NULL) {
  384                 next = STAILQ_NEXT(spa, spa_link);
  385                 if (zfs_spa_init(spa)) {
  386                         if (prev == NULL)
  387                                 STAILQ_REMOVE_HEAD(&zfs_pools, spa_link);
  388                         else
  389                                 STAILQ_REMOVE_AFTER(&zfs_pools, prev, spa_link);
  390                 } else
  391                         prev = spa;
  392                 spa = next;
  393         }
  394         return (0);
  395 }
  396 
  397 int
  398 zfs_probe_dev(const char *devname, uint64_t *pool_guid)
  399 {
  400         spa_t *spa;
  401         int fd;
  402         int ret;
  403 
  404         fd = open(devname, O_RDONLY);
  405         if (fd == -1)
  406                 return (ENXIO);
  407         ret = vdev_probe(vdev_read, (void *)(uintptr_t)fd, &spa);
  408         if (ret != 0)
  409                 close(fd);
  410         else if (pool_guid != NULL)
  411                 *pool_guid = spa->spa_guid;
  412         return (0);
  413 }
  414 
  415 /*
  416  * Print information about ZFS pools
  417  */
  418 static void
  419 zfs_dev_print(int verbose)
  420 {
  421         spa_t *spa;
  422         char line[80];
  423 
  424         if (verbose) {
  425                 spa_all_status();
  426                 return;
  427         }
  428         STAILQ_FOREACH(spa, &zfs_pools, spa_link) {
  429                 sprintf(line, "    zfs:%s\n", spa->spa_name);
  430                 pager_output(line);
  431         }
  432 }
  433 
  434 /*
  435  * Attempt to open the pool described by (dev) for use by (f).
  436  */
  437 static int
  438 zfs_dev_open(struct open_file *f, ...)
  439 {
  440         va_list         args;
  441         struct zfs_devdesc      *dev;
  442         struct zfsmount *mount;
  443         spa_t           *spa;
  444         int             rv;
  445 
  446         va_start(args, f);
  447         dev = va_arg(args, struct zfs_devdesc *);
  448         va_end(args);
  449 
  450         if (dev->pool_guid == 0)
  451                 spa = STAILQ_FIRST(&zfs_pools);
  452         else
  453                 spa = spa_find_by_guid(dev->pool_guid);
  454         if (!spa)
  455                 return (ENXIO);
  456         mount = malloc(sizeof(*mount));
  457         rv = zfs_mount(spa, dev->root_guid, mount);
  458         if (rv != 0) {
  459                 free(mount);
  460                 return (rv);
  461         }
  462         if (mount->objset.os_type != DMU_OST_ZFS) {
  463                 printf("Unexpected object set type %ju\n",
  464                     (uintmax_t)mount->objset.os_type);
  465                 free(mount);
  466                 return (EIO);
  467         }
  468         f->f_devdata = mount;
  469         free(dev);
  470         return (0);
  471 }
  472 
  473 static int
  474 zfs_dev_close(struct open_file *f)
  475 {
  476 
  477         free(f->f_devdata);
  478         f->f_devdata = NULL;
  479         return (0);
  480 }
  481 
  482 static int
  483 zfs_dev_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf, size_t *rsize)
  484 {
  485 
  486         return (ENOSYS);
  487 }
  488 
  489 struct devsw zfs_dev = {
  490         .dv_name = "zfs",
  491         .dv_type = DEVT_ZFS,
  492         .dv_init = zfs_dev_init,
  493         .dv_strategy = zfs_dev_strategy,
  494         .dv_open = zfs_dev_open,
  495         .dv_close = zfs_dev_close,
  496         .dv_ioctl = noioctl,
  497         .dv_print = zfs_dev_print,
  498         .dv_cleanup = NULL
  499 };
  500 
  501 int
  502 zfs_parsedev(struct zfs_devdesc *dev, const char *devspec, const char **path)
  503 {
  504         static char     rootname[ZFS_MAXNAMELEN];
  505         static char     poolname[ZFS_MAXNAMELEN];
  506         spa_t           *spa;
  507         const char      *end;
  508         const char      *np;
  509         const char      *sep;
  510         int             rv;
  511 
  512         np = devspec;
  513         if (*np != ':')
  514                 return (EINVAL);
  515         np++;
  516         end = strchr(np, ':');
  517         if (end == NULL)
  518                 return (EINVAL);
  519         sep = strchr(np, '/');
  520         if (sep == NULL || sep >= end)
  521                 sep = end;
  522         memcpy(poolname, np, sep - np);
  523         poolname[sep - np] = '\0';
  524         if (sep < end) {
  525                 sep++;
  526                 memcpy(rootname, sep, end - sep);
  527                 rootname[end - sep] = '\0';
  528         }
  529         else
  530                 rootname[0] = '\0';
  531 
  532         spa = spa_find_by_name(poolname);
  533         if (!spa)
  534                 return (ENXIO);
  535         dev->pool_guid = spa->spa_guid;
  536         rv = zfs_lookup_dataset(spa, rootname, &dev->root_guid);
  537         if (rv != 0)
  538                 return (rv);
  539         if (path != NULL)
  540                 *path = (*end == '\0') ? end : end + 1;
  541         dev->d_dev = &zfs_dev;
  542         dev->d_type = zfs_dev.dv_type;
  543         return (0);
  544 }
  545 
  546 char *
  547 zfs_fmtdev(void *vdev)
  548 {
  549         static char             rootname[ZFS_MAXNAMELEN];
  550         static char             buf[2 * ZFS_MAXNAMELEN + 8];
  551         struct zfs_devdesc      *dev = (struct zfs_devdesc *)vdev;
  552         spa_t                   *spa;
  553 
  554         buf[0] = '\0';
  555         if (dev->d_type != DEVT_ZFS)
  556                 return (buf);
  557 
  558         if (dev->pool_guid == 0) {
  559                 spa = STAILQ_FIRST(&zfs_pools);
  560                 dev->pool_guid = spa->spa_guid;
  561         } else
  562                 spa = spa_find_by_guid(dev->pool_guid);
  563         if (spa == NULL) {
  564                 printf("ZFS: can't find pool by guid\n");
  565                 return (buf);
  566         }
  567         if (dev->root_guid == 0 && zfs_get_root(spa, &dev->root_guid)) {
  568                 printf("ZFS: can't find root filesystem\n");
  569                 return (buf);
  570         }
  571         if (zfs_rlookup(spa, dev->root_guid, rootname)) {
  572                 printf("ZFS: can't find filesystem by guid\n");
  573                 return (buf);
  574         }
  575 
  576         if (rootname[0] == '\0')
  577                 sprintf(buf, "%s:%s:", dev->d_dev->dv_name, spa->spa_name);
  578         else
  579                 sprintf(buf, "%s:%s/%s:", dev->d_dev->dv_name, spa->spa_name,
  580                     rootname);
  581         return (buf);
  582 }
  583 
  584 int
  585 zfs_list(const char *name)
  586 {
  587         static char     poolname[ZFS_MAXNAMELEN];
  588         uint64_t        objid;
  589         spa_t           *spa;
  590         const char      *dsname;
  591         int             len;
  592         int             rv;
  593 
  594         len = strlen(name);
  595         dsname = strchr(name, '/');
  596         if (dsname != NULL) {
  597                 len = dsname - name;
  598                 dsname++;
  599         } else
  600                 dsname = "";
  601         memcpy(poolname, name, len);
  602         poolname[len] = '\0';
  603 
  604         spa = spa_find_by_name(poolname);
  605         if (!spa)
  606                 return (ENXIO);
  607         rv = zfs_lookup_dataset(spa, dsname, &objid);
  608         if (rv != 0)
  609                 return (rv);
  610         rv = zfs_list_dataset(spa, objid);
  611         return (rv);
  612 }

Cache object: a4f92e68ff6ca11bd209536979579c92


[ 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.