Skip to content

Commit 64f30e8

Browse files
author
Al Viro
committed
clean ufs_trunc_direct() up a bit...
For short files (== no indirect blocks needed) UFS allows the last block to be a partial one. That creates some complications for truncation down to "short file" lengths. ufs_trunc_direct() is called when we'd already made sure that new EOF is not in a hole; nothing needs to be done if we are extending the file and in case we are shrinking the file it needs to * shrink or free the old final block. * free all full direct blocks between the new and old EOF. * possibly shrink the new final block. The logics is needlessly complicated by trying to keep all cases handled by the same sequence of operations. if not shrinking nothing to do else if number of full blocks unchanged free the tail of possibly partial last block else free the tail of (currently full) new last block free all present (full) blocks in between free the (possibly partial) old last block is easier to follow than the result of trying to unify these cases. Signed-off-by: Al Viro <[email protected]>
1 parent db57044 commit 64f30e8

File tree

1 file changed

+61
-68
lines changed

1 file changed

+61
-68
lines changed

fs/ufs/inode.c

Lines changed: 61 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -878,91 +878,84 @@ static inline void free_data(struct to_free *ctx, u64 from, unsigned count)
878878

879879
#define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift)
880880

881+
/*
882+
* used only for truncation down to direct blocks.
883+
*/
881884
static void ufs_trunc_direct(struct inode *inode)
882885
{
883886
struct ufs_inode_info *ufsi = UFS_I(inode);
884-
struct super_block * sb;
885-
struct ufs_sb_private_info * uspi;
886-
void *p;
887-
u64 frag1, frag2, frag3, frag4, block1, block2;
887+
struct super_block *sb = inode->i_sb;
888+
struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
889+
unsigned int new_frags, old_frags;
890+
unsigned int old_slot, new_slot;
891+
unsigned int old_tail, new_tail;
888892
struct to_free ctx = {.inode = inode};
889-
unsigned i, tmp;
890893

891894
UFSD("ENTER: ino %lu\n", inode->i_ino);
892895

893-
sb = inode->i_sb;
894-
uspi = UFS_SB(sb)->s_uspi;
895-
896-
frag1 = DIRECT_FRAGMENT;
897-
frag4 = min_t(u64, UFS_NDIR_FRAGMENT, ufsi->i_lastfrag);
898-
frag2 = ((frag1 & uspi->s_fpbmask) ? ((frag1 | uspi->s_fpbmask) + 1) : frag1);
899-
frag3 = frag4 & ~uspi->s_fpbmask;
900-
block1 = block2 = 0;
901-
if (frag2 > frag3) {
902-
frag2 = frag4;
903-
frag3 = frag4 = 0;
904-
} else if (frag2 < frag3) {
905-
block1 = ufs_fragstoblks (frag2);
906-
block2 = ufs_fragstoblks (frag3);
907-
}
908-
909-
UFSD("ino %lu, frag1 %llu, frag2 %llu, block1 %llu, block2 %llu,"
910-
" frag3 %llu, frag4 %llu\n", inode->i_ino,
911-
(unsigned long long)frag1, (unsigned long long)frag2,
912-
(unsigned long long)block1, (unsigned long long)block2,
913-
(unsigned long long)frag3, (unsigned long long)frag4);
896+
new_frags = DIRECT_FRAGMENT;
897+
// new_frags = first fragment past the new EOF
898+
old_frags = min_t(u64, UFS_NDIR_FRAGMENT, ufsi->i_lastfrag);
899+
// old_frags = first fragment past the old EOF or covered by indirects
914900

915-
if (frag1 >= frag2)
916-
goto next1;
917-
918-
/*
919-
* Free first free fragments
920-
*/
921-
p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag1));
922-
tmp = ufs_data_ptr_to_cpu(sb, p);
923-
if (!tmp )
924-
ufs_panic (sb, "ufs_trunc_direct", "internal error");
925-
frag2 -= frag1;
926-
frag1 = ufs_fragnum (frag1);
901+
if (new_frags >= old_frags) // expanding - nothing to free
902+
goto done;
927903

928-
ufs_free_fragments(inode, tmp + frag1, frag2);
904+
old_tail = ufs_fragnum(old_frags);
905+
old_slot = ufs_fragstoblks(old_frags);
906+
new_tail = ufs_fragnum(new_frags);
907+
new_slot = ufs_fragstoblks(new_frags);
929908

930-
next1:
931-
/*
932-
* Free whole blocks
933-
*/
934-
for (i = block1 ; i < block2; i++) {
935-
p = ufs_get_direct_data_ptr(uspi, ufsi, i);
936-
tmp = ufs_data_ptr_to_cpu(sb, p);
909+
if (old_slot == new_slot) { // old_tail > 0
910+
void *p = ufs_get_direct_data_ptr(uspi, ufsi, old_slot);
911+
u64 tmp = ufs_data_ptr_to_cpu(sb, p);
937912
if (!tmp)
938-
continue;
939-
write_seqlock(&ufsi->meta_lock);
940-
ufs_data_ptr_clear(uspi, p);
941-
write_sequnlock(&ufsi->meta_lock);
913+
ufs_panic(sb, __func__, "internal error");
914+
if (!new_tail) {
915+
write_seqlock(&ufsi->meta_lock);
916+
ufs_data_ptr_clear(uspi, p);
917+
write_sequnlock(&ufsi->meta_lock);
918+
}
919+
ufs_free_fragments(inode, tmp + new_tail, old_tail - new_tail);
920+
} else {
921+
unsigned int slot = new_slot;
942922

943-
free_data(&ctx, tmp, uspi->s_fpb);
944-
}
923+
if (new_tail) {
924+
void *p = ufs_get_direct_data_ptr(uspi, ufsi, slot++);
925+
u64 tmp = ufs_data_ptr_to_cpu(sb, p);
926+
if (!tmp)
927+
ufs_panic(sb, __func__, "internal error");
945928

946-
free_data(&ctx, 0, 0);
929+
ufs_free_fragments(inode, tmp + new_tail,
930+
uspi->s_fpb - new_tail);
931+
}
932+
while (slot < old_slot) {
933+
void *p = ufs_get_direct_data_ptr(uspi, ufsi, slot++);
934+
u64 tmp = ufs_data_ptr_to_cpu(sb, p);
935+
if (!tmp)
936+
continue;
937+
write_seqlock(&ufsi->meta_lock);
938+
ufs_data_ptr_clear(uspi, p);
939+
write_sequnlock(&ufsi->meta_lock);
947940

948-
if (frag3 >= frag4)
949-
goto next3;
941+
free_data(&ctx, tmp, uspi->s_fpb);
942+
}
950943

951-
/*
952-
* Free last free fragments
953-
*/
954-
p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag3));
955-
tmp = ufs_data_ptr_to_cpu(sb, p);
956-
if (!tmp )
957-
ufs_panic(sb, "ufs_truncate_direct", "internal error");
958-
frag4 = ufs_fragnum (frag4);
959-
write_seqlock(&ufsi->meta_lock);
960-
ufs_data_ptr_clear(uspi, p);
961-
write_sequnlock(&ufsi->meta_lock);
944+
free_data(&ctx, 0, 0);
962945

963-
ufs_free_fragments (inode, tmp, frag4);
964-
next3:
946+
if (old_tail) {
947+
void *p = ufs_get_direct_data_ptr(uspi, ufsi, slot);
948+
u64 tmp = ufs_data_ptr_to_cpu(sb, p);
949+
if (!tmp)
950+
ufs_panic(sb, __func__, "internal error");
951+
write_seqlock(&ufsi->meta_lock);
952+
ufs_data_ptr_clear(uspi, p);
953+
write_sequnlock(&ufsi->meta_lock);
965954

955+
ufs_free_fragments(inode, tmp, old_tail);
956+
}
957+
}
958+
done:
966959
UFSD("EXIT: ino %lu\n", inode->i_ino);
967960
}
968961

0 commit comments

Comments
 (0)