1/* $NetBSD: chfs_erase.c,v 1.1 2011/11/24 15:51:31 ahoka Exp $ */ 2 3/*- 4 * Copyright (c) 2010 Department of Software Engineering, 5 * University of Szeged, Hungary 6 * Copyright (c) 2010 David Tengeri <dtengeri@inf.u-szeged.hu> 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to The NetBSD Foundation 10 * by the Department of Software Engineering, University of Szeged, Hungary 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#include "chfs.h" 35 36 37/* 38 * chfs_remap_leb - unmap and then map a leb 39 * 40 * Gets an eraseblock from the erasable queue, unmaps it through 41 * EBH and maps another eraseblock to the same LNR. 42 * EBH will find a free eraseblock if any or will erase one if there isn't any 43 * free, just dirty block. 44 * 45 * Needs more brainstorming here. 46 */ 47int 48chfs_remap_leb(struct chfs_mount *chmp) 49{ 50 int err; 51 struct chfs_eraseblock *cheb; 52 dbg("chfs_remap_leb\n"); 53 uint32_t dirty, unchecked, used, free, wasted; 54 55 KASSERT(!rw_write_held(&chmp->chm_lock_wbuf)); 56 KASSERT(mutex_owned(&chmp->chm_lock_mountfields)); 57 KASSERT(mutex_owned(&chmp->chm_lock_sizes)); 58 59 if (!chmp->chm_nr_erasable_blocks) { 60 //TODO 61 /* We don't have any erasable blocks, need to check if there are 62 * blocks on erasable_pending_wbuf_queue, flush the data and then 63 * we can remap it. 64 * If there aren't any blocks on that list too, we need to GC? 65 */ 66 if (!TAILQ_EMPTY(&chmp->chm_erasable_pending_wbuf_queue)) { 67 cheb = TAILQ_FIRST(&chmp->chm_erasable_pending_wbuf_queue); 68 TAILQ_REMOVE(&chmp->chm_erasable_pending_wbuf_queue, cheb, queue); 69 if (chmp->chm_wbuf_len) { 70 mutex_exit(&chmp->chm_lock_sizes); 71 chfs_flush_pending_wbuf(chmp); 72 mutex_enter(&chmp->chm_lock_sizes); 73 } 74 TAILQ_INSERT_TAIL(&chmp->chm_erase_pending_queue, cheb, queue); 75 chmp->chm_nr_erasable_blocks++; 76 } else { 77 /* We can't delete any block. */ 78 //FIXME should we return ENOSPC? 79 return ENOSPC; 80 } 81 } 82 cheb = TAILQ_FIRST(&chmp->chm_erase_pending_queue); 83 TAILQ_REMOVE(&chmp->chm_erase_pending_queue, cheb, queue); 84 chmp->chm_nr_erasable_blocks--; 85 86 dirty = cheb->dirty_size; 87 unchecked = cheb->unchecked_size; 88 used = cheb->used_size; 89 free = cheb->free_size; 90 wasted = cheb->wasted_size; 91 92 /* Free allocated node references for this eraseblock */ 93 chfs_free_node_refs(cheb); 94 95 err = chfs_unmap_leb(chmp, cheb->lnr); 96 if (err) 97 return err; 98 99 err = chfs_map_leb(chmp, cheb->lnr); 100 if (err) 101 return err; 102 /* Reset state to default and change chmp sizes too */ 103 chfs_change_size_dirty(chmp, cheb, -dirty); 104 chfs_change_size_unchecked(chmp, cheb, -unchecked); 105 chfs_change_size_used(chmp, cheb, -used); 106 chfs_change_size_free(chmp, cheb, chmp->chm_ebh->eb_size - free); 107 chfs_change_size_wasted(chmp, cheb, -wasted); 108 109 KASSERT(cheb->dirty_size == 0); 110 KASSERT(cheb->unchecked_size == 0); 111 KASSERT(cheb->used_size == 0); 112 KASSERT(cheb->free_size == chmp->chm_ebh->eb_size); 113 KASSERT(cheb->wasted_size == 0); 114 115 cheb->first_node = NULL; 116 cheb->last_node = NULL; 117 /* put it to free_queue */ 118 TAILQ_INSERT_TAIL(&chmp->chm_free_queue, cheb, queue); 119 chmp->chm_nr_free_blocks++; 120 dbg("remaped (free: %d, erasable: %d)\n", chmp->chm_nr_free_blocks, chmp->chm_nr_erasable_blocks); 121 KASSERT(!TAILQ_EMPTY(&chmp->chm_free_queue)); 122 123 return 0; 124} 125