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

Cache object: 555dc2e4dcc4942328ce951f3dc4c21d


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