aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ufs/inode.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index 1dda6c4875f9..9f4590261134 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -886,7 +886,6 @@ static inline void free_data(struct to_free *ctx, u64 from, unsigned count)
886 ctx->to = from + count; 886 ctx->to = from + count;
887} 887}
888 888
889#define DIRECT_BLOCK ((inode->i_size + uspi->s_bsize - 1) >> uspi->s_bshift)
890#define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift) 889#define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift)
891 890
892static void ufs_trunc_direct(struct inode *inode) 891static void ufs_trunc_direct(struct inode *inode)
@@ -1124,19 +1123,24 @@ static void ufs_truncate_blocks(struct inode *inode)
1124 struct super_block *sb = inode->i_sb; 1123 struct super_block *sb = inode->i_sb;
1125 struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; 1124 struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
1126 unsigned offsets[4]; 1125 unsigned offsets[4];
1127 int depth = ufs_block_to_path(inode, DIRECT_BLOCK, offsets); 1126 int depth;
1128 int depth2; 1127 int depth2;
1129 unsigned i; 1128 unsigned i;
1130 struct ufs_buffer_head *ubh[3]; 1129 struct ufs_buffer_head *ubh[3];
1131 void *p; 1130 void *p;
1132 u64 block; 1131 u64 block;
1133 1132
1134 if (!depth) 1133 if (inode->i_size) {
1135 return; 1134 sector_t last = (inode->i_size - 1) >> uspi->s_bshift;
1135 depth = ufs_block_to_path(inode, last, offsets);
1136 if (!depth)
1137 return;
1138 } else {
1139 depth = 1;
1140 }
1136 1141
1137 /* find the last non-zero in offsets[] */
1138 for (depth2 = depth - 1; depth2; depth2--) 1142 for (depth2 = depth - 1; depth2; depth2--)
1139 if (offsets[depth2]) 1143 if (offsets[depth2] != uspi->s_apb - 1)
1140 break; 1144 break;
1141 1145
1142 mutex_lock(&ufsi->truncate_mutex); 1146 mutex_lock(&ufsi->truncate_mutex);
@@ -1145,9 +1149,8 @@ static void ufs_truncate_blocks(struct inode *inode)
1145 offsets[0] = UFS_IND_BLOCK; 1149 offsets[0] = UFS_IND_BLOCK;
1146 } else { 1150 } else {
1147 /* get the blocks that should be partially emptied */ 1151 /* get the blocks that should be partially emptied */
1148 p = ufs_get_direct_data_ptr(uspi, ufsi, offsets[0]); 1152 p = ufs_get_direct_data_ptr(uspi, ufsi, offsets[0]++);
1149 for (i = 0; i < depth2; i++) { 1153 for (i = 0; i < depth2; i++) {
1150 offsets[i]++; /* next branch is fully freed */
1151 block = ufs_data_ptr_to_cpu(sb, p); 1154 block = ufs_data_ptr_to_cpu(sb, p);
1152 if (!block) 1155 if (!block)
1153 break; 1156 break;
@@ -1158,7 +1161,7 @@ static void ufs_truncate_blocks(struct inode *inode)
1158 write_sequnlock(&ufsi->meta_lock); 1161 write_sequnlock(&ufsi->meta_lock);
1159 break; 1162 break;
1160 } 1163 }
1161 p = ubh_get_data_ptr(uspi, ubh[i], offsets[i + 1]); 1164 p = ubh_get_data_ptr(uspi, ubh[i], offsets[i + 1]++);
1162 } 1165 }
1163 while (i--) 1166 while (i--)
1164 free_branch_tail(inode, offsets[i + 1], ubh[i], depth - i - 1); 1167 free_branch_tail(inode, offsets[i + 1], ubh[i], depth - i - 1);