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_cleaner.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) 2010-2012 Semihalf.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/conf.h>
   35 #include <sys/kernel.h>
   36 #include <sys/lock.h>
   37 #include <sys/malloc.h>
   38 #include <sys/mount.h>
   39 #include <sys/mutex.h>
   40 #include <sys/buf.h>
   41 #include <sys/namei.h>
   42 #include <sys/vnode.h>
   43 #include <sys/bio.h>
   44 
   45 #include <fs/nandfs/nandfs_mount.h>
   46 #include <fs/nandfs/nandfs.h>
   47 #include <fs/nandfs/nandfs_subr.h>
   48 
   49 #define NANDFS_CLEANER_KILL     1
   50 
   51 static void nandfs_cleaner(struct nandfs_device *);
   52 static int nandfs_cleaner_clean_segments(struct nandfs_device *,
   53     struct nandfs_vinfo *, uint32_t, struct nandfs_period *, uint32_t,
   54     struct nandfs_bdesc *, uint32_t, uint64_t *, uint32_t);
   55 
   56 static int
   57 nandfs_process_bdesc(struct nandfs_device *nffsdev, struct nandfs_bdesc *bd,
   58     uint64_t nmembs);
   59 
   60 static void
   61 nandfs_wakeup_wait_cleaner(struct nandfs_device *fsdev, int reason)
   62 {
   63 
   64         mtx_lock(&fsdev->nd_clean_mtx);
   65         if (reason == NANDFS_CLEANER_KILL)
   66                 fsdev->nd_cleaner_exit = 1;
   67         if (fsdev->nd_cleaning == 0) {
   68                 fsdev->nd_cleaning = 1;
   69                 wakeup(&fsdev->nd_cleaning);
   70         }
   71         cv_wait(&fsdev->nd_clean_cv, &fsdev->nd_clean_mtx);
   72         mtx_unlock(&fsdev->nd_clean_mtx);
   73 }
   74 
   75 int
   76 nandfs_start_cleaner(struct nandfs_device *fsdev)
   77 {
   78         int error;
   79 
   80         MPASS(fsdev->nd_cleaner == NULL);
   81 
   82         fsdev->nd_cleaner_exit = 0;
   83 
   84         error = kthread_add((void(*)(void *))nandfs_cleaner, fsdev, NULL,
   85             &fsdev->nd_cleaner, 0, 0, "nandfs_cleaner");
   86         if (error)
   87                 printf("nandfs: could not start cleaner: %d\n", error);
   88 
   89         return (error);
   90 }
   91 
   92 int
   93 nandfs_stop_cleaner(struct nandfs_device *fsdev)
   94 {
   95 
   96         MPASS(fsdev->nd_cleaner != NULL);
   97         nandfs_wakeup_wait_cleaner(fsdev, NANDFS_CLEANER_KILL);
   98         fsdev->nd_cleaner = NULL;
   99 
  100         DPRINTF(CLEAN, ("cleaner stopped\n"));
  101         return (0);
  102 }
  103 
  104 static int
  105 nandfs_cleaner_finished(struct nandfs_device *fsdev)
  106 {
  107         int exit;
  108 
  109         mtx_lock(&fsdev->nd_clean_mtx);
  110         fsdev->nd_cleaning = 0;
  111         if (!fsdev->nd_cleaner_exit) {
  112                 DPRINTF(CLEAN, ("%s: sleep\n", __func__));
  113                 msleep(&fsdev->nd_cleaning, &fsdev->nd_clean_mtx, PRIBIO, "-",
  114                     hz * nandfs_cleaner_interval);
  115         }
  116         exit = fsdev->nd_cleaner_exit;
  117         cv_broadcast(&fsdev->nd_clean_cv);
  118         mtx_unlock(&fsdev->nd_clean_mtx);
  119         if (exit) {
  120                 DPRINTF(CLEAN, ("%s: no longer active\n", __func__));
  121                 return (1);
  122         }
  123 
  124         return (0);
  125 }
  126 
  127 static void
  128 print_suinfo(struct nandfs_suinfo *suinfo, int nsegs)
  129 {
  130         int i;
  131 
  132         for (i = 0; i < nsegs; i++) {
  133                 DPRINTF(CLEAN, ("%jx  %jd  %c%c%c  %10u\n",
  134                     suinfo[i].nsi_num, suinfo[i].nsi_lastmod,
  135                     (suinfo[i].nsi_flags &
  136                     (NANDFS_SEGMENT_USAGE_ACTIVE) ? 'a' : '-'),
  137                     (suinfo[i].nsi_flags &
  138                     (NANDFS_SEGMENT_USAGE_DIRTY) ? 'd' : '-'),
  139                     (suinfo[i].nsi_flags &
  140                     (NANDFS_SEGMENT_USAGE_ERROR) ? 'e' : '-'),
  141                     suinfo[i].nsi_blocks));
  142         }
  143 }
  144 
  145 static int
  146 nandfs_cleaner_vblock_is_alive(struct nandfs_device *fsdev,
  147     struct nandfs_vinfo *vinfo, struct nandfs_cpinfo *cp, uint32_t ncps)
  148 {
  149         int64_t idx, min, max;
  150 
  151         if (vinfo->nvi_end >= fsdev->nd_last_cno)
  152                 return (1);
  153 
  154         if (ncps == 0)
  155                 return (0);
  156 
  157         if (vinfo->nvi_end < cp[0].nci_cno ||
  158             vinfo->nvi_start > cp[ncps - 1].nci_cno)
  159                 return (0);
  160 
  161         idx = min = 0;
  162         max = ncps - 1;
  163         while (min <= max) {
  164                 idx = (min + max) / 2;
  165                 if (vinfo->nvi_start == cp[idx].nci_cno)
  166                         return (1);
  167                 if (vinfo->nvi_start < cp[idx].nci_cno)
  168                         max = idx - 1;
  169                 else
  170                         min = idx + 1;
  171         }
  172 
  173         return (vinfo->nvi_end >= cp[idx].nci_cno);
  174 }
  175 
  176 static void
  177 nandfs_cleaner_vinfo_mark_alive(struct nandfs_device *fsdev,
  178     struct nandfs_vinfo *vinfo, uint32_t nmembs, struct nandfs_cpinfo *cp,
  179     uint32_t ncps)
  180 {
  181         uint32_t i;
  182 
  183         for (i = 0; i < nmembs; i++)
  184                 vinfo[i].nvi_alive =
  185                     nandfs_cleaner_vblock_is_alive(fsdev, &vinfo[i], cp, ncps);
  186 }
  187 
  188 static int
  189 nandfs_cleaner_bdesc_is_alive(struct nandfs_device *fsdev,
  190     struct nandfs_bdesc *bdesc)
  191 {
  192         int alive;
  193 
  194         alive = bdesc->bd_oblocknr == bdesc->bd_blocknr;
  195         if (!alive)
  196                 MPASS(abs(bdesc->bd_oblocknr - bdesc->bd_blocknr) > 2);
  197 
  198         return (alive);
  199 }
  200 
  201 static void
  202 nandfs_cleaner_bdesc_mark_alive(struct nandfs_device *fsdev,
  203     struct nandfs_bdesc *bdesc, uint32_t nmembs)
  204 {
  205         uint32_t i;
  206 
  207         for (i = 0; i < nmembs; i++)
  208                 bdesc[i].bd_alive = nandfs_cleaner_bdesc_is_alive(fsdev,
  209                     &bdesc[i]);
  210 }
  211 
  212 static void
  213 nandfs_cleaner_iterate_psegment(struct nandfs_device *fsdev,
  214     struct nandfs_segment_summary *segsum, union nandfs_binfo *binfo,
  215     nandfs_daddr_t blk, struct nandfs_vinfo **vipp, struct nandfs_bdesc **bdpp)
  216 {
  217         int i;
  218 
  219         DPRINTF(CLEAN, ("%s nbinfos %x\n", __func__, segsum->ss_nbinfos));
  220         for (i = 0; i < segsum->ss_nbinfos; i++) {
  221                 if (binfo[i].bi_v.bi_ino == NANDFS_DAT_INO) {
  222                         (*bdpp)->bd_oblocknr = blk + segsum->ss_nblocks -
  223                             segsum->ss_nbinfos + i;
  224                         /*
  225                          * XXX Hack
  226                          */
  227                         if (segsum->ss_flags & NANDFS_SS_SR)
  228                                 (*bdpp)->bd_oblocknr--;
  229                         (*bdpp)->bd_level = binfo[i].bi_dat.bi_level;
  230                         (*bdpp)->bd_offset = binfo[i].bi_dat.bi_blkoff;
  231                         (*bdpp)++;
  232                 } else {
  233                         (*vipp)->nvi_ino = binfo[i].bi_v.bi_ino;
  234                         (*vipp)->nvi_vblocknr = binfo[i].bi_v.bi_vblocknr;
  235                         (*vipp)++;
  236                 }
  237         }
  238 }
  239 
  240 static int
  241 nandfs_cleaner_iterate_segment(struct nandfs_device *fsdev, uint64_t segno,
  242     struct nandfs_vinfo **vipp, struct nandfs_bdesc **bdpp, int *select)
  243 {
  244         struct nandfs_segment_summary *segsum;
  245         union nandfs_binfo *binfo;
  246         struct buf *bp;
  247         uint32_t nblocks;
  248         nandfs_daddr_t curr, start, end;
  249         int error = 0;
  250 
  251         nandfs_get_segment_range(fsdev, segno, &start, &end);
  252 
  253         DPRINTF(CLEAN, ("%s: segno %jx start %jx end %jx\n", __func__, segno,
  254             start, end));
  255 
  256         *select = 0;
  257 
  258         for (curr = start; curr < end; curr += nblocks) {
  259                 error = nandfs_dev_bread(fsdev, curr, NOCRED, 0, &bp);
  260                 if (error) {
  261                         brelse(bp);
  262                         nandfs_error("%s: couldn't load segment summary of %jx: %d\n",
  263                             __func__, segno, error);
  264                         return (error);
  265                 }
  266 
  267                 segsum = (struct nandfs_segment_summary *)bp->b_data;
  268                 binfo = (union nandfs_binfo *)(bp->b_data + segsum->ss_bytes);
  269 
  270                 if (!nandfs_segsum_valid(segsum)) {
  271                         brelse(bp);
  272                         nandfs_error("nandfs: invalid summary of segment %jx\n", segno);
  273                         return (error);
  274                 }
  275 
  276                 DPRINTF(CLEAN, ("%s: %jx magic %x bytes %x nblocks %x nbinfos "
  277                     "%x\n", __func__, segno, segsum->ss_magic, segsum->ss_bytes,
  278                     segsum->ss_nblocks, segsum->ss_nbinfos));
  279 
  280                 nandfs_cleaner_iterate_psegment(fsdev, segsum, binfo, curr,
  281                     vipp, bdpp);
  282                 nblocks = segsum->ss_nblocks;
  283                 brelse(bp);
  284         }
  285 
  286         if (error == 0)
  287                 *select = 1;
  288 
  289         return (error);
  290 }
  291 
  292 static int
  293 nandfs_cleaner_choose_segment(struct nandfs_device *fsdev, uint64_t **segpp,
  294     uint64_t nsegs, uint64_t *rseg)
  295 {
  296         struct nandfs_suinfo *suinfo;
  297         uint64_t i, ssegs;
  298         int error;
  299 
  300         suinfo = malloc(sizeof(*suinfo) * nsegs, M_NANDFSTEMP,
  301             M_ZERO | M_WAITOK);
  302 
  303         if (*rseg >= fsdev->nd_fsdata.f_nsegments)
  304                 *rseg = 0;
  305 
  306 retry:
  307         error = nandfs_get_segment_info_filter(fsdev, suinfo, nsegs, *rseg,
  308             &ssegs, NANDFS_SEGMENT_USAGE_DIRTY,
  309             NANDFS_SEGMENT_USAGE_ACTIVE | NANDFS_SEGMENT_USAGE_ERROR |
  310             NANDFS_SEGMENT_USAGE_GC);
  311         if (error) {
  312                 nandfs_error("%s:%d", __FILE__, __LINE__);
  313                 goto out;
  314         }
  315         if (ssegs == 0 && *rseg != 0) {
  316                 *rseg = 0;
  317                 goto retry;
  318         }
  319         if (ssegs > 0) {
  320                 print_suinfo(suinfo, ssegs);
  321 
  322                 for (i = 0; i < ssegs; i++) {
  323                         (**segpp) = suinfo[i].nsi_num;
  324                         (*segpp)++;
  325                 }
  326                 *rseg = suinfo[i - 1].nsi_num + 1;
  327         }
  328 
  329 out:
  330         free(suinfo, M_NANDFSTEMP);
  331         return (error);
  332 }
  333 
  334 static int
  335 nandfs_cleaner_body(struct nandfs_device *fsdev, uint64_t *rseg)
  336 {
  337         struct nandfs_vinfo *vinfo, *vip, *vipi;
  338         struct nandfs_bdesc *bdesc, *bdp, *bdpi;
  339         struct nandfs_cpstat cpstat;
  340         struct nandfs_cpinfo *cpinfo = NULL;
  341         uint64_t *segnums, *segp;
  342         int select, selected;
  343         int error = 0;
  344         int nsegs;
  345         int i;
  346 
  347         nsegs = nandfs_cleaner_segments;
  348 
  349         vip = vinfo = malloc(sizeof(*vinfo) *
  350             fsdev->nd_fsdata.f_blocks_per_segment * nsegs, M_NANDFSTEMP,
  351             M_ZERO | M_WAITOK);
  352         bdp = bdesc = malloc(sizeof(*bdesc) *
  353             fsdev->nd_fsdata.f_blocks_per_segment * nsegs, M_NANDFSTEMP,
  354             M_ZERO | M_WAITOK);
  355         segp = segnums = malloc(sizeof(*segnums) * nsegs, M_NANDFSTEMP,
  356             M_WAITOK);
  357 
  358         error = nandfs_cleaner_choose_segment(fsdev, &segp, nsegs, rseg);
  359         if (error) {
  360                 nandfs_error("%s:%d", __FILE__, __LINE__);
  361                 goto out;
  362         }
  363 
  364         if (segnums == segp)
  365                 goto out;
  366 
  367         selected = 0;
  368         for (i = 0; i < segp - segnums; i++) {
  369                 error = nandfs_cleaner_iterate_segment(fsdev, segnums[i], &vip,
  370                     &bdp, &select);
  371                 if (error) {
  372                         /*
  373                          * XXX deselect (see below)?
  374                          */
  375                         goto out;
  376                 }
  377                 if (!select)
  378                         segnums[i] = NANDFS_NOSEGMENT;
  379                 else {
  380                         error = nandfs_markgc_segment(fsdev, segnums[i]);
  381                         if (error) {
  382                                 nandfs_error("%s:%d\n", __FILE__, __LINE__);
  383                                 goto out;
  384                         }
  385                         selected++;
  386                 }
  387         }
  388 
  389         if (selected == 0) {
  390                 MPASS(vinfo == vip);
  391                 MPASS(bdesc == bdp);
  392                 goto out;
  393         }
  394 
  395         error = nandfs_get_cpstat(fsdev->nd_cp_node, &cpstat);
  396         if (error) {
  397                 nandfs_error("%s:%d\n", __FILE__, __LINE__);
  398                 goto out;
  399         }
  400 
  401         if (cpstat.ncp_nss != 0) {
  402                 cpinfo = malloc(sizeof(struct nandfs_cpinfo) * cpstat.ncp_nss,
  403                     M_NANDFSTEMP, M_WAITOK);
  404                 error = nandfs_get_cpinfo(fsdev->nd_cp_node, 1, NANDFS_SNAPSHOT,
  405                     cpinfo, cpstat.ncp_nss, NULL);
  406                 if (error) {
  407                         nandfs_error("%s:%d\n", __FILE__, __LINE__);
  408                         goto out_locked;
  409                 }
  410         }
  411 
  412         NANDFS_WRITELOCK(fsdev);
  413         DPRINTF(CLEAN, ("%s: got lock\n", __func__));
  414 
  415         error = nandfs_get_dat_vinfo(fsdev, vinfo, vip - vinfo);
  416         if (error) {
  417                 nandfs_error("%s:%d\n", __FILE__, __LINE__);
  418                 goto out_locked;
  419         }
  420 
  421         nandfs_cleaner_vinfo_mark_alive(fsdev, vinfo, vip - vinfo, cpinfo,
  422             cpstat.ncp_nss);
  423 
  424         error = nandfs_get_dat_bdescs(fsdev, bdesc, bdp - bdesc);
  425         if (error) {
  426                 nandfs_error("%s:%d\n", __FILE__, __LINE__);
  427                 goto out_locked;
  428         }
  429 
  430         nandfs_cleaner_bdesc_mark_alive(fsdev, bdesc, bdp - bdesc);
  431 
  432         DPRINTF(CLEAN, ("got:\n"));
  433         for (vipi = vinfo; vipi < vip; vipi++) {
  434                 DPRINTF(CLEAN, ("v ino %jx vblocknr %jx start %jx end %jx "
  435                     "alive %d\n", vipi->nvi_ino, vipi->nvi_vblocknr,
  436                     vipi->nvi_start, vipi->nvi_end, vipi->nvi_alive));
  437         }
  438         for (bdpi = bdesc; bdpi < bdp; bdpi++) {
  439                 DPRINTF(CLEAN, ("b oblocknr %jx blocknr %jx offset %jx "
  440                     "alive %d\n", bdpi->bd_oblocknr, bdpi->bd_blocknr,
  441                     bdpi->bd_offset, bdpi->bd_alive));
  442         }
  443         DPRINTF(CLEAN, ("end list\n"));
  444 
  445         error = nandfs_cleaner_clean_segments(fsdev, vinfo, vip - vinfo, NULL,
  446             0, bdesc, bdp - bdesc, segnums, segp - segnums);
  447         if (error)
  448                 nandfs_error("%s:%d\n", __FILE__, __LINE__);
  449 
  450 out_locked:
  451         NANDFS_WRITEUNLOCK(fsdev);
  452 out:
  453         free(cpinfo, M_NANDFSTEMP);
  454         free(segnums, M_NANDFSTEMP);
  455         free(bdesc, M_NANDFSTEMP);
  456         free(vinfo, M_NANDFSTEMP);
  457 
  458         return (error);
  459 }
  460 
  461 static void
  462 nandfs_cleaner(struct nandfs_device *fsdev)
  463 {
  464         uint64_t checked_seg = 0;
  465         int error;
  466 
  467         while (!nandfs_cleaner_finished(fsdev)) {
  468                 if (!nandfs_cleaner_enable || rebooting)
  469                         continue;
  470 
  471                 DPRINTF(CLEAN, ("%s: run started\n", __func__));
  472 
  473                 fsdev->nd_cleaning = 1;
  474 
  475                 error = nandfs_cleaner_body(fsdev, &checked_seg);
  476 
  477                 DPRINTF(CLEAN, ("%s: run finished error %d\n", __func__,
  478                     error));
  479         }
  480 
  481         DPRINTF(CLEAN, ("%s: exiting\n", __func__));
  482         kthread_exit();
  483 }
  484 
  485 static int
  486 nandfs_cleaner_clean_segments(struct nandfs_device *nffsdev,
  487     struct nandfs_vinfo *vinfo, uint32_t nvinfo,
  488     struct nandfs_period *pd, uint32_t npd,
  489     struct nandfs_bdesc *bdesc, uint32_t nbdesc,
  490     uint64_t *segments, uint32_t nsegs)
  491 {
  492         struct nandfs_node *gc;
  493         struct buf *bp;
  494         uint32_t i;
  495         int error = 0;
  496 
  497         gc = nffsdev->nd_gc_node;
  498 
  499         DPRINTF(CLEAN, ("%s: enter\n", __func__));
  500 
  501         VOP_LOCK(NTOV(gc), LK_EXCLUSIVE);
  502         for (i = 0; i < nvinfo; i++) {
  503                 if (!vinfo[i].nvi_alive)
  504                         continue;
  505                 DPRINTF(CLEAN, ("%s: read vblknr:%#jx blk:%#jx\n",
  506                     __func__, (uintmax_t)vinfo[i].nvi_vblocknr,
  507                     (uintmax_t)vinfo[i].nvi_blocknr));
  508                 error = nandfs_bread(nffsdev->nd_gc_node, vinfo[i].nvi_blocknr,
  509                     NULL, 0, &bp);
  510                 if (error) {
  511                         nandfs_error("%s:%d", __FILE__, __LINE__);
  512                         VOP_UNLOCK(NTOV(gc), 0);
  513                         goto out;
  514                 }
  515                 nandfs_vblk_set(bp, vinfo[i].nvi_vblocknr);
  516                 nandfs_buf_set(bp, NANDFS_VBLK_ASSIGNED);
  517                 nandfs_dirty_buf(bp, 1);
  518         }
  519         VOP_UNLOCK(NTOV(gc), 0);
  520 
  521         /* Delete checkpoints */
  522         for (i = 0; i < npd; i++) {
  523                 DPRINTF(CLEAN, ("delete checkpoint: %jx\n",
  524                     (uintmax_t)pd[i].p_start));
  525                 error = nandfs_delete_cp(nffsdev->nd_cp_node, pd[i].p_start,
  526                     pd[i].p_end);
  527                 if (error) {
  528                         nandfs_error("%s:%d", __FILE__, __LINE__);
  529                         goto out;
  530                 }
  531         }
  532 
  533         /* Update vblocks */
  534         for (i = 0; i < nvinfo; i++) {
  535                 if (vinfo[i].nvi_alive)
  536                         continue;
  537                 DPRINTF(CLEAN, ("freeing vblknr: %jx\n", vinfo[i].nvi_vblocknr));
  538                 error = nandfs_vblock_free(nffsdev, vinfo[i].nvi_vblocknr);
  539                 if (error) {
  540                         nandfs_error("%s:%d", __FILE__, __LINE__);
  541                         goto out;
  542                 }
  543         }
  544 
  545         error = nandfs_process_bdesc(nffsdev, bdesc, nbdesc);
  546         if (error) {
  547                 nandfs_error("%s:%d", __FILE__, __LINE__);
  548                 goto out;
  549         }
  550 
  551         /* Add segments to clean */
  552         if (nffsdev->nd_free_count) {
  553                 nffsdev->nd_free_base = realloc(nffsdev->nd_free_base,
  554                     (nffsdev->nd_free_count + nsegs) * sizeof(uint64_t),
  555                     M_NANDFSTEMP, M_WAITOK | M_ZERO);
  556                 memcpy(&nffsdev->nd_free_base[nffsdev->nd_free_count], segments,
  557                     nsegs * sizeof(uint64_t));
  558                 nffsdev->nd_free_count += nsegs;
  559         } else {
  560                 nffsdev->nd_free_base = malloc(nsegs * sizeof(uint64_t),
  561                     M_NANDFSTEMP, M_WAITOK|M_ZERO);
  562                 memcpy(nffsdev->nd_free_base, segments,
  563                     nsegs * sizeof(uint64_t));
  564                 nffsdev->nd_free_count = nsegs;
  565         }
  566 
  567 out:
  568 
  569         DPRINTF(CLEAN, ("%s: exit error %d\n", __func__, error));
  570 
  571         return (error);
  572 }
  573 
  574 static int
  575 nandfs_process_bdesc(struct nandfs_device *nffsdev, struct nandfs_bdesc *bd,
  576     uint64_t nmembs)
  577 {
  578         struct nandfs_node *dat_node;
  579         struct buf *bp;
  580         uint64_t i;
  581         int error;
  582 
  583         dat_node = nffsdev->nd_dat_node;
  584 
  585         VOP_LOCK(NTOV(dat_node), LK_EXCLUSIVE);
  586 
  587         for (i = 0; i < nmembs; i++) {
  588                 if (!bd[i].bd_alive)
  589                         continue;
  590                 DPRINTF(CLEAN, ("%s: idx %jx offset %jx\n",
  591                     __func__, i, bd[i].bd_offset));
  592                 if (bd[i].bd_level) {
  593                         error = nandfs_bread_meta(dat_node, bd[i].bd_offset,
  594                             NULL, 0, &bp);
  595                         if (error) {
  596                                 nandfs_error("%s: cannot read dat node "
  597                                     "level:%d\n", __func__, bd[i].bd_level);
  598                                 brelse(bp);
  599                                 VOP_UNLOCK(NTOV(dat_node), 0);
  600                                 return (error);
  601                         }
  602                         nandfs_dirty_buf_meta(bp, 1);
  603                         nandfs_bmap_dirty_blocks(VTON(bp->b_vp), bp, 1);
  604                 } else {
  605                         error = nandfs_bread(dat_node, bd[i].bd_offset, NULL,
  606                             0, &bp);
  607                         if (error) {
  608                                 nandfs_error("%s: cannot read dat node\n",
  609                                     __func__);
  610                                 brelse(bp);
  611                                 VOP_UNLOCK(NTOV(dat_node), 0);
  612                                 return (error);
  613                         }
  614                         nandfs_dirty_buf(bp, 1);
  615                 }
  616                 DPRINTF(CLEAN, ("%s: bp: %p\n", __func__, bp));
  617         }
  618 
  619         VOP_UNLOCK(NTOV(dat_node), 0);
  620 
  621         return (0);
  622 }

Cache object: 29d5900bef69fa8db3a7ffe3a6ff366a


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