From f2cfd067d95f2ae69759ad847de914158ec1df3e Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 21 Mar 2011 20:19:26 +1100 Subject: [PATCH] inode map allocation add lafs_imap_alloc and use it to allocate an inode number for segment usage file. Signed-off-by: NeilBrown --- include/lafs/lafs.h | 1 + lib/internal.h | 50 ++++++++++++++++++++++++++++++++++ lib/lafs_find_next.c | 16 +++++------ lib/lafs_imap_alloc.c | 63 +++++++++++++++++++++++++++++++++++++++++++ lib/lafs_imap_clr.c | 3 ++- lib/lafs_imap_set.c | 4 ++- tools/lafs.c | 14 ++++++---- 7 files changed, 136 insertions(+), 15 deletions(-) create mode 100644 lib/lafs_imap_alloc.c diff --git a/include/lafs/lafs.h b/include/lafs/lafs.h index 7f60a38..874d2d5 100644 --- a/include/lafs/lafs.h +++ b/include/lafs/lafs.h @@ -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); diff --git a/lib/internal.h b/lib/internal.h index 7f16b74..ae238fa 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -3,6 +3,7 @@ * Internal use defines for liblafs - not externally visible */ #include +#include extern int lafs_trace_level; @@ -90,3 +91,52 @@ static inline int test_bit(int bit, unsigned long *map) { return *map & (1UL<> 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; +} diff --git a/lib/lafs_find_next.c b/lib/lafs_find_next.c index 4afa224..f946035 100644 --- a/lib/lafs_find_next.c +++ b/lib/lafs_find_next.c @@ -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 index 0000000..7e8cb64 --- /dev/null +++ b/lib/lafs_imap_alloc.c @@ -0,0 +1,63 @@ + +/* + * Allocate an unused inode number from the inode map. + * We don't set it as in-use + */ + +#include +#include +#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; + } +} diff --git a/lib/lafs_imap_clr.c b/lib/lafs_imap_clr.c index 2f46fc9..94532a4 100644 --- a/lib/lafs_imap_clr.c +++ b/lib/lafs_imap_clr.c @@ -4,6 +4,7 @@ */ #include +#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; diff --git a/lib/lafs_imap_set.c b/lib/lafs_imap_set.c index 2e2e18c..3c46394 100644 --- a/lib/lafs_imap_set.c +++ b/lib/lafs_imap_set.c @@ -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; diff --git a/tools/lafs.c b/tools/lafs.c index 437b080..c7fe06e 100644 --- a/tools/lafs.c +++ b/tools/lafs.c @@ -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); } -- 2.39.5