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 --- |