~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/udf/truncate.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * truncate.c
  3  *
  4  * PURPOSE
  5  *      Truncate handling routines for the OSTA-UDF(tm) filesystem.
  6  *
  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
 11  *
 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.
 17  *
 18  *  (C) 1999-2000 Ben Fennema
 19  *  (C) 1999 Stelias Computing Inc
 20  *
 21  * HISTORY
 22  *
 23  *  02/24/99 blf  Created.
 24  *
 25  */
 26 
 27 #include "udfdecl.h"
 28 #include <linux/fs.h>
 29 #include <linux/mm.h>
 30 #include <linux/udf_fs.h>
 31 
 32 #include "udf_i.h"
 33 #include "udf_sb.h"
 34 
 35 static void extent_trunc(struct inode * inode, lb_addr bloc, int extoffset,
 36         lb_addr eloc, Uint8 etype, Uint32 elen, struct buffer_head **bh, Uint32 nelen)
 37 {
 38         lb_addr neloc = { 0, 0 };
 39         int blocks = inode->i_sb->s_blocksize / 512;
 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;
 42 
 43         if (nelen)
 44         {
 45                 neloc = eloc;
 46                 nelen = (etype << 30) | nelen;
 47         }
 48 
 49         if (elen != nelen)
 50         {
 51                 udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 0);
 52                 if (last_block - first_block > 0)
 53                 {
 54                         if (etype == EXTENT_RECORDED_ALLOCATED)
 55                         {
 56                                 inode->i_blocks -= (blocks * (last_block - first_block));
 57                                 mark_inode_dirty(inode);
 58                         }
 59                         if (etype != EXTENT_NOT_RECORDED_NOT_ALLOCATED)
 60                                 udf_free_blocks(inode, eloc, first_block, last_block - first_block);
 61                 }
 62         }
 63 }
 64 
 65 void udf_trunc(struct inode * inode)
 66 {
 67         lb_addr bloc, eloc, neloc = { 0, 0 };
 68         Uint32 extoffset, elen, offset, nelen = 0, lelen = 0, lenalloc;
 69         int etype;
 70         int first_block = inode->i_size >> inode->i_sb->s_blocksize_bits;
 71         struct buffer_head *bh = NULL;
 72         int adsize;
 73 
 74         if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_SHORT)
 75                 adsize = sizeof(short_ad);
 76         else if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_LONG)
 77                 adsize = sizeof(long_ad);
 78         else
 79                 adsize = 0;
 80 
 81         etype = inode_bmap(inode, first_block, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
 82         offset = (offset << inode->i_sb->s_blocksize_bits) |
 83                 (inode->i_size & (inode->i_sb->s_blocksize - 1));
 84         if (etype != -1)
 85         {
 86                 extoffset -= adsize;
 87                 extent_trunc(inode, bloc, extoffset, eloc, etype, elen, &bh, offset);
 88                 extoffset += adsize;
 89 
 90                 if (offset)
 91                         lenalloc = extoffset;
 92                 else
 93                         lenalloc = extoffset - adsize;
 94 
 95                 if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
 96                         lenalloc -= udf_file_entry_alloc_offset(inode);
 97                 else
 98                         lenalloc -= sizeof(struct AllocExtDesc);
 99 
100                 while ((etype = udf_current_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 0)) != -1)
101                 {
102                         if (etype == EXTENT_NEXT_EXTENT_ALLOCDECS)
103                         {
104                                 udf_write_aext(inode, bloc, &extoffset, neloc, nelen, &bh, 0);
105                                 extoffset = 0;
106                                 if (lelen)
107                                 {
108                                         if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
109                                                 memset(bh->b_data, 0x00, udf_file_entry_alloc_offset(inode));
110                                         else
111                                                 memset(bh->b_data, 0x00, sizeof(struct AllocExtDesc));
112                                         udf_free_blocks(inode, bloc, 0, lelen);
113                                 }
114                                 else
115                                 {
116                                         if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
117                                         {
118                                                 UDF_I_LENALLOC(inode) = lenalloc;
119                                                 mark_inode_dirty(inode);
120                                         }
121                                         else
122                                         {
123                                                 struct AllocExtDesc *aed = (struct AllocExtDesc *)(bh->b_data);
124                                                 aed->lengthAllocDescs = cpu_to_le32(lenalloc);
125                                                 udf_update_tag(bh->b_data, lenalloc +
126                                                         sizeof(struct AllocExtDesc));
127                                                 mark_buffer_dirty(bh);
128                                         }
129                                 }
130 
131                                 udf_release_data(bh);
132                                 bh = NULL;
133 
134                                 bloc = eloc;
135                                 if (elen)
136                                         lelen = (elen + inode->i_sb->s_blocksize - 1) >>
137                                                 inode->i_sb->s_blocksize_bits;
138                                 else
139                                         lelen = 1;
140                         }
141                         else
142                         {
143                                 extent_trunc(inode, bloc, extoffset, eloc, etype, elen, &bh, 0);
144                                 extoffset += adsize;
145                         }
146                 }
147 
148                 if (lelen)
149                 {
150                         if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
151                                 memset(bh->b_data, 0x00, udf_file_entry_alloc_offset(inode));
152                         else
153                                 memset(bh->b_data, 0x00, sizeof(struct AllocExtDesc));
154                         udf_free_blocks(inode, bloc, 0, lelen);
155                 }
156                 else
157                 {
158                         if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
159                         {
160                                 UDF_I_LENALLOC(inode) = lenalloc;
161                                 mark_inode_dirty(inode);
162                         }
163                         else
164                         {
165                                 struct AllocExtDesc *aed = (struct AllocExtDesc *)(bh->b_data);
166                                 aed->lengthAllocDescs = cpu_to_le32(lenalloc);
167                                 udf_update_tag(bh->b_data, lenalloc +
168                                         sizeof(struct AllocExtDesc));
169                                 mark_buffer_dirty(bh);
170                         }
171                 }
172         }
173         else if (inode->i_size)
174         {
175                 if (offset)
176                 {
177                         extoffset -= adsize;
178                         etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1);
179                         if (etype == EXTENT_NOT_RECORDED_NOT_ALLOCATED)
180                         {
181                                 extoffset -= adsize;
182                                 elen = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) | (elen + offset);
183                                 udf_write_aext(inode, bloc, &extoffset, eloc, elen, &bh, 0);
184                         }
185                         else if (etype == EXTENT_NOT_RECORDED_ALLOCATED)
186                         {
187                                 lb_addr neloc = { 0, 0 };
188                                 extoffset -= adsize;
189                                 nelen = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) |
190                                         ((elen + offset + inode->i_sb->s_blocksize - 1) &
191                                         ~(inode->i_sb->s_blocksize - 1));
192                                 udf_write_aext(inode, bloc, &extoffset, neloc, nelen, &bh, 1);
193                                 udf_add_aext(inode, &bloc, &extoffset, eloc, (etype << 30) | elen, &bh, 1);
194                         }
195                         else
196                         {
197                                 if (elen & (inode->i_sb->s_blocksize - 1))
198                                 {
199                                         extoffset -= adsize;
200                                         elen = (EXTENT_RECORDED_ALLOCATED << 30) |
201                                                 ((elen + inode->i_sb->s_blocksize - 1) &
202                                                 ~(inode->i_sb->s_blocksize - 1));
203                                         udf_write_aext(inode, bloc, &extoffset, eloc, elen, &bh, 1);
204                                 }
205                                 memset(&eloc, 0x00, sizeof(lb_addr));
206                                 elen = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) | offset;
207                                 udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1);
208                         }
209                 }
210         }
211 
212         udf_release_data(bh);
213 }
214 
215 void udf_truncate(struct inode * inode)
216 {
217         int err;
218 
219         if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
220                         S_ISLNK(inode->i_mode)))
221                 return;
222         if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
223                 return;
224 
225         if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
226         {
227                 if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) +
228                         inode->i_size))
229                 {
230                         udf_expand_file_adinicb(inode, inode->i_size, &err);
231                         if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
232                         {
233                                 inode->i_size = UDF_I_LENALLOC(inode);
234                                 return;
235                         }
236                         else
237                                 udf_trunc(inode);
238                 }
239                 else
240                         UDF_I_LENALLOC(inode) = inode->i_size;
241         }
242         else
243                 udf_trunc(inode);
244 
245         inode->i_mtime = inode->i_ctime = CURRENT_TIME;
246         mark_inode_dirty(inode);
247 }
248 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.