This source file includes following definitions.
- ext2fs_buf_alloc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/buf.h>
40 #include <sys/proc.h>
41 #include <sys/file.h>
42 #include <sys/vnode.h>
43
44 #include <uvm/uvm_extern.h>
45
46 #include <ufs/ufs/quota.h>
47 #include <ufs/ufs/inode.h>
48 #include <ufs/ufs/ufs_extern.h>
49
50 #include <ufs/ext2fs/ext2fs.h>
51 #include <ufs/ext2fs/ext2fs_extern.h>
52
53
54
55
56
57
58 int
59 ext2fs_buf_alloc(struct inode *ip, daddr_t bn, int size, struct ucred *cred,
60 struct buf **bpp, int flags)
61 {
62 struct m_ext2fs *fs;
63 int32_t nb;
64 struct buf *bp, *nbp;
65 struct vnode *vp = ITOV(ip);
66 struct indir indirs[NIADDR + 2];
67 int32_t newb, lbn, *bap, pref;
68 int num, i, error;
69 u_int deallocated;
70 int32_t *allocib, *blkp, *allocblk, allociblk[NIADDR + 1];
71 int unwindidx = -1;
72
73 *bpp = NULL;
74 if (bn < 0)
75 return (EFBIG);
76 fs = ip->i_e2fs;
77 lbn = bn;
78
79
80
81
82 if (bn < NDADDR) {
83 nb = fs2h32(ip->i_e2fs_blocks[bn]);
84 if (nb != 0) {
85 error = bread(vp, bn, fs->e2fs_bsize, NOCRED, &bp);
86 if (error) {
87 brelse(bp);
88 return (error);
89 }
90 *bpp = bp;
91 return (0);
92 }
93
94
95
96
97 error = ext2fs_alloc(ip, bn,
98 ext2fs_blkpref(ip, bn, (int)bn, &ip->i_e2fs_blocks[0]),
99 cred, &newb);
100 if (error)
101 return (error);
102 ip->i_e2fs_last_lblk = lbn;
103 ip->i_e2fs_last_blk = newb;
104 ip->i_e2fs_blocks[bn] = h2fs32(newb);
105 ip->i_flag |= IN_CHANGE | IN_UPDATE;
106 bp = getblk(vp, bn, fs->e2fs_bsize, 0, 0);
107 bp->b_blkno = fsbtodb(fs, newb);
108 if (flags & B_CLRBUF)
109 clrbuf(bp);
110 *bpp = bp;
111 return (0);
112 }
113
114
115
116 pref = 0;
117 if ((error = ufs_getlbns(vp, bn, indirs, &num)) != 0)
118 return(error);
119 #ifdef DIAGNOSTIC
120 if (num < 1)
121 panic ("ext2fs_balloc: ufs_getlbns returned indirect block");
122 #endif
123
124
125
126 --num;
127 nb = fs2h32(ip->i_e2fs_blocks[NDADDR + indirs[0].in_off]);
128 allocib = NULL;
129 allocblk = allociblk;
130 if (nb == 0) {
131 pref = ext2fs_blkpref(ip, lbn, 0, (int32_t *)0);
132 error = ext2fs_alloc(ip, lbn, pref, cred, &newb);
133 if (error)
134 return (error);
135 nb = newb;
136 *allocblk++ = nb;
137 ip->i_e2fs_last_blk = newb;
138 bp = getblk(vp, indirs[1].in_lbn, fs->e2fs_bsize, 0, 0);
139 bp->b_blkno = fsbtodb(fs, newb);
140 clrbuf(bp);
141
142
143
144
145 if ((error = bwrite(bp)) != 0)
146 goto fail;
147 unwindidx = 0;
148 allocib = &ip->i_e2fs_blocks[NDADDR + indirs[0].in_off];
149 *allocib = h2fs32(newb);
150 ip->i_flag |= IN_CHANGE | IN_UPDATE;
151 }
152
153
154
155 for (i = 1;;) {
156 error = bread(vp,
157 indirs[i].in_lbn, (int)fs->e2fs_bsize, NOCRED, &bp);
158 if (error) {
159 brelse(bp);
160 goto fail;
161 }
162 bap = (int32_t *)bp->b_data;
163 nb = fs2h32(bap[indirs[i].in_off]);
164 if (i == num)
165 break;
166 i++;
167 if (nb != 0) {
168 brelse(bp);
169 continue;
170 }
171 pref = ext2fs_blkpref(ip, lbn, 0, (int32_t *)0);
172 error = ext2fs_alloc(ip, lbn, pref, cred, &newb);
173 if (error) {
174 brelse(bp);
175 goto fail;
176 }
177 nb = newb;
178 *allocblk++ = nb;
179 ip->i_e2fs_last_blk = newb;
180 nbp = getblk(vp, indirs[i].in_lbn, fs->e2fs_bsize, 0, 0);
181 nbp->b_blkno = fsbtodb(fs, nb);
182 clrbuf(nbp);
183
184
185
186
187 if ((error = bwrite(nbp)) != 0) {
188 brelse(bp);
189 goto fail;
190 }
191 if (unwindidx < 0)
192 unwindidx = i - 1;
193 bap[indirs[i - 1].in_off] = h2fs32(nb);
194
195
196
197
198 if (flags & B_SYNC) {
199 bwrite(bp);
200 } else {
201 bdwrite(bp);
202 }
203 }
204
205
206
207 if (nb == 0) {
208 pref = ext2fs_blkpref(ip, lbn, indirs[num].in_off, &bap[0]);
209 error = ext2fs_alloc(ip, lbn, pref, cred, &newb);
210 if (error) {
211 brelse(bp);
212 goto fail;
213 }
214 nb = newb;
215 *allocblk++ = nb;
216 ip->i_e2fs_last_lblk = lbn;
217 ip->i_e2fs_last_blk = newb;
218 bap[indirs[num].in_off] = h2fs32(nb);
219
220
221
222
223 if (flags & B_SYNC) {
224 bwrite(bp);
225 } else {
226 bdwrite(bp);
227 }
228 nbp = getblk(vp, lbn, fs->e2fs_bsize, 0, 0);
229 nbp->b_blkno = fsbtodb(fs, nb);
230 if (flags & B_CLRBUF)
231 clrbuf(nbp);
232 *bpp = nbp;
233 return (0);
234 }
235 brelse(bp);
236 if (flags & B_CLRBUF) {
237 error = bread(vp, lbn, (int)fs->e2fs_bsize, NOCRED, &nbp);
238 if (error) {
239 brelse(nbp);
240 goto fail;
241 }
242 } else {
243 nbp = getblk(vp, lbn, fs->e2fs_bsize, 0, 0);
244 nbp->b_blkno = fsbtodb(fs, nb);
245 }
246
247 *bpp = nbp;
248 return (0);
249 fail:
250
251
252
253
254 for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) {
255 ext2fs_blkfree(ip, *blkp);
256 deallocated += fs->e2fs_bsize;
257 }
258 if (unwindidx >= 0) {
259 if (unwindidx == 0) {
260 *allocib = 0;
261 } else {
262 int r;
263
264 r = bread(vp, indirs[unwindidx].in_lbn,
265 (int)fs->e2fs_bsize, NOCRED, &bp);
266 if (r) {
267 panic("Could not unwind indirect block, error %d", r);
268 brelse(bp);
269 } else {
270 bap = (int32_t *)bp->b_data;
271 bap[indirs[unwindidx].in_off] = 0;
272 if (flags & B_SYNC)
273 bwrite(bp);
274 else
275 bdwrite(bp);
276 }
277 }
278 for (i = unwindidx + 1; i <= num; i++) {
279 bp = getblk(vp, indirs[i].in_lbn, (int)fs->e2fs_bsize,
280 0, 0);
281 bp->b_flags |= B_INVAL;
282 brelse(bp);
283 }
284 }
285 if (deallocated) {
286 ip->i_e2fs_nblock -= btodb(deallocated);
287 ip->i_e2fs_flags |= IN_CHANGE | IN_UPDATE;
288 }
289 return error;
290 }