blob: 8c4fd4bc5a9772fc5d9c67346dca6623dde44da0 [file] [edit]
/*
* Copyright 2016, NICTA
*
* This software may be distributed and modified according to the terms of
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
* See "LICENSE_GPLv2.txt" for details.
*
* @TAG(NICTA_GPL)
*/
#include <bilbyfs.h>
int gc_init(struct bilbyfs_info *bi)
{
bi->gc_buf.buf = vmalloc(bi->super.leb_size);
if (bi->gc_buf.buf) {
bi->gc_buf.size = bi->super.leb_size;
return 0;
}
return -ENOMEM;
}
void gc_clean(struct bilbyfs_info *bi)
{
vfree(bi->gc_buf.buf);
}
int gc_garbage_collect(struct bilbyfs_info *bi)
{
int err, i;
int lnum;
int list_limit = BILBYFS_MAX_OBJ_PER_TRANS;
struct obj_ch *obj;
struct obj_ch **list, **valid_list;
int count = 0, valid_count = 0;
bilbyfs_err("bilbyfs GC\n");
bilbyfs_debug("gc_garbage_collect() starts\n");
/* Find block with most garbage */
lnum = fsm_get_dirtiest_eb(bi);
if (lnum < 0) {
bilbyfs_debug("gc_garbage_collect() : No erase-block to garbage collect.\n");
return -ENOENT;
}
// Scan erase-block to build object lists
list = kmalloc(sizeof(struct obj_ch *) *list_limit);
if (!list)
return -ENOMEM;
count = ostore_scan_leb_obj(bi, &bi->gc_buf, lnum, (void **) list, list_limit);
if (count < 0) {
kfree(list);
return count;
}
valid_list = kmalloc(sizeof(struct obj_ch *) * list_limit);
if (!valid_list) {
kfree(list);
return -ENOMEM;
}
for (i = 0; i < count; i++) {
obj = list[i];
if (!gim_is_removable(bi, obj)) {
valid_list[valid_count] = obj;
valid_count++;
}
}
/* Copy valid objects to new erase-block */
if (valid_count > 0) {
err = ostore_write_obj_list(bi, (void **) valid_list, valid_count, OSW_GC | OSW_SYNC);
kfree(valid_list);
if (err) {
kfree(list);
return err;
}
}
err = ostore_erase(bi, lnum);
if (err) {
kfree(list);
kfree(valid_list);
return err;
}
for (i = 0; i < count; i++)
gim_garbage_collected(bi, list[i]);
bilbyfs_debug("gc_garbage_collect() Successfully clean up lnum=%d\n", lnum);
kfree(list);
return 0;
}