else
err = lafs_setparent(dblk(b));
- if (test_bit(B_Realloc, &b->flags))
- alloc_type = CleanSpace;
- if (alloc_type == NewSpace && b->physaddr)
+ /* If there is already a physaddr, or the data is
+ * stored in the inode, then we aren't really allocating
+ * new space.
+ * When unlinking from a small directory, this can
+ * be an issue.
+ */
+ if (alloc_type == NewSpace &&
+ (b->physaddr || (b->fileaddr == 0
+ && LAFSI(b->inode)->depth == 0)))
alloc_type = ReleaseSpace;
- if (alloc_type == NewSpace && !b->physaddr &&
- b->fileaddr == 0 &&
- LAFSI(b->inode)->depth == 0) {
- /* HACK. If the file isn't growing, we can use
- * ReleaseSpace. But we don't really know.
- * This is needed for unlink
- */
- alloc_type = ReleaseSpace;
- }
- if (alloc_type == NewSpace && test_bit(B_InoIdx, &b->flags)) {
- /* HACK, phys isn't necessarily set for the InoIdx block.
- * Is this a good way to handle that?
+ if (alloc_type == NewSpace && test_bit(B_InoIdx, &b->flags))
+ /* physaddr isn't necessarily set for the InoIdx block.
*/
alloc_type = ReleaseSpace;
- }
+ /* Allocate space in the filesystem */
err = err ?: lafs_prealloc(b, alloc_type);
+ /* Allocate space in the file (and quota set) */
if (err == 0 && b->physaddr == 0 &&
!test_bit(B_Index, &b->flags) &&
!test_and_set_bit(B_Prealloc, &b->flags)) {
if (err)
clear_bit(B_Prealloc, &b->flags);
}
- if (err)
- return err;
/* Having reserved the block, we need to get a segref,
* which will involve reserving those blocks too.
&& !test_bit(B_SegRef, &b->flags))
err = lafs_seg_ref_block(b, 0);
- return err;
+ if (err == 0)
+ return 0;
+ if (alloc_type == CleanSpace || alloc_type == NewSpace)
+ return -ENOSPC;
+ if (alloc_type == ReleaseSpace)
+ return -EAGAIN;
+ LAFS_BUG(1, b);
}
int