ext2_balloc.c (153110) | ext2_balloc.c (202283) |
---|---|
1/*- 2 * modified for Lites 1.1 3 * 4 * Aug 1995, Godmar Back (gback@cs.utah.edu) 5 * University of Utah, Department of Computer Science 6 */ 7/*- 8 * Copyright (c) 1982, 1986, 1989, 1993 --- 19 unchanged lines hidden (view full) --- 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)ffs_balloc.c 8.4 (Berkeley) 9/23/93 | 1/*- 2 * modified for Lites 1.1 3 * 4 * Aug 1995, Godmar Back (gback@cs.utah.edu) 5 * University of Utah, Department of Computer Science 6 */ 7/*- 8 * Copyright (c) 1982, 1986, 1989, 1993 --- 19 unchanged lines hidden (view full) --- 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)ffs_balloc.c 8.4 (Berkeley) 9/23/93 |
36 * $FreeBSD: head/sys/gnu/fs/ext2fs/ext2_balloc.c 153110 2005-12-05 11:58:35Z ru $ | 36 * $FreeBSD: head/sys/fs/ext2fs/ext2_balloc.c 202283 2010-01-14 14:30:54Z lulf $ |
37 */ 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/bio.h> 42#include <sys/buf.h> 43#include <sys/lock.h> 44#include <sys/ucred.h> 45#include <sys/vnode.h> 46 | 37 */ 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/bio.h> 42#include <sys/buf.h> 43#include <sys/lock.h> 44#include <sys/ucred.h> 45#include <sys/vnode.h> 46 |
47#include <gnu/fs/ext2fs/inode.h> 48#include <gnu/fs/ext2fs/ext2_fs.h> 49#include <gnu/fs/ext2fs/ext2_fs_sb.h> 50#include <gnu/fs/ext2fs/fs.h> 51#include <gnu/fs/ext2fs/ext2_extern.h> 52 | 47#include 48#include <fs/ext2fs/ext2fs.h> 49#include <fs/ext2fs/fs.h> 50#include <fs/ext2fs/ext2_extern.h> 51#include <fs/ext2fs/ext2_mount.h> |
53/* 54 * Balloc defines the structure of file system storage 55 * by allocating the physical blocks on a device given 56 * the inode and the logical block number in a file. 57 */ 58int | 52/* 53 * Balloc defines the structure of file system storage 54 * by allocating the physical blocks on a device given 55 * the inode and the logical block number in a file. 56 */ 57int |
59ext2_balloc(ip, bn, size, cred, bpp, flags) | 58ext2_balloc(ip, lbn, size, cred, bpp, flags) |
60 struct inode *ip; | 59 struct inode *ip; |
61 int32_t bn; | 60 int32_t lbn; |
62 int size; 63 struct ucred *cred; 64 struct buf **bpp; 65 int flags; 66{ | 61 int size; 62 struct ucred *cred; 63 struct buf **bpp; 64 int flags; 65{ |
67 struct ext2_sb_info *fs; | 66 struct m_ext2fs *fs; 67 struct ext2mount *ump; |
68 int32_t nb; 69 struct buf *bp, *nbp; 70 struct vnode *vp = ITOV(ip); 71 struct indir indirs[NIADDR + 2]; | 68 int32_t nb; 69 struct buf *bp, *nbp; 70 struct vnode *vp = ITOV(ip); 71 struct indir indirs[NIADDR + 2]; |
72 int32_t newb, lbn, *bap, pref; | 72 int32_t newb, *bap, pref; |
73 int osize, nsize, num, i, error; | 73 int osize, nsize, num, i, error; |
74/* 75ext2_debug("ext2_balloc called (%d, %d, %d)\n", 76 ip->i_number, (int)bn, (int)size); 77*/ | 74 |
78 *bpp = NULL; | 75 *bpp = NULL; |
79 if (bn < 0) | 76 if (lbn < 0) |
80 return (EFBIG); 81 fs = ip->i_e2fs; | 77 return (EFBIG); 78 fs = ip->i_e2fs; |
82 lbn = bn; | 79 ump = ip->i_ump; |
83 84 /* 85 * check if this is a sequential block allocation. 86 * If so, increment next_alloc fields to allow ext2_blkpref 87 * to make a good guess 88 */ 89 if (lbn == ip->i_next_alloc_block + 1) { 90 ip->i_next_alloc_block++; 91 ip->i_next_alloc_goal++; 92 } 93 94 /* 95 * The first NDADDR blocks are direct blocks 96 */ | 80 81 /* 82 * check if this is a sequential block allocation. 83 * If so, increment next_alloc fields to allow ext2_blkpref 84 * to make a good guess 85 */ 86 if (lbn == ip->i_next_alloc_block + 1) { 87 ip->i_next_alloc_block++; 88 ip->i_next_alloc_goal++; 89 } 90 91 /* 92 * The first NDADDR blocks are direct blocks 93 */ |
97 if (bn < NDADDR) { 98 nb = ip->i_db[bn]; | 94 if (lbn < NDADDR) { 95 nb = ip->i_db[lbn]; |
99 /* no new block is to be allocated, and no need to expand 100 the file */ | 96 /* no new block is to be allocated, and no need to expand 97 the file */ |
101 if (nb != 0 && ip->i_size >= (bn + 1) * fs->s_blocksize) { 102 error = bread(vp, bn, fs->s_blocksize, NOCRED, &bp); | 98 if (nb != 0 && ip->i_size >= (lbn + 1) * fs->e2fs_bsize) { 99 error = bread(vp, lbn, fs->e2fs_bsize, NOCRED, &bp); |
103 if (error) { 104 brelse(bp); 105 return (error); 106 } 107 bp->b_blkno = fsbtodb(fs, nb); 108 *bpp = bp; 109 return (0); 110 } 111 if (nb != 0) { 112 /* 113 * Consider need to reallocate a fragment. 114 */ 115 osize = fragroundup(fs, blkoff(fs, ip->i_size)); 116 nsize = fragroundup(fs, size); 117 if (nsize <= osize) { | 100 if (error) { 101 brelse(bp); 102 return (error); 103 } 104 bp->b_blkno = fsbtodb(fs, nb); 105 *bpp = bp; 106 return (0); 107 } 108 if (nb != 0) { 109 /* 110 * Consider need to reallocate a fragment. 111 */ 112 osize = fragroundup(fs, blkoff(fs, ip->i_size)); 113 nsize = fragroundup(fs, size); 114 if (nsize <= osize) { |
118 error = bread(vp, bn, osize, NOCRED, &bp); | 115 error = bread(vp, lbn, osize, NOCRED, &bp); |
119 if (error) { 120 brelse(bp); 121 return (error); 122 } 123 bp->b_blkno = fsbtodb(fs, nb); 124 } else { 125 /* Godmar thinks: this shouldn't happen w/o fragments */ 126 printf("nsize %d(%d) > osize %d(%d) nb %d\n", 127 (int)nsize, (int)size, (int)osize, 128 (int)ip->i_size, (int)nb); 129 panic( 130 "ext2_balloc: Something is terribly wrong"); 131/* 132 * please note there haven't been any changes from here on - 133 * FFS seems to work. 134 */ 135 } 136 } else { | 116 if (error) { 117 brelse(bp); 118 return (error); 119 } 120 bp->b_blkno = fsbtodb(fs, nb); 121 } else { 122 /* Godmar thinks: this shouldn't happen w/o fragments */ 123 printf("nsize %d(%d) > osize %d(%d) nb %d\n", 124 (int)nsize, (int)size, (int)osize, 125 (int)ip->i_size, (int)nb); 126 panic( 127 "ext2_balloc: Something is terribly wrong"); 128/* 129 * please note there haven't been any changes from here on - 130 * FFS seems to work. 131 */ 132 } 133 } else { |
137 if (ip->i_size < (bn + 1) * fs->s_blocksize) | 134 if (ip->i_size < (lbn + 1) * fs->e2fs_bsize) |
138 nsize = fragroundup(fs, size); 139 else | 135 nsize = fragroundup(fs, size); 136 else |
140 nsize = fs->s_blocksize; 141 error = ext2_alloc(ip, bn, 142 ext2_blkpref(ip, bn, (int)bn, &ip->i_db[0], 0), | 137 nsize = fs->e2fs_bsize; 138 EXT2_LOCK(ump); 139 error = ext2_alloc(ip, lbn, 140 ext2_blkpref(ip, lbn, (int)lbn, &ip->i_db[0], 0), |
143 nsize, cred, &newb); 144 if (error) 145 return (error); | 141 nsize, cred, &newb); 142 if (error) 143 return (error); |
146 bp = getblk(vp, bn, nsize, 0, 0, 0); | 144 bp = getblk(vp, lbn, nsize, 0, 0, 0); |
147 bp->b_blkno = fsbtodb(fs, newb); 148 if (flags & B_CLRBUF) 149 vfs_bio_clrbuf(bp); 150 } | 145 bp->b_blkno = fsbtodb(fs, newb); 146 if (flags & B_CLRBUF) 147 vfs_bio_clrbuf(bp); 148 } |
151 ip->i_db[bn] = dbtofsb(fs, bp->b_blkno); | 149 ip->i_db[lbn] = dbtofsb(fs, bp->b_blkno); |
152 ip->i_flag |= IN_CHANGE | IN_UPDATE; 153 *bpp = bp; 154 return (0); 155 } 156 /* 157 * Determine the number of levels of indirection. 158 */ 159 pref = 0; | 150 ip->i_flag |= IN_CHANGE | IN_UPDATE; 151 *bpp = bp; 152 return (0); 153 } 154 /* 155 * Determine the number of levels of indirection. 156 */ 157 pref = 0; |
160 if ((error = ext2_getlbns(vp, bn, indirs, &num)) != 0) | 158 if ((error = ext2_getlbns(vp, lbn, indirs, &num)) != 0) |
161 return(error); 162#ifdef DIAGNOSTIC 163 if (num < 1) 164 panic ("ext2_balloc: ext2_getlbns returned indirect block"); 165#endif 166 /* 167 * Fetch the first indirect block allocating if necessary. 168 */ 169 --num; 170 nb = ip->i_ib[indirs[0].in_off]; 171 if (nb == 0) { | 159 return(error); 160#ifdef DIAGNOSTIC 161 if (num < 1) 162 panic ("ext2_balloc: ext2_getlbns returned indirect block"); 163#endif 164 /* 165 * Fetch the first indirect block allocating if necessary. 166 */ 167 --num; 168 nb = ip->i_ib[indirs[0].in_off]; 169 if (nb == 0) { |
172#if 0 173 pref = ext2_blkpref(ip, lbn, 0, (int32_t *)0, 0); 174#else 175 /* see the comment by ext2_blkpref. What we do here is 176 to pretend that it'd be good for a block holding indirect 177 pointers to be allocated near its predecessor in terms 178 of indirection, or the last direct block. 179 We shamelessly exploit the fact that i_ib immediately 180 follows i_db. 181 Godmar thinks it make sense to allocate i_ib[0] immediately 182 after i_db[11], but it's not utterly clear whether this also 183 applies to i_ib[1] and i_ib[0] 184 */ 185 | 170 EXT2_LOCK(ump); |
186 pref = ext2_blkpref(ip, lbn, indirs[0].in_off + 187 EXT2_NDIR_BLOCKS, &ip->i_db[0], 0); | 171 pref = ext2_blkpref(ip, lbn, indirs[0].in_off + 172 EXT2_NDIR_BLOCKS, &ip->i_db[0], 0); |
188#endif 189 if ((error = ext2_alloc(ip, lbn, pref, (int)fs->s_blocksize, 190 cred, &newb)) != 0) | 173 if ((error = ext2_alloc(ip, lbn, pref, 174 (int)fs->e2fs_bsize, cred, &newb))) |
191 return (error); 192 nb = newb; | 175 return (error); 176 nb = newb; |
193 bp = getblk(vp, indirs[1].in_lbn, fs->s_blocksize, 0, 0, 0); | 177 bp = getblk(vp, indirs[1].in_lbn, fs->e2fs_bsize, 0, 0, 0); |
194 bp->b_blkno = fsbtodb(fs, newb); 195 vfs_bio_clrbuf(bp); 196 /* 197 * Write synchronously so that indirect blocks 198 * never point at garbage. 199 */ 200 if ((error = bwrite(bp)) != 0) { | 178 bp->b_blkno = fsbtodb(fs, newb); 179 vfs_bio_clrbuf(bp); 180 /* 181 * Write synchronously so that indirect blocks 182 * never point at garbage. 183 */ 184 if ((error = bwrite(bp)) != 0) { |
201 ext2_blkfree(ip, nb, fs->s_blocksize); | 185 ext2_blkfree(ip, nb, fs->e2fs_bsize); |
202 return (error); 203 } 204 ip->i_ib[indirs[0].in_off] = newb; 205 ip->i_flag |= IN_CHANGE | IN_UPDATE; 206 } 207 /* 208 * Fetch through the indirect blocks, allocating as necessary. 209 */ 210 for (i = 1;;) { 211 error = bread(vp, | 186 return (error); 187 } 188 ip->i_ib[indirs[0].in_off] = newb; 189 ip->i_flag |= IN_CHANGE | IN_UPDATE; 190 } 191 /* 192 * Fetch through the indirect blocks, allocating as necessary. 193 */ 194 for (i = 1;;) { 195 error = bread(vp, |
212 indirs[i].in_lbn, (int)fs->s_blocksize, NOCRED, &bp); | 196 indirs[i].in_lbn, (int)fs->e2fs_bsize, NOCRED, &bp); |
213 if (error) { 214 brelse(bp); 215 return (error); 216 } 217 bap = (int32_t *)bp->b_data; 218 nb = bap[indirs[i].in_off]; 219 if (i == num) 220 break; 221 i += 1; 222 if (nb != 0) { | 197 if (error) { 198 brelse(bp); 199 return (error); 200 } 201 bap = (int32_t *)bp->b_data; 202 nb = bap[indirs[i].in_off]; 203 if (i == num) 204 break; 205 i += 1; 206 if (nb != 0) { |
223 brelse(bp); | 207 bqrelse(bp); |
224 continue; 225 } | 208 continue; 209 } |
226 if (pref == 0) 227#if 1 228 /* see the comment above and by ext2_blkpref 229 * I think this implements Linux policy, but 230 * does it really make sense to allocate to 231 * block containing pointers together ? 232 * Also, will it ever succeed ? 233 */ | 210 EXT2_LOCK(ump); 211 if (pref == 0) |
234 pref = ext2_blkpref(ip, lbn, indirs[i].in_off, bap, 235 bp->b_lblkno); | 212 pref = ext2_blkpref(ip, lbn, indirs[i].in_off, bap, 213 bp->b_lblkno); |
236#else 237 pref = ext2_blkpref(ip, lbn, 0, (int32_t *)0, 0); 238#endif 239 if ((error = 240 ext2_alloc(ip, lbn, pref, (int)fs->s_blocksize, cred, &newb)) != 0) { | 214 error = ext2_alloc(ip, lbn, pref, (int)fs->e2fs_bsize, cred, &newb); 215 if (error) { |
241 brelse(bp); 242 return (error); 243 } 244 nb = newb; | 216 brelse(bp); 217 return (error); 218 } 219 nb = newb; |
245 nbp = getblk(vp, indirs[i].in_lbn, fs->s_blocksize, 0, 0, 0); | 220 nbp = getblk(vp, indirs[i].in_lbn, fs->e2fs_bsize, 0, 0, 0); |
246 nbp->b_blkno = fsbtodb(fs, nb); 247 vfs_bio_clrbuf(nbp); 248 /* 249 * Write synchronously so that indirect blocks 250 * never point at garbage. 251 */ 252 if ((error = bwrite(nbp)) != 0) { | 221 nbp->b_blkno = fsbtodb(fs, nb); 222 vfs_bio_clrbuf(nbp); 223 /* 224 * Write synchronously so that indirect blocks 225 * never point at garbage. 226 */ 227 if ((error = bwrite(nbp)) != 0) { |
253 ext2_blkfree(ip, nb, fs->s_blocksize); | 228 ext2_blkfree(ip, nb, fs->e2fs_bsize); 229 EXT2_UNLOCK(ump); |
254 brelse(bp); 255 return (error); 256 } 257 bap[indirs[i - 1].in_off] = nb; 258 /* 259 * If required, write synchronously, otherwise use 260 * delayed write. 261 */ 262 if (flags & B_SYNC) { 263 bwrite(bp); 264 } else { | 230 brelse(bp); 231 return (error); 232 } 233 bap[indirs[i - 1].in_off] = nb; 234 /* 235 * If required, write synchronously, otherwise use 236 * delayed write. 237 */ 238 if (flags & B_SYNC) { 239 bwrite(bp); 240 } else { |
241 if (bp->b_bufsize == fs->e2fs_bsize) 242 bp->b_flags |= B_CLUSTEROK; |
|
265 bdwrite(bp); 266 } 267 } 268 /* 269 * Get the data block, allocating if necessary. 270 */ 271 if (nb == 0) { | 243 bdwrite(bp); 244 } 245 } 246 /* 247 * Get the data block, allocating if necessary. 248 */ 249 if (nb == 0) { |
250 EXT2_LOCK(ump); |
|
272 pref = ext2_blkpref(ip, lbn, indirs[i].in_off, &bap[0], 273 bp->b_lblkno); 274 if ((error = ext2_alloc(ip, | 251 pref = ext2_blkpref(ip, lbn, indirs[i].in_off, &bap[0], 252 bp->b_lblkno); 253 if ((error = ext2_alloc(ip, |
275 lbn, pref, (int)fs->s_blocksize, cred, &newb)) != 0) { | 254 lbn, pref, (int)fs->e2fs_bsize, cred, &newb)) != 0) { |
276 brelse(bp); 277 return (error); 278 } 279 nb = newb; | 255 brelse(bp); 256 return (error); 257 } 258 nb = newb; |
280 nbp = getblk(vp, lbn, fs->s_blocksize, 0, 0, 0); | 259 nbp = getblk(vp, lbn, fs->e2fs_bsize, 0, 0, 0); |
281 nbp->b_blkno = fsbtodb(fs, nb); 282 if (flags & B_CLRBUF) 283 vfs_bio_clrbuf(nbp); 284 bap[indirs[i].in_off] = nb; 285 /* 286 * If required, write synchronously, otherwise use 287 * delayed write. 288 */ 289 if (flags & B_SYNC) { 290 bwrite(bp); 291 } else { | 260 nbp->b_blkno = fsbtodb(fs, nb); 261 if (flags & B_CLRBUF) 262 vfs_bio_clrbuf(nbp); 263 bap[indirs[i].in_off] = nb; 264 /* 265 * If required, write synchronously, otherwise use 266 * delayed write. 267 */ 268 if (flags & B_SYNC) { 269 bwrite(bp); 270 } else { |
271 if (bp->b_bufsize == fs->e2fs_bsize) 272 bp->b_flags |= B_CLUSTEROK; |
|
292 bdwrite(bp); 293 } 294 *bpp = nbp; 295 return (0); 296 } 297 brelse(bp); 298 if (flags & B_CLRBUF) { | 273 bdwrite(bp); 274 } 275 *bpp = nbp; 276 return (0); 277 } 278 brelse(bp); 279 if (flags & B_CLRBUF) { |
299 error = bread(vp, lbn, (int)fs->s_blocksize, NOCRED, &nbp); | 280 error = bread(vp, lbn, (int)fs->e2fs_bsize, NOCRED, &nbp); |
300 if (error) { 301 brelse(nbp); 302 return (error); 303 } 304 } else { | 281 if (error) { 282 brelse(nbp); 283 return (error); 284 } 285 } else { |
305 nbp = getblk(vp, lbn, fs->s_blocksize, 0, 0, 0); | 286 nbp = getblk(vp, lbn, fs->e2fs_bsize, 0, 0, 0); |
306 nbp->b_blkno = fsbtodb(fs, nb); 307 } 308 *bpp = nbp; 309 return (0); 310} | 287 nbp->b_blkno = fsbtodb(fs, nb); 288 } 289 *bpp = nbp; 290 return (0); 291} |
292 |
|