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 ostore_init(struct bilbyfs_info *bi)
14{
15        struct bilbyfs_wbuf *wbuf = &bi->wbuf;
16        int err;
17
18        wbuf->buf = vmalloc(bi->super.leb_size);
19        if (!wbuf->buf)
20                return -ENOMEM;
21        bi->sup_wbuf.buf = vmalloc(bi->super.leb_size);
22        if (!bi->sup_wbuf.buf) {
23                vfree(wbuf->buf);
24                return -ENOMEM;
25        }
26        bi->summary = vmalloc(bi->super.leb_size);
27        if (!bi->summary) {
28                vfree(wbuf->buf);
29                vfree(bi->sup_wbuf.buf);
30                return -ENOMEM;
31        }
32        bi->summary->nb_sum_entry = 0;
33        wbuf->size = bi->super.leb_size;
34        bi->sup_wbuf.size = bi->super.leb_size;
35        err = allocpool_init(&bi->node_pool);
36        if (!err) {
37                err = idx_init(bi);
38                if (!err) {
39                        err = fsm_init(bi);
40                        if (!err) {
41                                err = wbuf_init(bi);
42                                if (!err) {
43                                        err = gim_init(bi);
44                                        if (!err) {
45                                                err = gc_init(bi);
46                                                if (!err)
47                                                        return 0;
48                                                gim_clean(bi);
49                                        }
50                                        wbuf_clean(bi);
51                                }
52                                fsm_clean(bi);
53                        }
54                        idx_clean(bi);
55                }
56                allocpool_destroy(&bi->node_pool);
57        }
58        vfree(wbuf->buf);
59        vfree(bi->sup_wbuf.buf);
60        vfree(bi->summary);
61        return err;
62}
63
64void ostore_clean(struct bilbyfs_info *bi)
65{
66        struct bilbyfs_wbuf *wbuf = &bi->wbuf;
67
68        vfree(wbuf->buf);
69        memset(wbuf, 0, sizeof(*wbuf));
70        vfree(bi->sup_wbuf.buf);
71        memset(&bi->sup_wbuf, 0, sizeof(*wbuf));
72        vfree(bi->summary);
73        idx_clean(bi);
74        fsm_clean(bi);
75        wbuf_clean(bi);
76        gim_clean(bi);
77        gc_clean(bi);
78        allocpool_destroy(&bi->node_pool);
79}
80
81int ostore_get_obj_size(struct bilbyfs_info *bi, obj_id id)
82{
83        struct obj_addr addr;
84        int err;
85
86        err = idx_get_obj_addr(bi, id, &addr);
87        if (err)
88                return err;
89        return addr.len;
90}
91
92int ostore_read_obj(struct bilbyfs_info *bi, obj_id id, void *buf, u32 len)
93{
94        struct obj_addr addr;
95        int err;
96
97        err = idx_get_obj_addr(bi, id, &addr);
98        if (err)
99                return err;
100
101        if (len < addr.len) {
102                bilbyfs_err("ostore_read_obj: buf too small\n");
103                return -EINVAL; /* please try again with a larger buffer */
104        }
105
106        if (addr.lnum == fsm_get_lnum(bi)) { /* Read from write-buffer */
107                bilbyfs_debug("read_obj(oid=%llx) from buffer\n", id);
108                memcpy(buf, bi->wbuf.buf + addr.offs, addr.len);
109                return 0;
110        }
111        err = wbuf_read_obj(bi, buf, &addr);
112        {
113                struct obj_ch *obj = buf;
114                bilbyfs_debug("read_obj({%s,oid=%llx}, {lnum=%d,offs=%d,len=%d}) = %d\n",
115                        (obj->type == BILBYFS_INODE_OBJ ? "inode" :
116                        (obj->type == BILBYFS_DENTARR_OBJ ? "dentarr":
117                        (obj->type == BILBYFS_DATA_OBJ ? "data" :
118                        (obj->type == BILBYFS_DEL_OBJ ? "del" : "unknown")))),
119                        id,
120                        addr.lnum, addr.offs, addr.len, err);
121                bilbyfs_assert(get_obj_id(obj) == id);
122                (void)obj;
123        }
124        return err;
125}
126
127obj_id ostore_next_obj_id(struct bilbyfs_info *bi, obj_id id)
128{
129        obj_id nxt = idx_next_obj_id(bi, id);
130        if (inum_from_id(id) == inum_from_id(nxt))
131                return nxt;
132        return NIL_ID;
133}
134
135/**
136 * proc_obj - process an object
137 *
138 * @bi: global fs info
139 * @type: type of the object
140 * @id: ID of the object
141 * @addr: address of the object on disk
142 *
143 * This function will update:
144 *  - Index: if the object is newer, update the index with the object
145 *  - FSM: older version (if exist) of an object is marked as dirty
146 *
147 * Returns negative error code if unsuccessful or zero otherwise
148 */
149static int proc_obj(struct bilbyfs_info *bi, u8 type, obj_id id, struct obj_addr *addr)
150{
151        obj_id curr_id;
152        struct obj_addr old_addr;
153        struct idx_node *idx_node;
154        struct gim_node *gnode;
155        int err = 0;
156
157        switch (type) {
158        case BILBYFS_PAD_OBJ:
159                fsm_mark_dirty(bi, addr);
160                break;
161        case BILBYFS_INODE_OBJ:
162        case BILBYFS_DENTARR_OBJ:
163        case BILBYFS_DATA_OBJ:
164                /* Valid object */
165                idx_node = idx_get_or_create_obj_addr_node(bi, id);
166                if (!idx_node->addr.sqnum) { /* If we just created this node */
167                        idx_node->addr = *addr;
168                } else {
169                        if (idx_node->addr.sqnum < addr->sqnum) {
170                                /* idx_set_obj_addr(bi, id, addr, NULL); */
171                                idx_node->addr = *addr;
172                                gim_mark_garbage(bi, id, &idx_node->addr, NULL);
173                                fsm_mark_dirty(bi, &idx_node->addr);
174                        } else {
175                                gim_mark_garbage(bi, id, addr, NULL);
176                                fsm_mark_dirty(bi, addr);
177                        }
178                }
179                break;
180        case BILBYFS_DEL_OBJ:
181                /* Delete object */
182                switch (type_from_id(id)) {
183                case BILBYFS_DENTARR_OBJ:
184                        /* Deletion object that cover single object */
185                        err = idx_get_obj_addr(bi, id, &old_addr);
186                        if (!err) { /* Obj found in index */
187                                if (old_addr.sqnum < addr->sqnum) {
188                                        gnode = idx_del_obj_addr(bi, id);
189                                        gim_mark_garbage(bi, id, &old_addr, gnode);
190                                        fsm_mark_dirty(bi, &old_addr);
191                                }
192                        }
193
194                        break;
195                case BILBYFS_INODE_OBJ:
196                case BILBYFS_DATA_OBJ:
197                        /* Deletion object that cover a range of objects */
198                        for (curr_id = id; curr_id != NIL_ID; curr_id = idx_next_obj_id(bi, curr_id)) {
199                                err = idx_get_obj_addr(bi, curr_id, &old_addr);
200                                if (!err) {
201                                        if (old_addr.sqnum < addr->sqnum) {
202                                                gnode = idx_del_obj_addr(bi, curr_id);
203                                                gim_mark_garbage(bi, curr_id, &old_addr, gnode);
204                                                fsm_mark_dirty(bi, &old_addr);
205                                        }
206                                }
207                        }
208                        break;
209                default:
210                        bilbyfs_assert(0);
211                }
212                /* Mark the deletion object itself as dirty */
213                gim_mark_garbage(bi, id, addr, NULL);
214                fsm_mark_dirty(bi, addr);
215                break;
216        default:
217                bilbyfs_assert(0);
218        }
219
220        return 0;
221}
222
223static u8 get_obj_trans(int count, int i)
224{
225        if (count == 1)
226                return BILBYFS_TRANS_ATOM;
227        else if (i == 0)
228                return BILBYFS_TRANS_ST;
229        else if (i == count - 1)
230                return BILBYFS_TRANS_END;
231        return BILBYFS_TRANS_IN;
232}
233
234#define NOBJ BILBYFS_MAX_OBJ_PER_TRANS
235int obj_has_id(struct obj_ch *obj)
236{
237        return (obj->type == BILBYFS_INODE_OBJ ||
238                obj->type == BILBYFS_DENTARR_OBJ ||
239                obj->type == BILBYFS_DATA_OBJ ||
240                obj->type == BILBYFS_DEL_OBJ);
241}
242
243static inline int debug_print_objs(struct bilbyfs_info *bi, u32 lnum)
244{
245        struct obj_ch **olist, **olist2;
246        struct obj_addr addr;
247        int err;
248        int i;
249        struct obj_ch *obj;
250        struct bilbyfs_rbuf rbuf;
251        int nbo, nbo2;
252
253        bilbyfs_debug("ostore_scan_obj() : alloc = %lu\n", (unsigned long)(sizeof(*olist) * NOBJ));
254        olist = kmalloc(sizeof(*olist) * NOBJ);
255        if (!olist)
256                return -ENOMEM;
257        rbuf.buf = bi->wbuf.buf;
258        rbuf.size = bi->wbuf.size;
259        rbuf.offs = 0;
260        err = ostore_scan_obj(bi, &rbuf, lnum, (void **)olist, NOBJ);
261        bilbyfs_debug("ostore_scan_obj() = %d\n", err);
262        if (err < 0) {
263                kfree(olist);
264                return err;
265        }
266        addr.lnum = lnum;
267        addr.offs = 0;
268        addr.len = 0;
269        nbo = err;
270        for (i = 0; i < nbo; i++) {
271                obj = olist[i];
272                addr.len = obj->len;
273                bilbyfs_debug("scan_obj({%s,oid=%llx}, {lnum=%d,offs=%d,len=%d})\n",
274                              (obj->type == BILBYFS_INODE_OBJ ? "inode" :
275                               (obj->type == BILBYFS_DENTARR_OBJ ? "dentarr":
276                                (obj->type == BILBYFS_DATA_OBJ ? "data" :
277                                 (obj->type == BILBYFS_DEL_OBJ ? "del" :
278                                  (obj->type == BILBYFS_SUP_OBJ ? "super" :
279                                   (obj->type == BILBYFS_PAD_OBJ ? "pad" : "unknown")))))),
280                                (!obj_has_id(obj) ? 0 : get_obj_id(obj)),
281                              addr.lnum, addr.offs, addr.len);
282                addr.offs += addr.len;
283        }
284        bilbyfs_debug("ostore_scan_obj() = %d\n", err);
285        olist2 = kmalloc(sizeof(*olist) * NOBJ);
286        if (!olist2)
287                return -ENOMEM;
288        err = ostore_scan_leb_obj(bi, &bi->rbuf, lnum, (void **)olist2, NOBJ);
289        if (err < 0) {
290                kfree(olist);
291                kfree(olist2);
292                return err;
293        }
294        addr.lnum = lnum;
295        addr.offs = 0;
296        addr.len = 0;
297        nbo2 = err;
298        for (i = 0; i < nbo2; i++) {
299                obj = olist2[i];
300                addr.len = obj->len;
301                bilbyfs_debug("scan_obj({%s,oid=%llx}, {lnum=%d,offs=%d,len=%d})\n",
302                              (obj->type == BILBYFS_INODE_OBJ ? "inode" :
303                               (obj->type == BILBYFS_DENTARR_OBJ ? "dentarr":
304                                (obj->type == BILBYFS_DATA_OBJ ? "data" :
305                                 (obj->type == BILBYFS_DEL_OBJ ? "del" :
306                                  (obj->type == BILBYFS_SUP_OBJ ? "super" :
307                                   (obj->type == BILBYFS_PAD_OBJ ? "pad" : "unknown")))))),
308                                (!obj_has_id(obj) ? 0 : get_obj_id(obj)),
309                              addr.lnum, addr.offs, addr.len);
310                err = memcmp(obj, olist[i], obj->len);
311                bilbyfs_assert(!err);
312                addr.offs += addr.len;
313        }
314        if (nbo != nbo2) {
315                print_hex_dump(KERN_ERR, "wbuf: ", DUMP_PREFIX_ADDRESS, 32, 8, rbuf.buf, rbuf.size, true);
316                print_hex_dump(KERN_ERR, "rbuf: ", DUMP_PREFIX_ADDRESS, 32, 8, bi->rbuf.buf, bi->rbuf.size, true);
317        }
318        kfree(olist2);
319        kfree(olist);
320        return 0;
321}
322
323int obj_sum_size_with_extra(struct obj_sum *sum, u32 nb_extra_entries)
324{
325        return ALIGN(obj_sum_size(sum) + nb_extra_entries * BILBYFS_SUM_ENTRY_SZ, BILBYFS_OBJ_PADDING);
326}
327
328int ostore_write_summary(struct bilbyfs_info *bi, u32 *padding_sz)
329{
330        struct bilbyfs_wbuf *wbuf = &bi->wbuf;
331        struct obj_ch *ch;
332        int err;
333        u32 len;
334        u32 pad_sz;
335
336        len = obj_sum_size(bi->summary);
337        bilbyfs_assert(wbuf->avail >= len);
338
339        /* wbuf summary aware padding */
340        pad_sz = wbuf->avail - len;
341        if (pad_sz < BILBYFS_CH_SZ) {
342                memset(wbuf->buf + wbuf->used, BILBYFS_PAD_BYTE, pad_sz);
343        } else {
344                ch = wbuf->buf + wbuf->used;
345                pack_obj_pad(ch, pad_sz);
346                pack_obj_header(ch, next_sqnum(bi), BILBYFS_TRANS_ATOM);
347        }
348        if (padding_sz)
349                *padding_sz = pad_sz;
350        wbuf->avail -= pad_sz;
351        wbuf->used += pad_sz;
352        pack_obj_sum(bi->summary, wbuf->used);
353        pack_obj_header(&bi->summary->ch, next_sqnum(bi), BILBYFS_TRANS_ATOM);
354        err = wbuf_write_obj(bi, bi->summary, len, wbuf);
355        bilbyfs_debug("ostore_write_summary(offset=%u) = %d\n", wbuf->used, err);
356        if (!err)
357                bi->summary->nb_sum_entry = 0;
358        bilbyfs_assert(wbuf->avail == 0);
359        return err;
360}
361
362void sum_obj(struct bilbyfs_info *bi, struct obj_ch *obj, struct obj_addr *addr)
363{
364        struct obj_sum *sum = bi->summary;
365        struct obj_sum_entry *entry;
366        obj_id oid, eoid;
367        u8 oid_type;
368        u32 nb_sum_entry = le32_to_cpu(sum->nb_sum_entry);
369        bool is_del;
370        int i;
371
372        oid = get_obj_id(obj);
373        oid_type = type_from_id(oid);
374        is_del = obj->type == BILBYFS_DEL_OBJ;
375
376        /* If we have a deletion object, we can only replace younger deletion
377         * objects that have the exact same oid in case of dentarr deletion or
378         * objects that have a higher oid for inode and data deletion objects.
379         * Summary of non-deletion objects can only replace objects with
380         * the exact same oid.
381         */
382        if (is_del) {
383                for (i = 0; i < nb_sum_entry; i++) {
384                        entry = &sum->entries[i];
385                        eoid = le64_to_cpu(entry->id);
386
387                        if (oid_type == BILBYFS_DENTARR_OBJ) {
388                                if (eoid == oid) {
389                                        if (le64_to_cpu(entry->sqnum) > addr->sqnum) {
390                                                return;
391                                        }
392                                        break;
393                                }
394                        } else if (inum_from_id(eoid) == inum_from_id(oid) && eoid > oid) {
395                                if (le64_to_cpu(entry->sqnum) < addr->sqnum)
396                                        break;
397                        }
398                }
399        } else {
400                for (i = 0; i < nb_sum_entry; i++) {
401                        entry = &sum->entries[i];
402                        /* We cannot replace a del object with an new object */
403                        if (obj_sum_entry_is_del(entry) && oid_type != BILBYFS_DENTARR_OBJ)
404                                continue;
405                        eoid = le64_to_cpu(entry->id);
406                        if (eoid == oid) {
407                                if (le64_to_cpu(entry->sqnum) > addr->sqnum)
408                                        return;
409                                break;
410                        }
411                }
412        }
413        /*  Not that the whole if/else above is an optimisation to
414         *  reuse a sum_entry, we could safely replace it with
415         *  i = nb_sum_entry;
416         */
417        entry = &sum->entries[i];
418        entry->id = oid;
419        entry->len = cpu_to_le32(addr->len);
420        entry->sqnum = cpu_to_le64(addr->sqnum);
421        entry->del_flag_and_offs = cpu_to_le32(addr->offs | (is_del ? BILBYFS_SUM_ENTRY_DEL_FLAG_MASK : 0));
422        if (i == nb_sum_entry) {
423                sum->nb_sum_entry = cpu_to_le32(nb_sum_entry + 1);
424                entry->count = 0;
425        } else
426                entry->count = cpu_to_le32(le32_to_cpu(entry->count) + 1);
427}
428
429int ostore_sync(struct bilbyfs_info *bi, int force_summary)
430{
431        struct bilbyfs_wbuf *wbuf = &bi->wbuf;
432        int err = 0;
433        u32 padding_size;
434        struct obj_addr curr_addr;
435        u32 sum_sz;
436
437        bilbyfs_debug("ostore_sync()\n");
438        if (bi->no_summary)
439                force_summary = 0;
440        if (wbuf->sync_offs == wbuf->used && !force_summary)
441                return 0;
442        if (!wbuf->avail)
443                return 0;
444        bilbyfs_assert(!!fsm_get_lnum(bi));
445        curr_addr.lnum = fsm_get_lnum(bi);
446        curr_addr.offs = wbuf->used;
447        /* Pad buffer to min_io_size */
448        /*
449         * We want to pad with a obj_pad only if that leaves enough space to
450         * write at least one more object (remember we also need to count space
451         * for the summary).
452         */
453        sum_sz = obj_sum_size_with_extra(bi->summary, 1);
454        if (!bi->no_summary && (force_summary || ALIGN(wbuf->used, bi->super.min_io_size) + sum_sz + BILBYFS_MIN_OBJ_SZ > bi->super.leb_size)) {
455                err = ostore_write_summary(bi, &padding_size);
456                if (err)
457                        return err;
458        } else
459                wbuf_prepare_commit(bi, &padding_size, wbuf);
460
461        if (padding_size > 0) {
462                curr_addr.len = padding_size;
463                fsm_mark_dirty(bi, &curr_addr);
464        }
465        err = wbuf_commit(bi, fsm_get_lnum(bi), wbuf);
466        /* bilbyfs_debug("debug_print_obj(%u) = %d\n", fsm_get_lnum(bi), debug_print_objs(bi, fsm_get_lnum(bi))); */
467        return err;
468}
469
470u32 obj_list_serial_size(struct obj_ch **obj_list, int count)
471{
472        u32 sz = 0;
473        int i;
474
475        for (i = 0; i < count; i++) {
476                sz += obj_list[i]->len;
477        }
478        return sz;
479}
480
481int ostore_write_obj_list(struct bilbyfs_info *bi, void **obj_list, int count, int osw_flag)
482{
483        int i;
484        int err = 0;
485        struct obj_ch *obj;
486        struct obj_addr curr_addr;
487        struct bilbyfs_wbuf *wbuf = &bi->wbuf;
488        u32 serial_sz;
489        u32 offs;
490
491	if (!fsm_get_lnum(bi) || !wbuf->avail) {
492                err = fsm_alloc_eb(bi, osw_flag);
493                if (err)
494                        return err;
495                wbuf_start(bi, wbuf);
496        }
497        bilbyfs_debug("wbuf->avail = %u, obj_sum_size = %u\n", wbuf->avail , obj_sum_size(bi->summary));
498        if (!bi->no_summary)
499                bilbyfs_assert(wbuf->avail >= obj_sum_size(bi->summary));
500        if (osw_flag & OSW_SYNC) {
501               err = ostore_sync(bi, false);
502               if (err)
503                       return err;
504        }
505        if (!bi->no_summary)
506                bilbyfs_assert(wbuf->avail >= obj_sum_size(bi->summary));
507        bilbyfs_assert(count > 0);
508        for (i = 0; i < count; i++) {
509                obj = obj_list[i];
510                pack_obj_header(obj, next_sqnum(bi), get_obj_trans(count, i));
511        }
512        serial_sz = obj_list_serial_size((struct obj_ch **)obj_list, count);
513        bilbyfs_assert(serial_sz <= bi->super.leb_size);
514        if (wbuf->avail < serial_sz + (bi->no_summary ? 0 : obj_sum_size_with_extra(bi->summary, count))) {
515                err = ostore_sync(bi, true);
516                if (err)
517                        return err;
518                err = fsm_alloc_eb(bi, osw_flag);
519                if (err)
520                        return err;
521                wbuf_start(bi, wbuf);
522        }
523
524        offs = wbuf->used;
525        /* Write objects into wbuf */
526        for (i = 0; i < count; i++) {
527                obj = obj_list[i];
528                err = wbuf_write_obj(bi, obj, le32_to_cpu(obj->len), wbuf);
529                if (err)
530                        return err;
531        }
532
533        if (osw_flag & OSW_SYNC) {
534               err = ostore_sync(bi, false);
535               if (err)
536                       return err;
537        }
538
539        /* Preallocate new index and gim entries */
540        err = allocpool_alloc(&bi->node_pool, count * 2, NODE_SIZE);
541        if (err)
542                return err;
543
544        /* Update index & fsm */
545        curr_addr.lnum = fsm_get_lnum(bi);
546        curr_addr.offs = offs;
547        curr_addr.len = 0;
548        bilbyfs_debug(".\n");
549        for (i = 0; i < count; i++) {
550                obj = obj_list[i];
551                curr_addr.offs += curr_addr.len;
552                curr_addr.len = le32_to_cpu(obj->len);
553                curr_addr.sqnum = le64_to_cpu(obj->sqnum);
554
555                err = proc_obj(bi, obj->type, get_obj_id(obj), &curr_addr);
556                bilbyfs_debug("write_obj({%s,oid=%llx}, {lnum=%d,offs=%d,len=%d,sqnum=%llu}) = %d\n",
557                              (obj->type == BILBYFS_INODE_OBJ ? "inode" :
558                               (obj->type == BILBYFS_DENTARR_OBJ ? "dentarr":
559                                (obj->type == BILBYFS_DATA_OBJ ? "data" :
560                                 (obj->type == BILBYFS_DEL_OBJ ? "del" : "unknown")))),
561                                get_obj_id(obj),
562                              curr_addr.lnum, curr_addr.offs, curr_addr.len, curr_addr.sqnum, err);
563                if (err)
564                        bilbyfs_assert(false);
565                if (!bi->no_summary)
566                        sum_obj(bi, obj, &curr_addr);
567        }
568        allocpool_empty(&bi->node_pool);
569        return 0;
570}
571
572int ostore_erase(struct bilbyfs_info *bi, int lnum)
573{
574        int err;
575
576        err = wbuf_erase(bi, lnum);
577        if (err)
578                return err;
579
580        fsm_mark_erased(bi, lnum);
581        return 0;
582}
583
584int ostore_scan_obj(struct bilbyfs_info *bi, struct bilbyfs_rbuf *rbuf, int lnum,
585                    void **list, int max_count)
586{
587        int err;
588        struct obj_addr addr;
589        struct obj_ch *obj;
590        int count = 0;
591
592        addr.lnum = lnum;
593        addr.offs = 0;
594        addr.len = 0;
595        obj = wbuf_next_obj_addr(bi, &addr, rbuf);
596        while (!IS_ERR(obj)) {
597                if (count >= max_count)
598                        return -EOVERFLOW;
599                list[count] = obj;
600                count++;
601                obj = wbuf_next_obj_addr(bi, &addr, rbuf);
602        }
603        err = PTR_ERR(obj);
604        if (err == -ENOENT)
605                if (count > 0)
606                        return count;
607        return err;
608}
609
610int ostore_scan_leb_obj(struct bilbyfs_info *bi, struct bilbyfs_rbuf *rbuf, int lnum,
611                        void **list, int max_count)
612{
613        int err;
614
615        rbuf->offs = 0;
616        err = wbuf_read_leb(bi, lnum, rbuf);
617        if (err)
618                return err;
619        return ostore_scan_obj(bi, rbuf, lnum, list, max_count);
620}
621
622unsigned long long ostore_get_free_space(struct bilbyfs_info *bi)
623{
624        return fsm_get_free_space(bi);
625}
626
627unsigned long long ostore_get_available_space(struct bilbyfs_info *bi)
628{
629        return fsm_get_available_space(bi);
630}
631
632static struct obj_super *next_super_addr(struct bilbyfs_info *bi,
633                                         struct obj_addr *addr,
634                                         struct bilbyfs_rbuf *rbuf)
635{
636        struct obj_ch *obj;
637
638        do {
639                obj = wbuf_next_obj_addr(bi, addr, rbuf);
640                if (IS_ERR(obj))
641                        return (struct obj_super *)obj;
642        } while (obj->type != BILBYFS_SUP_OBJ);
643        return (struct obj_super *)obj;
644}
645
646/* SuperBlock objects are sequentially stored in BILBYFS_SUP_LNUM
647 * When BILBYFS_SUP_LNUM is full we need to atomically erase the erase-block
648 * and store a new object in it. To this end we use ubi_leb_change.
649 */
650static int mount_read_super(struct bilbyfs_info *bi)
651{
652        struct bilbyfs_rbuf *rbuf = &bi->rbuf;
653        struct obj_super *super, *perr;
654        struct obj_addr addr;
655        int err;
656
657        err = wbuf_read_leb_fast(bi, BILBYFS_SUP_LNUM, rbuf);
658        if (err)
659                return err;
660
661        addr.lnum = BILBYFS_SUP_LNUM;
662        addr.offs = 0;
663        addr.len = 0;
664        perr = next_super_addr(bi, &addr, rbuf);
665        super = perr;
666        while (!IS_ERR(perr)) {
667                super = perr;
668                perr = next_super_addr(bi, &addr, rbuf);
669        }
670        if (IS_ERR(super))
671                return PTR_ERR(super);
672
673        if (super->ch.type != BILBYFS_SUP_OBJ ||
674            le32_to_cpu(super->ch.len) != BILBYFS_SUPER_SZ) {
675                bilbyfs_err("Invalid Super object!\n");
676                return -EINVAL;
677        }
678        unpack_obj_super(&bi->super, super);
679        bi->super.min_io_size = bi->di.min_io_size;
680        /* FIXME: Ensure that max_io_size is only used for write accesses */
681        bi->super.max_io_size = bi->di.max_write_size;
682        /* Go to the very last object and get the offs */
683        while (!IS_ERR(wbuf_next_obj_addr(bi, &addr, rbuf)));
684        bi->super_offs = addr.offs + addr.len;
685
686        if (bi->next_sqnum < bi->super.sqnum) /* FIXME sanity check */
687                bi->next_sqnum = bi->super.sqnum + 1;
688        if (bi->next_inum < bi->super.last_inum) /* FIXME sanity check */
689                bi->next_inum = bi->super.last_inum + 1;
690        return 0;
691}
692
693int ostore_write_super(struct bilbyfs_info *bi)
694{
695        struct bilbyfs_wbuf *wbuf = &bi->sup_wbuf;
696        struct obj_super sup;
697        int size_trans;
698        int err;
699
700        bilbyfs_debug("ostore_write_super(lnum = %d, offs = %d) = ?\n",
701                      BILBYFS_SUP_LNUM, bi->super_offs);
702
703        bi->super.log_lnum = fsm_get_lnum(bi);
704        bi->super.log_offs = bi->wbuf.sync_offs;
705        bi->super.last_inum = bi->next_inum - 1;
706        wbuf_start(bi, wbuf);
707        wbuf->used = bi->super_offs;
708        wbuf->sync_offs = bi->super_offs;
709        memset(&sup, 0, sizeof(sup));
710        pack_obj_super(&sup, &bi->super);
711        pack_obj_header(&sup, next_sqnum(bi), BILBYFS_TRANS_ATOM);
712        err = wbuf_write_obj(bi, &sup, BILBYFS_SUPER_SZ, wbuf);
713        if (!err) {
714                size_trans = wbuf_prepare_commit(bi, NULL, wbuf);
715                err = wbuf_commit(bi, BILBYFS_SUP_LNUM, wbuf);
716                if (!err) /* Obtain the next super offset */
717                        bi->super_offs = wbuf->used;
718        } else {
719                wbuf_start(bi, wbuf);
720                err = wbuf_write_obj(bi, &sup, BILBYFS_SUPER_SZ, wbuf);
721                if (!err) {
722                        size_trans = wbuf_prepare_commit(bi, NULL, wbuf);
723                        err = wbuf_atom_leb_commit(bi, BILBYFS_SUP_LNUM, wbuf);
724                        if (!err) /* Obtain the next super offset */
725                                bi->super_offs = wbuf->used;
726                }
727        }
728        return err;
729}
730
731static int mount_check_super(struct bilbyfs_info *bi)
732{
733        struct bilbyfs_super *sup = &bi->super;
734
735        if (sup->leb_size != bi->vi.usable_leb_size) {
736                bilbyfs_err("super.leb_size (%d) is not compatible with the"
737                            "vi.usable_leb_size (%d) of the flash\n",
738                            sup->leb_size, bi->vi.usable_leb_size);
739                return -EINVAL;
740        }
741        if (sup->min_io_size > sup->leb_size ||
742            sup->max_io_size > sup->leb_size ||
743            sup->min_io_size > sup->max_io_size ||
744            (sup->max_io_size % sup->min_io_size) != 0 ||
745            (sup->leb_size % sup->min_io_size) != 0 ||
746            (sup->leb_size % sup->max_io_size) != 0) {
747                bilbyfs_err("Invalid leb_size/min_io_size/max_io_size "
748                            "combinaison: "
749                            "(leb_size = %d, max_io_sz = %d, min_io_sz = %d)",
750                            sup->leb_size, sup->max_io_size, sup->min_io_size);
751                return -EINVAL;
752        }
753        if (sup->leb_cnt < sup->nb_reserved_gc + sup->nb_reserved_del + BILBYFS_MIN_USABLE_LOG_SZ) {
754                bilbyfs_err("Number of erasble-blocks too small for nb_(eb|gc|del) and min_usable_log_sz "
755                            "(leb_cnt = %d, nb_gc = %d, nb_del = %d, min_usable_log_sz = %d)\n",
756                            sup->leb_cnt, sup->nb_reserved_gc, sup->nb_reserved_del, BILBYFS_MIN_USABLE_LOG_SZ);
757                return -EINVAL;
758        }
759
760        return 0;
761}
762
763/**
764 * A list list to store deletion objects and their addresses at mount time
765 */
766struct list_obj_del {
767        u8 type;
768        obj_id id;
769        struct obj_addr addr;
770        struct list_obj_del *next;
771};
772
773static int add_to_del_list(struct list_obj_del **del_list, obj_id id, struct obj_addr *addr)
774{
775        struct list_obj_del *node;
776
777        node = kmalloc(sizeof(*node));
778        if (!node)
779                return -ENOMEM;
780
781        node->id = id;
782        memcpy(&node->addr, addr, sizeof(*addr));
783
784        node->next = *del_list;
785        *del_list = node;
786
787        return 0;
788}
789
790static void clean_del_list(struct list_obj_del *del_list)
791{
792        struct list_obj_del *curr, *next;
793        curr = del_list;
794
795        while (curr != NULL) {
796                next = curr->next;
797                kfree(curr);
798                curr = next;
799        }
800}
801
802/* check_trans_pos: Checks whether the transaction attribute @pos is
803 * valid.
804 * @trans_nb_obj: current number of elements in the transaction
805 * @pos: transaction attribute of last element read
806 *
807 * This function returns %-EINVAL if the attribute is invalid, it
808 * returns 1 if it's the last element of the transaction, 0 if more
809 * objects are expected.
810 */
811static int check_trans_pos(int trans_nb_obj, u8 pos)
812{
813        switch (pos) {
814        case BILBYFS_TRANS_ATOM:
815                if (trans_nb_obj)
816                        return -EINVAL;
817                return  1;
818        case BILBYFS_TRANS_ST:
819                if (trans_nb_obj)
820                        return -EINVAL;
821                return 0;
822        case BILBYFS_TRANS_IN:
823                if (!trans_nb_obj)
824                        return -EINVAL;
825                return 0;
826        case BILBYFS_TRANS_END:
827                if (!trans_nb_obj)
828                        return -EINVAL;
829                return 1;
830        default:
831                bilbyfs_err("Unknown trans pos value %x", pos);
832                return -EINVAL;
833        }
834}
835
836/* mount_scan_rbuf: Scan every object stored in a read-buffer
837 * @bi: global fs info
838 * @addr: address to start with
839 * @rbuf: read-buffer to scan
840 * @del_list: a list to store the deletion objects
841 *
842 * This function returns a negative error-code if unsuccessful.
843 */
844static int mount_scan_rbuf(struct bilbyfs_info *bi, struct obj_addr *addr,
845                           struct bilbyfs_rbuf *rbuf, struct list_obj_del **del_list)
846{
847        struct obj_addr *addrs;
848        struct obj_ch *obj;
849        int trans_nb_obj = 0;
850        int last;
851        int err;
852        int i;
853
854        bilbyfs_assert(addr->len == 0);
855        addrs = bi->addrs;
856        if (!addrs)
857                return -ENOMEM;
858
859        for (obj = wbuf_next_obj_addr(bi, addr, rbuf);
860             !IS_ERR(obj);
861             obj = wbuf_next_obj_addr(bi, addr, rbuf)) {
862                bilbyfs_debug("mount_scan_rbuf() loop obj->type = %d nb_obj_in_trans=%d\n", obj->type, trans_nb_obj);
863                last = check_trans_pos(trans_nb_obj, obj->trans);
864                /* Invalid transaction value */
865                if (last < 0) {
866                        bilbyfs_err("Invalid trans pos value 0x%x, this may just"
867                                    "be because of a power-failure.", obj->trans);
868                        trans_nb_obj = 0;
869                        continue;
870                }
871
872                /* We enqueue all the objects of a transaction */
873                memcpy(&addrs[trans_nb_obj], addr, sizeof(*addr));
874                trans_nb_obj++;
875                if (!last) {
876                        if (trans_nb_obj == BILBYFS_MAX_OBJ_PER_TRANS) {
877                                bilbyfs_err("Invalid transaction with too many objects (%d"
878                                            "objects, limit=%d)", trans_nb_obj,
879                                            BILBYFS_MAX_OBJ_PER_TRANS);
880                                trans_nb_obj = 0;
881                        }
882                        continue;
883                }
884                /* This was the last object of the transaction,
885                 * will process all the objects.
886                 * Note: deletion objects are saved in a list and will be processed later.
887                 */
888                err = allocpool_alloc(&bi->node_pool, trans_nb_obj * 2, NODE_SIZE);
889                if (err)
890                        return err;
891                for (i = 0; i < trans_nb_obj; i++) {
892                        obj = rbuf->buf + addrs[i].offs;
893                        if (obj->type == BILBYFS_DEL_OBJ)
894                                err = add_to_del_list(del_list, get_obj_id(obj), &addrs[i]);
895                        else if (obj->type == BILBYFS_PAD_OBJ)
896                                err = proc_obj(bi, obj->type, 0, &addrs[i]);
897                        else if  (obj->type != BILBYFS_SUM_OBJ)
898                                err = proc_obj(bi, obj->type, get_obj_id(obj), &addrs[i]);
899
900                        if (err) {
901                                allocpool_empty(&bi->node_pool);
902                                return err;
903                        }
904                }
905                trans_nb_obj = 0;
906                allocpool_empty(&bi->node_pool);
907        }
908
909        err = PTR_ERR(obj);
910        return err;
911}
912
913int mount_proc_sum(struct bilbyfs_info *bi, u32 lnum, struct obj_sum *sum, u32 maxsz, struct list_obj_del **del_list)
914{
915        int i;
916        int err;
917        struct obj_addr addr;
918        struct obj_sum_entry *entry;
919        obj_id id;
920        u32 tot_used = 0;
921
922        addr.lnum = lnum;
923        err = check_obj_header(&sum->ch, maxsz);
924        if (err)
925                return err;
926        if (sum->ch.type != BILBYFS_SUM_OBJ) {
927                bilbyfs_debug("Summary object expected, found %d\n", sum->ch.type);
928                return -EINVAL;
929        }
930        for (i = 0; i < le32_to_cpu(sum->nb_sum_entry); i++) {
931                entry = &sum->entries[i];
932                addr.offs = obj_sum_entry_offs(entry);
933                addr.len = le32_to_cpu(entry->len);
934                tot_used += addr.len;
935                addr.sqnum = le64_to_cpu(entry->sqnum);
936                id = le64_to_cpu(entry->id);
937                // bilbyfs_debug("sum_entry{.offs = %u, .len = %u, .sqnum = %llu, .oid = %llu, .is_del=%u}\n", obj_sum_entry_offs(entry), le32_to_cpu(entry->len), le64_to_cpu(entry->sqnum), le64_to_cpu(entry->id), obj_sum_entry_is_del(entry));
938                if (obj_sum_entry_is_del(entry)) {
939                        err = add_to_del_list(del_list, id, &addr);
940                        if (err)
941                                return err;
942                } else {
943                        err = proc_obj(bi, type_from_id(id), id, &addr);
944                        if (err)
945                                return err;
946                }
947                gim_mark_garbage_cnt(bi, id, &addr, (u32) cpu_to_le16(entry->count), NULL);
948        }
949        addr.lnum = lnum;
950        addr.len = bi->super.leb_size - tot_used;
951        fsm_mark_dirty(bi, &addr);
952        return 0;
953}
954
955static inline int mount_init_log(struct bilbyfs_info *bi, struct list_obj_del **del_list)
956{
957        struct bilbyfs_rbuf rbuf;
958        struct obj_addr addr;
959        int err;
960
961        rbuf.buf = bi->wbuf.buf;
962        rbuf.size = bi->wbuf.size;
963        rbuf.offs = 0;
964        bi->fsm_lnum = bi->super.log_lnum;
965        fsm_mark_used(bi, bi->fsm_lnum);
966        err = wbuf_read_leb(bi, bi->super.log_lnum, &rbuf);
967        if (err)
968                return err;
969        addr.lnum = bi->fsm_lnum;
970        addr.offs = 0;
971        addr.len = 0;
972        err = mount_scan_rbuf(bi, &addr, &rbuf, del_list);
973        if (err == -ENOENT) {
974                bi->wbuf.sync_offs = addr.offs + addr.len;
975                bi->wbuf.used = addr.offs + addr.len;
976                bi->wbuf.avail = bi->super.leb_size - bi->wbuf.used;
977        } else if (err) {
978                clean_del_list(*del_list);
979                return err;
980        } else { /* mount_scan_rbuf didn't fail, erase-block is full of valid data */
981                bi->wbuf.sync_offs = bi->super.leb_size;
982                bi->wbuf.used = bi->super.leb_size;
983                bi->wbuf.avail = 0;
984        }
985        bi->wbuf.buf = rbuf.buf;
986        if (bi->wbuf.sync_offs  != bi->super.log_offs) {
987                bilbyfs_err("super.log_offs is different from the content of the erase-block %d, %d != %d\n", bi->super.log_lnum, bi->wbuf.sync_offs, bi->super.log_offs);
988        }
989        return 0;
990}
991
992static int mount_scan(struct bilbyfs_info *bi)
993{
994        struct obj_addr addr;
995        struct list_obj_del *del_list = NULL;
996        struct list_obj_del *curr;
997        int err = 0;
998        u32 sum_offs;
999        /* struct timeval st, stp; */
1000
1001        bilbyfs_debug("mount_scan(): Scanning each LEB\n");
1002        /*
1003        if (bi->super.log_lnum > 0) {
1004                err = mount_init_log(bi, &del_list);
1005                if (err)
1006                        return err;
1007        }
1008        */
1009        bilbyfs_err("BilbyFs mount start\n");
1010        bi->nb_pages = 0;
1011        bi->nb_extra_pages = 0;
1012        bi->node_pool.tot_nodes_needed = 0;
1013        bi->gim_allocated_for_nothing = 0;
1014        for (addr.lnum = BILBYFS_LOG_FST_LNUM;
1015             addr.lnum < bi->super.leb_cnt;
1016             addr.lnum++) {
1017                if (!ubi_is_mapped(bi->ubi, addr.lnum) /* || addr.lnum == bi->super.log_lnum */)
1018                        continue;
1019                fsm_mark_used(bi, addr.lnum);
1020                if (!bi->no_summary) {
1021                        /*
1022                        do_gettimeofday(&st);
1023                        */
1024                        err = wbuf_read_sum(bi, addr.lnum, &bi->rbuf, &sum_offs);
1025                        /*
1026                        do_gettimeofday(&stp);
1027                        pr_err("timed wbuf_read_sum() : %ld sec %ld usec\n", stp.tv_sec - st.tv_sec, stp. tv_usec - st.tv_usec);
1028                        */
1029                        if (!err) {
1030                         /*       do_gettimeofday(&st); */
1031                                err = mount_proc_sum(bi, addr.lnum, (struct obj_sum *)(bi->rbuf.buf + sum_offs),
1032                                                     bi->super.leb_size - sum_offs, &del_list);
1033                        /*
1034                                do_gettimeofday(&stp);
1035                                pr_err("timed mount_proc_sum() : %ld sec %ld usec\n", stp.tv_sec - st.tv_sec, stp. tv_usec - st.tv_usec);
1036                        */
1037                                if (err)
1038                                        return err;
1039                                continue;
1040                        }
1041                        bilbyfs_err("Failure to use the summary, fall back to scanning the erase-block (lnum=%d), err = %d\n", addr.lnum, err);
1042                        if (err != -ENOENT)
1043                                return err;
1044                }
1045                err = wbuf_read_leb(bi, addr.lnum, &bi->rbuf);
1046                if (err) {
1047                        clean_del_list(del_list);
1048                        return err;
1049                }
1050                addr.offs = 0;
1051                addr.len = 0;
1052                err = mount_scan_rbuf(bi, &addr, &bi->rbuf, &del_list);
1053                if (err == -ENOENT) {
1054                        addr.offs += addr.len;
1055                        addr.len = bi->super.leb_size - addr.offs;
1056                        fsm_mark_dirty(bi, &addr);
1057                } else if (err) {
1058                        clean_del_list(del_list);
1059                        return err;
1060                }
1061        }
1062
1063        bilbyfs_debug("mount_scan(): Processing deletion objects\n");
1064        /* do_gettimeofday(&st); */
1065        for (curr = del_list; curr; curr = curr->next) {
1066                err = proc_obj(bi, BILBYFS_DEL_OBJ, curr->id, &curr->addr);
1067                if (err) {
1068                        clean_del_list(del_list);
1069                        return err;
1070                }
1071        }
1072
1073        clean_del_list(del_list);
1074        /*
1075        do_gettimeofday(&stp);
1076        pr_err("timed del_obj_proc() : %ld.%ld\n", stp.tv_sec - st.tv_sec, stp. tv_usec - st.tv_usec);
1077        */
1078
1079        bilbyfs_err("BilbyFs mount finished pages = %d, extra_pages = %d, tot_nodes = %d, gim_allocated_for nothing = %d\n", bi->nb_pages, bi->nb_extra_pages, bi->node_pool.tot_nodes_needed, bi->gim_allocated_for_nothing);
1080        return 0;
1081}
1082
1083/* Move this to wbuf? */
1084static int check_flash_empty(struct bilbyfs_info *bi)
1085{
1086        int empty = 1;
1087        int lnum;
1088        int err;
1089
1090        for (lnum = 0; lnum < bi->super.leb_cnt; lnum++) {
1091                err = ubi_is_mapped(bi->ubi, lnum);
1092                if (err < 0)
1093                        return err;
1094                if (err == 1) {
1095                        empty = 0;
1096                        break;
1097                }
1098        }
1099        return empty;
1100}
1101
1102int ostore_mount(struct bilbyfs_info *bi)
1103{
1104        int empty;
1105        int err;
1106
1107        empty = check_flash_empty(bi);
1108        if (empty < 0) {
1109                err = empty;
1110        } else if (empty) {
1111                return -ENODATA;
1112        } else {
1113                err = mount_read_super(bi);
1114                if (!err) {
1115                        err = mount_check_super(bi);
1116                        if (!err) {
1117                                bi->is_mounting = true;
1118                                bi->addrs = kmalloc(sizeof(*(bi->addrs)) * BILBYFS_MAX_OBJ_PER_TRANS);
1119                                if (!bi->addrs)
1120                                        return -ENOMEM;
1121                                err = allocpool_alloc(&bi->node_pool, 10000, NODE_SIZE);
1122                                if (err) {
1123                                        kfree(bi->addrs);
1124                                        return err;
1125                                }
1126                                err = mount_scan(bi);
1127                                allocpool_empty(&bi->node_pool);
1128                                kfree(bi->addrs);
1129                                bi->is_mounting = false;
1130                                if (!err)
1131                                        return 0;
1132                        }
1133                } else if (err == -ENOENT) {
1134                        bilbyfs_err("Not a BilbyFs file system!\n");
1135                }
1136        }
1137        ostore_unmount(bi);
1138        return err;
1139}
1140
1141void ostore_unmount(struct bilbyfs_info *bi)
1142{
1143        int err;
1144
1145        /* We write a new super object only if we have written objects to the
1146         * media since the last update. (i.e. the last written object is not
1147         * the super block).
1148         */
1149        if (bi->super.sqnum + 1 < bi->next_sqnum) {
1150                err = ostore_sync(bi, true);
1151                if (err) {
1152                        bilbyfs_err("Could not synchronize FS when unmounting.\n");
1153                }
1154                err = ostore_write_super(bi);
1155                if (err)
1156                        bilbyfs_err("Could not write the super object %d\n", err);
1157                else
1158                        bilbyfs_debug("ostore_unmount(): super block written\n");
1159        }
1160}
1161
1162