Initial import from FreeBSD RELENG_4:
[games.git] / sys / vfs / ufs / ffs_inode.c
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
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
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: src/sys/ufs/ffs/ffs_inode.c,v 1.56.2.5 2002/02/05 18:35:03 dillon Exp $
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>
43 #include <sys/buf.h>
44 #include <sys/vnode.h>
45 #include <sys/kernel.h>
46 #include <sys/malloc.h>
47 #include <sys/resourcevar.h>
48 #include <sys/vmmeter.h>
49
50 #include <vm/vm.h>
51 #include <vm/vm_extern.h>
52
53 #include <ufs/ufs/quota.h>
54 #include <ufs/ufs/ufsmount.h>
55 #include <ufs/ufs/inode.h>
56 #include <ufs/ufs/ufs_extern.h>
57
58 #include <ufs/ffs/fs.h>
59 #include <ufs/ffs/ffs_extern.h>
60
61 static int ffs_indirtrunc __P((struct inode *, ufs_daddr_t, ufs_daddr_t,
62             ufs_daddr_t, int, long *));
63
64 /*
65  * Update the access, modified, and inode change times as specified by the
66  * IN_ACCESS, IN_UPDATE, and IN_CHANGE flags respectively.  Write the inode
67  * to disk if the IN_MODIFIED flag is set (it may be set initially, or by
68  * the timestamp update).  The IN_LAZYMOD flag is set to force a write
69  * later if not now.  If we write now, then clear both IN_MODIFIED and
70  * IN_LAZYMOD to reflect the presumably successful write, and if waitfor is
71  * set, then wait for the write to complete.
72  */
73 int
74 ffs_update(vp, waitfor)
75         struct vnode *vp;
76         int waitfor;
77 {
78         register struct fs *fs;
79         struct buf *bp;
80         struct inode *ip;
81         int error;
82
83         ufs_itimes(vp);
84         ip = VTOI(vp);
85         if ((ip->i_flag & IN_MODIFIED) == 0 && waitfor == 0)
86                 return (0);
87         ip->i_flag &= ~(IN_LAZYMOD | IN_MODIFIED);
88         fs = ip->i_fs;
89         if (fs->fs_ronly)
90                 return (0);
91         /*
92          * Ensure that uid and gid are correct. This is a temporary
93          * fix until fsck has been changed to do the update.
94          */
95         if (fs->fs_inodefmt < FS_44INODEFMT) {          /* XXX */
96                 ip->i_din.di_ouid = ip->i_uid;          /* XXX */
97                 ip->i_din.di_ogid = ip->i_gid;          /* XXX */
98         }                                               /* XXX */
99         error = bread(ip->i_devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
100                 (int)fs->fs_bsize, NOCRED, &bp);
101         if (error) {
102                 brelse(bp);
103                 return (error);
104         }
105         if (DOINGSOFTDEP(vp))
106                 softdep_update_inodeblock(ip, bp, waitfor);
107         else if (ip->i_effnlink != ip->i_nlink)
108                 panic("ffs_update: bad link cnt");
109         *((struct dinode *)bp->b_data +
110             ino_to_fsbo(fs, ip->i_number)) = ip->i_din;
111         if (waitfor && !DOINGASYNC(vp)) {
112                 return (bwrite(bp));
113         } else if (vm_page_count_severe() || buf_dirty_count_severe()) {
114                 return (bwrite(bp));
115         } else {
116                 if (bp->b_bufsize == fs->fs_bsize)
117                         bp->b_flags |= B_CLUSTEROK;
118                 bdwrite(bp);
119                 return (0);
120         }
121 }
122
123 #define SINGLE  0       /* index of single indirect block */
124 #define DOUBLE  1       /* index of double indirect block */
125 #define TRIPLE  2       /* index of triple indirect block */
126 /*
127  * Truncate the inode oip to at most length size, freeing the
128  * disk blocks.
129  */
130 int
131 ffs_truncate(vp, length, flags, cred, p)
132         struct vnode *vp;
133         off_t length;
134         int flags;
135         struct ucred *cred;
136         struct proc *p;
137 {
138         register struct vnode *ovp = vp;
139         ufs_daddr_t lastblock;
140         register struct inode *oip;
141         ufs_daddr_t bn, lbn, lastiblock[NIADDR], indir_lbn[NIADDR];
142         ufs_daddr_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR];
143         register struct fs *fs;
144         struct buf *bp;
145         int offset, size, level;
146         long count, nblocks, blocksreleased = 0;
147         register int i;
148         int aflags, error, allerror;
149         off_t osize;
150
151         oip = VTOI(ovp);
152         fs = oip->i_fs;
153         if (length < 0)
154                 return (EINVAL);
155         if (length > fs->fs_maxfilesize)
156                 return (EFBIG);
157         if (ovp->v_type == VLNK &&
158             (oip->i_size < ovp->v_mount->mnt_maxsymlinklen || oip->i_din.di_blocks == 0)) {
159 #ifdef DIAGNOSTIC
160                 if (length != 0)
161                         panic("ffs_truncate: partial truncate of symlink");
162 #endif
163                 bzero((char *)&oip->i_shortlink, (u_int)oip->i_size);
164                 oip->i_size = 0;
165                 oip->i_flag |= IN_CHANGE | IN_UPDATE;
166                 return (UFS_UPDATE(ovp, 1));
167         }
168         if (oip->i_size == length) {
169                 oip->i_flag |= IN_CHANGE | IN_UPDATE;
170                 return (UFS_UPDATE(ovp, 0));
171         }
172         if (fs->fs_ronly)
173                 panic("ffs_truncate: read-only filesystem");
174 #ifdef QUOTA
175         error = getinoquota(oip);
176         if (error)
177                 return (error);
178 #endif
179         ovp->v_lasta = ovp->v_clen = ovp->v_cstart = ovp->v_lastw = 0;
180         if (DOINGSOFTDEP(ovp)) {
181                 if (length > 0 || softdep_slowdown(ovp)) {
182                         /*
183                          * If a file is only partially truncated, then
184                          * we have to clean up the data structures
185                          * describing the allocation past the truncation
186                          * point. Finding and deallocating those structures
187                          * is a lot of work. Since partial truncation occurs
188                          * rarely, we solve the problem by syncing the file
189                          * so that it will have no data structures left.
190                          */
191                         if ((error = VOP_FSYNC(ovp, cred, MNT_WAIT,
192                             p)) != 0)
193                                 return (error);
194                 } else {
195 #ifdef QUOTA
196                         (void) chkdq(oip, -oip->i_blocks, NOCRED, 0);
197 #endif
198                         softdep_setup_freeblocks(oip, length);
199                         vinvalbuf(ovp, 0, cred, p, 0, 0);
200                         oip->i_flag |= IN_CHANGE | IN_UPDATE;
201                         return (ffs_update(ovp, 0));
202                 }
203         }
204         osize = oip->i_size;
205         /*
206          * Lengthen the size of the file. We must ensure that the
207          * last byte of the file is allocated. Since the smallest
208          * value of osize is 0, length will be at least 1.
209          */
210         if (osize < length) {
211                 vnode_pager_setsize(ovp, length);
212                 aflags = B_CLRBUF;
213                 if (flags & IO_SYNC)
214                         aflags |= B_SYNC;
215                 error = VOP_BALLOC(ovp, length - 1, 1,
216                     cred, aflags, &bp);
217                 if (error)
218                         return (error);
219                 oip->i_size = length;
220                 if (bp->b_bufsize == fs->fs_bsize)
221                         bp->b_flags |= B_CLUSTEROK;
222                 if (aflags & B_SYNC)
223                         bwrite(bp);
224                 else
225                         bawrite(bp);
226                 oip->i_flag |= IN_CHANGE | IN_UPDATE;
227                 return (UFS_UPDATE(ovp, 1));
228         }
229         /*
230          * Shorten the size of the file. If the file is not being
231          * truncated to a block boundary, the contents of the
232          * partial block following the end of the file must be
233          * zero'ed in case it ever becomes accessible again because
234          * of subsequent file growth. Directories however are not
235          * zero'ed as they should grow back initialized to empty.
236          */
237         offset = blkoff(fs, length);
238         if (offset == 0) {
239                 oip->i_size = length;
240         } else {
241                 lbn = lblkno(fs, length);
242                 aflags = B_CLRBUF;
243                 if (flags & IO_SYNC)
244                         aflags |= B_SYNC;
245                 error = VOP_BALLOC(ovp, length - 1, 1, cred, aflags, &bp);
246                 if (error) {
247                         return (error);
248                 }
249                 /*
250                  * When we are doing soft updates and the UFS_BALLOC
251                  * above fills in a direct block hole with a full sized
252                  * block that will be truncated down to a fragment below,
253                  * we must flush out the block dependency with an FSYNC
254                  * so that we do not get a soft updates inconsistency
255                  * when we create the fragment below.
256                  */
257                 if (DOINGSOFTDEP(ovp) && lbn < NDADDR &&
258                     fragroundup(fs, blkoff(fs, length)) < fs->fs_bsize &&
259                     (error = VOP_FSYNC(ovp, cred, MNT_WAIT, p)) != 0) {
260                                 return (error);
261                 }
262                 oip->i_size = length;
263                 size = blksize(fs, oip, lbn);
264                 if (ovp->v_type != VDIR)
265                         bzero((char *)bp->b_data + offset,
266                             (u_int)(size - offset));
267                 /* Kirk's code has reallocbuf(bp, size, 1) here */
268                 allocbuf(bp, size);
269                 if (bp->b_bufsize == fs->fs_bsize)
270                         bp->b_flags |= B_CLUSTEROK;
271                 if (aflags & B_SYNC)
272                         bwrite(bp);
273                 else
274                         bawrite(bp);
275         }
276         /*
277          * Calculate index into inode's block list of
278          * last direct and indirect blocks (if any)
279          * which we want to keep.  Lastblock is -1 when
280          * the file is truncated to 0.
281          */
282         lastblock = lblkno(fs, length + fs->fs_bsize - 1) - 1;
283         lastiblock[SINGLE] = lastblock - NDADDR;
284         lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs);
285         lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs);
286         nblocks = btodb(fs->fs_bsize);
287         /*
288          * Update file and block pointers on disk before we start freeing
289          * blocks.  If we crash before free'ing blocks below, the blocks
290          * will be returned to the free list.  lastiblock values are also
291          * normalized to -1 for calls to ffs_indirtrunc below.
292          */
293         bcopy((caddr_t)&oip->i_db[0], (caddr_t)oldblks, sizeof oldblks);
294         for (level = TRIPLE; level >= SINGLE; level--)
295                 if (lastiblock[level] < 0) {
296                         oip->i_ib[level] = 0;
297                         lastiblock[level] = -1;
298                 }
299         for (i = NDADDR - 1; i > lastblock; i--)
300                 oip->i_db[i] = 0;
301         oip->i_flag |= IN_CHANGE | IN_UPDATE;
302         allerror = UFS_UPDATE(ovp, 1);
303         
304         /*
305          * Having written the new inode to disk, save its new configuration
306          * and put back the old block pointers long enough to process them.
307          * Note that we save the new block configuration so we can check it
308          * when we are done.
309          */
310         bcopy((caddr_t)&oip->i_db[0], (caddr_t)newblks, sizeof newblks);
311         bcopy((caddr_t)oldblks, (caddr_t)&oip->i_db[0], sizeof oldblks);
312         oip->i_size = osize;
313
314         error = vtruncbuf(ovp, cred, p, length, fs->fs_bsize);
315         if (error && (allerror == 0))
316                 allerror = error;
317
318         /*
319          * Indirect blocks first.
320          */
321         indir_lbn[SINGLE] = -NDADDR;
322         indir_lbn[DOUBLE] = indir_lbn[SINGLE] - NINDIR(fs) - 1;
323         indir_lbn[TRIPLE] = indir_lbn[DOUBLE] - NINDIR(fs) * NINDIR(fs) - 1;
324         for (level = TRIPLE; level >= SINGLE; level--) {
325                 bn = oip->i_ib[level];
326                 if (bn != 0) {
327                         error = ffs_indirtrunc(oip, indir_lbn[level],
328                             fsbtodb(fs, bn), lastiblock[level], level, &count);
329                         if (error)
330                                 allerror = error;
331                         blocksreleased += count;
332                         if (lastiblock[level] < 0) {
333                                 oip->i_ib[level] = 0;
334                                 ffs_blkfree(oip, bn, fs->fs_bsize);
335                                 blocksreleased += nblocks;
336                         }
337                 }
338                 if (lastiblock[level] >= 0)
339                         goto done;
340         }
341
342         /*
343          * All whole direct blocks or frags.
344          */
345         for (i = NDADDR - 1; i > lastblock; i--) {
346                 register long bsize;
347
348                 bn = oip->i_db[i];
349                 if (bn == 0)
350                         continue;
351                 oip->i_db[i] = 0;
352                 bsize = blksize(fs, oip, i);
353                 ffs_blkfree(oip, bn, bsize);
354                 blocksreleased += btodb(bsize);
355         }
356         if (lastblock < 0)
357                 goto done;
358
359         /*
360          * Finally, look for a change in size of the
361          * last direct block; release any frags.
362          */
363         bn = oip->i_db[lastblock];
364         if (bn != 0) {
365                 long oldspace, newspace;
366
367                 /*
368                  * Calculate amount of space we're giving
369                  * back as old block size minus new block size.
370                  */
371                 oldspace = blksize(fs, oip, lastblock);
372                 oip->i_size = length;
373                 newspace = blksize(fs, oip, lastblock);
374                 if (newspace == 0)
375                         panic("ffs_truncate: newspace");
376                 if (oldspace - newspace > 0) {
377                         /*
378                          * Block number of space to be free'd is
379                          * the old block # plus the number of frags
380                          * required for the storage we're keeping.
381                          */
382                         bn += numfrags(fs, newspace);
383                         ffs_blkfree(oip, bn, oldspace - newspace);
384                         blocksreleased += btodb(oldspace - newspace);
385                 }
386         }
387 done:
388 #ifdef DIAGNOSTIC
389         for (level = SINGLE; level <= TRIPLE; level++)
390                 if (newblks[NDADDR + level] != oip->i_ib[level])
391                         panic("ffs_truncate1");
392         for (i = 0; i < NDADDR; i++)
393                 if (newblks[i] != oip->i_db[i])
394                         panic("ffs_truncate2");
395         if (length == 0 &&
396             (!TAILQ_EMPTY(&ovp->v_dirtyblkhd) ||
397              !TAILQ_EMPTY(&ovp->v_cleanblkhd)))
398                 panic("ffs_truncate3");
399 #endif /* DIAGNOSTIC */
400         /*
401          * Put back the real size.
402          */
403         oip->i_size = length;
404         oip->i_blocks -= blocksreleased;
405
406         if (oip->i_blocks < 0)                  /* sanity */
407                 oip->i_blocks = 0;
408         oip->i_flag |= IN_CHANGE;
409 #ifdef QUOTA
410         (void) chkdq(oip, -blocksreleased, NOCRED, 0);
411 #endif
412         return (allerror);
413 }
414
415 /*
416  * Release blocks associated with the inode ip and stored in the indirect
417  * block bn.  Blocks are free'd in LIFO order up to (but not including)
418  * lastbn.  If level is greater than SINGLE, the block is an indirect block
419  * and recursive calls to indirtrunc must be used to cleanse other indirect
420  * blocks.
421  *
422  * NB: triple indirect blocks are untested.
423  */
424 static int
425 ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
426         register struct inode *ip;
427         ufs_daddr_t lbn, lastbn;
428         ufs_daddr_t dbn;
429         int level;
430         long *countp;
431 {
432         register int i;
433         struct buf *bp;
434         register struct fs *fs = ip->i_fs;
435         register ufs_daddr_t *bap;
436         struct vnode *vp;
437         ufs_daddr_t *copy = NULL, nb, nlbn, last;
438         long blkcount, factor;
439         int nblocks, blocksreleased = 0;
440         int error = 0, allerror = 0;
441
442         /*
443          * Calculate index in current block of last
444          * block to be kept.  -1 indicates the entire
445          * block so we need not calculate the index.
446          */
447         factor = 1;
448         for (i = SINGLE; i < level; i++)
449                 factor *= NINDIR(fs);
450         last = lastbn;
451         if (lastbn > 0)
452                 last /= factor;
453         nblocks = btodb(fs->fs_bsize);
454         /*
455          * Get buffer of block pointers, zero those entries corresponding
456          * to blocks to be free'd, and update on disk copy first.  Since
457          * double(triple) indirect before single(double) indirect, calls
458          * to bmap on these blocks will fail.  However, we already have
459          * the on disk address, so we have to set the b_blkno field
460          * explicitly instead of letting bread do everything for us.
461          */
462         vp = ITOV(ip);
463         bp = getblk(vp, lbn, (int)fs->fs_bsize, 0, 0);
464         if ((bp->b_flags & B_CACHE) == 0) {
465                 curproc->p_stats->p_ru.ru_inblock++;    /* pay for read */
466                 bp->b_flags |= B_READ;
467                 bp->b_flags &= ~(B_ERROR|B_INVAL);
468                 if (bp->b_bcount > bp->b_bufsize)
469                         panic("ffs_indirtrunc: bad buffer size");
470                 bp->b_blkno = dbn;
471                 vfs_busy_pages(bp, 0);
472                 VOP_STRATEGY(bp->b_vp, bp);
473                 error = biowait(bp);
474         }
475         if (error) {
476                 brelse(bp);
477                 *countp = 0;
478                 return (error);
479         }
480
481         bap = (ufs_daddr_t *)bp->b_data;
482         if (lastbn != -1) {
483                 MALLOC(copy, ufs_daddr_t *, fs->fs_bsize, M_TEMP, M_WAITOK);
484                 bcopy((caddr_t)bap, (caddr_t)copy, (u_int)fs->fs_bsize);
485                 bzero((caddr_t)&bap[last + 1],
486                     (u_int)(NINDIR(fs) - (last + 1)) * sizeof (ufs_daddr_t));
487                 if (DOINGASYNC(vp)) {
488                         bawrite(bp);
489                 } else {
490                         error = bwrite(bp);
491                         if (error)
492                                 allerror = error;
493                 }
494                 bap = copy;
495         }
496
497         /*
498          * Recursively free totally unused blocks.
499          */
500         for (i = NINDIR(fs) - 1, nlbn = lbn + 1 - i * factor; i > last;
501             i--, nlbn += factor) {
502                 nb = bap[i];
503                 if (nb == 0)
504                         continue;
505                 if (level > SINGLE) {
506                         if ((error = ffs_indirtrunc(ip, nlbn, fsbtodb(fs, nb),
507                             (ufs_daddr_t)-1, level - 1, &blkcount)) != 0)
508                                 allerror = error;
509                         blocksreleased += blkcount;
510                 }
511                 ffs_blkfree(ip, nb, fs->fs_bsize);
512                 blocksreleased += nblocks;
513         }
514
515         /*
516          * Recursively free last partial block.
517          */
518         if (level > SINGLE && lastbn >= 0) {
519                 last = lastbn % factor;
520                 nb = bap[i];
521                 if (nb != 0) {
522                         error = ffs_indirtrunc(ip, nlbn, fsbtodb(fs, nb),
523                             last, level - 1, &blkcount);
524                         if (error)
525                                 allerror = error;
526                         blocksreleased += blkcount;
527                 }
528         }
529         if (copy != NULL) {
530                 FREE(copy, M_TEMP);
531         } else {
532                 bp->b_flags |= B_INVAL | B_NOCACHE;
533                 brelse(bp);
534         }
535                 
536         *countp = blocksreleased;
537         return (allerror);
538 }