int lafs_imap_set(struct lafs_ino *, int inum);
int lafs_add_free_seg(struct lafs*, int dev, loff_t seg);
+void lafs_find_free(struct lafs *fs);
void lafs_inode_init(struct lafs *, char *, int type);
struct lafs_ino *lafs_import_inode_buf(struct lafs *fs,
--- /dev/null
+
+#include <lafs/lafs.h>
+#include "internal.h"
+
+/* lafs_find_free
+ * Find free blocks and add them to the list.
+ * Only run if free list is empty, to avoid any chance
+ * of duplicate entries.
+ * We add anything which has a youth of 0 in the
+ * segusage files, but not any currently open segment
+ */
+
+void lafs_find_free(struct lafs *fs)
+{
+ struct lafs_device *dev;
+ int mask = (1<<(fs->blockbits - 1)) - 1;
+
+ for (dev = fs->devs; dev; dev = dev->next) {
+ struct lafs_ino *ino = dev->segsum;
+ struct lafs_dblk *db = NULL;
+ loff_t seg;
+
+ for (seg = 0; seg < dev->segment_count; seg++) {
+ u32 bnum = seg >> (fs->blockbits-1);
+ if (db == NULL || db->b.fileaddr != bnum) {
+ db = lafs_dblk(ino, bnum);
+ if (!db || lafs_load_dblk(db))
+ break;
+ if (((u16*)db->b.data)[seg&mask] == 0) {
+ /* possible contender */
+ int s;
+ for (s = 0; s < WC_NUM;s++)
+ if (fs->wc[s].seg.dev == dev->devnum &&
+ fs->wc[s].seg.num == seg)
+ break;
+ if (s == WC_NUM)
+ if (lafs_add_free_seg(fs, dev->devnum,
+ seg) == 0)
+ return;
+ }
+ }
+ }
+ }
+}
loff_t seg;
struct lafs_cluster *wc = &fs->wc[cnum];
- if (fs->free_head == fs->free_tail)
+ if (fs->free_head == fs->free_tail) {
/* list is empty */
- return 0;
-
+ lafs_find_free(fs);
+ if (fs->free_head == fs->free_tail)
+ return 0;
+ }
dev = fs->freelist[fs->free_head].dev;
seg = fs->freelist[fs->free_head].seg;
lafs_imap_set(imfile, 16);
lafs_cluster_init(lafs, 0, 0, 0, 1);
- lafs_add_free_seg(lafs, dev->devnum, 0);
/* Write checkpoint and state blocks */
lafs_checkpoint(lafs);
/* Write state blocks a second time, so all 4 copies are written */