Skip to content

Commit 030fe79

Browse files
driver/mtd/dhara.c: Metadata Cache Implementation
A Metadata Cache based on Most Recently Used Metadata Page has been implemented inside file dhara.c that can be useful for faster page reads. Signed-off-by: Aditya Singh <aditya.s4@samsung.com> Signed-off-by: Aashish Lakhwara <aashish.l@samsung.com>w
1 parent 964d6bd commit 030fe79

File tree

1 file changed

+182
-16
lines changed

1 file changed

+182
-16
lines changed

os/fs/driver/mtd/dhara.c

Lines changed: 182 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,11 @@
4040
****************************************************************************/
4141

4242
#include <tinyara/config.h>
43-
4443
#include <errno.h>
4544
#include <debug.h>
4645
#include <stdio.h>
47-
4846
#include <tinyara/kmalloc.h>
4947
#include <tinyara/fs/mtd.h>
50-
5148
#include "dhara/map.h"
5249
#include "dhara/nand.h"
5350

@@ -57,19 +54,24 @@
5754
/****************************************************************************
5855
* Pre-processor Definitions
5956
****************************************************************************/
60-
57+
#define CONFIG_DHARA_METADATA_NCACHES 8
6158
/****************************************************************************
6259
* Private Types
6360
****************************************************************************/
64-
6561
struct dhara_pagecache_s {
6662
dq_entry_t node;
6763
dhara_page_t page;
6864
FAR uint8_t *buffer;
6965
};
7066

7167
typedef struct dhara_pagecache_s dhara_pagecache_t;
68+
struct dhara_metadatacache_s {
69+
dq_entry_t node;
70+
dhara_page_t page; /* Page number for this metadata */
71+
FAR uint8_t *buffer; /* 132-byte metadata buffer */
72+
};
7273

74+
typedef struct dhara_metadatacache_s dhara_metadatacache_t;
7375
struct dhara_dev_s {
7476
struct dhara_nand nand;
7577
struct dhara_map map;
@@ -91,6 +93,8 @@ struct dhara_dev_s {
9193

9294
struct dq_queue_s readcache;
9395
dhara_pagecache_t readpage[CONFIG_DHARA_READ_NCACHES];
96+
struct dq_queue_s metadatacache;
97+
dhara_metadatacache_t metadata[CONFIG_DHARA_METADATA_NCACHES];
9498
};
9599

96100
typedef struct dhara_dev_s dhara_dev_t;
@@ -269,7 +273,6 @@ static void dhara_discard_readcache(FAR dhara_dev_t *dev, dhara_page_t page)
269273
}
270274
}
271275
}
272-
273276
static void dhara_update_readcache(FAR dhara_dev_t *dev, dhara_page_t page, FAR const uint8_t *data)
274277
{
275278
FAR dhara_pagecache_t *cache;
@@ -294,6 +297,129 @@ static void dhara_update_readcache(FAR dhara_dev_t *dev, dhara_page_t page, FAR
294297
* Description: Open the block device
295298
*
296299
****************************************************************************/
300+
/****************************************************************************
301+
* Name: dhara_init_metadatacache
302+
****************************************************************************/
303+
static int dhara_init_metadatacache(FAR dhara_dev_t *dev)
304+
{
305+
FAR dq_queue_t *q = &dev->metadatacache;
306+
int i = 0;
307+
308+
dq_init(q);
309+
310+
do {
311+
dev->metadata[i].page = DHARA_PAGE_NONE;
312+
dev->metadata[i].buffer = kmm_malloc(2048);
313+
dq_addfirst(&dev->metadata[i].node, q);
314+
} while (dev->metadata[i++].buffer && i < CONFIG_DHARA_METADATA_NCACHES);
315+
return i == CONFIG_DHARA_METADATA_NCACHES ? 0 : -ENOMEM;
316+
}
317+
318+
/****************************************************************************
319+
* Name: dhara_deinit_metadatacache
320+
****************************************************************************/
321+
static void dhara_deinit_metadatacache(FAR dhara_dev_t *dev)
322+
{
323+
int i;
324+
325+
for (i = 0; i < CONFIG_DHARA_METADATA_NCACHES; i++) {
326+
if (dev->metadata[i].buffer) {
327+
kmm_free(dev->metadata[i].buffer);
328+
}
329+
}
330+
}
331+
332+
/****************************************************************************
333+
* Name: dhara_find_metadatacache
334+
****************************************************************************/
335+
static uint8_t *dhara_find_metadatacache(FAR dhara_dev_t *dev, dhara_page_t page)
336+
{
337+
FAR dq_queue_t *q = &dev->metadatacache;
338+
FAR dhara_metadatacache_t *cache;
339+
FAR dq_entry_t *c;
340+
341+
for (c = dq_peek(q); c; c = dq_next(c)) {
342+
cache = (FAR dhara_metadatacache_t *) c;
343+
if (cache->page == page) {
344+
dq_rem(c, q);
345+
dq_addfirst(c, q);
346+
return cache->buffer;
347+
}
348+
}
349+
350+
return NULL;
351+
}
352+
353+
/****************************************************************************
354+
* Name: dhara_grab_metadatacache
355+
****************************************************************************/
356+
static dhara_metadatacache_t *dhara_grab_metadatacache(FAR dhara_dev_t *dev)
357+
{
358+
FAR dq_queue_t *q = &dev->metadatacache;
359+
FAR dhara_metadatacache_t *cache;
360+
FAR dq_entry_t *c;
361+
362+
c = dq_tail(q);
363+
dq_rem(c, q);
364+
cache = (FAR dhara_metadatacache_t *) c;
365+
cache->page = DHARA_PAGE_NONE;
366+
return cache;
367+
}
368+
369+
/****************************************************************************
370+
* Name: dhara_insert_metadatacache
371+
****************************************************************************/
372+
static void dhara_insert_metadatacache(FAR dhara_dev_t *dev, dhara_metadatacache_t *cache)
373+
{
374+
FAR dq_queue_t *q = &dev->metadatacache;
375+
376+
if (cache->page != DHARA_PAGE_NONE) {
377+
dq_addfirst((dq_entry_t *) cache, q);
378+
} else {
379+
dq_addlast((dq_entry_t *) cache, q);
380+
}
381+
}
382+
383+
/****************************************************************************
384+
* Name: dhara_update_metadatacache
385+
****************************************************************************/
386+
static void dhara_update_metadatacache(FAR dhara_dev_t *dev, dhara_page_t page, FAR const uint8_t *data)
387+
{
388+
FAR dq_queue_t *q = &dev->metadatacache;
389+
FAR dhara_metadatacache_t *cache;
390+
FAR dq_entry_t *c;
391+
392+
for (c = dq_peek(q); c; c = dq_next(c)) {
393+
cache = (FAR dhara_metadatacache_t *) c;
394+
if (cache->page == page) {
395+
cache->page = page;
396+
memcpy(cache->buffer, data, dev->geo.blocksize);
397+
dq_rem(c, q);
398+
dq_addfirst(c, q);
399+
break;
400+
}
401+
}
402+
}
403+
404+
/****************************************************************************
405+
* Name: dhara_discard_metadatacache
406+
****************************************************************************/
407+
static void dhara_discard_metadatacache(FAR dhara_dev_t *dev, dhara_page_t page)
408+
{
409+
FAR dq_queue_t *q = &dev->metadatacache;
410+
FAR dhara_metadatacache_t *cache;
411+
FAR dq_entry_t *c;
412+
413+
for (c = dq_peek(q); c; c = dq_next(c)) {
414+
cache = (FAR dhara_metadatacache_t *) c;
415+
if (cache->page == page) {
416+
cache->page = DHARA_PAGE_NONE;
417+
dq_rem(c, q);
418+
dq_addlast(c, q);
419+
break;
420+
}
421+
}
422+
}
297423

298424
static int dhara_open(FAR struct inode *inode)
299425
{
@@ -525,22 +651,30 @@ int dhara_nand_erase(FAR const struct dhara_nand *n, dhara_block_t bno, FAR dhar
525651
for (i = 0; i < dev->blkper; i++) {
526652
dhara_discard_readcache(dev, pno + i);
527653
}
528-
654+
dhara_page_t metadata_page = pno + dev->blkper - 1;
655+
dhara_discard_metadatacache(dev, metadata_page);
529656
return 0;
530657
}
531658

532659
int dhara_nand_prog(FAR const struct dhara_nand *n, dhara_page_t p, FAR const uint8_t *data, FAR dhara_error_t *err)
533660
{
534661
FAR dhara_dev_t *dev = (FAR dhara_dev_t *) n;
535662
int ret;
663+
int page_in_block = p%64;
536664

537665
ret = MTD_BWRITE(dev->mtd, p, 1, data);
538666
if (ret < 0) {
539667
dhara_set_error(err, DHARA_E_BAD_BLOCK);
540668
return ret;
541669
}
542-
670+
if (ret < 0) {
671+
dhara_set_error(err, DHARA_E_BAD_BLOCK);
672+
return ret;
673+
}
543674
dhara_update_readcache(dev, p, data);
675+
if (page_in_block == 15 || page_in_block == 31 || page_in_block == 47 || page_in_block == 63) {
676+
dhara_update_metadatacache(dev, p, data);
677+
}
544678
return 0;
545679
}
546680

@@ -550,53 +684,84 @@ int dhara_nand_is_free(FAR const struct dhara_nand *n, dhara_page_t p)
550684
size_t page_size = 1 << n->log2_page_size;
551685
FAR uint8_t *buf = dev->pagebuf;
552686
dhara_error_t err;
553-
554687
if (dhara_nand_read(n, p, 0, page_size, buf, &err) < 0) {
555688
ferr("Fail to read page for free check err %s\n", dhara_strerror(err));
556689
return 0;
557690
}
558691

559692
return dhara_check_ff(buf, page_size);
560693
}
561-
562694
int dhara_nand_read(FAR const struct dhara_nand *n, dhara_page_t p, size_t offset, size_t length, FAR uint8_t *data, dhara_error_t *err)
563695
{
564696
FAR dhara_dev_t *dev = (FAR dhara_dev_t *) n;
565697
FAR dhara_pagecache_t *cache;
698+
FAR dhara_metadatacache_t *mcache;
699+
566700
FAR uint8_t *buf;
567701
int ret;
702+
int page_in_block = p % 64;
568703

704+
if (page_in_block == 15 || page_in_block == 31 || page_in_block == 47 || page_in_block == 63) {
705+
706+
/* Check metadata cache */
707+
buf = dhara_find_metadatacache(dev, p);
708+
if (buf) {
709+
memcpy(data, buf+offset, length);
710+
return 0;
711+
}
712+
mcache = dhara_grab_metadatacache(dev);
713+
ret = MTD_BREAD(dev->mtd, p, 1, mcache->buffer);
714+
if (ret == -EUCLEAN) {
715+
ret = 0;
716+
}
717+
if (ret < 0) {
718+
dhara_insert_metadatacache(dev, mcache);
719+
dhara_set_error(err, DHARA_E_ECC);
720+
return ret;
721+
}
722+
memcpy(data, mcache->buffer + offset, length);
723+
mcache->page = p;
724+
dhara_insert_metadatacache(dev, mcache);
725+
726+
} else {
727+
/* Check data page cache first */
569728
buf = dhara_find_readcache(dev, p);
570729
if (buf) {
571730
memcpy(data, buf + offset, length);
572731
return 0;
573732
}
574733

734+
/* Grab a cache entry */
575735
cache = dhara_grab_readcache(dev);
736+
737+
/* Read page from flash */
576738
ret = MTD_BREAD(dev->mtd, p, 1, cache->buffer);
577-
if (ret == -EUCLEAN) {
578-
ret = 0; /* Ignore the correctable ECC error */
579-
}
739+
if (ret == -EUCLEAN)
740+
ret = 0; /* Ignore correctable ECC error */
580741

581742
if (ret < 0) {
582743
dhara_insert_readcache(dev, cache);
583744
dhara_set_error(err, DHARA_E_ECC);
584745
return ret;
585746
}
586747

748+
/* Copy requested data */
587749
memcpy(data, cache->buffer + offset, length);
588750
cache->page = p;
589751
dhara_insert_readcache(dev, cache);
752+
753+
/* Check if this is a metadata page and cache it */
754+
}
590755
return ret >= 0 ? OK : ret;
591756
}
592757

758+
593759
int dhara_nand_copy(FAR const struct dhara_nand *n, dhara_page_t src, dhara_page_t dst, FAR dhara_error_t *err)
594760
{
595761
FAR dhara_dev_t *dev = (FAR dhara_dev_t *) n;
596762
size_t page_size = 1 << n->log2_page_size;
597763
FAR uint8_t *buf = dev->pagebuf;
598764
int ret;
599-
600765
ret = dhara_nand_read(n, src, 0, page_size, buf, err);
601766
if (ret < 0) {
602767
ferr("src_page %d, ret %d failed: %s\n", src, ret, dhara_strerror(*err));
@@ -682,7 +847,7 @@ int dhara_initialize_by_path(FAR const char *path, FAR struct mtd_dev_s *mtd)
682847
if (ret != 0) {
683848
goto err;
684849
}
685-
850+
ret = dhara_init_metadatacache(dev);
686851
dhara_map_init(&dev->map, &dev->nand, dev->pagebuf + dev->geo.blocksize, CONFIG_DHARA_GC_RATIO);
687852

688853
dhara_map_resume(&dev->map, NULL);
@@ -702,6 +867,7 @@ int dhara_initialize_by_path(FAR const char *path, FAR struct mtd_dev_s *mtd)
702867
err:
703868
sem_destroy(&dev->lock);
704869
dhara_deinit_readcache(dev);
870+
dhara_deinit_metadatacache(dev);
705871
kmm_free(dev->pagebuf);
706872
kmm_free(dev);
707873
return ret;
@@ -719,7 +885,7 @@ int dhara_initialize_by_path(FAR const char *path, FAR struct mtd_dev_s *mtd)
719885
* mtd - The MTD device that supports the FLASH interface.
720886
*
721887
****************************************************************************/
722-
888+
//extern int cache_init(FAR const struct dhara_nand *n,FAR uint8_t *data);
723889
int dhara_initialize(int minor, FAR struct mtd_dev_s *mtd)
724890
{
725891
char path[PATH_MAX];

0 commit comments

Comments
 (0)