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/fs/nandfs/nandfs_dat.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) 2010-2012 Semihalf.
    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 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/conf.h>
   33 #include <sys/kernel.h>
   34 #include <sys/lock.h>
   35 #include <sys/malloc.h>
   36 #include <sys/mount.h>
   37 #include <sys/mutex.h>
   38 #include <sys/namei.h>
   39 #include <sys/sysctl.h>
   40 #include <sys/vnode.h>
   41 #include <sys/buf.h>
   42 #include <sys/bio.h>
   43 
   44 #include <vm/vm.h>
   45 #include <vm/vm_param.h>
   46 #include <vm/vm_kern.h>
   47 #include <vm/vm_page.h>
   48 
   49 #include <fs/nandfs/nandfs_mount.h>
   50 #include <fs/nandfs/nandfs.h>
   51 #include <fs/nandfs/nandfs_subr.h>
   52 
   53 int
   54 nandfs_vblock_alloc(struct nandfs_device *nandfsdev, nandfs_daddr_t *vblock)
   55 {
   56         struct nandfs_node *dat;
   57         struct nandfs_mdt *mdt;
   58         struct nandfs_alloc_request req;
   59         struct nandfs_dat_entry *dat_entry;
   60         uint64_t start;
   61         uint32_t entry;
   62         int locked, error;
   63 
   64         dat = nandfsdev->nd_dat_node;
   65         mdt = &nandfsdev->nd_dat_mdt;
   66         start = nandfsdev->nd_last_cno + 1;
   67 
   68         locked = NANDFS_VOP_ISLOCKED(NTOV(dat));
   69         if (!locked)
   70                 VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
   71         req.entrynum = 0;
   72 
   73         /* Alloc vblock number */
   74         error = nandfs_find_free_entry(mdt, dat, &req);
   75         if (error) {
   76                 nandfs_error("%s: cannot find free vblk entry\n",
   77                     __func__);
   78                 if (!locked)
   79                         VOP_UNLOCK(NTOV(dat), 0);
   80                 return (error);
   81         }
   82 
   83         /* Read/create buffer */
   84         error = nandfs_get_entry_block(mdt, dat, &req, &entry, 1);
   85         if (error) {
   86                 nandfs_error("%s: cannot get free vblk entry\n",
   87                     __func__);
   88                 nandfs_abort_entry(&req);
   89                 if (!locked)
   90                         VOP_UNLOCK(NTOV(dat), 0);
   91                 return (error);
   92         }
   93 
   94         /* Fill out vblock data */
   95         dat_entry = (struct nandfs_dat_entry *) req.bp_entry->b_data;
   96         dat_entry[entry].de_start = start;
   97         dat_entry[entry].de_end = UINTMAX_MAX;
   98         dat_entry[entry].de_blocknr = 0;
   99 
  100         /* Commit allocation */
  101         error = nandfs_alloc_entry(mdt, &req);
  102         if (error) {
  103                 nandfs_error("%s: cannot get free vblk entry\n",
  104                     __func__);
  105                 if (!locked)
  106                         VOP_UNLOCK(NTOV(dat), 0);
  107                 return (error);
  108         }
  109 
  110         /* Return allocated vblock */
  111         *vblock = req.entrynum;
  112         DPRINTF(DAT, ("%s: allocated vblock %#jx\n",
  113             __func__, (uintmax_t)*vblock));
  114 
  115         if (!locked)
  116                 VOP_UNLOCK(NTOV(dat), 0);
  117         return (error);
  118 }
  119 
  120 int
  121 nandfs_vblock_assign(struct nandfs_device *nandfsdev, nandfs_daddr_t vblock,
  122     nandfs_lbn_t block)
  123 {
  124         struct nandfs_node *dat;
  125         struct nandfs_mdt *mdt;
  126         struct nandfs_alloc_request req;
  127         struct nandfs_dat_entry *dat_entry;
  128         uint32_t entry;
  129         int locked, error;
  130 
  131         dat = nandfsdev->nd_dat_node;
  132         mdt = &nandfsdev->nd_dat_mdt;
  133 
  134         locked = NANDFS_VOP_ISLOCKED(NTOV(dat));
  135         if (!locked)
  136                 VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
  137         req.entrynum = vblock;
  138 
  139         error = nandfs_get_entry_block(mdt, dat, &req, &entry, 0);
  140         if (!error) {
  141                 dat_entry = (struct nandfs_dat_entry *) req.bp_entry->b_data;
  142                 dat_entry[entry].de_blocknr = block;
  143 
  144                 DPRINTF(DAT, ("%s: assing vblock %jx->%jx\n",
  145                     __func__, (uintmax_t)vblock, (uintmax_t)block));
  146 
  147                 /*
  148                  * It is mostly called from syncer() so
  149                  * we want to force making buf dirty
  150                  */
  151                 error = nandfs_dirty_buf(req.bp_entry, 1);
  152         }
  153 
  154         if (!locked)
  155                 VOP_UNLOCK(NTOV(dat), 0);
  156 
  157         return (error);
  158 }
  159 
  160 int
  161 nandfs_vblock_end(struct nandfs_device *nandfsdev, nandfs_daddr_t vblock)
  162 {
  163         struct nandfs_node *dat;
  164         struct nandfs_mdt *mdt;
  165         struct nandfs_alloc_request req;
  166         struct nandfs_dat_entry *dat_entry;
  167         uint64_t end;
  168         uint32_t entry;
  169         int locked, error;
  170 
  171         dat = nandfsdev->nd_dat_node;
  172         mdt = &nandfsdev->nd_dat_mdt;
  173         end = nandfsdev->nd_last_cno;
  174 
  175         locked = NANDFS_VOP_ISLOCKED(NTOV(dat));
  176         if (!locked)
  177                 VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
  178         req.entrynum = vblock;
  179 
  180         error = nandfs_get_entry_block(mdt, dat, &req, &entry, 0);
  181         if (!error) {
  182                 dat_entry = (struct nandfs_dat_entry *) req.bp_entry->b_data;
  183                 dat_entry[entry].de_end = end;
  184                 DPRINTF(DAT, ("%s: end vblock %#jx at checkpoint %#jx\n",
  185                     __func__, (uintmax_t)vblock, (uintmax_t)end));
  186 
  187                 /*
  188                  * It is mostly called from syncer() so
  189                  * we want to force making buf dirty
  190                  */
  191                 error = nandfs_dirty_buf(req.bp_entry, 1);
  192         }
  193 
  194         if (!locked)
  195                 VOP_UNLOCK(NTOV(dat), 0);
  196 
  197         return (error);
  198 }
  199 
  200 int
  201 nandfs_vblock_free(struct nandfs_device *nandfsdev, nandfs_daddr_t vblock)
  202 {
  203         struct nandfs_node *dat;
  204         struct nandfs_mdt *mdt;
  205         struct nandfs_alloc_request req;
  206         int error;
  207 
  208         dat = nandfsdev->nd_dat_node;
  209         mdt = &nandfsdev->nd_dat_mdt;
  210 
  211         VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
  212         req.entrynum = vblock;
  213 
  214         error = nandfs_find_entry(mdt, dat, &req);
  215         if (!error) {
  216                 DPRINTF(DAT, ("%s: vblk %#jx\n", __func__, (uintmax_t)vblock));
  217                 nandfs_free_entry(mdt, &req);
  218         }
  219 
  220         VOP_UNLOCK(NTOV(dat), 0);
  221         return (error);
  222 }
  223 
  224 int
  225 nandfs_get_dat_vinfo_ioctl(struct nandfs_device *nandfsdev, struct nandfs_argv *nargv)
  226 {
  227         struct nandfs_vinfo *vinfo;
  228         size_t size;
  229         int error;
  230 
  231         if (nargv->nv_nmembs > NANDFS_VINFO_MAX)
  232                 return (EINVAL);
  233 
  234         size = sizeof(struct nandfs_vinfo) * nargv->nv_nmembs;
  235         vinfo = malloc(size, M_NANDFSTEMP, M_WAITOK|M_ZERO);
  236 
  237         error = copyin((void *)(uintptr_t)nargv->nv_base, vinfo, size);
  238         if (error) {
  239                 free(vinfo, M_NANDFSTEMP);
  240                 return (error);
  241         }
  242 
  243         error = nandfs_get_dat_vinfo(nandfsdev, vinfo, nargv->nv_nmembs);
  244         if (error == 0)
  245                 error = copyout(vinfo, (void *)(uintptr_t)nargv->nv_base, size);
  246         free(vinfo, M_NANDFSTEMP);
  247         return (error);
  248 }
  249 
  250 int
  251 nandfs_get_dat_vinfo(struct nandfs_device *nandfsdev, struct nandfs_vinfo *vinfo,
  252     uint32_t nmembs)
  253 {
  254         struct nandfs_node *dat;
  255         struct nandfs_mdt *mdt;
  256         struct nandfs_alloc_request req;
  257         struct nandfs_dat_entry *dat_entry;
  258         uint32_t i, idx;
  259         int error = 0;
  260 
  261         dat = nandfsdev->nd_dat_node;
  262         mdt = &nandfsdev->nd_dat_mdt;
  263 
  264         DPRINTF(DAT, ("%s: nmembs %#x\n", __func__, nmembs));
  265 
  266         VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
  267 
  268         for (i = 0; i < nmembs; i++) {
  269                 req.entrynum = vinfo[i].nvi_vblocknr;
  270 
  271                 error = nandfs_get_entry_block(mdt, dat,&req, &idx, 0);
  272                 if (error)
  273                         break;
  274 
  275                 dat_entry = ((struct nandfs_dat_entry *) req.bp_entry->b_data);
  276                 vinfo[i].nvi_start = dat_entry[idx].de_start;
  277                 vinfo[i].nvi_end = dat_entry[idx].de_end;
  278                 vinfo[i].nvi_blocknr = dat_entry[idx].de_blocknr;
  279 
  280                 DPRINTF(DAT, ("%s: vinfo: %jx[%jx-%jx]->%jx\n",
  281                     __func__, vinfo[i].nvi_vblocknr, vinfo[i].nvi_start,
  282                     vinfo[i].nvi_end, vinfo[i].nvi_blocknr));
  283 
  284                 brelse(req.bp_entry);
  285         }
  286 
  287         VOP_UNLOCK(NTOV(dat), 0);
  288         return (error);
  289 }
  290 
  291 int
  292 nandfs_get_dat_bdescs_ioctl(struct nandfs_device *nffsdev,
  293     struct nandfs_argv *nargv)
  294 {
  295         struct nandfs_bdesc *bd;
  296         size_t size;
  297         int error;
  298 
  299         size = nargv->nv_nmembs * sizeof(struct nandfs_bdesc);
  300         bd = malloc(size, M_NANDFSTEMP, M_WAITOK);
  301         error = copyin((void *)(uintptr_t)nargv->nv_base, bd, size);
  302         if (error) {
  303                 free(bd, M_NANDFSTEMP);
  304                 return (error);
  305         }
  306 
  307         error = nandfs_get_dat_bdescs(nffsdev, bd, nargv->nv_nmembs);
  308 
  309         if (error == 0)
  310                 error = copyout(bd, (void *)(uintptr_t)nargv->nv_base, size);
  311 
  312         free(bd, M_NANDFSTEMP);
  313         return (error);
  314 }
  315 
  316 int
  317 nandfs_get_dat_bdescs(struct nandfs_device *nffsdev, struct nandfs_bdesc *bd,
  318     uint32_t nmembs)
  319 {
  320         struct nandfs_node *dat_node;
  321         uint64_t map;
  322         uint32_t i;
  323         int error = 0;
  324 
  325         dat_node = nffsdev->nd_dat_node;
  326 
  327         VOP_LOCK(NTOV(dat_node), LK_EXCLUSIVE);
  328 
  329         for (i = 0; i < nmembs; i++) {
  330                 DPRINTF(CLEAN,
  331                     ("%s: bd ino:%#jx oblk:%#jx blocknr:%#jx off:%#jx\n",
  332                     __func__,  (uintmax_t)bd[i].bd_ino,
  333                     (uintmax_t)bd[i].bd_oblocknr, (uintmax_t)bd[i].bd_blocknr,
  334                     (uintmax_t)bd[i].bd_offset));
  335 
  336                 error = nandfs_bmap_lookup(dat_node, bd[i].bd_offset, &map);
  337                 if (error)
  338                         break;
  339                 bd[i].bd_blocknr = map;
  340         }
  341 
  342         VOP_UNLOCK(NTOV(dat_node), 0);
  343         return (error);
  344 }

Cache object: a641375ddc1eeee94113b476bcee67a0


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