Import 2.3.26pre2
[davej-history.git] / fs / udf / truncate.c
blobf11ccf7afb5ff49830cdc812f598f777a8a00e99
1 /*
2 * truncate.c
4 * PURPOSE
5 * Truncate handling routines for the OSTA-UDF(tm) filesystem.
7 * CONTACTS
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
12 * COPYRIGHT
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
21 * HISTORY
23 * 02/24/99 blf Created.
27 #include "udfdecl.h"
28 #include <linux/fs.h>
29 #include <linux/mm.h>
30 #include <linux/udf_fs.h>
32 #include "udf_i.h"
33 #include "udf_sb.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 };
39 int nelen = 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;
44 if (offset)
46 nelen = ((offset - 1) << inode->i_sb->s_blocksize_bits) +
47 (inode->i_size & (inode->i_sb->s_blocksize - 1));
48 neloc = eloc;
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;
66 int etype;
67 int first_block = (inode->i_size + inode->i_sb->s_blocksize - 1) / inode->i_sb->s_blocksize;
68 struct buffer_head *bh = NULL;
69 int adsize;
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);
75 else
76 adsize = 0;
78 if ((etype = inode_bmap(inode, first_block, &bloc, &extoffset, &eloc, &elen, &offset, &bh)) != -1)
80 extoffset -= adsize;
81 extent_trunc(inode, bloc, &extoffset, eloc, elen, &bh, offset);
83 if (offset)
84 lenalloc = extoffset;
85 else
86 lenalloc = extoffset - adsize;
88 if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
89 lenalloc -= udf_file_entry_alloc_offset(inode);
90 else
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);
98 extoffset = 0;
99 if (lelen)
101 if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
102 memset(bh->b_data, 0x00, udf_file_entry_alloc_offset(inode));
103 else
104 memset(bh->b_data, 0x00, sizeof(struct AllocExtDesc));
105 udf_free_blocks(inode, bloc, 0, lelen);
107 else
109 if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
110 UDF_I_LENALLOC(inode) = lenalloc;
111 else
113 struct AllocExtDesc *aed = (struct AllocExtDesc *)(bh->b_data);
114 aed->lengthAllocDescs = cpu_to_le32(lenalloc);
118 udf_release_data(bh);
119 bh = NULL;
121 bloc = eloc;
122 if (elen)
123 lelen = (elen + inode->i_sb->s_blocksize - 1) >>
124 inode->i_sb->s_blocksize_bits;
125 else
126 lelen = 1;
128 else if (etype != EXTENT_NOT_RECORDED_NOT_ALLOCATED)
129 extent_trunc(inode, bloc, &extoffset, eloc, elen, &bh, 0);
130 else
131 udf_write_aext(inode, bloc, &extoffset, neloc, nelen, &bh, 1);
134 if (lelen)
136 if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
137 memset(bh->b_data, 0x00, udf_file_entry_alloc_offset(inode));
138 else
139 memset(bh->b_data, 0x00, sizeof(struct AllocExtDesc));
140 udf_free_blocks(inode, bloc, 0, lelen);
142 else
144 if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
145 UDF_I_LENALLOC(inode) = lenalloc;
146 else
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);
157 char tetype;
159 if (offset)
161 extoffset -= adsize;
162 tetype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1);
163 if (tetype == EXTENT_NOT_RECORDED_NOT_ALLOCATED)
165 extoffset -= adsize;
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);
172 else
174 if (elen & (inode->i_sb->s_blocksize - 1))
176 extoffset -= adsize;
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)))
204 return;
205 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
206 return;
208 if (!UDF_I_EXT0OFFS(inode))
210 udf_discard_prealloc(inode);
212 trunc(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)))
223 return;
224 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
225 return;
227 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
228 mark_inode_dirty(inode);