5 * Truncate handling routines for the OSTA-UDF(tm) filesystem.
8 * E-mail regarding any portion of the Linux UDF file system should be
9 * directed to the development team mailing list (run by majordomo):
10 * linux_udf@hpesjro.fc.hp.com
13 * This file is distributed under the terms of the GNU General Public
14 * License (GPL). Copies of the GPL can be obtained from:
15 * ftp://prep.ai.mit.edu/pub/gnu/GPL
16 * Each contributing author retains all rights to their own work.
18 * (C) 1999-2004 Ben Fennema
19 * (C) 1999 Stelias Computing Inc
23 * 02/24/99 blf Created.
30 #include <linux/udf_fs.h>
31 #include <linux/buffer_head.h>
36 static void extent_trunc(struct inode
* inode
, kernel_lb_addr bloc
, int extoffset
,
37 kernel_lb_addr eloc
, int8_t etype
, uint32_t elen
, struct buffer_head
*bh
, uint32_t nelen
)
39 kernel_lb_addr neloc
= { 0, 0 };
40 int last_block
= (elen
+ inode
->i_sb
->s_blocksize
- 1) >> inode
->i_sb
->s_blocksize_bits
;
41 int first_block
= (nelen
+ inode
->i_sb
->s_blocksize
- 1) >> inode
->i_sb
->s_blocksize_bits
;
45 if (etype
== (EXT_NOT_RECORDED_ALLOCATED
>> 30))
47 udf_free_blocks(inode
->i_sb
, inode
, eloc
, 0, last_block
);
48 etype
= (EXT_NOT_RECORDED_NOT_ALLOCATED
>> 30);
52 nelen
= (etype
<< 30) | nelen
;
57 udf_write_aext(inode
, bloc
, &extoffset
, neloc
, nelen
, bh
, 0);
58 if (last_block
- first_block
> 0)
60 if (etype
== (EXT_RECORDED_ALLOCATED
>> 30))
61 mark_inode_dirty(inode
);
63 if (etype
!= (EXT_NOT_RECORDED_NOT_ALLOCATED
>> 30))
64 udf_free_blocks(inode
->i_sb
, inode
, eloc
, first_block
, last_block
- first_block
);
69 void udf_discard_prealloc(struct inode
* inode
)
71 kernel_lb_addr bloc
, eloc
;
72 uint32_t extoffset
= 0, elen
, nelen
;
74 int8_t etype
= -1, netype
;
75 struct buffer_head
*bh
= NULL
;
78 if (UDF_I_ALLOCTYPE(inode
) == ICBTAG_FLAG_AD_IN_ICB
||
79 inode
->i_size
== UDF_I_LENEXTENTS(inode
))
84 if (UDF_I_ALLOCTYPE(inode
) == ICBTAG_FLAG_AD_SHORT
)
85 adsize
= sizeof(short_ad
);
86 else if (UDF_I_ALLOCTYPE(inode
) == ICBTAG_FLAG_AD_LONG
)
87 adsize
= sizeof(long_ad
);
91 bloc
= UDF_I_LOCATION(inode
);
93 while ((netype
= udf_next_aext(inode
, &bloc
, &extoffset
, &eloc
, &elen
, &bh
, 1)) != -1)
97 if (lbcount
> inode
->i_size
&& lbcount
- inode
->i_size
< inode
->i_sb
->s_blocksize
)
99 nelen
= elen
- (lbcount
- inode
->i_size
);
100 extent_trunc(inode
, bloc
, extoffset
-adsize
, eloc
, etype
, elen
, bh
, nelen
);
101 lbcount
= inode
->i_size
;
104 if (etype
== (EXT_NOT_RECORDED_ALLOCATED
>> 30))
108 extent_trunc(inode
, bloc
, extoffset
, eloc
, etype
, elen
, bh
, 0);
111 UDF_I_LENALLOC(inode
) = extoffset
- udf_file_entry_alloc_offset(inode
);
112 mark_inode_dirty(inode
);
116 struct allocExtDesc
*aed
= (struct allocExtDesc
*)(bh
->b_data
);
117 aed
->lengthAllocDescs
= cpu_to_le32(extoffset
- sizeof(struct allocExtDesc
));
118 if (!UDF_QUERY_FLAG(inode
->i_sb
, UDF_FLAG_STRICT
) || UDF_SB_UDFREV(inode
->i_sb
) >= 0x0201)
119 udf_update_tag(bh
->b_data
, extoffset
);
121 udf_update_tag(bh
->b_data
, sizeof(struct allocExtDesc
));
122 mark_buffer_dirty_inode(bh
, inode
);
125 UDF_I_LENEXTENTS(inode
) = lbcount
;
127 udf_release_data(bh
);
130 void udf_truncate_extents(struct inode
* inode
)
132 kernel_lb_addr bloc
, eloc
, neloc
= { 0, 0 };
133 uint32_t extoffset
, elen
, offset
, nelen
= 0, lelen
= 0, lenalloc
;
135 int first_block
= inode
->i_size
>> inode
->i_sb
->s_blocksize_bits
;
136 struct buffer_head
*bh
= NULL
;
139 if (UDF_I_ALLOCTYPE(inode
) == ICBTAG_FLAG_AD_SHORT
)
140 adsize
= sizeof(short_ad
);
141 else if (UDF_I_ALLOCTYPE(inode
) == ICBTAG_FLAG_AD_LONG
)
142 adsize
= sizeof(long_ad
);
146 etype
= inode_bmap(inode
, first_block
, &bloc
, &extoffset
, &eloc
, &elen
, &offset
, &bh
);
147 offset
+= (inode
->i_size
& (inode
->i_sb
->s_blocksize
- 1));
151 extent_trunc(inode
, bloc
, extoffset
, eloc
, etype
, elen
, bh
, offset
);
155 lenalloc
= extoffset
;
157 lenalloc
= extoffset
- adsize
;
160 lenalloc
-= udf_file_entry_alloc_offset(inode
);
162 lenalloc
-= sizeof(struct allocExtDesc
);
164 while ((etype
= udf_current_aext(inode
, &bloc
, &extoffset
, &eloc
, &elen
, &bh
, 0)) != -1)
166 if (etype
== (EXT_NEXT_EXTENT_ALLOCDECS
>> 30))
168 udf_write_aext(inode
, bloc
, &extoffset
, neloc
, nelen
, bh
, 0);
175 memset(bh
->b_data
, 0x00, sizeof(struct allocExtDesc
));
176 udf_free_blocks(inode
->i_sb
, inode
, bloc
, 0, lelen
);
182 UDF_I_LENALLOC(inode
) = lenalloc
;
183 mark_inode_dirty(inode
);
187 struct allocExtDesc
*aed
= (struct allocExtDesc
*)(bh
->b_data
);
188 aed
->lengthAllocDescs
= cpu_to_le32(lenalloc
);
189 if (!UDF_QUERY_FLAG(inode
->i_sb
, UDF_FLAG_STRICT
) || UDF_SB_UDFREV(inode
->i_sb
) >= 0x0201)
190 udf_update_tag(bh
->b_data
, lenalloc
+
191 sizeof(struct allocExtDesc
));
193 udf_update_tag(bh
->b_data
, sizeof(struct allocExtDesc
));
194 mark_buffer_dirty_inode(bh
, inode
);
198 udf_release_data(bh
);
199 extoffset
= sizeof(struct allocExtDesc
);
201 bh
= udf_tread(inode
->i_sb
, udf_get_lb_pblock(inode
->i_sb
, bloc
, 0));
203 lelen
= (elen
+ inode
->i_sb
->s_blocksize
- 1) >>
204 inode
->i_sb
->s_blocksize_bits
;
210 extent_trunc(inode
, bloc
, extoffset
, eloc
, etype
, elen
, bh
, 0);
220 memset(bh
->b_data
, 0x00, sizeof(struct allocExtDesc
));
221 udf_free_blocks(inode
->i_sb
, inode
, bloc
, 0, lelen
);
227 UDF_I_LENALLOC(inode
) = lenalloc
;
228 mark_inode_dirty(inode
);
232 struct allocExtDesc
*aed
= (struct allocExtDesc
*)(bh
->b_data
);
233 aed
->lengthAllocDescs
= cpu_to_le32(lenalloc
);
234 if (!UDF_QUERY_FLAG(inode
->i_sb
, UDF_FLAG_STRICT
) || UDF_SB_UDFREV(inode
->i_sb
) >= 0x0201)
235 udf_update_tag(bh
->b_data
, lenalloc
+
236 sizeof(struct allocExtDesc
));
238 udf_update_tag(bh
->b_data
, sizeof(struct allocExtDesc
));
239 mark_buffer_dirty_inode(bh
, inode
);
243 else if (inode
->i_size
)
248 etype
= udf_next_aext(inode
, &bloc
, &extoffset
, &eloc
, &elen
, &bh
, 1);
249 if (etype
== (EXT_NOT_RECORDED_NOT_ALLOCATED
>> 30))
252 elen
= EXT_NOT_RECORDED_NOT_ALLOCATED
| (elen
+ offset
);
253 udf_write_aext(inode
, bloc
, &extoffset
, eloc
, elen
, bh
, 0);
255 else if (etype
== (EXT_NOT_RECORDED_ALLOCATED
>> 30))
257 kernel_lb_addr neloc
= { 0, 0 };
259 nelen
= EXT_NOT_RECORDED_NOT_ALLOCATED
|
260 ((elen
+ offset
+ inode
->i_sb
->s_blocksize
- 1) &
261 ~(inode
->i_sb
->s_blocksize
- 1));
262 udf_write_aext(inode
, bloc
, &extoffset
, neloc
, nelen
, bh
, 1);
263 udf_add_aext(inode
, &bloc
, &extoffset
, eloc
, (etype
<< 30) | elen
, &bh
, 1);
267 if (elen
& (inode
->i_sb
->s_blocksize
- 1))
270 elen
= EXT_RECORDED_ALLOCATED
|
271 ((elen
+ inode
->i_sb
->s_blocksize
- 1) &
272 ~(inode
->i_sb
->s_blocksize
- 1));
273 udf_write_aext(inode
, bloc
, &extoffset
, eloc
, elen
, bh
, 1);
275 memset(&eloc
, 0x00, sizeof(kernel_lb_addr
));
276 elen
= EXT_NOT_RECORDED_NOT_ALLOCATED
| offset
;
277 udf_add_aext(inode
, &bloc
, &extoffset
, eloc
, elen
, &bh
, 1);
281 UDF_I_LENEXTENTS(inode
) = inode
->i_size
;
283 udf_release_data(bh
);