소스 검색

Passing all of the basic functionality tests

Integration with the new journaling metadata has now progressed to the
point where all of the basic functionality tests are passing. This
includes:
- test_format
- test_dirs
- test_files
- test_seek
- test_truncate
- test_interspersed
- test_paths

Some of the fixes:
- Modified move to correctly change entry ids
- Called lfs_commit_move directly from compact, avoiding commit parsing
  logic during a compact
- Opened up commit filters to be passed down from compact for moves
- Added correct drop logic to lfs_dir_delete
- Updated lfs_dir_seek to use ids instead of offsets
- Caught id updates manually where possible (this needs to be fixed)
Christopher Haster 7 년 전
부모
커밋
483d41c545
2개의 변경된 파일106개의 추가작업 그리고 36개의 파일을 삭제
  1. 105 35
      lfs.c
  2. 1 1
      tests/test_dirs.sh

+ 105 - 35
lfs.c

@@ -475,7 +475,8 @@ struct lfs_commit {
 
 // TODO predelcare
 static int lfs_commit_move_(lfs_t *lfs, struct lfs_commit *commit,
-        lfs_entry_t entry);
+        uint16_t fromid, uint16_t toid,
+        lfs_dir_t *dir, lfs_entrylist_t *list);
 
 //static int lfs_commit_compactcheck(lfs_t *lfs, void *p, lfs_entry_t entry) {
 //    struct lfs_commit *commit = p;
@@ -499,7 +500,9 @@ static int lfs_commit_commit(lfs_t *lfs,
 
     // special cases
     if ((lfs_tag_type(entry.tag) & 0x103) == LFS_FROM_MOVE) {
-        return lfs_commit_move_(lfs, commit, entry); 
+        return lfs_commit_move_(lfs, commit,
+                lfs_tag_size(entry.tag), lfs_tag_id(entry.tag),
+                entry.u.dir, NULL); 
     }
 
     uint16_t id = lfs_tag_id(entry.tag) - commit->filter.begin;
@@ -633,7 +636,7 @@ static int lfs_commit_list(lfs_t *lfs, struct lfs_commit *commit,
 // committer for moves
 // TODO rename?
 struct lfs_commit_move {
-    lfs_dir_t *dir;
+    lfs_dir_t *dir; // TODO need dir?
     struct {
         uint16_t from;
         uint16_t to;
@@ -680,7 +683,8 @@ static int lfs_commit_movescan(lfs_t *lfs, void *p, lfs_entry_t entry) {
                 .stop_at_commit=true},
             lfs_tag_type(entry.tag) & 0x100 ? 0x7ffff000 : 0x7c1ff000,
             &(lfs_entry_t){
-                lfs_mktag(lfs_tag_type(entry.tag), move->id.to, 0)});
+                lfs_mktag(lfs_tag_type(entry.tag),
+                    move->id.to - move->commit->filter.begin, 0)}); // TODO can all these filter adjustments be consolidated?
     if (err && err != LFS_ERR_NOENT) {
         return err;
     }
@@ -714,15 +718,22 @@ static int lfs_commit_move(lfs_t *lfs, void *p, struct lfs_commit *commit) {
 }
 
 static int lfs_commit_move_(lfs_t *lfs, struct lfs_commit *commit,
-        lfs_entry_t entry) {
+        uint16_t fromid, uint16_t toid,
+        lfs_dir_t *dir, lfs_entrylist_t *list) {
     struct lfs_commit_move move = {
-        .dir = entry.u.dir,
-        .id.to = lfs_tag_id(entry.tag),
-        .id.from = lfs_tag_size(entry.tag),
+        .id.from = fromid,
+        .id.to = toid,
         .commit = commit,
     };
 
-    int err = lfs_dir_traverse(lfs, entry.u.dir, lfs_commit_movescan, &move);
+    for (; list; list = list->next) {
+        int err = lfs_commit_movescan(lfs, &move, list->e);
+        if (err) {
+            return err;
+        }
+    }
+
+    int err = lfs_dir_traverse(lfs, dir, lfs_commit_movescan, &move);
     if (err) {
         return err;
     }
@@ -1185,6 +1196,7 @@ static int lfs_dir_compact_(lfs_t *lfs, lfs_dir_t *dir, lfs_entrylist_t *list,
     // save some state in case block is bad
     const lfs_block_t oldpair[2] = {dir->pair[1], dir->pair[0]};
     bool relocated = false;
+    lfs_dir_t tail;
 
     // increment revision count
     dir->rev += 1;
@@ -1236,22 +1248,23 @@ static int lfs_dir_compact_(lfs_t *lfs, lfs_dir_t *dir, lfs_entrylist_t *list,
                 .filter.end = end,
             };
 
-            // commit regions which can't fend for themselves
-            err = lfs_commit_list(lfs, &commit, list);
-            if (err) {
-                if (err == LFS_ERR_NOSPC) {
-                    goto split;
-                } else if (err == LFS_ERR_CORRUPT) {
-                    goto relocate;
-                }
-                return err;
-            }
-
-            // move over other commits, leaving it up to lfs_commit_move to
-            // filter out duplicates, and the commit filtering to reassign ids
+//            // commit regions which can't fend for themselves
+//            err = lfs_commit_list(lfs, &commit, list);
+//            if (err) {
+//                if (err == LFS_ERR_NOSPC) {
+//                    goto split;
+//                } else if (err == LFS_ERR_CORRUPT) {
+//                    goto relocate;
+//                }
+//                return err;
+//            }
+//
+//            // move over other commits, leaving it up to lfs_commit_move to
+//            // filter out duplicates, and the commit filtering to reassign ids
             for (uint16_t id = begin; id < end; id++) {
-                err = lfs_commit_commit(lfs, &commit, (lfs_entry_t){
-                        lfs_mktag(LFS_FROM_MOVE, id, id), .u.dir=source});
+                err = lfs_commit_move_(lfs, &commit, id, id, source, list);
+//                err = lfs_commit_commit(lfs, &commit, (lfs_entry_t){
+//                        lfs_mktag(LFS_FROM_MOVE, id, id), .u.dir=source});
                 if (err) {
                     if (err == LFS_ERR_NOSPC) {
                         goto split;
@@ -1458,8 +1471,55 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, uint16_t *id) {
 
 static int lfs_dir_delete(lfs_t *lfs, lfs_dir_t *dir, uint16_t id) {
     dir->count -= 1;
-    return lfs_dir_commit_(lfs, dir, &(lfs_entrylist_t){
+
+    // check if we should drop the directory block
+    if (dir->count == 0) {
+        lfs_dir_t pdir;
+        int res = lfs_pred(lfs, dir->pair, &pdir);
+        if (res < 0) {
+            return res;
+        }
+
+        if (res && pdir.split) {
+            pdir.split = dir->split;
+            pdir.tail[0] = dir->tail[0];
+            pdir.tail[1] = dir->tail[1];
+            int err = lfs_dir_commit(lfs, &pdir, &(lfs_entrylist_t){
+                    {lfs_mktag(LFS_TYPE_SOFTTAIL + pdir.split*0x10,
+                        0x1ff, sizeof(pdir.tail)),
+                     .u.buffer=pdir.tail}});
+            return err;
+        }
+    }
+
+    int err = lfs_dir_commit_(lfs, dir, &(lfs_entrylist_t){
             {lfs_mktag(LFS_TYPE_DELETE, id, 0)}});
+    if (err) {
+        return err;
+    }
+
+    // shift over any files that are affected
+    // TODO move this to dir_commit?
+    for (lfs_file_t *f = lfs->files; f; f = f->next) {
+        if (lfs_paircmp(f->pair, dir->pair) == 0) {
+            if (f->id == id) {
+                f->pair[0] = 0xffffffff;
+                f->pair[1] = 0xffffffff;
+            } else if (f->id > id) {
+                f->id -= 1;
+            }
+        }
+    }
+
+// TODO ?
+//    for (lfs_dir_t *d = lfs->dirs; d; d = d->next) {
+//        if (lfs_paircmp(d->pair, dir->pair) == 0) {
+//            if (d->id > id) {
+//                d->id -= 1;
+//                d->pos -= 1;
+//            }
+//        }
+//    }
 }
 
 struct lfs_dir_getter {
@@ -1674,7 +1734,7 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir,
 
         // find path
         while (true) {
-            printf("checking %d %d for %s\n", entry.u.pair[0], entry.u.pair[1], *path);
+            //printf("checking %d %d for %s\n", entry.u.pair[0], entry.u.pair[1], *path);
             find.id = -1;
             int err = lfs_dir_fetchwith(lfs, dir, entry.u.pair,
                     lfs_dir_finder, &find);
@@ -2796,11 +2856,14 @@ int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) {
     }
 
     // first two for ./..
-    dir->id = lfs_min(2 + dir->count, off);
-    dir->pos += dir->id;
-    off -= dir->id;
+    dir->pos = lfs_min(2, off);
+    off -= dir->pos;
 
     while (off != 0) {
+        dir->id = lfs_min(dir->count, off);
+        dir->pos += dir->id;
+        off -= dir->id;
+
         if (dir->id == dir->count) {
             if (!dir->split) {
                 return LFS_ERR_INVAL;
@@ -2811,10 +2874,6 @@ int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) {
                 return err;
             }
         }
-
-        dir->id = lfs_min(dir->count, off);
-        dir->pos += dir->id;
-        off -= dir->id;
     }
 
     return 0;
@@ -3209,6 +3268,7 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
             return err;
         }
 
+        // TODO do we need to make file registered to list to catch updates from this commit? ie if id/cwd change
         err = lfs_dir_commit_(lfs, &cwd, &(lfs_entrylist_t){
                 {lfs_mktag(LFS_TYPE_NAME, id, nlen),
                  .u.buffer=(void*)path}, &(lfs_entrylist_t){
@@ -3217,9 +3277,19 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
             return err;
         }
 
+        // TODO eh
+        if (id >= cwd.count) {
+            // catch updates from a compact in the above commit
+            id -= cwd.count;
+            cwd.pair[0] = cwd.tail[0];
+            cwd.pair[1] = cwd.tail[1];
+        }
+
         entry.tag = lfs_mktag(LFS_TYPE_REG | LFS_STRUCT_INLINE, id, 0);
     } else {
-        if (flags & LFS_O_EXCL) {
+        if (id == -1) {
+            return LFS_ERR_ISDIR;
+        } else if (flags & LFS_O_EXCL) {
             return LFS_ERR_EXIST;
         }
 
@@ -4502,7 +4572,7 @@ static int lfs_pred(lfs_t *lfs, const lfs_block_t pair[2], lfs_dir_t *pdir) {
     pdir->tail[1] = 1;
     while (!lfs_pairisnull(pdir->tail)) {
         if (lfs_paircmp(pdir->tail, pair) == 0) {
-            return true;
+            return true; // TODO should we return true only if pred is part of dir?
         }
 
         int err = lfs_dir_fetch(lfs, pdir, pdir->tail);

+ 1 - 1
tests/test_dirs.sh

@@ -329,7 +329,7 @@ tests/test.py << TEST
 TEST
 
 echo "--- Multi-block remove ---"
-tests/test.py -s << TEST
+tests/test.py << TEST
     lfs_mount(&lfs, &cfg) => 0;
     lfs_remove(&lfs, "cactus") => LFS_ERR_NOTEMPTY;