Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
9fc995cf | 2 | * Copyright (c) 1989, 1991 Regents of the University of California. |
7188ac27 | 3 | * All rights reserved. |
da7c5cc6 | 4 | * |
b702c21d | 5 | * %sccs.include.redist.c% |
7188ac27 | 6 | * |
f8d81b3c | 7 | * @(#)lfs_balloc.c 7.41 (Berkeley) %G% |
da7c5cc6 | 8 | */ |
f6437c6d KB |
9 | #include <sys/param.h> |
10 | #include <sys/buf.h> | |
11 | #include <sys/proc.h> | |
12 | #include <sys/vnode.h> | |
13 | #include <sys/mount.h> | |
14 | #include <sys/resourcevar.h> | |
f6437c6d | 15 | #include <sys/trace.h> |
c6f5111d | 16 | |
cf9550bf KM |
17 | #include <miscfs/specfs/specdev.h> |
18 | ||
9fc995cf KB |
19 | #include <ufs/ufs/quota.h> |
20 | #include <ufs/ufs/inode.h> | |
21 | #include <ufs/ufs/ufsmount.h> | |
f6437c6d | 22 | |
9fc995cf KB |
23 | #include <ufs/lfs/lfs.h> |
24 | #include <ufs/lfs/lfs_extern.h> | |
52212483 | 25 | |
ce90ef66 KB |
26 | int |
27 | lfs_balloc(vp, iosize, lbn, bpp) | |
28 | struct vnode *vp; | |
29 | u_long iosize; | |
30 | daddr_t lbn; | |
31 | struct buf **bpp; | |
32 | { | |
9294084a | 33 | struct buf *ibp, *bp; |
ce90ef66 KB |
34 | struct inode *ip; |
35 | struct lfs *fs; | |
9294084a | 36 | struct indir indirs[NIADDR+2]; |
ce90ef66 | 37 | daddr_t daddr; |
9294084a | 38 | int bb, error, i, num; |
ce90ef66 KB |
39 | |
40 | ip = VTOI(vp); | |
41 | fs = ip->i_lfs; | |
42 | ||
43 | /* | |
44 | * Three cases: it's a block beyond the end of file, it's a block in | |
45 | * the file that may or may not have been assigned a disk address or | |
46 | * we're writing an entire block. Note, if the daddr is unassigned, | |
9294084a MS |
47 | * the block might still have existed in the cache (if it was read |
48 | * or written earlier). If it did, make sure we don't count it as a | |
49 | * new block or zero out its contents. If it did not, make sure | |
50 | * we allocate any necessary indirect blocks. | |
ce90ef66 | 51 | */ |
09bd76f7 KB |
52 | |
53 | *bpp = NULL; | |
9294084a | 54 | if (error = ufs_bmaparray(vp, lbn, &daddr, &indirs[0], &num, NULL )) |
cb92c035 | 55 | return (error); |
ce90ef66 | 56 | |
9294084a MS |
57 | *bpp = bp = getblk(vp, lbn, fs->lfs_bsize); |
58 | bb = VFSTOUFS(vp->v_mount)->um_seqinc; | |
59 | if (daddr == UNASSIGNED) | |
60 | /* May need to allocate indirect blocks */ | |
61 | for (i = 1; i < num; ++i) | |
62 | if (!indirs[i].in_exists) { | |
63 | ibp = | |
64 | getblk(vp, indirs[i].in_lbn, fs->lfs_bsize); | |
65 | if (!(ibp->b_flags & (B_DONE | B_DELWRI))) { | |
66 | if (!ISSPACE(fs, bb, curproc->p_ucred)){ | |
67 | ibp->b_flags |= B_INVAL; | |
68 | brelse(ibp); | |
69 | error = ENOSPC; | |
70 | } else { | |
71 | ip->i_blocks += bb; | |
72 | ip->i_lfs->lfs_bfree -= bb; | |
73 | clrbuf(ibp); | |
74 | error = VOP_BWRITE(ibp); | |
75 | } | |
76 | } else | |
77 | panic ("Indirect block should not exist"); | |
78 | } | |
79 | if (error) { | |
80 | if (bp) | |
81 | brelse(bp); | |
82 | return(error); | |
83 | } | |
84 | ||
85 | ||
86 | /* Now, we may need to allocate the data block */ | |
87 | if (!(bp->b_flags & (B_CACHE | B_DONE | B_DELWRI))) { | |
88 | if (daddr == UNASSIGNED) | |
89 | if (!ISSPACE(fs, bb, curproc->p_ucred)) { | |
13661328 | 90 | bp->b_flags |= B_INVAL; |
13661328 | 91 | brelse(bp); |
9294084a MS |
92 | return(ENOSPC); |
93 | } else { | |
94 | ip->i_blocks += bb; | |
95 | ip->i_lfs->lfs_bfree -= bb; | |
96 | if (iosize != fs->lfs_bsize) | |
97 | clrbuf(bp); | |
13661328 | 98 | } |
9294084a MS |
99 | else if (iosize == fs->lfs_bsize) |
100 | bp->b_blkno = daddr; /* Skip the I/O */ | |
101 | else { | |
102 | bp->b_blkno = daddr; | |
f8d81b3c | 103 | bp->b_flags |= B_READ; |
9294084a | 104 | VOP_STRATEGY(bp); |
c8c7b337 | 105 | return(biowait(bp)); |
ce90ef66 | 106 | } |
ce90ef66 | 107 | } |
9294084a | 108 | return (error); |
ce90ef66 | 109 | } |