5 * Truncate handling routines for the OSTA-UDF(tm) filesystem.
8 * This file is distributed under the terms of the GNU General Public
9 * License (GPL). Copies of the GPL can be obtained from:
10 * ftp://prep.ai.mit.edu/pub/gnu/GPL
11 * Each contributing author retains all rights to their own work.
13 * (C) 1999-2004 Ben Fennema
14 * (C) 1999 Stelias Computing Inc
18 * 02/24/99 blf Created.
25 #include <linux/udf_fs.h>
26 #include <linux/buffer_head.h>
31 static void extent_trunc(struct inode
* inode
, kernel_lb_addr bloc
, int extoffset
,
32 kernel_lb_addr eloc
, int8_t etype
, uint32_t elen
, struct buffer_head
*bh
, uint32_t nelen
)
34 kernel_lb_addr neloc
= { 0, 0 };
35 int last_block
= (elen
+ inode
->i_sb
->s_blocksize
- 1) >> inode
->i_sb
->s_blocksize_bits
;
36 int first_block
= (nelen
+ inode
->i_sb
->s_blocksize
- 1) >> inode
->i_sb
->s_blocksize_bits
;
40 if (etype
== (EXT_NOT_RECORDED_ALLOCATED
>> 30))
42 udf_free_blocks(inode
->i_sb
, inode
, eloc
, 0, last_block
);
43 etype
= (EXT_NOT_RECORDED_NOT_ALLOCATED
>> 30);
47 nelen
= (etype
<< 30) | nelen
;
52 udf_write_aext(inode
, bloc
, &extoffset
, neloc
, nelen
, bh
, 0);
53 if (last_block
- first_block
> 0)
55 if (etype
== (EXT_RECORDED_ALLOCATED
>> 30))
56 mark_inode_dirty(inode
);
58 if (etype
!= (EXT_NOT_RECORDED_NOT_ALLOCATED
>> 30))
59 udf_free_blocks(inode
->i_sb
, inode
, eloc
, first_block
, last_block
- first_block
);
64 void udf_discard_prealloc(struct inode
* inode
)
66 kernel_lb_addr bloc
, eloc
;
67 uint32_t extoffset
= 0, elen
, nelen
;
69 int8_t etype
= -1, netype
;
70 struct buffer_head
*bh
= NULL
;
73 if (UDF_I_ALLOCTYPE(inode
) == ICBTAG_FLAG_AD_IN_ICB
||
74 inode
->i_size
== UDF_I_LENEXTENTS(inode
))
79 if (UDF_I_ALLOCTYPE(inode
) == ICBTAG_FLAG_AD_SHORT
)
80 adsize
= sizeof(short_ad
);
81 else if (UDF_I_ALLOCTYPE(inode
) == ICBTAG_FLAG_AD_LONG
)
82 adsize
= sizeof(long_ad
);
86 bloc
= UDF_I_LOCATION(inode
);
88 while ((netype
= udf_next_aext(inode
, &bloc
, &extoffset
, &eloc
, &elen
, &bh
, 1)) != -1)
92 if (lbcount
> inode
->i_size
&& lbcount
- inode
->i_size
< inode
->i_sb
->s_blocksize
)
94 nelen
= elen
- (lbcount
- inode
->i_size
);
95 extent_trunc(inode
, bloc
, extoffset
-adsize
, eloc
, etype
, elen
, bh
, nelen
);
96 lbcount
= inode
->i_size
;
99 if (etype
== (EXT_NOT_RECORDED_ALLOCATED
>> 30))
103 extent_trunc(inode
, bloc
, extoffset
, eloc
, etype
, elen
, bh
, 0);
106 UDF_I_LENALLOC(inode
) = extoffset
- udf_file_entry_alloc_offset(inode
);
107 mark_inode_dirty(inode
);
111 struct allocExtDesc
*aed
= (struct allocExtDesc
*)(bh
->b_data
);
112 aed
->lengthAllocDescs
= cpu_to_le32(extoffset
- sizeof(struct allocExtDesc
));
113 if (!UDF_QUERY_FLAG(inode
->i_sb
, UDF_FLAG_STRICT
) || UDF_SB_UDFREV(inode
->i_sb
) >= 0x0201)
114 udf_update_tag(bh
->b_data
, extoffset
);
116 udf_update_tag(bh
->b_data
, sizeof(struct allocExtDesc
));
117 mark_buffer_dirty_inode(bh
, inode
);
120 UDF_I_LENEXTENTS(inode
) = lbcount
;
122 udf_release_data(bh
);
125 void udf_truncate_extents(struct inode
* inode
)
127 kernel_lb_addr bloc
, eloc
, neloc
= { 0, 0 };
128 uint32_t extoffset
, elen
, offset
, nelen
= 0, lelen
= 0, lenalloc
;
130 int first_block
= inode
->i_size
>> inode
->i_sb
->s_blocksize_bits
;
131 struct buffer_head
*bh
= NULL
;
134 if (UDF_I_ALLOCTYPE(inode
) == ICBTAG_FLAG_AD_SHORT
)
135 adsize
= sizeof(short_ad
);
136 else if (UDF_I_ALLOCTYPE(inode
) == ICBTAG_FLAG_AD_LONG
)
137 adsize
= sizeof(long_ad
);
141 etype
= inode_bmap(inode
, first_block
, &bloc
, &extoffset
, &eloc
, &elen
, &offset
, &bh
);
142 offset
+= (inode
->i_size
& (inode
->i_sb
->s_blocksize
- 1));
146 extent_trunc(inode
, bloc
, extoffset
, eloc
, etype
, elen
, bh
, offset
);
150 lenalloc
= extoffset
;
152 lenalloc
= extoffset
- adsize
;
155 lenalloc
-= udf_file_entry_alloc_offset(inode
);
157 lenalloc
-= sizeof(struct allocExtDesc
);
159 while ((etype
= udf_current_aext(inode
, &bloc
, &extoffset
, &eloc
, &elen
, &bh
, 0)) != -1)
161 if (etype
== (EXT_NEXT_EXTENT_ALLOCDECS
>> 30))
163 udf_write_aext(inode
, bloc
, &extoffset
, neloc
, nelen
, bh
, 0);
170 memset(bh
->b_data
, 0x00, sizeof(struct allocExtDesc
));
171 udf_free_blocks(inode
->i_sb
, inode
, bloc
, 0, lelen
);
177 UDF_I_LENALLOC(inode
) = lenalloc
;
178 mark_inode_dirty(inode
);
182 struct allocExtDesc
*aed
= (struct allocExtDesc
*)(bh
->b_data
);
183 aed
->lengthAllocDescs
= cpu_to_le32(lenalloc
);
184 if (!UDF_QUERY_FLAG(inode
->i_sb
, UDF_FLAG_STRICT
) || UDF_SB_UDFREV(inode
->i_sb
) >= 0x0201)
185 udf_update_tag(bh
->b_data
, lenalloc
+
186 sizeof(struct allocExtDesc
));
188 udf_update_tag(bh
->b_data
, sizeof(struct allocExtDesc
));
189 mark_buffer_dirty_inode(bh
, inode
);
193 udf_release_data(bh
);
194 extoffset
= sizeof(struct allocExtDesc
);
196 bh
= udf_tread(inode
->i_sb
, udf_get_lb_pblock(inode
->i_sb
, bloc
, 0));
198 lelen
= (elen
+ inode
->i_sb
->s_blocksize
- 1) >>
199 inode
->i_sb
->s_blocksize_bits
;
205 extent_trunc(inode
, bloc
, extoffset
, eloc
, etype
, elen
, bh
, 0);
215 memset(bh
->b_data
, 0x00, sizeof(struct allocExtDesc
));
216 udf_free_blocks(inode
->i_sb
, inode
, bloc
, 0, lelen
);
222 UDF_I_LENALLOC(inode
) = lenalloc
;
223 mark_inode_dirty(inode
);
227 struct allocExtDesc
*aed
= (struct allocExtDesc
*)(bh
->b_data
);
228 aed
->lengthAllocDescs
= cpu_to_le32(lenalloc
);
229 if (!UDF_QUERY_FLAG(inode
->i_sb
, UDF_FLAG_STRICT
) || UDF_SB_UDFREV(inode
->i_sb
) >= 0x0201)
230 udf_update_tag(bh
->b_data
, lenalloc
+
231 sizeof(struct allocExtDesc
));
233 udf_update_tag(bh
->b_data
, sizeof(struct allocExtDesc
));
234 mark_buffer_dirty_inode(bh
, inode
);
238 else if (inode
->i_size
)
243 etype
= udf_next_aext(inode
, &bloc
, &extoffset
, &eloc
, &elen
, &bh
, 1);
244 if (etype
== (EXT_NOT_RECORDED_NOT_ALLOCATED
>> 30))
247 elen
= EXT_NOT_RECORDED_NOT_ALLOCATED
| (elen
+ offset
);
248 udf_write_aext(inode
, bloc
, &extoffset
, eloc
, elen
, bh
, 0);
250 else if (etype
== (EXT_NOT_RECORDED_ALLOCATED
>> 30))
252 kernel_lb_addr neloc
= { 0, 0 };
254 nelen
= EXT_NOT_RECORDED_NOT_ALLOCATED
|
255 ((elen
+ offset
+ inode
->i_sb
->s_blocksize
- 1) &
256 ~(inode
->i_sb
->s_blocksize
- 1));
257 udf_write_aext(inode
, bloc
, &extoffset
, neloc
, nelen
, bh
, 1);
258 udf_add_aext(inode
, &bloc
, &extoffset
, eloc
, (etype
<< 30) | elen
, &bh
, 1);
262 if (elen
& (inode
->i_sb
->s_blocksize
- 1))
265 elen
= EXT_RECORDED_ALLOCATED
|
266 ((elen
+ inode
->i_sb
->s_blocksize
- 1) &
267 ~(inode
->i_sb
->s_blocksize
- 1));
268 udf_write_aext(inode
, bloc
, &extoffset
, eloc
, elen
, bh
, 1);
270 memset(&eloc
, 0x00, sizeof(kernel_lb_addr
));
271 elen
= EXT_NOT_RECORDED_NOT_ALLOCATED
| offset
;
272 udf_add_aext(inode
, &bloc
, &extoffset
, eloc
, elen
, &bh
, 1);
276 UDF_I_LENEXTENTS(inode
) = inode
->i_size
;
278 udf_release_data(bh
);