1/*
2 * Copyright 2016, NICTA
3 *
4 * This software may be distributed and modified according to the terms of
5 * the GNU General Public License version 2. Note that NO WARRANTY is provided.
6 * See "LICENSE_GPLv2.txt" for details.
7 *
8 * @TAG(NICTA_GPL)
9 */
10
11#include <bilbyfs.h>
12
13int gc_init(struct bilbyfs_info *bi)
14{
15        bi->gc_buf.buf = vmalloc(bi->super.leb_size);
16        if (bi->gc_buf.buf) {
17                bi->gc_buf.size = bi->super.leb_size;
18                return 0;
19        }
20        return -ENOMEM;
21}
22
23void gc_clean(struct bilbyfs_info *bi)
24{
25        vfree(bi->gc_buf.buf);
26}
27
28int gc_garbage_collect(struct bilbyfs_info *bi)
29{
30        int err, i;
31        int lnum;
32        int list_limit = BILBYFS_MAX_OBJ_PER_TRANS;
33        struct obj_ch *obj;
34        struct obj_ch **list, **valid_list;
35        int count = 0, valid_count = 0;
36
37        bilbyfs_err("bilbyfs GC\n");
38        bilbyfs_debug("gc_garbage_collect() starts\n");
39
40        /* Find block with most garbage */
41        lnum = fsm_get_dirtiest_eb(bi);
42        if (lnum < 0) {
43                bilbyfs_debug("gc_garbage_collect() : No erase-block to garbage collect.\n");
44                return -ENOENT;
45        }
46
47        // Scan erase-block to build object lists
48        list = kmalloc(sizeof(struct obj_ch *) *list_limit);
49        if (!list)
50                return -ENOMEM;
51        count = ostore_scan_leb_obj(bi, &bi->gc_buf, lnum, (void **) list, list_limit);
52        if (count < 0) {
53                kfree(list);
54                return count;
55        }
56
57        valid_list = kmalloc(sizeof(struct obj_ch *) * list_limit);
58        if (!valid_list) {
59                kfree(list);
60                return -ENOMEM;
61        }
62        for (i = 0; i < count; i++) {
63                obj = list[i];
64                if (!gim_is_removable(bi, obj)) {
65                        valid_list[valid_count] = obj;
66                        valid_count++;
67                }
68        }
69
70        /* Copy valid objects to new erase-block */
71        if (valid_count > 0) {
72                err = ostore_write_obj_list(bi, (void **) valid_list, valid_count, OSW_GC | OSW_SYNC);
73                kfree(valid_list);
74                if (err) {
75                        kfree(list);
76                        return err;
77                }
78        }
79
80        err = ostore_erase(bi, lnum);
81        if (err) {
82                kfree(list);
83                kfree(valid_list);
84                return err;
85        }
86
87        for (i = 0; i < count; i++)
88                gim_garbage_collected(bi, list[i]);
89
90        bilbyfs_debug("gc_garbage_collect() Successfully clean up lnum=%d\n", lnum);
91        kfree(list);
92        return 0;
93}
94
95
96