]> git.neil.brown.name Git - lafs-utils.git/commitdiff
Support flushing blocks without forcing them into a checkpoint.
authorNeilBrown <neilb@suse.de>
Fri, 25 Mar 2011 21:32:10 +0000 (08:32 +1100)
committerNeilBrown <neilb@suse.de>
Fri, 25 Mar 2011 21:32:10 +0000 (08:32 +1100)
Each inode has a list of blocks that are either dirty or own and
inode which has a list of blocks.

Then 'flush' can go through this list and flush them to a
write_cluster.

Signed-off-by: NeilBrown <neilb@suse.de>
16 files changed:
include/lafs/lafs.h
include/lafs/struct.h
lib/lafs_add_inode.c
lib/lafs_cluster_allocate.c
lib/lafs_dirty_blk.c [new file with mode: 0644]
lib/lafs_flush_inode.c [new file with mode: 0644]
lib/lafs_get_itable.c
lib/lafs_imap_alloc.c
lib/lafs_imap_clr.c
lib/lafs_imap_set.c
lib/lafs_import_inode_buf.c
lib/lafs_incorporate.c
lib/lafs_new_segment.c
lib/lafs_sched_blk.c
lib/lafs_segment_count.c
tools/lafs.c

index 874d2d5fc5690854420e6ffa56765d712d6fc398..792c80400e49b238cdfad63f51ced973fac8f89d 100644 (file)
@@ -49,6 +49,7 @@ struct lafs_ino *lafs_import_inode(struct lafs_dblk *db);
 
 int lafs_read_virtual(struct lafs *, char *, loff_t);
 int lafs_sched_blk(struct lafs_blk *);
+int lafs_dirty_blk(struct lafs_dblk *);
 
 int lafs_write_dev(struct lafs_device *dev);
 int lafs_write_state(struct lafs *fs);
@@ -56,6 +57,8 @@ int lafs_checkpoint(struct lafs *fs);
 void lafs_incorporate(struct lafs_iblk *ib);
 void lafs_cluster_allocate(struct lafs_blk *b, int cnum);
 void lafs_cluster_flush(struct lafs *fs, int cnum);
+void lafs_flush_inode(struct lafs_ino *inode);
+void lafs_flush(struct lafs *lafs);
 int lafs_new_segment(struct lafs *, int cnum);
 struct lafs_device *lafs_dev_find(struct lafs *fs, loff_t virt);
 void lafs_allocated_block(struct lafs_blk *b, loff_t addr);
@@ -110,12 +113,6 @@ static inline struct lafs_iblk *iblk(struct lafs_blk *b)
        return container_of(b, struct lafs_iblk, b);
 }
 
-static inline int lafs_dirty_blk(struct lafs_blk *blk)
-{
-       blk->flags |= B_Dirty;
-       return lafs_sched_blk(blk);
-}
-
 static inline uint64_t lafs_encode_timeval(struct timeval *tm)
 {
        uint64_t nano = tm->tv_usec * 1000;
index 1d90850954a84a6802c266532acd767e2fac526a..9e66ef5990d5c7fa7a03a652e8ff4e75ddb51a9e 100644 (file)
@@ -89,6 +89,9 @@ struct lafs_ino {
        struct lafs_iblk *iblock;
        int             inum;
        struct lafs_ino *filesys;
+       struct list_head dirty; /* blocks that might be dirty, or might belong
+                                * to inodes with dirty blocks.
+                                */
 
        u32     cblocks, /* data blocks which are commited to this file */
                ablocks, /* data blocks that are allocated */
index 9ddd6fec5b7225646eeec6995ad6801dcf59210d..62b9efc463d77c6e4b86f04d5505cb3595856f57 100644 (file)
@@ -20,6 +20,6 @@ struct lafs_ino *lafs_add_inode(struct lafs_ino *fsys, int inum, int type)
        db->b.flags |= B_Valid;
 
        ino = lafs_import_inode(db);
-       lafs_dirty_blk(&db->b);
+       lafs_sched_blk(&db->b);
        return ino;
 }
index 96acc4f1d2012bfd65df17c3526f1b63bc108e1b..3e5e627449ca1a1c63ce58843f0ae42b271322fd 100644 (file)
@@ -18,8 +18,6 @@ void lafs_cluster_allocate(struct lafs_blk *b, int cnum)
        struct lafs_cluster *wc;
        if (!(b->flags & B_Dirty))
                abort();
-       if (!(b->flags & B_Sched))
-               abort();
 
        if (!(b->flags & B_Index) &&
            b->ino->type == TypeInodeFile &&
@@ -31,7 +29,7 @@ void lafs_cluster_allocate(struct lafs_blk *b, int cnum)
            b->ino->iblock == iblk(b)) {
                /* InoIdx block - cannot write that, must write the
                 * data block instead */
-               lafs_dirty_blk(&b->ino->dblock->b);
+               lafs_sched_blk(&b->ino->dblock->b);
                de_sched(b);
                return;
        }
@@ -40,7 +38,7 @@ void lafs_cluster_allocate(struct lafs_blk *b, int cnum)
        wc = &fs->wc[cnum];
 
        if (wc->remaining == 0) {
-               /* FIXME lafs_cluster_flush(fs, cnum) ?? */
+               lafs_cluster_flush(fs, cnum);
                lafs_new_segment(fs, cnum);
                if (!wc->remaining)
                        abort();
diff --git a/lib/lafs_dirty_blk.c b/lib/lafs_dirty_blk.c
new file mode 100644 (file)
index 0000000..f4bb874
--- /dev/null
@@ -0,0 +1,32 @@
+
+/*
+ * mark a block for writeout eventually.
+ */
+
+#include <lafs/lafs.h>
+
+#include <stdio.h>
+#include "internal.h"
+
+int lafs_dirty_blk(struct lafs_dblk *db)
+{
+       int was_empty;
+
+       if (db->b.flags & B_Dirty)
+               return 0;
+
+       if (lafs_find_dblk(db) < 0)
+               return -1;
+
+       db->b.flags |= B_Dirty;
+       if (db->b.flags & B_Sched)
+               return 0;
+
+       trace(1, "dirty %p\n", db);
+       do {
+               was_empty = list_empty(&db->b.ino->dirty);
+               list_move_tail(&db->b.leafs, &db->b.ino->dirty);
+               db = db->b.ino->dblock;
+       } while (db && was_empty && db != db->b.ino->dblock);
+       return 0;
+}
diff --git a/lib/lafs_flush_inode.c b/lib/lafs_flush_inode.c
new file mode 100644 (file)
index 0000000..b84a42b
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Flush all dirty blocks in an inode to write cluster
+ */
+#include <lafs/lafs.h>
+#include "internal.h"
+
+void lafs_flush_inode(struct lafs_ino *inode)
+{
+       struct lafs_blk *blk;
+       struct list_head *tmp;
+       struct lafs_ino *ino;
+       list_for_each_entry_safe(blk, tmp, &inode->dirty, leafs) {
+               if (!(blk->flags & B_Index) &&
+                   blk->ino->type == TypeInodeFile &&
+                   (ino = dblk(blk)->my_inode) != NULL &&
+                   !list_empty(&ino->dirty))
+                       lafs_flush_inode(ino);
+               else if (!(blk->flags & B_Dirty))
+                       list_del_init(&blk->leafs);
+
+               if ((blk->flags & B_Dirty) &&
+                   !(blk->flags & B_Sched))
+                       lafs_cluster_allocate(blk, 0);
+       }
+}
+
+void lafs_flush(struct lafs *lafs)
+{
+       struct lafs_ino *fsys = lafs->ss.root;
+
+       if (fsys)
+               lafs_flush_inode(fsys);
+}
+       
index 535637109f9b0ec898e161cc5e4960f5145e2081..9c537addc3834bcd71f172db0b8319d2297c8c53 100644 (file)
@@ -37,7 +37,7 @@ struct lafs_ino *lafs_get_itable(struct lafs *fs)
        blk->b.physaddr = fs->ss.root_addr;
        blk->my_inode = ino;
        if (blk->b.physaddr == 0)
-               lafs_dirty_blk(&blk->b);
+               lafs_sched_blk(&blk->b);
        fs->ss.root = ino;
        return ino;
 }
index fa0548177e64f6143e015bc28c607543a983a61f..414dd8f98f5a6e47b1ea99cdf8bcb113e3054a80 100644 (file)
@@ -28,7 +28,7 @@ int lafs_imap_alloc(struct lafs_ino *imap)
                                bnum = imap->md.inodemap.size;
                                imap->md.inodemap.size = bnum+1;
                                db = lafs_dblk(imap, bnum);
-                               lafs_dirty_blk(&db->b);
+                               lafs_sched_blk(&db->b);
                                memset(db->b.data, 0xff, fs->blocksize);
                                db->b.flags |= B_Valid;
                        }
@@ -37,7 +37,7 @@ int lafs_imap_alloc(struct lafs_ino *imap)
                lafs_load_dblk(db);
                bit = find_first_bit(db->b.data, fs->blocksize);
                if (bit < fs->blocksize * 8) {
-                       lafs_dirty_blk(&db->b);
+                       lafs_sched_blk(&db->b);
                        clear_c_bit(bit, (unsigned char *)db->b.data);
                        if (*(u32*)(db->b.data) == 0
                            && db->b.data[fs->blocksize-1] == 0 &&
index 94532a489b366b652308b31759984d6d2518418a..128c41aedb20ef4e30b60928982fde5c3f7c3232 100644 (file)
@@ -22,6 +22,6 @@ int lafs_imap_clr(struct lafs_ino *ino, int inum)
        inum -= blknum * fs->blocksize * 8;
        set_c_bit(inum, (unsigned char *)db->b.data);
        /* FIXME if block is now empty, possibly contract file */
-       lafs_dirty_blk(&db->b);
+       lafs_sched_blk(&db->b);
        return 0;
 }
index 3c463940a09fbb7fa17d622ca3c3196b6c3963c0..651ffc038cc6e6dcdadffe9aebcd07a001b2844a 100644 (file)
@@ -34,6 +34,6 @@ int lafs_imap_set(struct lafs_ino *ino, int inum)
                return 1;
        clear_c_bit(inum, (unsigned char*)db->b.data);
        /* FIXME if block is now empty, punch a hole */
-       lafs_dirty_blk(&db->b);
+       lafs_sched_blk(&db->b);
        return 0;
 }
index da6f167b3e0f4976e1002ab8a36cfc05448287c4..87f0583f32bdb68b7caf37a0658b33dfb0651cf3 100644 (file)
@@ -26,6 +26,7 @@ struct lafs_ino *lafs_import_inode_buf(struct lafs *fs,
        ino->fs = fs;
        ino->inum = inum;
        ino->filesys = parent;
+       INIT_LIST_HEAD(&ino->dirty);
 
        if (inode_load(ino, (struct la_inode *)buf))
                /* FIXME callers of this should reparent it to themselves. */
index ef5b414ef2da16baff15985ff6fb2eae57017c90..626adeddf85a8f2e1104b199474809a5bb408dda 100644 (file)
@@ -55,5 +55,5 @@ void lafs_incorporate(struct lafs_iblk *ib)
        }
        trace(1, "incorporate %d/%lld\n", ib->b.ino->dblock->b.ino->inum,
               (long long)ib->b.ino->dblock->b.fileaddr);
-       lafs_dirty_blk(&ib->b);
+       lafs_sched_blk(&ib->b);
 }
index 2930b00d03470b11bab38a1fd2949070ac1b5164..38c84d8aa324562ca269364fa2faa0bd0c844a3e 100644 (file)
@@ -26,7 +26,7 @@ void set_youth(struct lafs *fs, int dev, loff_t seg, int youth)
        lafs_load_dblk(db);
        p = (void*)db->b.data;
        p[seg % (fs->blocksize/2)] = __cpu_to_le16(youth);
-       lafs_dirty_blk(&db->b);
+       lafs_sched_blk(&db->b);
 }
 
 int lafs_new_segment(struct lafs *fs, int cnum)
index 150f0f0d352f810625f48e7019de2f83299580f9..2a740f3dc3069219750cce35ed41cb3839ec5bd3 100644 (file)
@@ -13,6 +13,7 @@ int lafs_sched_blk(struct lafs_blk *blk)
 {
        struct lafs *fs = blk->ino->fs;
 
+       blk->flags |= B_Dirty;
        if (blk->flags & B_Sched)
                return 0;
 
@@ -25,6 +26,6 @@ int lafs_sched_blk(struct lafs_blk *blk)
        if (blk->parent)
                blk->parent->sched_cnt++;
        trace(1, "schedule %p\n", blk);
-       list_add(&blk->leafs, &fs->leafs);
+       list_move_tail(&blk->leafs, &fs->leafs);
        return 0;
 }
index 930c7edcdae85e09b7287a1e0a56e5915cc53ee0..a332c2fed68026e5387edbba2391d5847280694b 100644 (file)
@@ -39,7 +39,7 @@ void segment_count(struct lafs *fs, int dev, loff_t seg, int diff)
        cnt = __le16_to_cpu(p[seg % (fs->blocksize/2)]);
        cnt += diff;
        p[seg % (fs->blocksize/2)] = __cpu_to_le16(cnt);
-       lafs_dirty_blk(&db->b);
+       lafs_sched_blk(&db->b);
 }
 
 
index c7fe06e31cddbd50ce6f57bcb7bd87d460870579..94c2ee942c9c13618975f3295462cf007a85fd23 100644 (file)
@@ -1542,12 +1542,65 @@ static void c_ls(struct state *st, void **args)
                printf("\n");
 }
 
+/****** FLUSH ******/
+static char help_flush[] = "Flush out all changes to one or all files";
+static struct args args_flush[] = {
+       { "PATH", internal, -1, {NULL}, "Path to inode to flush"},
+       { "-inum", opaque, 0, {NULL}, "Inode number to flush"},
+       TERMINAL_ARG
+};
+static void c_flush(struct state *st, void **args)
+{
+       struct lafs_ino *inode;
+       if (!args[1]) {
+               lafs_flush(st->lafs);
+               lafs_cluster_flush(st->lafs, 0);
+               if (st->verbose)
+                       printf("Filesystem flushed\n");
+               return;
+       }
+       if (st->lafs->ss.root == 0) {
+               printf("show inode: filesytem not ready\n");
+               return;
+       }
+       inode = lafs_get_itable(st->lafs);
+       if (args[2]) {
+               char *inostr = args[2];
+               char *endp;
+               int ino = strtoul(inostr, &endp, 10);
+               if (endp == inostr || *endp) {
+                       printf("flush: %s is not a valid inode number\n",
+                              inostr);
+                       return;
+               }
+               if (ino)
+                       inode = lafs_get_inode(inode, ino);
+               if (!inode)
+                       printf("flush: cannot find inode %d\n",ino);
+       } else {
+               char *path = args[1];
+               inode = lafs_get_inode(inode, 2);
+               inode = lafs_lookup_path(inode, inode, path, NULL);
+
+               if (!inode) {
+                       printf("flush: cannot find inode for %s\n", path);
+                       return;
+               }
+       }
+       lafs_flush_inode(inode);
+       lafs_cluster_flush(st->lafs, 0);
+       if (st->verbose)
+               printf("Inode %d flushed\n", (int)inode->inum);
+}
+
+/***********************************************************/
 /* list of all commands - preferably in alphabetical order */
 #define CMD(x) {#x, c_##x, args_##x, help_##x}
 static struct cmd lafs_cmds[] = {
        {"?", c_help, args_help, help_help},
        CMD(add_device),
        CMD(exit),
+       CMD(flush),
        CMD(help),
        CMD(load_dev),
        CMD(ls),