xref: /minix/sys/ufs/chfs/chfs_erase.c (revision 84d9c625)
1 /*	$NetBSD: chfs_erase.c,v 1.2 2012/10/19 12:44:39 ttoth 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  */
47 int
chfs_remap_leb(struct chfs_mount * chmp)48 chfs_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