* This is split into pre_create and commit_create
* We already know that the name doesn't exist so a lookup will fail,
* but will find the right place in the tree.
- * FIXME cache the results of the prior lookup??
* pre_create allocates blocks as needed and stores info in the dirop_handle.
* commit_create finalises the create and cannot fail.
*/
const char *name, int nlen, struct dirop_handle *doh)
{
struct datablock *dirblk;
- int err;
+ int orphan = 0;
doh->dirent_block =
dirblk = dir_lookup_blk(dir, name, nlen, &doh->index,
/* i_mutex protect us now, so don't need to maintain the lock */
lafs_iounlock_block(&dirblk->b);
- /* FIXME should I check if the orphanage is needed
- * before committing this block to it?
+ /* Only make this block an orphan if there is a real
+ * possibilitiy.
+ * i.e. one of
+ * We found the last possible entry
+ * We found the first entry
+ * We found the only entry (in which case we found the first)
+ * First entry is deleted
*/
- err = lafs_make_orphan(fs, doh->dirent_block, dir);
- return err;
+ if (((doh->hash+1) & MaxDirHash) == doh->dirent_block->b.fileaddr)
+ /* Last possible entry is being remove */
+ orphan=1;
+ if (!orphan) {
+ u32 seed = LAFSI(dir)->md.file.seed;
+ u8 firstpiece = 0;
+ struct dir_ent de;
+ char bits = dir->i_blkbits - 8;
+ char *buf = map_dblock(dirblk);
+ lafs_dir_find(buf, bits, seed, 0, &firstpiece);
+ if (doh->index == firstpiece ||
+ lafs_dir_extract(buf, bits, &de,
+ firstpiece, NULL)->target == 0)
+ orphan = 1;
+ unmap_dblock(dirblk, buf);
+ }
+ if (orphan)
+ return lafs_make_orphan(fs, doh->dirent_block, dir);
+ return 0;
}
static void
* and remove the unanchor.
*/
lafs_dir_find(buf, bits, seed, 0, &firstpiece);
- hash = LAFSI(dir)->md.file.seed;
+ hash = seed;
if (firstpiece &&
lafs_dir_extract(buf, bits, &de, firstpiece, &hash)->target == 0 &&
lafs_dir_find(buf, bits, seed, hash+1, &piece) == 0) {