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);
* Internal use defines for liblafs - not externally visible
*/
#include <stdio.h>
+#include <strings.h>
extern int lafs_trace_level;
{
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;
+}
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++;
+ }
}
}
--- /dev/null
+
+/*
+ * 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;
+ }
+}
*/
#include <lafs/lafs.h>
+#include "internal.h"
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;
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;
}
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,
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);
}