Skip to content

Commit 21217d7

Browse files
committed
Dropped lfs_fs_getattr for the more implicit lfs_getattr("/")
This was a pretty simple oversight on my part. Conceptually, there's no difference between lfs_fs_getattr and lfs_getattr("/"). Any operations on directories can be applied "globally" by referring to the root directory. Implementation wise, this actually fixes the "corner case" of storing attributes on the root directory, which is broken since the root directory doesn't have a related entry. Instead we need to use the root superblock for this purpose. Fewer functions means less code to document and maintain, so this is a nice benefit. Now we just have a single lfs_getattr/setattr/removeattr set of functions along with the ability to access attributes atomically in lfs_file_opencfg.
1 parent 38011f4 commit 21217d7

File tree

4 files changed

+107
-131
lines changed

4 files changed

+107
-131
lines changed

lfs.c

Lines changed: 70 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -540,15 +540,16 @@ static int lfs_commit_attrs(lfs_t *lfs, struct lfs_commit *commit,
540540
uint16_t id, const struct lfs_attr *attrs);
541541

542542
static int lfs_commit_move(lfs_t *lfs, struct lfs_commit *commit,
543-
uint16_t fromid, uint16_t toid,
543+
uint32_t frommask, uint32_t fromtag, uint32_t tomask, uint32_t totag,
544544
const lfs_mdir_t *dir, const lfs_mattr_t *attrs);
545545

546546
static int lfs_commit_attr(lfs_t *lfs, struct lfs_commit *commit,
547547
uint32_t tag, const void *buffer) {
548548
if (lfs_tag_subtype(tag) == LFS_FROM_MOVE) {
549549
// special case for moves
550550
return lfs_commit_move(lfs, commit,
551-
lfs_tag_size(tag), lfs_tag_id(tag),
551+
0x003ff000, LFS_MKTAG(0, lfs_tag_size(tag), 0),
552+
0x003ff000, LFS_MKTAG(0, lfs_tag_id(tag), 0),
552553
buffer, NULL);
553554
} else if (lfs_tag_subtype(tag) == LFS_FROM_ATTRS) {
554555
// special case for custom attributes
@@ -617,7 +618,7 @@ static int lfs_commit_attrs(lfs_t *lfs, struct lfs_commit *commit,
617618
}
618619

619620
static int lfs_commit_move(lfs_t *lfs, struct lfs_commit *commit,
620-
uint16_t fromid, uint16_t toid,
621+
uint32_t frommask, uint32_t fromtag, uint32_t tomask, uint32_t totag,
621622
const lfs_mdir_t *dir, const lfs_mattr_t *attrs) {
622623
// iterate through list and commits, only committing unique entries
623624
lfs_off_t off = dir->off;
@@ -650,17 +651,15 @@ static int lfs_commit_move(lfs_t *lfs, struct lfs_commit *commit,
650651
}
651652

652653
if (lfs_tag_type(tag) == LFS_TYPE_DELETE &&
653-
lfs_tag_id(tag) <= fromid) {
654+
lfs_tag_id(tag) <= lfs_tag_id(fromtag)) {
654655
// something was deleted, we need to move around it
655-
fromid += 1;
656-
} else if (lfs_tag_id(tag) != fromid) {
657-
// ignore non-matching ids
658-
} else {
656+
fromtag += LFS_MKTAG(0, 1, 0);
657+
} else if ((tag & frommask) == (fromtag & frommask)) {
659658
// check if type has already been committed
660659
int32_t res = lfs_commit_get(lfs, commit->block,
661660
commit->off, commit->ptag,
662661
lfs_tag_isuser(tag) ? 0x7ffff000 : 0x7c3ff000,
663-
(tag & 0x7fc00000) | LFS_MKTAG(0, toid, 0),
662+
(tag & ~tomask) | totag,
664663
0, NULL, true);
665664
if (res < 0 && res != LFS_ERR_NOENT) {
666665
return res;
@@ -669,7 +668,7 @@ static int lfs_commit_move(lfs_t *lfs, struct lfs_commit *commit,
669668
if (res == LFS_ERR_NOENT) {
670669
// update id and commit, as we are currently unique
671670
int err = lfs_commit_attr(lfs, commit,
672-
(tag & 0xffc00fff) | LFS_MKTAG(0, toid, 0),
671+
(tag & ~tomask) | totag,
673672
buffer);
674673
if (err) {
675674
return err;
@@ -1068,8 +1067,7 @@ static int lfs_dir_compact(lfs_t *lfs,
10681067
// do we have enough space to expand?
10691068
if (res < lfs->cfg->block_count/2) {
10701069
LFS_DEBUG("Expanding superblock at rev %"PRIu32, dir->rev);
1071-
ack = 0;
1072-
exhausted = (lfs_pair_cmp(dir->pair, lfs->root) != 0);
1070+
exhausted = true;
10731071
goto split;
10741072
}
10751073
} else {
@@ -1118,7 +1116,9 @@ static int lfs_dir_compact(lfs_t *lfs,
11181116
// commit with a move
11191117
for (uint16_t id = begin; id < end; id++) {
11201118
err = lfs_commit_move(lfs, &commit,
1121-
id, id - begin, source, attrs);
1119+
0x003ff000, LFS_MKTAG(0, id, 0),
1120+
0x003ff000, LFS_MKTAG(0, id - begin, 0),
1121+
source, attrs);
11221122
if (err) {
11231123
if (err == LFS_ERR_NOSPC) {
11241124
goto split;
@@ -1134,7 +1134,23 @@ static int lfs_dir_compact(lfs_t *lfs,
11341134
// reopen reserved space at the end
11351135
commit.end = lfs->cfg->block_size - 8;
11361136

1137+
if (lfs_pair_cmp(dir->pair, (const lfs_block_t[2]){0, 1}) == 0) {
1138+
// move over (duplicate) superblock if we are root
1139+
err = lfs_commit_move(lfs, &commit,
1140+
0x7c000000, LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, 0),
1141+
0x7ffff000, LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, 0),
1142+
source, attrs);
1143+
if (err) {
1144+
if (err == LFS_ERR_CORRUPT) {
1145+
goto relocate;
1146+
}
1147+
return err;
1148+
}
1149+
}
1150+
11371151
if (!relocated) {
1152+
// commit any globals, unless we're relocating, in which case our
1153+
// parent will steal our globals
11381154
err = lfs_commit_globals(lfs, &commit, &dir->locals);
11391155
if (err) {
11401156
if (err == LFS_ERR_CORRUPT) {
@@ -1178,8 +1194,7 @@ static int lfs_dir_compact(lfs_t *lfs,
11781194
// commit no longer fits, need to split dir,
11791195
// drop caches and create tail
11801196
lfs_cache_drop(lfs, &lfs->pcache);
1181-
1182-
if (ack == -1) {
1197+
if (!exhausted && ack < 0) {
11831198
// If we can't fit in this block, we won't fit in next block
11841199
return LFS_ERR_NOSPC;
11851200
}
@@ -1190,11 +1205,16 @@ static int lfs_dir_compact(lfs_t *lfs,
11901205
return err;
11911206
}
11921207

1208+
if (exhausted) {
1209+
lfs->root[0] = tail.pair[0];
1210+
lfs->root[1] = tail.pair[1];
1211+
}
1212+
11931213
tail.split = dir->split;
11941214
tail.tail[0] = dir->tail[0];
11951215
tail.tail[1] = dir->tail[1];
11961216

1197-
err = lfs_dir_compact(lfs, &tail, attrs, source, ack+1-exhausted, end);
1217+
err = lfs_dir_compact(lfs, &tail, attrs, source, ack+1, end);
11981218
if (err) {
11991219
return err;
12001220
}
@@ -2770,9 +2790,19 @@ lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
27702790
return res;
27712791
}
27722792

2793+
uint16_t id = lfs_tag_id(res);
2794+
if (id == 0x3ff) {
2795+
// special case for root
2796+
id = 0;
2797+
int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
2798+
if (err) {
2799+
return err;
2800+
}
2801+
}
2802+
27732803
res = lfs_dir_get(lfs, &cwd, 0x7ffff000,
2774-
LFS_MKTAG(0x100 | type, lfs_tag_id(res),
2775-
lfs_min(size, lfs->attr_max)), buffer);
2804+
LFS_MKTAG(0x100 | type, id, lfs_min(size, lfs->attr_max)),
2805+
buffer);
27762806
if (res < 0 && res != LFS_ERR_NOENT) {
27772807
return res;
27782808
}
@@ -2792,8 +2822,18 @@ int lfs_setattr(lfs_t *lfs, const char *path,
27922822
return res;
27932823
}
27942824

2825+
uint16_t id = lfs_tag_id(res);
2826+
if (id == 0x3ff) {
2827+
// special case for root
2828+
id = 0;
2829+
int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
2830+
if (err) {
2831+
return err;
2832+
}
2833+
}
2834+
27952835
return lfs_dir_commit(lfs, &cwd,
2796-
LFS_MKATTR(0x100 | type, lfs_tag_id(res), buffer, size,
2836+
LFS_MKATTR(0x100 | type, id, buffer, size,
27972837
NULL));
27982838
}
27992839

@@ -2941,9 +2981,8 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
29412981

29422982
lfs_superblock_tole32(&superblock);
29432983
err = lfs_dir_commit(lfs, &root,
2944-
LFS_MKATTR(LFS_TYPE_SUPERBLOCK, 0, &superblock, sizeof(superblock),
2945-
LFS_MKATTR(LFS_TYPE_ROOT, 1, NULL, 0,
2946-
NULL)));
2984+
LFS_MKATTR(LFS_TYPE_ROOT, 0, &superblock, sizeof(superblock),
2985+
NULL));
29472986
if (err) {
29482987
goto cleanup;
29492988
}
@@ -2965,15 +3004,18 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
29653004
return err;
29663005
}
29673006

2968-
// load superblock
3007+
// find root/superblock
29693008
lfs_mdir_t root;
2970-
err = lfs_dir_fetch(lfs, &root, (const lfs_block_t[2]){0, 1});
2971-
if (err) {
2972-
return err;
3009+
lfs_superblock_t superblock;
3010+
int32_t tag = lfs_dir_find(lfs,
3011+
&root, (const lfs_block_t[2]){0, 1}, false, 0x7fc00000,
3012+
LFS_MKTAG(LFS_TYPE_ROOT, 0, 8), "littlefs");
3013+
if (tag < 0) {
3014+
err = tag;
3015+
goto cleanup;
29733016
}
29743017

2975-
lfs_superblock_t superblock;
2976-
int32_t res = lfs_dir_get(lfs, &root, 0x7fc00000,
3018+
int32_t res = lfs_dir_get(lfs, &root, 0x7c000000,
29773019
LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, sizeof(superblock)),
29783020
&superblock);
29793021
if (res < 0) {
@@ -2982,14 +3024,6 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
29823024
}
29833025
lfs_superblock_fromle32(&superblock);
29843026

2985-
// find root
2986-
int32_t tag = lfs_dir_find(lfs,
2987-
&root, (const lfs_block_t[2]){0, 1}, false, 0x7fc00000,
2988-
LFS_MKTAG(LFS_TYPE_ROOT, 0, 0), NULL);
2989-
if (tag < 0) {
2990-
return tag;
2991-
}
2992-
29933027
lfs->root[0] = root.pair[0];
29943028
lfs->root[1] = root.pair[1];
29953029

@@ -3370,41 +3404,6 @@ static int lfs_fs_forceconsistency(lfs_t *lfs) {
33703404
return 0;
33713405
}
33723406

3373-
lfs_ssize_t lfs_fs_getattr(lfs_t *lfs,
3374-
uint8_t type, void *buffer, lfs_size_t size) {
3375-
lfs_mdir_t superdir;
3376-
int err = lfs_dir_fetch(lfs, &superdir, (const lfs_block_t[2]){0, 1});
3377-
if (err) {
3378-
return err;
3379-
}
3380-
3381-
int32_t res = lfs_dir_get(lfs, &superdir, 0x7ffff000,
3382-
LFS_MKTAG(0x100 | type, 0,
3383-
lfs_min(size, lfs->attr_max)), buffer);
3384-
if (res < 0) {
3385-
return res;
3386-
}
3387-
3388-
return (res == LFS_ERR_NOENT) ? 0 : lfs_tag_size(res);
3389-
}
3390-
3391-
int lfs_fs_setattr(lfs_t *lfs,
3392-
uint8_t type, const void *buffer, lfs_size_t size) {
3393-
if (size > lfs->attr_max) {
3394-
return LFS_ERR_NOSPC;
3395-
}
3396-
3397-
lfs_mdir_t superdir;
3398-
int err = lfs_dir_fetch(lfs, &superdir, (const lfs_block_t[2]){0, 1});
3399-
if (err) {
3400-
return err;
3401-
}
3402-
3403-
return lfs_dir_commit(lfs, &superdir,
3404-
LFS_MKATTR(0x100 | type, 0, buffer, size,
3405-
NULL));
3406-
}
3407-
34083407
static int lfs_fs_size_count(void *p, lfs_block_t block) {
34093408
(void)block;
34103409
lfs_size_t *size = p;

lfs.h

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ enum lfs_type {
9494
// internally used types
9595
LFS_TYPE_USER = 0x100,
9696
LFS_TYPE_SUPERBLOCK = 0x011,
97-
LFS_TYPE_ROOT = 0x012,
97+
LFS_TYPE_ROOT = 0x010,
9898
LFS_TYPE_NAME = 0x000,
9999
LFS_TYPE_DELETE = 0x030,
100100
LFS_TYPE_STRUCT = 0x040,
@@ -624,35 +624,6 @@ lfs_ssize_t lfs_fs_size(lfs_t *lfs);
624624
// Returns a negative error code on failure.
625625
int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data);
626626

627-
// Get custom attributes on the filesystem
628-
//
629-
// Custom attributes are uniquely identified by an 8-bit type and limited
630-
// to LFS_ATTR_MAX bytes. When read, if the stored attribute is smaller than
631-
// the buffer, it will be padded with zeros. If the stored attribute is larger,
632-
// then it will be silently truncated.
633-
//
634-
// Note, filesystem-level attributes are not available for wear-leveling
635-
//
636-
// Returns the size of the attribute, or a negative error code on failure.
637-
// Note, the returned size is the size of the attribute on disk, irrespective
638-
// of the size of the buffer. This can be used to dynamically allocate a buffer
639-
// or check for existance.
640-
lfs_ssize_t lfs_fs_getattr(lfs_t *lfs,
641-
uint8_t type, void *buffer, lfs_size_t size);
642-
643-
// Set custom attributes on the filesystem
644-
//
645-
// Custom attributes are uniquely identified by an 8-bit type and limited
646-
// to LFS_ATTR_MAX bytes. If an attribute is not found, it will be
647-
// implicitly created, and setting the size of an attribute to zero deletes
648-
// the attribute.
649-
//
650-
// Note, filesystem-level attributes are not available for wear-leveling
651-
//
652-
// Returns a negative error code on failure.
653-
int lfs_fs_setattr(lfs_t *lfs,
654-
uint8_t type, const void *buffer, lfs_size_t size);
655-
656627

657628
#ifdef __cplusplus
658629
} /* extern "C" */

tests/debug.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
(0x1ff, 0x001): 'reg',
88
(0x1ff, 0x002): 'dir',
99
(0x1ff, 0x011): 'superblock',
10-
(0x1ff, 0x012): 'root',
10+
(0x1ff, 0x010): 'root',
1111
(0x1ff, 0x030): 'delete',
1212
(0x1f0, 0x080): 'globals',
1313
(0x1ff, 0x0c0): 'tail soft',
@@ -50,9 +50,13 @@ def main(*blocks):
5050
crc = ncrc
5151

5252
versions.append((nrev, '%s (rev %d)' % (block, nrev)))
53-
except IOError:
53+
except (IOError, struct.error):
5454
pass
5555

56+
if not file:
57+
print 'Bad metadata pair {%s}' % ', '.join(blocks)
58+
return 1
59+
5660
print "--- %s ---" % ', '.join(v for _,v in sorted(versions, reverse=True))
5761

5862
# go through each tag, print useful information
@@ -93,6 +97,8 @@ def main(*blocks):
9397
if type == 0x0f0:
9498
crc = 0
9599

100+
return 0
101+
96102
if __name__ == "__main__":
97103
import sys
98-
main(*sys.argv[1:])
104+
sys.exit(main(*sys.argv[1:]))

0 commit comments

Comments
 (0)