Loading fs/ufs/inode.c +60 −138 Original line number Original line Diff line number Diff line Loading @@ -1068,32 +1068,40 @@ static void ufs_trunc_direct(struct inode *inode) UFSD("EXIT: ino %lu\n", inode->i_ino); UFSD("EXIT: ino %lu\n", inode->i_ino); } } static void ufs_trunc_branch(struct inode *inode, unsigned *offsets, int depth2, int depth, void *p) static void ufs_trunc_indirect(struct inode *inode, unsigned *offsets, int depth2, void *p) { { struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb; struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; struct ufs_buffer_head * ind_ubh; struct ufs_inode_info *ufsi = UFS_I(inode); void *ind; struct ufs_buffer_head *ubh; u64 tmp, frag_to_free = 0; u64 tmp; unsigned free_count = 0; bool free_it = !offsets || !depth2; unsigned from = offsets ? *offsets : 0; unsigned from = offsets ? *offsets++ : 0; bool to_free = !offsets || !depth2; unsigned i; unsigned i; tmp = ufs_data_ptr_to_cpu(sb, p); tmp = ufs_data_ptr_to_cpu(sb, p); if (!tmp) if (!tmp) return; return; ind_ubh = ubh_bread(sb, tmp, uspi->s_bsize); ubh = ubh_bread (sb, tmp, uspi->s_bsize); if (!ind_ubh) { if (!ubh) { write_seqlock(&UFS_I(inode)->meta_lock); write_seqlock(&ufsi->meta_lock); ufs_data_ptr_clear(uspi, p); ufs_data_ptr_clear(uspi, p); write_sequnlock(&UFS_I(inode)->meta_lock); write_sequnlock(&ufsi->meta_lock); return; return; } } if (--depth) { for (i = from ; i < uspi->s_apb ; i++, offsets = NULL) { void *ind = ubh_get_data_ptr(uspi, ubh, i); ufs_trunc_branch(inode, offsets, depth2 - 1, depth, ind); ubh_mark_buffer_dirty(ubh); } } else { u64 frag_to_free = 0; unsigned free_count = 0; for (i = from; i < uspi->s_apb; i++) { for (i = from; i < uspi->s_apb; i++) { ind = ubh_get_data_ptr(uspi, ind_ubh, i); void *ind = ubh_get_data_ptr(uspi, ubh, i); tmp = ufs_data_ptr_to_cpu(sb, ind); tmp = ufs_data_ptr_to_cpu(sb, ind); if (!tmp) if (!tmp) continue; continue; Loading @@ -1101,7 +1109,7 @@ static void ufs_trunc_indirect(struct inode *inode, unsigned *offsets, int depth write_seqlock(&UFS_I(inode)->meta_lock); write_seqlock(&UFS_I(inode)->meta_lock); ufs_data_ptr_clear(uspi, ind); ufs_data_ptr_clear(uspi, ind); write_sequnlock(&UFS_I(inode)->meta_lock); write_sequnlock(&UFS_I(inode)->meta_lock); ubh_mark_buffer_dirty(ind_ubh); ubh_mark_buffer_dirty(ubh); if (free_count == 0) { if (free_count == 0) { frag_to_free = tmp; frag_to_free = tmp; free_count = uspi->s_fpb; free_count = uspi->s_fpb; Loading @@ -1119,96 +1127,6 @@ static void ufs_trunc_indirect(struct inode *inode, unsigned *offsets, int depth if (free_count > 0) { if (free_count > 0) { ufs_free_blocks (inode, frag_to_free, free_count); ufs_free_blocks (inode, frag_to_free, free_count); } } if (to_free) { tmp = ufs_data_ptr_to_cpu(sb, p); write_seqlock(&UFS_I(inode)->meta_lock); ufs_data_ptr_clear(uspi, p); write_sequnlock(&UFS_I(inode)->meta_lock); ubh_bforget(ind_ubh); ufs_free_blocks (inode, tmp, uspi->s_fpb); mark_inode_dirty(inode); return; } if (IS_SYNC(inode) && ubh_buffer_dirty(ind_ubh)) ubh_sync_block(ind_ubh); ubh_brelse (ind_ubh); } static void ufs_trunc_dindirect(struct inode *inode, unsigned *offsets, int depth2, void *p) { struct super_block *sb = inode->i_sb; struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; struct ufs_buffer_head *dind_bh; u64 tmp; void *dind; bool free_it = !offsets || !depth2; unsigned dindirect_block = offsets ? *offsets++ : 0; unsigned i; tmp = ufs_data_ptr_to_cpu(sb, p); if (!tmp) return; dind_bh = ubh_bread(sb, tmp, uspi->s_bsize); if (!dind_bh) { write_seqlock(&UFS_I(inode)->meta_lock); ufs_data_ptr_clear(uspi, p); write_sequnlock(&UFS_I(inode)->meta_lock); return; } for (i = dindirect_block ; i < uspi->s_apb ; i++, offsets = NULL) { dind = ubh_get_data_ptr(uspi, dind_bh, i); tmp = ufs_data_ptr_to_cpu(sb, dind); if (!tmp) continue; ufs_trunc_indirect(inode, offsets, depth2 - 1, dind); ubh_mark_buffer_dirty(dind_bh); } if (free_it) { tmp = ufs_data_ptr_to_cpu(sb, p); write_seqlock(&UFS_I(inode)->meta_lock); ufs_data_ptr_clear(uspi, p); write_sequnlock(&UFS_I(inode)->meta_lock); ubh_bforget(dind_bh); ufs_free_blocks(inode, tmp, uspi->s_fpb); mark_inode_dirty(inode); return; } if (IS_SYNC(inode) && ubh_buffer_dirty(dind_bh)) ubh_sync_block(dind_bh); ubh_brelse (dind_bh); } static void ufs_trunc_tindirect(struct inode *inode, unsigned *offsets, int depth2) { struct super_block *sb = inode->i_sb; struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; struct ufs_inode_info *ufsi = UFS_I(inode); struct ufs_buffer_head * tind_bh; u64 tmp; void *tind, *p; bool free_it = !offsets || !depth2; unsigned tindirect_block = offsets ? *offsets++ : 0; unsigned i; p = ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK); if (!(tmp = ufs_data_ptr_to_cpu(sb, p))) return; tind_bh = ubh_bread (sb, tmp, uspi->s_bsize); if (!tind_bh) { write_seqlock(&ufsi->meta_lock); ufs_data_ptr_clear(uspi, p); write_sequnlock(&ufsi->meta_lock); return; } for (i = tindirect_block ; i < uspi->s_apb ; i++, offsets = NULL) { tind = ubh_get_data_ptr(uspi, tind_bh, i); ufs_trunc_dindirect(inode, offsets, depth2 - 1, tind); ubh_mark_buffer_dirty(tind_bh); } } if (free_it) { if (free_it) { tmp = ufs_data_ptr_to_cpu(sb, p); tmp = ufs_data_ptr_to_cpu(sb, p); Loading @@ -1216,14 +1134,14 @@ static void ufs_trunc_tindirect(struct inode *inode, unsigned *offsets, int dept ufs_data_ptr_clear(uspi, p); ufs_data_ptr_clear(uspi, p); write_sequnlock(&ufsi->meta_lock); write_sequnlock(&ufsi->meta_lock); ubh_bforget(tind_bh); ubh_bforget(ubh); ufs_free_blocks(inode, tmp, uspi->s_fpb); ufs_free_blocks(inode, tmp, uspi->s_fpb); mark_inode_dirty(inode); mark_inode_dirty(inode); return; return; } } if (IS_SYNC(inode) && ubh_buffer_dirty(tind_bh)) if (IS_SYNC(inode) && ubh_buffer_dirty(ubh)) ubh_sync_block(tind_bh); ubh_sync_block(ubh); ubh_brelse (tind_bh); ubh_brelse(ubh); } } static int ufs_alloc_lastblock(struct inode *inode, loff_t size) static int ufs_alloc_lastblock(struct inode *inode, loff_t size) Loading Loading @@ -1317,26 +1235,30 @@ static void __ufs_truncate_blocks(struct inode *inode) switch (depth) { switch (depth) { case 1: case 1: ufs_trunc_direct(inode); ufs_trunc_direct(inode); ufs_trunc_indirect(inode, NULL, 0, ufs_trunc_branch(inode, NULL, 0, 1, ufs_get_direct_data_ptr(uspi, ufsi, UFS_IND_BLOCK)); ufs_get_direct_data_ptr(uspi, ufsi, UFS_IND_BLOCK)); ufs_trunc_dindirect(inode, NULL, 0, ufs_trunc_branch(inode, NULL, 0, 2, ufs_get_direct_data_ptr(uspi, ufsi, UFS_DIND_BLOCK)); ufs_get_direct_data_ptr(uspi, ufsi, UFS_DIND_BLOCK)); ufs_trunc_tindirect(inode, NULL, 0); ufs_trunc_branch(inode, NULL, 0, 3, ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK)); break; break; case 2: case 2: ufs_trunc_indirect(inode, offsets + 1, depth2, ufs_trunc_branch(inode, offsets + 1, depth2, 1, ufs_get_direct_data_ptr(uspi, ufsi, UFS_IND_BLOCK)); ufs_get_direct_data_ptr(uspi, ufsi, UFS_IND_BLOCK)); ufs_trunc_dindirect(inode, NULL, 0, ufs_trunc_branch(inode, NULL, 0, 2, ufs_get_direct_data_ptr(uspi, ufsi, UFS_DIND_BLOCK)); ufs_get_direct_data_ptr(uspi, ufsi, UFS_DIND_BLOCK)); ufs_trunc_tindirect(inode, NULL, 0); ufs_trunc_branch(inode, NULL, 0, 3, ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK)); break; break; case 3: case 3: ufs_trunc_dindirect(inode, offsets + 1, depth2, ufs_trunc_branch(inode, offsets + 1, depth2, 2, ufs_get_direct_data_ptr(uspi, ufsi, UFS_DIND_BLOCK)); ufs_get_direct_data_ptr(uspi, ufsi, UFS_DIND_BLOCK)); ufs_trunc_tindirect(inode, NULL, 0); ufs_trunc_branch(inode, NULL, 0, 3, ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK)); break; break; case 4: case 4: ufs_trunc_tindirect(inode, offsets + 1, depth2); ufs_trunc_branch(inode, offsets + 1, depth2, 3, ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK)); } } ufsi->i_lastfrag = DIRECT_FRAGMENT; ufsi->i_lastfrag = DIRECT_FRAGMENT; mutex_unlock(&ufsi->truncate_mutex); mutex_unlock(&ufsi->truncate_mutex); Loading Loading
fs/ufs/inode.c +60 −138 Original line number Original line Diff line number Diff line Loading @@ -1068,32 +1068,40 @@ static void ufs_trunc_direct(struct inode *inode) UFSD("EXIT: ino %lu\n", inode->i_ino); UFSD("EXIT: ino %lu\n", inode->i_ino); } } static void ufs_trunc_branch(struct inode *inode, unsigned *offsets, int depth2, int depth, void *p) static void ufs_trunc_indirect(struct inode *inode, unsigned *offsets, int depth2, void *p) { { struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb; struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; struct ufs_buffer_head * ind_ubh; struct ufs_inode_info *ufsi = UFS_I(inode); void *ind; struct ufs_buffer_head *ubh; u64 tmp, frag_to_free = 0; u64 tmp; unsigned free_count = 0; bool free_it = !offsets || !depth2; unsigned from = offsets ? *offsets : 0; unsigned from = offsets ? *offsets++ : 0; bool to_free = !offsets || !depth2; unsigned i; unsigned i; tmp = ufs_data_ptr_to_cpu(sb, p); tmp = ufs_data_ptr_to_cpu(sb, p); if (!tmp) if (!tmp) return; return; ind_ubh = ubh_bread(sb, tmp, uspi->s_bsize); ubh = ubh_bread (sb, tmp, uspi->s_bsize); if (!ind_ubh) { if (!ubh) { write_seqlock(&UFS_I(inode)->meta_lock); write_seqlock(&ufsi->meta_lock); ufs_data_ptr_clear(uspi, p); ufs_data_ptr_clear(uspi, p); write_sequnlock(&UFS_I(inode)->meta_lock); write_sequnlock(&ufsi->meta_lock); return; return; } } if (--depth) { for (i = from ; i < uspi->s_apb ; i++, offsets = NULL) { void *ind = ubh_get_data_ptr(uspi, ubh, i); ufs_trunc_branch(inode, offsets, depth2 - 1, depth, ind); ubh_mark_buffer_dirty(ubh); } } else { u64 frag_to_free = 0; unsigned free_count = 0; for (i = from; i < uspi->s_apb; i++) { for (i = from; i < uspi->s_apb; i++) { ind = ubh_get_data_ptr(uspi, ind_ubh, i); void *ind = ubh_get_data_ptr(uspi, ubh, i); tmp = ufs_data_ptr_to_cpu(sb, ind); tmp = ufs_data_ptr_to_cpu(sb, ind); if (!tmp) if (!tmp) continue; continue; Loading @@ -1101,7 +1109,7 @@ static void ufs_trunc_indirect(struct inode *inode, unsigned *offsets, int depth write_seqlock(&UFS_I(inode)->meta_lock); write_seqlock(&UFS_I(inode)->meta_lock); ufs_data_ptr_clear(uspi, ind); ufs_data_ptr_clear(uspi, ind); write_sequnlock(&UFS_I(inode)->meta_lock); write_sequnlock(&UFS_I(inode)->meta_lock); ubh_mark_buffer_dirty(ind_ubh); ubh_mark_buffer_dirty(ubh); if (free_count == 0) { if (free_count == 0) { frag_to_free = tmp; frag_to_free = tmp; free_count = uspi->s_fpb; free_count = uspi->s_fpb; Loading @@ -1119,96 +1127,6 @@ static void ufs_trunc_indirect(struct inode *inode, unsigned *offsets, int depth if (free_count > 0) { if (free_count > 0) { ufs_free_blocks (inode, frag_to_free, free_count); ufs_free_blocks (inode, frag_to_free, free_count); } } if (to_free) { tmp = ufs_data_ptr_to_cpu(sb, p); write_seqlock(&UFS_I(inode)->meta_lock); ufs_data_ptr_clear(uspi, p); write_sequnlock(&UFS_I(inode)->meta_lock); ubh_bforget(ind_ubh); ufs_free_blocks (inode, tmp, uspi->s_fpb); mark_inode_dirty(inode); return; } if (IS_SYNC(inode) && ubh_buffer_dirty(ind_ubh)) ubh_sync_block(ind_ubh); ubh_brelse (ind_ubh); } static void ufs_trunc_dindirect(struct inode *inode, unsigned *offsets, int depth2, void *p) { struct super_block *sb = inode->i_sb; struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; struct ufs_buffer_head *dind_bh; u64 tmp; void *dind; bool free_it = !offsets || !depth2; unsigned dindirect_block = offsets ? *offsets++ : 0; unsigned i; tmp = ufs_data_ptr_to_cpu(sb, p); if (!tmp) return; dind_bh = ubh_bread(sb, tmp, uspi->s_bsize); if (!dind_bh) { write_seqlock(&UFS_I(inode)->meta_lock); ufs_data_ptr_clear(uspi, p); write_sequnlock(&UFS_I(inode)->meta_lock); return; } for (i = dindirect_block ; i < uspi->s_apb ; i++, offsets = NULL) { dind = ubh_get_data_ptr(uspi, dind_bh, i); tmp = ufs_data_ptr_to_cpu(sb, dind); if (!tmp) continue; ufs_trunc_indirect(inode, offsets, depth2 - 1, dind); ubh_mark_buffer_dirty(dind_bh); } if (free_it) { tmp = ufs_data_ptr_to_cpu(sb, p); write_seqlock(&UFS_I(inode)->meta_lock); ufs_data_ptr_clear(uspi, p); write_sequnlock(&UFS_I(inode)->meta_lock); ubh_bforget(dind_bh); ufs_free_blocks(inode, tmp, uspi->s_fpb); mark_inode_dirty(inode); return; } if (IS_SYNC(inode) && ubh_buffer_dirty(dind_bh)) ubh_sync_block(dind_bh); ubh_brelse (dind_bh); } static void ufs_trunc_tindirect(struct inode *inode, unsigned *offsets, int depth2) { struct super_block *sb = inode->i_sb; struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; struct ufs_inode_info *ufsi = UFS_I(inode); struct ufs_buffer_head * tind_bh; u64 tmp; void *tind, *p; bool free_it = !offsets || !depth2; unsigned tindirect_block = offsets ? *offsets++ : 0; unsigned i; p = ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK); if (!(tmp = ufs_data_ptr_to_cpu(sb, p))) return; tind_bh = ubh_bread (sb, tmp, uspi->s_bsize); if (!tind_bh) { write_seqlock(&ufsi->meta_lock); ufs_data_ptr_clear(uspi, p); write_sequnlock(&ufsi->meta_lock); return; } for (i = tindirect_block ; i < uspi->s_apb ; i++, offsets = NULL) { tind = ubh_get_data_ptr(uspi, tind_bh, i); ufs_trunc_dindirect(inode, offsets, depth2 - 1, tind); ubh_mark_buffer_dirty(tind_bh); } } if (free_it) { if (free_it) { tmp = ufs_data_ptr_to_cpu(sb, p); tmp = ufs_data_ptr_to_cpu(sb, p); Loading @@ -1216,14 +1134,14 @@ static void ufs_trunc_tindirect(struct inode *inode, unsigned *offsets, int dept ufs_data_ptr_clear(uspi, p); ufs_data_ptr_clear(uspi, p); write_sequnlock(&ufsi->meta_lock); write_sequnlock(&ufsi->meta_lock); ubh_bforget(tind_bh); ubh_bforget(ubh); ufs_free_blocks(inode, tmp, uspi->s_fpb); ufs_free_blocks(inode, tmp, uspi->s_fpb); mark_inode_dirty(inode); mark_inode_dirty(inode); return; return; } } if (IS_SYNC(inode) && ubh_buffer_dirty(tind_bh)) if (IS_SYNC(inode) && ubh_buffer_dirty(ubh)) ubh_sync_block(tind_bh); ubh_sync_block(ubh); ubh_brelse (tind_bh); ubh_brelse(ubh); } } static int ufs_alloc_lastblock(struct inode *inode, loff_t size) static int ufs_alloc_lastblock(struct inode *inode, loff_t size) Loading Loading @@ -1317,26 +1235,30 @@ static void __ufs_truncate_blocks(struct inode *inode) switch (depth) { switch (depth) { case 1: case 1: ufs_trunc_direct(inode); ufs_trunc_direct(inode); ufs_trunc_indirect(inode, NULL, 0, ufs_trunc_branch(inode, NULL, 0, 1, ufs_get_direct_data_ptr(uspi, ufsi, UFS_IND_BLOCK)); ufs_get_direct_data_ptr(uspi, ufsi, UFS_IND_BLOCK)); ufs_trunc_dindirect(inode, NULL, 0, ufs_trunc_branch(inode, NULL, 0, 2, ufs_get_direct_data_ptr(uspi, ufsi, UFS_DIND_BLOCK)); ufs_get_direct_data_ptr(uspi, ufsi, UFS_DIND_BLOCK)); ufs_trunc_tindirect(inode, NULL, 0); ufs_trunc_branch(inode, NULL, 0, 3, ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK)); break; break; case 2: case 2: ufs_trunc_indirect(inode, offsets + 1, depth2, ufs_trunc_branch(inode, offsets + 1, depth2, 1, ufs_get_direct_data_ptr(uspi, ufsi, UFS_IND_BLOCK)); ufs_get_direct_data_ptr(uspi, ufsi, UFS_IND_BLOCK)); ufs_trunc_dindirect(inode, NULL, 0, ufs_trunc_branch(inode, NULL, 0, 2, ufs_get_direct_data_ptr(uspi, ufsi, UFS_DIND_BLOCK)); ufs_get_direct_data_ptr(uspi, ufsi, UFS_DIND_BLOCK)); ufs_trunc_tindirect(inode, NULL, 0); ufs_trunc_branch(inode, NULL, 0, 3, ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK)); break; break; case 3: case 3: ufs_trunc_dindirect(inode, offsets + 1, depth2, ufs_trunc_branch(inode, offsets + 1, depth2, 2, ufs_get_direct_data_ptr(uspi, ufsi, UFS_DIND_BLOCK)); ufs_get_direct_data_ptr(uspi, ufsi, UFS_DIND_BLOCK)); ufs_trunc_tindirect(inode, NULL, 0); ufs_trunc_branch(inode, NULL, 0, 3, ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK)); break; break; case 4: case 4: ufs_trunc_tindirect(inode, offsets + 1, depth2); ufs_trunc_branch(inode, offsets + 1, depth2, 3, ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK)); } } ufsi->i_lastfrag = DIRECT_FRAGMENT; ufsi->i_lastfrag = DIRECT_FRAGMENT; mutex_unlock(&ufsi->truncate_mutex); mutex_unlock(&ufsi->truncate_mutex); Loading