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/9.0/sys/boot/zfs/zfs.c 219089 2011-02-27 19:41:40Z pjd $
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD: releng/9.0/sys/boot/zfs/zfs.c 219089 2011-02-27 19:41:40Z pjd $");
   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 "zfsimpl.c"
   47 
   48 #define MAXBDDEV        31
   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         spa_t *spa = (spa_t *) f->f_devdata;
   89         struct file *fp;
   90         int rc;
   91 
   92         if (f->f_dev != &zfs_dev)
   93                 return (EINVAL);
   94 
   95         rc = zfs_mount_pool(spa);
   96         if (rc)
   97                 return (rc);
   98 
   99         /* allocate file system specific data structure */
  100         fp = malloc(sizeof(struct file));
  101         bzero(fp, sizeof(struct file));
  102         f->f_fsdata = (void *)fp;
  103 
  104         if (spa->spa_root_objset.os_type != DMU_OST_ZFS) {
  105                 printf("Unexpected object set type %llu\n",
  106                     spa->spa_root_objset.os_type);
  107                 rc = EIO;
  108                 goto out;
  109         }
  110 
  111         rc = zfs_lookup(spa, upath, &fp->f_dnode);
  112         if (rc)
  113                 goto out;
  114 
  115         fp->f_seekp = 0;
  116 out:
  117         if (rc) {
  118                 f->f_fsdata = NULL;
  119                 free(fp);
  120         }
  121         return (rc);
  122 }
  123 
  124 static int
  125 zfs_close(struct open_file *f)
  126 {
  127         struct file *fp = (struct file *)f->f_fsdata;
  128 
  129         dnode_cache_obj = 0;
  130         f->f_fsdata = (void *)0;
  131         if (fp == (struct file *)0)
  132                 return (0);
  133 
  134         free(fp);
  135         return (0);
  136 }
  137 
  138 /*
  139  * Copy a portion of a file into kernel memory.
  140  * Cross block boundaries when necessary.
  141  */
  142 static int
  143 zfs_read(struct open_file *f, void *start, size_t size, size_t *resid   /* out */)
  144 {
  145         spa_t *spa = (spa_t *) f->f_devdata;
  146         struct file *fp = (struct file *)f->f_fsdata;
  147         struct stat sb;
  148         size_t n;
  149         int rc;
  150 
  151         rc = zfs_stat(f, &sb);
  152         if (rc)
  153                 return (rc);
  154         n = size;
  155         if (fp->f_seekp + n > sb.st_size)
  156                 n = sb.st_size - fp->f_seekp;
  157         
  158         rc = dnode_read(spa, &fp->f_dnode, fp->f_seekp, start, n);
  159         if (rc)
  160                 return (rc);
  161 
  162         if (0) {
  163             int i;
  164             for (i = 0; i < n; i++)
  165                 putchar(((char*) start)[i]);
  166         }
  167         fp->f_seekp += n;
  168         if (resid)
  169                 *resid = size - n;
  170 
  171         return (0);
  172 }
  173 
  174 /*
  175  * Don't be silly - the bootstrap has no business writing anything.
  176  */
  177 static int
  178 zfs_write(struct open_file *f, void *start, size_t size, size_t *resid  /* out */)
  179 {
  180 
  181         return (EROFS);
  182 }
  183 
  184 static off_t
  185 zfs_seek(struct open_file *f, off_t offset, int where)
  186 {
  187         struct file *fp = (struct file *)f->f_fsdata;
  188 
  189         switch (where) {
  190         case SEEK_SET:
  191                 fp->f_seekp = offset;
  192                 break;
  193         case SEEK_CUR:
  194                 fp->f_seekp += offset;
  195                 break;
  196         case SEEK_END:
  197             {
  198                 struct stat sb;
  199                 int error;
  200 
  201                 error = zfs_stat(f, &sb);
  202                 if (error != 0) {
  203                         errno = error;
  204                         return (-1);
  205                 }
  206                 fp->f_seekp = sb.st_size - offset;
  207                 break;
  208             }
  209         default:
  210                 errno = EINVAL;
  211                 return (-1);
  212         }
  213         return (fp->f_seekp);
  214 }
  215 
  216 static int
  217 zfs_stat(struct open_file *f, struct stat *sb)
  218 {
  219         spa_t *spa = (spa_t *) f->f_devdata;
  220         struct file *fp = (struct file *)f->f_fsdata;
  221 
  222         return (zfs_dnode_stat(spa, &fp->f_dnode, sb));
  223 }
  224 
  225 static int
  226 zfs_readdir(struct open_file *f, struct dirent *d)
  227 {
  228         spa_t *spa = (spa_t *) f->f_devdata;
  229         struct file *fp = (struct file *)f->f_fsdata;
  230         mzap_ent_phys_t mze;
  231         struct stat sb;
  232         size_t bsize = fp->f_dnode.dn_datablkszsec << SPA_MINBLOCKSHIFT;
  233         int rc;
  234 
  235         rc = zfs_stat(f, &sb);
  236         if (rc)
  237                 return (rc);
  238         if (!S_ISDIR(sb.st_mode))
  239                 return (ENOTDIR);
  240 
  241         /*
  242          * If this is the first read, get the zap type.
  243          */
  244         if (fp->f_seekp == 0) {
  245                 rc = dnode_read(spa, &fp->f_dnode,
  246                                 0, &fp->f_zap_type, sizeof(fp->f_zap_type));
  247                 if (rc)
  248                         return (rc);
  249 
  250                 if (fp->f_zap_type == ZBT_MICRO) {
  251                         fp->f_seekp = offsetof(mzap_phys_t, mz_chunk);
  252                 } else {
  253                         rc = dnode_read(spa, &fp->f_dnode,
  254                                         offsetof(zap_phys_t, zap_num_leafs),
  255                                         &fp->f_num_leafs,
  256                                         sizeof(fp->f_num_leafs));
  257                         if (rc)
  258                                 return (rc);
  259 
  260                         fp->f_seekp = bsize;
  261                         fp->f_zap_leaf = (zap_leaf_phys_t *)malloc(bsize);
  262                         rc = dnode_read(spa, &fp->f_dnode,
  263                                         fp->f_seekp,
  264                                         fp->f_zap_leaf,
  265                                         bsize);
  266                         if (rc)
  267                                 return (rc);
  268                 }
  269         }
  270 
  271         if (fp->f_zap_type == ZBT_MICRO) {
  272         mzap_next:
  273                 if (fp->f_seekp >= bsize)
  274                         return (ENOENT);
  275 
  276                 rc = dnode_read(spa, &fp->f_dnode,
  277                                 fp->f_seekp, &mze, sizeof(mze));
  278                 if (rc)
  279                         return (rc);
  280                 fp->f_seekp += sizeof(mze);
  281 
  282                 if (!mze.mze_name[0])
  283                         goto mzap_next;
  284 
  285                 d->d_fileno = ZFS_DIRENT_OBJ(mze.mze_value);
  286                 d->d_type = ZFS_DIRENT_TYPE(mze.mze_value);
  287                 strcpy(d->d_name, mze.mze_name);
  288                 d->d_namlen = strlen(d->d_name);
  289                 return (0);
  290         } else {
  291                 zap_leaf_t zl;
  292                 zap_leaf_chunk_t *zc, *nc;
  293                 int chunk;
  294                 size_t namelen;
  295                 char *p;
  296                 uint64_t value;
  297 
  298                 /*
  299                  * Initialise this so we can use the ZAP size
  300                  * calculating macros.
  301                  */
  302                 zl.l_bs = ilog2(bsize);
  303                 zl.l_phys = fp->f_zap_leaf;
  304 
  305                 /*
  306                  * Figure out which chunk we are currently looking at
  307                  * and consider seeking to the next leaf. We use the
  308                  * low bits of f_seekp as a simple chunk index.
  309                  */
  310         fzap_next:
  311                 chunk = fp->f_seekp & (bsize - 1);
  312                 if (chunk == ZAP_LEAF_NUMCHUNKS(&zl)) {
  313                         fp->f_seekp = (fp->f_seekp & ~(bsize - 1)) + bsize;
  314                         chunk = 0;
  315 
  316                         /*
  317                          * Check for EOF and read the new leaf.
  318                          */
  319                         if (fp->f_seekp >= bsize * fp->f_num_leafs)
  320                                 return (ENOENT);
  321 
  322                         rc = dnode_read(spa, &fp->f_dnode,
  323                                         fp->f_seekp,
  324                                         fp->f_zap_leaf,
  325                                         bsize);
  326                         if (rc)
  327                                 return (rc);
  328                 }
  329 
  330                 zc = &ZAP_LEAF_CHUNK(&zl, chunk);
  331                 fp->f_seekp++;
  332                 if (zc->l_entry.le_type != ZAP_CHUNK_ENTRY)
  333                         goto fzap_next;
  334 
  335                 namelen = zc->l_entry.le_name_length;
  336                 if (namelen > sizeof(d->d_name))
  337                         namelen = sizeof(d->d_name);
  338 
  339                 /*
  340                  * Paste the name back together.
  341                  */
  342                 nc = &ZAP_LEAF_CHUNK(&zl, zc->l_entry.le_name_chunk);
  343                 p = d->d_name;
  344                 while (namelen > 0) {
  345                         int len;
  346                         len = namelen;
  347                         if (len > ZAP_LEAF_ARRAY_BYTES)
  348                                 len = ZAP_LEAF_ARRAY_BYTES;
  349                         memcpy(p, nc->l_array.la_array, len);
  350                         p += len;
  351                         namelen -= len;
  352                         nc = &ZAP_LEAF_CHUNK(&zl, nc->l_array.la_next);
  353                 }
  354                 d->d_name[sizeof(d->d_name) - 1] = 0;
  355 
  356                 /*
  357                  * Assume the first eight bytes of the value are
  358                  * a uint64_t.
  359                  */
  360                 value = fzap_leaf_value(&zl, zc);
  361 
  362                 d->d_fileno = ZFS_DIRENT_OBJ(value);
  363                 d->d_type = ZFS_DIRENT_TYPE(value);
  364                 d->d_namlen = strlen(d->d_name);
  365 
  366                 return (0);
  367         }
  368 }
  369 
  370 static int
  371 vdev_read(vdev_t *vdev, void *priv, off_t offset, void *buf, size_t size)
  372 {
  373         int fd;
  374 
  375         fd = (uintptr_t) priv;
  376         lseek(fd, offset, SEEK_SET);
  377         if (read(fd, buf, size) == size) {
  378                 return 0;
  379         } else {
  380                 return (EIO);
  381         }
  382 }
  383 
  384 /*
  385  * Convert a pool guid to a 'unit number' suitable for use with zfs_dev_open.
  386  */
  387 int
  388 zfs_guid_to_unit(uint64_t guid)
  389 {
  390         spa_t *spa;
  391         int unit;
  392 
  393         unit = 0;
  394         STAILQ_FOREACH(spa, &zfs_pools, spa_link) {
  395                 if (spa->spa_guid == guid)
  396                         return unit;
  397                 unit++;
  398         }
  399         return (-1);
  400 }
  401 
  402 static int
  403 zfs_dev_init(void) 
  404 {
  405         char devname[512];
  406         int unit, slice;
  407         int fd;
  408 
  409         /*
  410          * Open all the disks we can find and see if we can reconstruct
  411          * ZFS pools from them. Bogusly assumes that the disks are named
  412          * diskN, diskNpM or diskNsM.
  413          */
  414         zfs_init();
  415         for (unit = 0; unit < MAXBDDEV; unit++) {
  416                 sprintf(devname, "disk%d:", unit);
  417                 fd = open(devname, O_RDONLY);
  418                 if (fd == -1)
  419                         continue;
  420 
  421                 /*
  422                  * If we find a vdev, the zfs code will eat the fd, otherwise
  423                  * we close it.
  424                  */
  425                 if (vdev_probe(vdev_read, (void*) (uintptr_t) fd, 0))
  426                         close(fd);
  427 
  428                 for (slice = 1; slice <= 128; slice++) {
  429                         sprintf(devname, "disk%dp%d:", unit, slice);
  430                         fd = open(devname, O_RDONLY);
  431                         if (fd == -1) {
  432                                 sprintf(devname, "disk%ds%d:", unit, slice);
  433                                 fd = open(devname, O_RDONLY);
  434                                 if (fd == -1)
  435                                         continue;
  436                         }
  437                         if (vdev_probe(vdev_read, (void*) (uintptr_t) fd, 0))
  438                                 close(fd);
  439                 }
  440         }
  441 
  442         return (0);
  443 }
  444 
  445 /*
  446  * Print information about ZFS pools
  447  */
  448 static void
  449 zfs_dev_print(int verbose)
  450 {
  451         spa_t *spa;
  452         char line[80];
  453         int unit;
  454 
  455         if (verbose) {
  456                 spa_all_status();
  457                 return;
  458         }
  459         unit = 0;
  460         STAILQ_FOREACH(spa, &zfs_pools, spa_link) {
  461                 sprintf(line, "    zfs%d:   %s\n", unit, spa->spa_name);
  462                 pager_output(line);
  463                 unit++;
  464         }
  465 }
  466 
  467 /*
  468  * Attempt to open the pool described by (dev) for use by (f).
  469  */
  470 static int 
  471 zfs_dev_open(struct open_file *f, ...)
  472 {
  473         va_list         args;
  474         struct devdesc  *dev;
  475         int             unit, i;
  476         spa_t           *spa;
  477 
  478         va_start(args, f);
  479         dev = va_arg(args, struct devdesc*);
  480         va_end(args);
  481 
  482         /*
  483          * We mostly ignore the stuff that devopen sends us. For now,
  484          * use the unit to find a pool - later we will override the
  485          * devname parsing so that we can name a pool and a fs within
  486          * the pool.
  487          */
  488         unit = dev->d_unit;
  489         
  490         i = 0;
  491         STAILQ_FOREACH(spa, &zfs_pools, spa_link) {
  492                 if (i == unit)
  493                         break;
  494                 i++;
  495         }
  496         if (!spa) {
  497                 return (ENXIO);
  498         }
  499 
  500         f->f_devdata = spa;
  501         free(dev);
  502         return (0);
  503 }
  504 
  505 static int 
  506 zfs_dev_close(struct open_file *f)
  507 {
  508 
  509         f->f_devdata = NULL;
  510         return (0);
  511 }
  512 
  513 static int 
  514 zfs_dev_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf, size_t *rsize)
  515 {
  516 
  517         return (ENOSYS);
  518 }
  519 
  520 struct devsw zfs_dev = {
  521         .dv_name = "zfs", 
  522         .dv_type = DEVT_ZFS, 
  523         .dv_init = zfs_dev_init,
  524         .dv_strategy = zfs_dev_strategy, 
  525         .dv_open = zfs_dev_open, 
  526         .dv_close = zfs_dev_close, 
  527         .dv_ioctl = noioctl,
  528         .dv_print = zfs_dev_print,
  529         .dv_cleanup = NULL
  530 };

Cache object: f26975870e83a5a360e28a8940d8e336


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