Deleted Added
full compact
ffs_inode.c (98658) ffs_inode.c (100344)
1/*
2 * Copyright (c) 1982, 1986, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 17 unchanged lines hidden (view full) ---

26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)ffs_inode.c 8.13 (Berkeley) 4/21/95
1/*
2 * Copyright (c) 1982, 1986, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 17 unchanged lines hidden (view full) ---

26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)ffs_inode.c 8.13 (Berkeley) 4/21/95
34 * $FreeBSD: head/sys/ufs/ffs/ffs_inode.c 98658 2002-06-23 06:12:22Z dillon $
34 * $FreeBSD: head/sys/ufs/ffs/ffs_inode.c 100344 2002-07-19 07:29:39Z mckusick $
35 */
36
37#include "opt_quota.h"
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/mount.h>
42#include <sys/proc.h>

--- 98 unchanged lines hidden (view full) ---

141 int flags;
142 struct ucred *cred;
143 struct thread *td;
144{
145 struct vnode *ovp = vp;
146 struct inode *oip;
147 ufs2_daddr_t bn, lbn, lastblock, lastiblock[NIADDR], indir_lbn[NIADDR];
148 ufs2_daddr_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR];
35 */
36
37#include "opt_quota.h"
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/mount.h>
42#include <sys/proc.h>

--- 98 unchanged lines hidden (view full) ---

141 int flags;
142 struct ucred *cred;
143 struct thread *td;
144{
145 struct vnode *ovp = vp;
146 struct inode *oip;
147 ufs2_daddr_t bn, lbn, lastblock, lastiblock[NIADDR], indir_lbn[NIADDR];
148 ufs2_daddr_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR];
149 ufs2_daddr_t count, blocksreleased = 0;
149 ufs2_daddr_t count, blocksreleased = 0, datablocks;
150 struct fs *fs;
151 struct buf *bp;
150 struct fs *fs;
151 struct buf *bp;
152 int needextclean, softdepslowdown, extblocks;
152 int offset, size, level, nblocks;
153 int offset, size, level, nblocks;
153 int i, aflags, error, allerror;
154 int i, error, allerror;
154 off_t osize;
155
156 oip = VTOI(ovp);
157 fs = oip->i_fs;
158 if (length < 0)
159 return (EINVAL);
155 off_t osize;
156
157 oip = VTOI(ovp);
158 fs = oip->i_fs;
159 if (length < 0)
160 return (EINVAL);
161 /*
162 * Historically clients did not have to specify which data
163 * they were truncating. So, if not specified, we assume
164 * traditional behavior, e.g., just the normal data.
165 */
166 if ((flags & (IO_EXT | IO_NORMAL)) == 0)
167 flags |= IO_NORMAL;
168 /*
169 * If we are truncating the extended-attributes, and cannot
170 * do it with soft updates, then do it slowly here. If we are
171 * truncating both the extended attributes and the file contents
172 * (e.g., the file is being unlinked), then pick it off with
173 * soft updates below.
174 */
175 needextclean = 0;
176 softdepslowdown = softdep_slowdown(ovp);
177 extblocks = 0;
178 datablocks = DIP(oip, i_blocks);
179 if (fs->fs_magic == FS_UFS2_MAGIC && oip->i_din2->di_extsize > 0) {
180 extblocks = btodb(fragroundup(fs, oip->i_din2->di_extsize));
181 datablocks -= extblocks;
182 }
183 if ((flags & IO_EXT) && extblocks > 0) {
184 if (DOINGSOFTDEP(ovp) && softdepslowdown == 0 && length == 0) {
185 if ((flags & IO_NORMAL) == 0) {
186 softdep_setup_freeblocks(oip, length, IO_EXT);
187 return (0);
188 }
189 needextclean = 1;
190 } else {
191 if (length != 0)
192 panic("ffs_truncate: partial trunc of extdata");
193 if ((error = VOP_FSYNC(ovp, cred, MNT_WAIT, td)) != 0)
194 return (error);
195 osize = oip->i_din2->di_extsize;
196 oip->i_din2->di_blocks -= extblocks;
197#ifdef QUOTA
198 (void) chkdq(oip, -extblocks, NOCRED, 0);
199#endif
200 vinvalbuf(ovp, V_ALT, cred, td, 0, 0);
201 oip->i_din2->di_extsize = 0;
202 for (i = 0; i < NXADDR; i++) {
203 oldblks[i] = oip->i_din2->di_extb[i];
204 oip->i_din2->di_extb[i] = 0;
205 }
206 oip->i_flag |= IN_CHANGE | IN_UPDATE;
207 if ((error = ffs_update(ovp, 1)))
208 return (error);
209 for (i = 0; i < NXADDR; i++) {
210 if (oldblks[i] == 0)
211 continue;
212 ffs_blkfree(fs, oip->i_devvp, oldblks[i],
213 sblksize(fs, osize, i), oip->i_number);
214 }
215 }
216 }
217 if ((flags & IO_NORMAL) == 0)
218 return (0);
160 if (length > fs->fs_maxfilesize)
161 return (EFBIG);
162 if (ovp->v_type == VLNK &&
163 (oip->i_size < ovp->v_mount->mnt_maxsymlinklen ||
219 if (length > fs->fs_maxfilesize)
220 return (EFBIG);
221 if (ovp->v_type == VLNK &&
222 (oip->i_size < ovp->v_mount->mnt_maxsymlinklen ||
164 DIP(oip, i_blocks) == 0)) {
223 datablocks == 0)) {
165#ifdef DIAGNOSTIC
166 if (length != 0)
167 panic("ffs_truncate: partial truncate of symlink");
168#endif
169 bzero(SHORTLINK(oip), (u_int)oip->i_size);
170 oip->i_size = 0;
171 DIP(oip, i_size) = 0;
172 oip->i_flag |= IN_CHANGE | IN_UPDATE;
224#ifdef DIAGNOSTIC
225 if (length != 0)
226 panic("ffs_truncate: partial truncate of symlink");
227#endif
228 bzero(SHORTLINK(oip), (u_int)oip->i_size);
229 oip->i_size = 0;
230 DIP(oip, i_size) = 0;
231 oip->i_flag |= IN_CHANGE | IN_UPDATE;
232 if (needextclean)
233 softdep_setup_freeblocks(oip, length, IO_EXT);
173 return (UFS_UPDATE(ovp, 1));
174 }
175 if (oip->i_size == length) {
176 oip->i_flag |= IN_CHANGE | IN_UPDATE;
234 return (UFS_UPDATE(ovp, 1));
235 }
236 if (oip->i_size == length) {
237 oip->i_flag |= IN_CHANGE | IN_UPDATE;
238 if (needextclean)
239 softdep_setup_freeblocks(oip, length, IO_EXT);
177 return (UFS_UPDATE(ovp, 0));
178 }
179 if (fs->fs_ronly)
180 panic("ffs_truncate: read-only filesystem");
181#ifdef QUOTA
182 error = getinoquota(oip);
183 if (error)
184 return (error);
185#endif
186 if ((oip->i_flags & SF_SNAPSHOT) != 0)
187 ffs_snapremove(ovp);
188 ovp->v_lasta = ovp->v_clen = ovp->v_cstart = ovp->v_lastw = 0;
189 if (DOINGSOFTDEP(ovp)) {
240 return (UFS_UPDATE(ovp, 0));
241 }
242 if (fs->fs_ronly)
243 panic("ffs_truncate: read-only filesystem");
244#ifdef QUOTA
245 error = getinoquota(oip);
246 if (error)
247 return (error);
248#endif
249 if ((oip->i_flags & SF_SNAPSHOT) != 0)
250 ffs_snapremove(ovp);
251 ovp->v_lasta = ovp->v_clen = ovp->v_cstart = ovp->v_lastw = 0;
252 if (DOINGSOFTDEP(ovp)) {
190 if (length > 0 || softdep_slowdown(ovp)) {
253 if (length > 0 || softdepslowdown) {
191 /*
192 * If a file is only partially truncated, then
193 * we have to clean up the data structures
194 * describing the allocation past the truncation
195 * point. Finding and deallocating those structures
196 * is a lot of work. Since partial truncation occurs
197 * rarely, we solve the problem by syncing the file
198 * so that it will have no data structures left.
199 */
254 /*
255 * If a file is only partially truncated, then
256 * we have to clean up the data structures
257 * describing the allocation past the truncation
258 * point. Finding and deallocating those structures
259 * is a lot of work. Since partial truncation occurs
260 * rarely, we solve the problem by syncing the file
261 * so that it will have no data structures left.
262 */
200 if ((error = VOP_FSYNC(ovp, cred, MNT_WAIT,
201 td)) != 0)
263 if ((error = VOP_FSYNC(ovp, cred, MNT_WAIT, td)) != 0)
202 return (error);
203 if (oip->i_flag & IN_SPACECOUNTED)
264 return (error);
265 if (oip->i_flag & IN_SPACECOUNTED)
204 fs->fs_pendingblocks -= DIP(oip, i_blocks);
266 fs->fs_pendingblocks -= datablocks;
205 } else {
206#ifdef QUOTA
267 } else {
268#ifdef QUOTA
207 (void) chkdq(oip, -DIP(oip, i_blocks), NOCRED, 0);
269 (void) chkdq(oip, -datablocks, NOCRED, 0);
208#endif
270#endif
209 softdep_setup_freeblocks(oip, length);
210 vinvalbuf(ovp, 0, cred, td, 0, 0);
271 softdep_setup_freeblocks(oip, length, needextclean ?
272 IO_EXT | IO_NORMAL : IO_NORMAL);
273 vinvalbuf(ovp, needextclean ? 0 : V_NORMAL,
274 cred, td, 0, 0);
211 oip->i_flag |= IN_CHANGE | IN_UPDATE;
212 return (ffs_update(ovp, 0));
213 }
214 }
215 osize = oip->i_size;
216 /*
217 * Lengthen the size of the file. We must ensure that the
218 * last byte of the file is allocated. Since the smallest
219 * value of osize is 0, length will be at least 1.
220 */
221 if (osize < length) {
222 vnode_pager_setsize(ovp, length);
275 oip->i_flag |= IN_CHANGE | IN_UPDATE;
276 return (ffs_update(ovp, 0));
277 }
278 }
279 osize = oip->i_size;
280 /*
281 * Lengthen the size of the file. We must ensure that the
282 * last byte of the file is allocated. Since the smallest
283 * value of osize is 0, length will be at least 1.
284 */
285 if (osize < length) {
286 vnode_pager_setsize(ovp, length);
223 aflags = BA_CLRBUF;
224 if (flags & IO_SYNC)
225 aflags |= BA_SYNC;
226 error = UFS_BALLOC(ovp, length - 1, 1,
227 cred, aflags, &bp);
287 flags |= BA_CLRBUF;
288 error = UFS_BALLOC(ovp, length - 1, 1, cred, flags, &bp);
228 if (error)
229 return (error);
230 oip->i_size = length;
231 DIP(oip, i_size) = length;
232 if (bp->b_bufsize == fs->fs_bsize)
233 bp->b_flags |= B_CLUSTEROK;
289 if (error)
290 return (error);
291 oip->i_size = length;
292 DIP(oip, i_size) = length;
293 if (bp->b_bufsize == fs->fs_bsize)
294 bp->b_flags |= B_CLUSTEROK;
234 if (aflags & BA_SYNC)
295 if (flags & IO_SYNC)
235 bwrite(bp);
236 else
237 bawrite(bp);
238 oip->i_flag |= IN_CHANGE | IN_UPDATE;
239 return (UFS_UPDATE(ovp, 1));
240 }
241 /*
242 * Shorten the size of the file. If the file is not being

--- 4 unchanged lines hidden (view full) ---

247 * zero'ed as they should grow back initialized to empty.
248 */
249 offset = blkoff(fs, length);
250 if (offset == 0) {
251 oip->i_size = length;
252 DIP(oip, i_size) = length;
253 } else {
254 lbn = lblkno(fs, length);
296 bwrite(bp);
297 else
298 bawrite(bp);
299 oip->i_flag |= IN_CHANGE | IN_UPDATE;
300 return (UFS_UPDATE(ovp, 1));
301 }
302 /*
303 * Shorten the size of the file. If the file is not being

--- 4 unchanged lines hidden (view full) ---

308 * zero'ed as they should grow back initialized to empty.
309 */
310 offset = blkoff(fs, length);
311 if (offset == 0) {
312 oip->i_size = length;
313 DIP(oip, i_size) = length;
314 } else {
315 lbn = lblkno(fs, length);
255 aflags = BA_CLRBUF;
256 if (flags & IO_SYNC)
257 aflags |= BA_SYNC;
258 error = UFS_BALLOC(ovp, length - 1, 1, cred, aflags, &bp);
316 flags |= BA_CLRBUF;
317 error = UFS_BALLOC(ovp, length - 1, 1, cred, flags, &bp);
259 if (error) {
260 return (error);
261 }
262 /*
263 * When we are doing soft updates and the UFS_BALLOC
264 * above fills in a direct block hole with a full sized
265 * block that will be truncated down to a fragment below,
266 * we must flush out the block dependency with an FSYNC

--- 9 unchanged lines hidden (view full) ---

276 size = blksize(fs, oip, lbn);
277 if (ovp->v_type != VDIR)
278 bzero((char *)bp->b_data + offset,
279 (u_int)(size - offset));
280 /* Kirk's code has reallocbuf(bp, size, 1) here */
281 allocbuf(bp, size);
282 if (bp->b_bufsize == fs->fs_bsize)
283 bp->b_flags |= B_CLUSTEROK;
318 if (error) {
319 return (error);
320 }
321 /*
322 * When we are doing soft updates and the UFS_BALLOC
323 * above fills in a direct block hole with a full sized
324 * block that will be truncated down to a fragment below,
325 * we must flush out the block dependency with an FSYNC

--- 9 unchanged lines hidden (view full) ---

335 size = blksize(fs, oip, lbn);
336 if (ovp->v_type != VDIR)
337 bzero((char *)bp->b_data + offset,
338 (u_int)(size - offset));
339 /* Kirk's code has reallocbuf(bp, size, 1) here */
340 allocbuf(bp, size);
341 if (bp->b_bufsize == fs->fs_bsize)
342 bp->b_flags |= B_CLUSTEROK;
284 if (aflags & BA_SYNC)
343 if (flags & IO_SYNC)
285 bwrite(bp);
286 else
287 bawrite(bp);
288 }
289 /*
290 * Calculate index into inode's block list of
291 * last direct and indirect blocks (if any)
292 * which we want to keep. Lastblock is -1 when

--- 122 unchanged lines hidden (view full) ---

415#ifdef DIAGNOSTIC
416 for (level = SINGLE; level <= TRIPLE; level++)
417 if (newblks[NDADDR + level] != DIP(oip, i_ib[level]))
418 panic("ffs_truncate1");
419 for (i = 0; i < NDADDR; i++)
420 if (newblks[i] != DIP(oip, i_db[i]))
421 panic("ffs_truncate2");
422 if (length == 0 &&
344 bwrite(bp);
345 else
346 bawrite(bp);
347 }
348 /*
349 * Calculate index into inode's block list of
350 * last direct and indirect blocks (if any)
351 * which we want to keep. Lastblock is -1 when

--- 122 unchanged lines hidden (view full) ---

474#ifdef DIAGNOSTIC
475 for (level = SINGLE; level <= TRIPLE; level++)
476 if (newblks[NDADDR + level] != DIP(oip, i_ib[level]))
477 panic("ffs_truncate1");
478 for (i = 0; i < NDADDR; i++)
479 if (newblks[i] != DIP(oip, i_db[i]))
480 panic("ffs_truncate2");
481 if (length == 0 &&
482 (fs->fs_magic != FS_UFS2_MAGIC || oip->i_din2->di_extsize == 0) &&
423 (!TAILQ_EMPTY(&ovp->v_dirtyblkhd) ||
424 !TAILQ_EMPTY(&ovp->v_cleanblkhd)))
425 panic("ffs_truncate3");
426#endif /* DIAGNOSTIC */
427 /*
428 * Put back the real size.
429 */
430 oip->i_size = length;

--- 142 unchanged lines hidden ---
483 (!TAILQ_EMPTY(&ovp->v_dirtyblkhd) ||
484 !TAILQ_EMPTY(&ovp->v_cleanblkhd)))
485 panic("ffs_truncate3");
486#endif /* DIAGNOSTIC */
487 /*
488 * Put back the real size.
489 */
490 oip->i_size = length;

--- 142 unchanged lines hidden ---