diff options
-rw-r--r-- | fs/ufs/inode.c | 21 |
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 | ||
892 | static void ufs_trunc_direct(struct inode *inode) | 891 | static 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); |