truncate.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * truncate.c
  4. *
  5. * PURPOSE
  6. * Truncate handling routines for the OSTA-UDF(tm) filesystem.
  7. *
  8. * COPYRIGHT
  9. * (C) 1999-2004 Ben Fennema
  10. * (C) 1999 Stelias Computing Inc
  11. *
  12. * HISTORY
  13. *
  14. * 02/24/99 blf Created.
  15. *
  16. */
  17. #include "udfdecl.h"
  18. #include <linux/fs.h>
  19. #include <linux/mm.h>
  20. #include "udf_i.h"
  21. #include "udf_sb.h"
  22. static void extent_trunc(struct inode *inode, struct extent_position *epos,
  23. struct kernel_lb_addr *eloc, int8_t etype, uint32_t elen,
  24. uint32_t nelen)
  25. {
  26. struct kernel_lb_addr neloc = {};
  27. int last_block = (elen + inode->i_sb->s_blocksize - 1) >>
  28. inode->i_sb->s_blocksize_bits;
  29. int first_block = (nelen + inode->i_sb->s_blocksize - 1) >>
  30. inode->i_sb->s_blocksize_bits;
  31. if (nelen) {
  32. if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) {
  33. udf_free_blocks(inode->i_sb, inode, eloc, 0,
  34. last_block);
  35. etype = (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30);
  36. } else
  37. neloc = *eloc;
  38. nelen = (etype << 30) | nelen;
  39. }
  40. if (elen != nelen) {
  41. udf_write_aext(inode, epos, &neloc, nelen, 0);
  42. if (last_block > first_block) {
  43. if (etype == (EXT_RECORDED_ALLOCATED >> 30))
  44. mark_inode_dirty(inode);
  45. if (etype != (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
  46. udf_free_blocks(inode->i_sb, inode, eloc,
  47. first_block,
  48. last_block - first_block);
  49. }
  50. }
  51. }
  52. /*
  53. * Truncate the last extent to match i_size. This function assumes
  54. * that preallocation extent is already truncated.
  55. */
  56. void udf_truncate_tail_extent(struct inode *inode)
  57. {
  58. struct extent_position epos = {};
  59. struct kernel_lb_addr eloc;
  60. uint32_t elen, nelen;
  61. uint64_t lbcount = 0;
  62. int8_t etype = -1, netype;
  63. int adsize;
  64. struct udf_inode_info *iinfo = UDF_I(inode);
  65. int ret;
  66. if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB ||
  67. inode->i_size == iinfo->i_lenExtents)
  68. return;
  69. /* Are we going to delete the file anyway? */
  70. if (inode->i_nlink == 0)
  71. return;
  72. if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
  73. adsize = sizeof(struct short_ad);
  74. else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
  75. adsize = sizeof(struct long_ad);
  76. else
  77. BUG();
  78. /* Find the last extent in the file */
  79. while (1) {
  80. ret = udf_next_aext(inode, &epos, &eloc, &elen, &netype, 1);
  81. if (ret <= 0)
  82. break;
  83. etype = netype;
  84. lbcount += elen;
  85. if (lbcount > inode->i_size) {
  86. if (lbcount - inode->i_size >= inode->i_sb->s_blocksize)
  87. udf_warn(inode->i_sb,
  88. "Too long extent after EOF in inode %u: i_size: %lld lbcount: %lld extent %u+%u\n",
  89. (unsigned)inode->i_ino,
  90. (long long)inode->i_size,
  91. (long long)lbcount,
  92. (unsigned)eloc.logicalBlockNum,
  93. (unsigned)elen);
  94. nelen = elen - (lbcount - inode->i_size);
  95. epos.offset -= adsize;
  96. extent_trunc(inode, &epos, &eloc, etype, elen, nelen);
  97. epos.offset += adsize;
  98. if (udf_next_aext(inode, &epos, &eloc, &elen,
  99. &netype, 1) > 0)
  100. udf_err(inode->i_sb,
  101. "Extent after EOF in inode %u\n",
  102. (unsigned)inode->i_ino);
  103. break;
  104. }
  105. }
  106. /* This inode entry is in-memory only and thus we don't have to mark
  107. * the inode dirty */
  108. if (ret >= 0)
  109. iinfo->i_lenExtents = inode->i_size;
  110. brelse(epos.bh);
  111. }
  112. void udf_discard_prealloc(struct inode *inode)
  113. {
  114. struct extent_position epos = {};
  115. struct extent_position prev_epos = {};
  116. struct kernel_lb_addr eloc;
  117. uint32_t elen;
  118. uint64_t lbcount = 0;
  119. int8_t etype = -1;
  120. struct udf_inode_info *iinfo = UDF_I(inode);
  121. int bsize = i_blocksize(inode);
  122. int8_t tmpetype = -1;
  123. int ret;
  124. if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB ||
  125. ALIGN(inode->i_size, bsize) == ALIGN(iinfo->i_lenExtents, bsize))
  126. return;
  127. epos.block = iinfo->i_location;
  128. /* Find the last extent in the file */
  129. while (1) {
  130. ret = udf_next_aext(inode, &epos, &eloc, &elen, &tmpetype, 0);
  131. if (ret < 0)
  132. goto out;
  133. if (ret == 0)
  134. break;
  135. brelse(prev_epos.bh);
  136. prev_epos = epos;
  137. if (prev_epos.bh)
  138. get_bh(prev_epos.bh);
  139. ret = udf_next_aext(inode, &epos, &eloc, &elen, &etype, 1);
  140. if (ret < 0)
  141. goto out;
  142. lbcount += elen;
  143. }
  144. if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) {
  145. lbcount -= elen;
  146. udf_delete_aext(inode, prev_epos);
  147. udf_free_blocks(inode->i_sb, inode, &eloc, 0,
  148. DIV_ROUND_UP(elen, bsize));
  149. }
  150. /* This inode entry is in-memory only and thus we don't have to mark
  151. * the inode dirty */
  152. iinfo->i_lenExtents = lbcount;
  153. out:
  154. brelse(epos.bh);
  155. brelse(prev_epos.bh);
  156. }
  157. static void udf_update_alloc_ext_desc(struct inode *inode,
  158. struct extent_position *epos,
  159. u32 lenalloc)
  160. {
  161. struct super_block *sb = inode->i_sb;
  162. struct udf_sb_info *sbi = UDF_SB(sb);
  163. struct allocExtDesc *aed = (struct allocExtDesc *) (epos->bh->b_data);
  164. int len = sizeof(struct allocExtDesc);
  165. aed->lengthAllocDescs = cpu_to_le32(lenalloc);
  166. if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT) || sbi->s_udfrev >= 0x0201)
  167. len += lenalloc;
  168. udf_update_tag(epos->bh->b_data, len);
  169. mark_buffer_dirty_inode(epos->bh, inode);
  170. }
  171. /*
  172. * Truncate extents of inode to inode->i_size. This function can be used only
  173. * for making file shorter. For making file longer, udf_extend_file() has to
  174. * be used.
  175. */
  176. int udf_truncate_extents(struct inode *inode)
  177. {
  178. struct extent_position epos;
  179. struct kernel_lb_addr eloc, neloc = {};
  180. uint32_t elen, nelen = 0, indirect_ext_len = 0, lenalloc;
  181. int8_t etype;
  182. struct super_block *sb = inode->i_sb;
  183. sector_t first_block = inode->i_size >> sb->s_blocksize_bits, offset;
  184. loff_t byte_offset;
  185. int adsize;
  186. struct udf_inode_info *iinfo = UDF_I(inode);
  187. int ret = 0;
  188. if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
  189. adsize = sizeof(struct short_ad);
  190. else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
  191. adsize = sizeof(struct long_ad);
  192. else
  193. BUG();
  194. ret = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset, &etype);
  195. if (ret < 0)
  196. return ret;
  197. byte_offset = (offset << sb->s_blocksize_bits) +
  198. (inode->i_size & (sb->s_blocksize - 1));
  199. if (ret == 0) {
  200. /* We should extend the file? */
  201. WARN_ON(byte_offset);
  202. return 0;
  203. }
  204. epos.offset -= adsize;
  205. extent_trunc(inode, &epos, &eloc, etype, elen, byte_offset);
  206. epos.offset += adsize;
  207. if (byte_offset)
  208. lenalloc = epos.offset;
  209. else
  210. lenalloc = epos.offset - adsize;
  211. if (!epos.bh)
  212. lenalloc -= udf_file_entry_alloc_offset(inode);
  213. else
  214. lenalloc -= sizeof(struct allocExtDesc);
  215. while ((ret = udf_current_aext(inode, &epos, &eloc,
  216. &elen, &etype, 0)) > 0) {
  217. if (etype == (EXT_NEXT_EXTENT_ALLOCDESCS >> 30)) {
  218. udf_write_aext(inode, &epos, &neloc, nelen, 0);
  219. if (indirect_ext_len) {
  220. /* We managed to free all extents in the
  221. * indirect extent - free it too */
  222. BUG_ON(!epos.bh);
  223. udf_free_blocks(sb, NULL, &epos.block,
  224. 0, indirect_ext_len);
  225. } else if (!epos.bh) {
  226. iinfo->i_lenAlloc = lenalloc;
  227. mark_inode_dirty(inode);
  228. } else
  229. udf_update_alloc_ext_desc(inode,
  230. &epos, lenalloc);
  231. brelse(epos.bh);
  232. epos.offset = sizeof(struct allocExtDesc);
  233. epos.block = eloc;
  234. epos.bh = sb_bread(sb,
  235. udf_get_lb_pblock(sb, &eloc, 0));
  236. /* Error reading indirect block? */
  237. if (!epos.bh)
  238. return -EIO;
  239. if (elen)
  240. indirect_ext_len =
  241. (elen + sb->s_blocksize - 1) >>
  242. sb->s_blocksize_bits;
  243. else
  244. indirect_ext_len = 1;
  245. } else {
  246. extent_trunc(inode, &epos, &eloc, etype, elen, 0);
  247. epos.offset += adsize;
  248. }
  249. }
  250. if (ret < 0) {
  251. brelse(epos.bh);
  252. return ret;
  253. }
  254. if (indirect_ext_len) {
  255. BUG_ON(!epos.bh);
  256. udf_free_blocks(sb, NULL, &epos.block, 0, indirect_ext_len);
  257. } else if (!epos.bh) {
  258. iinfo->i_lenAlloc = lenalloc;
  259. mark_inode_dirty(inode);
  260. } else
  261. udf_update_alloc_ext_desc(inode, &epos, lenalloc);
  262. iinfo->i_lenExtents = inode->i_size;
  263. brelse(epos.bh);
  264. return 0;
  265. }