From: NeilBrown Date: Wed, 23 Jun 2010 06:20:28 +0000 (+1000) Subject: Revise error returns for allocation failure. X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=d611d8d603759ead8e07d7a678304ceed5329da2;p=LaFS.git Revise error returns for allocation failure. lafs_prealloc, like lafs_space_alloc, just succeeds or fails, it doesn't choose the error type. lafs_cluster_update_pin and lafs_reserve_block need to indicate either -ENOSPC or -EAGAIN depending on context. Signed-off-by: NeilBrown --- diff --git a/block.c b/block.c index 2712451..89431fe 100644 --- a/block.c +++ b/block.c @@ -366,29 +366,26 @@ lafs_reserve_block(struct block *b, int alloc_type) 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)) { @@ -396,8 +393,6 @@ lafs_reserve_block(struct block *b, int alloc_type) 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. @@ -409,7 +404,13 @@ lafs_reserve_block(struct block *b, int alloc_type) && !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 diff --git a/cluster.c b/cluster.c index 377d536..ba2f7b7 100644 --- a/cluster.c +++ b/cluster.c @@ -894,6 +894,7 @@ lafs_cluster_update_prepare(struct update_handle *uh, struct fs *fs, uh->reserved = 0; return 0; } + int lafs_cluster_update_pin(struct update_handle *uh) { @@ -903,7 +904,7 @@ lafs_cluster_update_pin(struct update_handle *uh) uh->fs->cluster_updates++; return 0; } - return -ENOSPC; + return -EAGAIN; } static unsigned long long diff --git a/modify.c b/modify.c index 481057d..33b2cf8 100644 --- a/modify.c +++ b/modify.c @@ -1932,11 +1932,7 @@ int __must_check lafs_prealloc(struct block *blk, int why) } lafs_space_return(fs, credits); - /* allocation failed. */ - if (why == NewSpace) - return -ENOSPC; - else - return -EAGAIN; + return -ENOSPC; } /* If a datablock is dirty and pinned to the previous phase,