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@hootie.lvld.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 Ben Fennema
19 * (C) 1999 Stelias Computing Inc
23 * 02/24/99 blf Created.
30 #include <linux/udf_fs.h>
35 static void extent_trunc(struct inode
* inode
, lb_addr bloc
, int *extoffset
,
36 lb_addr eloc
, Uint32 elen
, struct buffer_head
**bh
, Uint32 offset
)
38 lb_addr neloc
= { 0, 0 };
40 int blocks
= inode
->i_sb
->s_blocksize
/ 512;
41 int last_block
= (elen
+ inode
->i_sb
->s_blocksize
- 1) / inode
->i_sb
->s_blocksize
;
46 nelen
= ((offset
- 1) << inode
->i_sb
->s_blocksize_bits
) +
47 (inode
->i_size
& (inode
->i_sb
->s_blocksize
- 1));
51 inode
->i_blocks
-= (blocks
* (last_block
- offset
));
52 udf_write_aext(inode
, bloc
, extoffset
, neloc
, nelen
, bh
, 1);
53 if (!memcmp(&UDF_I_EXT0LOC(inode
), &eloc
, sizeof(lb_addr
)))
55 UDF_I_EXT0LOC(inode
) = neloc
;
56 UDF_I_EXT0LEN(inode
) = nelen
;
58 mark_inode_dirty(inode
);
59 udf_free_blocks(inode
, eloc
, offset
, last_block
- offset
);
62 static void trunc(struct inode
* inode
)
64 lb_addr bloc
, eloc
, neloc
= { 0, 0 };
65 Uint32 extoffset
, elen
, offset
, nelen
= 0, lelen
= 0, lenalloc
;
67 int first_block
= (inode
->i_size
+ inode
->i_sb
->s_blocksize
- 1) / inode
->i_sb
->s_blocksize
;
68 struct buffer_head
*bh
= NULL
;
71 if (UDF_I_ALLOCTYPE(inode
) == ICB_FLAG_AD_SHORT
)
72 adsize
= sizeof(short_ad
);
73 else if (UDF_I_ALLOCTYPE(inode
) == ICB_FLAG_AD_LONG
)
74 adsize
= sizeof(long_ad
);
78 if ((etype
= inode_bmap(inode
, first_block
, &bloc
, &extoffset
, &eloc
, &elen
, &offset
, &bh
)) != -1)
81 extent_trunc(inode
, bloc
, &extoffset
, eloc
, elen
, &bh
, offset
);
86 lenalloc
= extoffset
- adsize
;
88 if (!memcmp(&UDF_I_LOCATION(inode
), &bloc
, sizeof(lb_addr
)))
89 lenalloc
-= udf_file_entry_alloc_offset(inode
);
91 lenalloc
-= sizeof(struct AllocExtDesc
);
93 while ((etype
= udf_current_aext(inode
, &bloc
, &extoffset
, &eloc
, &elen
, &bh
, 0)) != -1)
95 if (etype
== EXTENT_NEXT_EXTENT_ALLOCDECS
)
97 udf_write_aext(inode
, bloc
, &extoffset
, neloc
, nelen
, &bh
, 0);
101 if (!memcmp(&UDF_I_LOCATION(inode
), &bloc
, sizeof(lb_addr
)))
102 memset(bh
->b_data
, 0x00, udf_file_entry_alloc_offset(inode
));
104 memset(bh
->b_data
, 0x00, sizeof(struct AllocExtDesc
));
105 udf_free_blocks(inode
, bloc
, 0, lelen
);
109 if (!memcmp(&UDF_I_LOCATION(inode
), &bloc
, sizeof(lb_addr
)))
110 UDF_I_LENALLOC(inode
) = lenalloc
;
113 struct AllocExtDesc
*aed
= (struct AllocExtDesc
*)(bh
->b_data
);
114 aed
->lengthAllocDescs
= cpu_to_le32(lenalloc
);
118 udf_release_data(bh
);
123 lelen
= (elen
+ inode
->i_sb
->s_blocksize
- 1) >>
124 inode
->i_sb
->s_blocksize_bits
;
128 else if (etype
!= EXTENT_NOT_RECORDED_NOT_ALLOCATED
)
129 extent_trunc(inode
, bloc
, &extoffset
, eloc
, elen
, &bh
, 0);
131 udf_write_aext(inode
, bloc
, &extoffset
, neloc
, nelen
, &bh
, 1);
136 if (!memcmp(&UDF_I_LOCATION(inode
), &bloc
, sizeof(lb_addr
)))
137 memset(bh
->b_data
, 0x00, udf_file_entry_alloc_offset(inode
));
139 memset(bh
->b_data
, 0x00, sizeof(struct AllocExtDesc
));
140 udf_free_blocks(inode
, bloc
, 0, lelen
);
144 if (!memcmp(&UDF_I_LOCATION(inode
), &bloc
, sizeof(lb_addr
)))
145 UDF_I_LENALLOC(inode
) = lenalloc
;
148 struct AllocExtDesc
*aed
= (struct AllocExtDesc
*)(bh
->b_data
);
149 aed
->lengthAllocDescs
= cpu_to_le32(lenalloc
);
153 else if (inode
->i_size
)
155 lb_addr e0loc
= UDF_I_LOCATION(inode
);
156 Uint32 ext0offset
= udf_file_entry_alloc_offset(inode
);
162 tetype
= udf_next_aext(inode
, &bloc
, &extoffset
, &eloc
, &elen
, &bh
, 1);
163 if (tetype
== EXTENT_NOT_RECORDED_NOT_ALLOCATED
)
166 elen
= (EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30) |
167 (elen
+ (offset
<< inode
->i_sb
->s_blocksize_bits
));
168 if (ext0offset
== extoffset
&& !memcmp(&e0loc
, &bloc
, sizeof(lb_addr
)))
169 UDF_I_EXT0LEN(inode
) = elen
;
170 udf_write_aext(inode
, bloc
, &extoffset
, eloc
, elen
, &bh
, 0);
174 if (elen
& (inode
->i_sb
->s_blocksize
- 1))
177 elen
= (EXTENT_RECORDED_ALLOCATED
<< 30) |
178 ((elen
+ inode
->i_sb
->s_blocksize
- 1) &
179 ~(inode
->i_sb
->s_blocksize
- 1));
180 if (ext0offset
== extoffset
&& !memcmp(&e0loc
, &bloc
, sizeof(lb_addr
)))
181 UDF_I_EXT0LEN(inode
) = elen
;
182 udf_write_aext(inode
, bloc
, &extoffset
, eloc
, elen
, &bh
, 1);
184 memset(&eloc
, 0x00, sizeof(lb_addr
));
185 elen
= (EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30) |
186 (offset
<< inode
->i_sb
->s_blocksize_bits
);
187 if (ext0offset
== extoffset
&& !memcmp(&e0loc
, &bloc
, sizeof(lb_addr
)))
189 UDF_I_EXT0LOC(inode
) = eloc
;
190 UDF_I_EXT0LEN(inode
) = elen
;
192 udf_add_aext(inode
, &bloc
, &extoffset
, eloc
, elen
, &bh
, 1);
197 udf_release_data(bh
);
200 void udf_truncate(struct inode
* inode
)
202 if (!(S_ISREG(inode
->i_mode
) || S_ISDIR(inode
->i_mode
) ||
203 S_ISLNK(inode
->i_mode
)))
205 if (IS_APPEND(inode
) || IS_IMMUTABLE(inode
))
208 if (!UDF_I_EXT0OFFS(inode
))
210 udf_discard_prealloc(inode
);
215 inode
->i_mtime
= inode
->i_ctime
= CURRENT_TIME
;
216 mark_inode_dirty(inode
);
219 void udf_truncate_adinicb(struct inode
* inode
)
221 if (!(S_ISREG(inode
->i_mode
) || S_ISDIR(inode
->i_mode
) ||
222 S_ISLNK(inode
->i_mode
)))
224 if (IS_APPEND(inode
) || IS_IMMUTABLE(inode
))
227 inode
->i_mtime
= inode
->i_ctime
= CURRENT_TIME
;
228 mark_inode_dirty(inode
);