]> git.neil.brown.name Git - lafs-utils.git/commitdiff
inode map allocation
authorNeilBrown <neilb@suse.de>
Mon, 21 Mar 2011 09:19:26 +0000 (20:19 +1100)
committerNeilBrown <neilb@suse.de>
Mon, 21 Mar 2011 09:19:26 +0000 (20:19 +1100)
add lafs_imap_alloc and use it to allocate an inode number for
segment usage file.

Signed-off-by: NeilBrown <neilb@suse.de>
include/lafs/lafs.h
lib/internal.h
lib/lafs_find_next.c
lib/lafs_imap_alloc.c [new file with mode: 0644]
lib/lafs_imap_clr.c
lib/lafs_imap_set.c
tools/lafs.c

index 7f60a38c7b9309609f71c261136c3c9abe0d5d41..874d2d5fc5690854420e6ffa56765d712d6fc398 100644 (file)
@@ -95,6 +95,7 @@ struct lafs_iblk *lafs_leaf_find(struct lafs_ino *inode,
 u32 lafs_dir_lookup(struct lafs_ino *dir, char *name, int len);
 struct lafs_ino *lafs_lookup_path(struct lafs_ino *root, struct lafs_ino *cwd,
                                  char *path, char **remainder);
+int lafs_imap_alloc(struct lafs_ino *imap);
 
 
 
index 7f16b745c7fa46700cfe4f244f9b841f60714352..ae238fa7ba839c6c611df8bcd7e17f487bd91fc6 100644 (file)
@@ -3,6 +3,7 @@
  * Internal use defines for liblafs - not externally visible
  */
 #include <stdio.h>
+#include <strings.h>
 
 extern int lafs_trace_level;
 
@@ -90,3 +91,52 @@ static inline int test_bit(int bit, unsigned long *map)
 {
        return *map & (1UL<<bit);
 }
+
+
+static inline int set_c_bit(int nr, unsigned char * addr)
+{
+       int     mask, retval;
+
+       addr += nr >> 3;
+       mask = 1 << (nr & 0x7);
+
+       retval = (mask & *addr) != 0;
+       *addr |= mask;
+
+       return retval;
+}
+
+static inline int clear_c_bit(int nr, unsigned char * addr)
+{
+       int     mask, retval;
+
+       addr += nr >> 3;
+       mask = 1 << (nr & 0x7);
+
+       retval = (mask & *addr) != 0;
+       *addr &= ~mask;
+
+       return retval;
+}
+
+static inline int test_c_bit(int nr, const unsigned char * addr)
+{
+       int     mask;
+
+       addr += nr >> 3;
+       mask = 1 << (nr & 0x7);
+       return ((mask & *addr) != 0);
+}
+
+static inline int find_first_bit(char *buf, int size)
+{
+       int b = 0;
+       while (size && *buf == 0) {
+               size--;
+               buf++;
+               b += 8;
+       }
+       if (!size)
+               return b;
+       return b + ffs(*buf)-1;
+}
index 4afa224e5a2dff385fffa9579f4d976e5a423107..f9460351161f11e628c57e9545df80687b1476e0 100644 (file)
@@ -6,18 +6,18 @@ static int __block_find_next(struct lafs_ino *inode, u32 *addrp);
 u32 lafs_find_next(struct lafs_ino *inode, u32 addr)
 {
        /* Find the first allocated block in 'ino'
-        * which is at-or-after 'bnum'.
-        p* making sure to skip over Recent hole.
+        * which is at-or-after 'addr'.
+        * making sure to skip over Recent hole.
         */
        while(1) {
-               int rv = __block_find_next(inode, &addr);
-               struct lafs_dblk *b;
-               if (rv == 0)
+               switch(__block_find_next(inode, &addr)) {
+               case 0:
                        return LAFS_NOBLOCK;
-               if (rv == 2)
+               case 1:
+                       return addr;
+               case 2:
                        continue;
-               b = lafs_dblk(inode, addr);
-               addr++;
+               }
        }
 }
 
diff --git a/lib/lafs_imap_alloc.c b/lib/lafs_imap_alloc.c
new file mode 100644 (file)
index 0000000..7e8cb64
--- /dev/null
@@ -0,0 +1,63 @@
+
+/*
+ * Allocate an unused inode number from the inode map.
+ * We don't set it as in-use
+ */
+
+#include <lafs/lafs.h>
+#include <memory.h>
+#include "internal.h"
+
+int lafs_imap_alloc(struct lafs_ino *imap)
+{
+       struct lafs *fs = imap->fs;
+       struct lafs_dblk *db = NULL;
+
+       u32 addr;
+       u32 start = 0;
+       u32 bit;
+
+       while(1) {
+               if (!db) {
+                       u32 bnum = lafs_find_next(imap, start);
+                       if (bnum < imap->md.inodemap.size)
+                               db = lafs_dblk(imap, bnum);
+
+                       else {
+                               /* need to allocate a new block past end of file */
+                               bnum = imap->md.inodemap.size;
+                               imap->md.inodemap.size = bnum+1;
+                               db = lafs_dblk(imap, bnum);
+                               lafs_dirty_blk(&db->b);
+                               memset(db->b.data, 0xff, fs->blocksize);
+                               db->b.flags |= B_Valid;
+                       }
+               }
+               addr = db->b.fileaddr * fs->blocksize << 8;
+               lafs_load_dblk(db);
+               bit = find_first_bit(db->b.data, fs->blocksize);
+               if (bit < fs->blocksize * 8) {
+                       lafs_dirty_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 &&
+                           memcmp(db->b.data, 
+                                  db->b.data+4, fs->blocksize-4) == 0) {
+                               /* block is completely zero, so we have to punch
+                                * a hole
+                                */
+                               db->b.flags &= ~B_Dirty;
+                               lafs_allocated_block(&db->b, 0);
+                       }
+                       if (bit+addr < 16) {
+                               db=NULL;
+                               continue;
+                       }
+                       return bit + addr;
+               }
+               /* no 1 bits, so again, punch a hole */
+               db->b.flags &= ~B_Dirty;
+               lafs_allocated_block(&db->b, 0);
+               db = NULL;
+       }
+}
index 2f46fc95bb91b893b95c634bda8eb437d87098c9..94532a489b366b652308b31759984d6d2518418a 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <lafs/lafs.h>
+#include "internal.h"
 
 int lafs_imap_clr(struct lafs_ino *ino, int inum)
 {
@@ -19,7 +20,7 @@ int lafs_imap_clr(struct lafs_ino *ino, int inum)
        db = lafs_dblk(ino, blknum);
        lafs_load_dblk(db);
        inum -= blknum * fs->blocksize * 8;
-       db->b.data[inum/8] |= (1<<(inum&7));
+       set_c_bit(inum, (unsigned char *)db->b.data);
        /* FIXME if block is now empty, possibly contract file */
        lafs_dirty_blk(&db->b);
        return 0;
index 2e2e18cead4fe47c2b8821b72097bf37cd836448..3c463940a09fbb7fa17d622ca3c3196b6c3963c0 100644 (file)
@@ -30,7 +30,9 @@ int lafs_imap_set(struct lafs_ino *ino, int inum)
                lafs_dirty_inode(ino);
        }
        inum -= blknum * fs->blocksize * 8;
-       db->b.data[inum/8] &= ~ (1<<(inum&7));
+       if (test_c_bit(inum, (unsigned char*)db->b.data))
+               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);
        return 0;
index 437b080f401b07d1ab2ea3ff1cae58547e8907e9..c7fe06e31cddbd50ce6f57bcb7bd87d460870579 100644 (file)
@@ -995,9 +995,12 @@ static void c_add_device(struct state *st, void **args)
        }
 
        if (!usage_inum) {
-               printf("FIXME defaulting usage inum to 16 "
-                      "- should check if in-use\n");
-               usage_inum = 16;
+               usage_inum = lafs_imap_alloc(imfile);
+       } else {
+               if (lafs_imap_set(imfile, usage_inum) == 1) {
+                       printf("newfs: inum %d already in use.\n", usage_inum);
+                       return;
+               }
        }
        dev = lafs_add_device(st->lafs, devname, fd,
                              segment_bytes / block_bytes,
@@ -1017,11 +1020,12 @@ static void c_add_device(struct state *st, void **args)
        lafs_dirty_inode(segmap);
        lafs_imap_set(imfile, usage_inum);
 
-       printf("Added device %s at %llu with %llu segments of %llu %dk blocks\n",
+       printf("Added device %s at %llu with %llu segments of %llu %dk blocks\n"
+              "    Usage inode %d\n",
               devname, (unsigned long long)dev->start,
                       (unsigned long long)dev->segment_count,
               (unsigned long long)dev->segment_size,
-              st->lafs->blocksize/1024);
+              st->lafs->blocksize/1024, usage_inum);
 
 }