Deleted Added
full compact
msdosfs_fat.c (33181) msdosfs_fat.c (33548)
1/* $Id: msdosfs_fat.c,v 1.15 1998/02/06 12:13:46 eivind Exp $ */
2/* $NetBSD: msdosfs_fat.c,v 1.12 1994/08/21 18:44:04 ws Exp $ */
1/* $Id: msdosfs_fat.c,v 1.16 1998/02/09 06:09:52 eivind Exp $ */
2/* $NetBSD: msdosfs_fat.c,v 1.28 1997/11/17 15:36:49 ws Exp $ */
3
4/*-
3
4/*-
5 * Copyright (C) 1994 Wolfgang Solfrank.
6 * Copyright (C) 1994 TooLs GmbH.
5 * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
6 * Copyright (C) 1994, 1995, 1997 TooLs GmbH.
7 * All rights reserved.
8 * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below).
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.

--- 36 unchanged lines hidden (view full) ---

51/*
52 * kernel include files.
53 */
54#include <sys/param.h>
55#include <sys/systm.h>
56#include <sys/buf.h>
57#include <sys/mount.h> /* to define statfs structure */
58#include <sys/vnode.h> /* to define vattr structure */
7 * All rights reserved.
8 * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below).
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.

--- 36 unchanged lines hidden (view full) ---

51/*
52 * kernel include files.
53 */
54#include <sys/param.h>
55#include <sys/systm.h>
56#include <sys/buf.h>
57#include <sys/mount.h> /* to define statfs structure */
58#include <sys/vnode.h> /* to define vattr structure */
59#include <sys/errno.h>
59
60/*
61 * msdosfs include files.
62 */
63#include <msdosfs/bpb.h>
64#include <msdosfs/msdosfsmount.h>
65#include <msdosfs/direntry.h>
66#include <msdosfs/denode.h>

--- 7 unchanged lines hidden (view full) ---

74 * was empty */
75static int fc_bmapcalls; /* # of times pcbmap was called */
76
77#define LMMAX 20
78static int fc_lmdistance[LMMAX];/* counters for how far off the last
79 * cluster mapped entry was. */
80static int fc_largedistance; /* off by more than LMMAX */
81
60
61/*
62 * msdosfs include files.
63 */
64#include <msdosfs/bpb.h>
65#include <msdosfs/msdosfsmount.h>
66#include <msdosfs/direntry.h>
67#include <msdosfs/denode.h>

--- 7 unchanged lines hidden (view full) ---

75 * was empty */
76static int fc_bmapcalls; /* # of times pcbmap was called */
77
78#define LMMAX 20
79static int fc_lmdistance[LMMAX];/* counters for how far off the last
80 * cluster mapped entry was. */
81static int fc_largedistance; /* off by more than LMMAX */
82
82/* Byte offset in FAT on filesystem pmp, cluster cn */
83#define FATOFS(pmp, cn) (FAT12(pmp) ? (cn) * 3 / 2 : (cn) * 2)
84
85static int chainalloc __P((struct msdosfsmount *pmp, u_long start,
86 u_long count, u_long fillwith,
87 u_long *retcluster, u_long *got));
88static int chainlength __P((struct msdosfsmount *pmp, u_long start,
89 u_long count));
90static void fatblock __P((struct msdosfsmount *pmp, u_long ofs,
91 u_long *bnp, u_long *sizep, u_long *bop));
92static int fatchain __P((struct msdosfsmount *pmp, u_long start,

--- 13 unchanged lines hidden (view full) ---

106 u_long *sizep;
107 u_long *bop;
108{
109 u_long bn, size;
110
111 bn = ofs / pmp->pm_fatblocksize * pmp->pm_fatblocksec;
112 size = min(pmp->pm_fatblocksec, pmp->pm_FATsecs - bn)
113 * pmp->pm_BytesPerSec;
83static int chainalloc __P((struct msdosfsmount *pmp, u_long start,
84 u_long count, u_long fillwith,
85 u_long *retcluster, u_long *got));
86static int chainlength __P((struct msdosfsmount *pmp, u_long start,
87 u_long count));
88static void fatblock __P((struct msdosfsmount *pmp, u_long ofs,
89 u_long *bnp, u_long *sizep, u_long *bop));
90static int fatchain __P((struct msdosfsmount *pmp, u_long start,

--- 13 unchanged lines hidden (view full) ---

104 u_long *sizep;
105 u_long *bop;
106{
107 u_long bn, size;
108
109 bn = ofs / pmp->pm_fatblocksize * pmp->pm_fatblocksec;
110 size = min(pmp->pm_fatblocksec, pmp->pm_FATsecs - bn)
111 * pmp->pm_BytesPerSec;
114 bn += pmp->pm_fatblk;
112 bn += pmp->pm_fatblk + pmp->pm_curfat * pmp->pm_FATsecs;
113
115 if (bnp)
116 *bnp = bn;
117 if (sizep)
118 *sizep = size;
119 if (bop)
120 *bop = ofs % pmp->pm_fatblocksize;
121}
122

--- 11 unchanged lines hidden (view full) ---

134 *
135 * NOTE: Either bnp or cnp must be non-null.
136 * This function has one side effect. If the requested file relative cluster
137 * is beyond the end of file, then the actual number of clusters in the file
138 * is returned in *cnp. This is useful for determining how long a directory is.
139 * If cnp is null, nothing is returned.
140 */
141int
114 if (bnp)
115 *bnp = bn;
116 if (sizep)
117 *sizep = size;
118 if (bop)
119 *bop = ofs % pmp->pm_fatblocksize;
120}
121

--- 11 unchanged lines hidden (view full) ---

133 *
134 * NOTE: Either bnp or cnp must be non-null.
135 * This function has one side effect. If the requested file relative cluster
136 * is beyond the end of file, then the actual number of clusters in the file
137 * is returned in *cnp. This is useful for determining how long a directory is.
138 * If cnp is null, nothing is returned.
139 */
140int
142pcbmap(dep, findcn, bnp, cnp)
141pcbmap(dep, findcn, bnp, cnp, sp)
143 struct denode *dep;
144 u_long findcn; /* file relative cluster to get */
145 daddr_t *bnp; /* returned filesys relative blk number */
146 u_long *cnp; /* returned cluster number */
142 struct denode *dep;
143 u_long findcn; /* file relative cluster to get */
144 daddr_t *bnp; /* returned filesys relative blk number */
145 u_long *cnp; /* returned cluster number */
146 int *sp; /* returned block size */
147{
148 int error;
149 u_long i;
150 u_long cn;
147{
148 int error;
149 u_long i;
150 u_long cn;
151 u_long prevcn;
151 u_long prevcn = 0; /* XXX: prevcn could be used unititialized */
152 u_long byteoffset;
153 u_long bn;
154 u_long bo;
155 struct buf *bp = NULL;
156 u_long bp_bn = -1;
157 struct msdosfsmount *pmp = dep->de_pmp;
158 u_long bsize;
152 u_long byteoffset;
153 u_long bn;
154 u_long bo;
155 struct buf *bp = NULL;
156 u_long bp_bn = -1;
157 struct msdosfsmount *pmp = dep->de_pmp;
158 u_long bsize;
159 int fat12 = FAT12(pmp); /* 12 bit fat */
160
161 fc_bmapcalls++;
162
163 /*
164 * If they don't give us someplace to return a value then don't
165 * bother doing anything.
166 */
159
160 fc_bmapcalls++;
161
162 /*
163 * If they don't give us someplace to return a value then don't
164 * bother doing anything.
165 */
167 if (bnp == NULL && cnp == NULL)
168 return 0;
166 if (bnp == NULL && cnp == NULL && sp == NULL)
167 return (0);
169
170 cn = dep->de_StartCluster;
171 /*
172 * The "file" that makes up the root directory is contiguous,
173 * permanently allocated, of fixed size, and is not made up of
174 * clusters. If the cluster number is beyond the end of the root
175 * directory, then return the number of clusters in the file.
176 */
177 if (cn == MSDOSFSROOT) {
178 if (dep->de_Attributes & ATTR_DIRECTORY) {
168
169 cn = dep->de_StartCluster;
170 /*
171 * The "file" that makes up the root directory is contiguous,
172 * permanently allocated, of fixed size, and is not made up of
173 * clusters. If the cluster number is beyond the end of the root
174 * directory, then return the number of clusters in the file.
175 */
176 if (cn == MSDOSFSROOT) {
177 if (dep->de_Attributes & ATTR_DIRECTORY) {
179 if (findcn * pmp->pm_SectPerClust >= pmp->pm_rootdirsize) {
178 if (de_cn2off(pmp, findcn) >= dep->de_FileSize) {
180 if (cnp)
179 if (cnp)
181 *cnp = pmp->pm_rootdirsize / pmp->pm_SectPerClust;
182 return E2BIG;
180 *cnp = de_bn2cn(pmp, pmp->pm_rootdirsize);
181 return (E2BIG);
183 }
184 if (bnp)
182 }
183 if (bnp)
185 *bnp = pmp->pm_rootdirblk + (findcn * pmp->pm_SectPerClust);
184 *bnp = pmp->pm_rootdirblk + de_cn2bn(pmp, findcn);
186 if (cnp)
187 *cnp = MSDOSFSROOT;
185 if (cnp)
186 *cnp = MSDOSFSROOT;
188 return 0;
187 if (sp)
188 *sp = min(pmp->pm_bpcluster,
189 dep->de_FileSize - de_cn2off(pmp, findcn));
190 return (0);
189 } else { /* just an empty file */
190 if (cnp)
191 *cnp = 0;
191 } else { /* just an empty file */
192 if (cnp)
193 *cnp = 0;
192 return E2BIG;
194 return (E2BIG);
193 }
194 }
195
196 /*
195 }
196 }
197
198 /*
199 * All other files do I/O in cluster sized blocks
200 */
201 if (sp)
202 *sp = pmp->pm_bpcluster;
203
204 /*
197 * Rummage around in the fat cache, maybe we can avoid tromping
198 * thru every fat entry for the file. And, keep track of how far
199 * off the cache was from where we wanted to be.
200 */
201 i = 0;
202 fc_lookup(dep, findcn, &i, &cn);
203 if ((bn = findcn - i) >= LMMAX)
204 fc_largedistance++;
205 else
206 fc_lmdistance[bn]++;
207
208 /*
209 * Handle all other files or directories the normal way.
210 */
205 * Rummage around in the fat cache, maybe we can avoid tromping
206 * thru every fat entry for the file. And, keep track of how far
207 * off the cache was from where we wanted to be.
208 */
209 i = 0;
210 fc_lookup(dep, findcn, &i, &cn);
211 if ((bn = findcn - i) >= LMMAX)
212 fc_largedistance++;
213 else
214 fc_lmdistance[bn]++;
215
216 /*
217 * Handle all other files or directories the normal way.
218 */
211 prevcn = 0;
212 for (; i < findcn; i++) {
219 for (; i < findcn; i++) {
213 if (MSDOSFSEOF(cn))
220 /*
221 * Stop with all reserved clusters, not just with EOF.
222 */
223 if ((cn | ~pmp->pm_fatmask) >= CLUST_RSRVD)
214 goto hiteof;
215 byteoffset = FATOFS(pmp, cn);
216 fatblock(pmp, byteoffset, &bn, &bsize, &bo);
217 if (bn != bp_bn) {
218 if (bp)
219 brelse(bp);
220 error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
224 goto hiteof;
225 byteoffset = FATOFS(pmp, cn);
226 fatblock(pmp, byteoffset, &bn, &bsize, &bo);
227 if (bn != bp_bn) {
228 if (bp)
229 brelse(bp);
230 error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
221 if (error)
222 return error;
231 if (error) {
232 brelse(bp);
233 return (error);
234 }
223 bp_bn = bn;
224 }
225 prevcn = cn;
235 bp_bn = bn;
236 }
237 prevcn = cn;
226 cn = getushort(&bp->b_data[bo]);
227 if (fat12) {
228 if (prevcn & 1)
229 cn >>= 4;
230 cn &= 0x0fff;
231 /*
232 * Force the special cluster numbers in the range
233 * 0x0ff0-0x0fff to be the same as for 16 bit
234 * cluster numbers to let the rest of msdosfs think
235 * it is always dealing with 16 bit fats.
236 */
237 if ((cn & 0x0ff0) == 0x0ff0)
238 cn |= 0xf000;
239 }
238 if (FAT32(pmp))
239 cn = getulong(&bp->b_data[bo]);
240 else
241 cn = getushort(&bp->b_data[bo]);
242 if (FAT12(pmp) && (prevcn & 1))
243 cn >>= 4;
244 cn &= pmp->pm_fatmask;
245
246 /*
247 * Force the special cluster numbers
248 * to be the same for all cluster sizes
249 * to let the rest of msdosfs handle
250 * all cases the same.
251 */
252 if ((cn | ~pmp->pm_fatmask) >= CLUST_RSRVD)
253 cn |= ~pmp->pm_fatmask;
240 }
241
254 }
255
242 if (!MSDOSFSEOF(cn)) {
256 if (!MSDOSFSEOF(pmp, cn)) {
243 if (bp)
244 brelse(bp);
245 if (bnp)
246 *bnp = cntobn(pmp, cn);
247 if (cnp)
248 *cnp = cn;
249 fc_setcache(dep, FC_LASTMAP, i, cn);
257 if (bp)
258 brelse(bp);
259 if (bnp)
260 *bnp = cntobn(pmp, cn);
261 if (cnp)
262 *cnp = cn;
263 fc_setcache(dep, FC_LASTMAP, i, cn);
250 return 0;
264 return (0);
251 }
252
253hiteof:;
254 if (cnp)
255 *cnp = i;
256 if (bp)
257 brelse(bp);
258 /* update last file cluster entry in the fat cache */
259 fc_setcache(dep, FC_LASTFC, i - 1, prevcn);
265 }
266
267hiteof:;
268 if (cnp)
269 *cnp = i;
270 if (bp)
271 brelse(bp);
272 /* update last file cluster entry in the fat cache */
273 fc_setcache(dep, FC_LASTFC, i - 1, prevcn);
260 return E2BIG;
274 return (E2BIG);
261}
262
263/*
264 * Find the closest entry in the fat cache to the cluster we are looking
265 * for.
266 */
267static void
268fc_lookup(dep, findcn, frcnp, fsrcnp)

--- 18 unchanged lines hidden (view full) ---

287 *fsrcnp = closest->fc_fsrcn;
288 }
289}
290
291/*
292 * Purge the fat cache in denode dep of all entries relating to file
293 * relative cluster frcn and beyond.
294 */
275}
276
277/*
278 * Find the closest entry in the fat cache to the cluster we are looking
279 * for.
280 */
281static void
282fc_lookup(dep, findcn, frcnp, fsrcnp)

--- 18 unchanged lines hidden (view full) ---

301 *fsrcnp = closest->fc_fsrcn;
302 }
303}
304
305/*
306 * Purge the fat cache in denode dep of all entries relating to file
307 * relative cluster frcn and beyond.
308 */
295void fc_purge(dep, frcn)
309void
310fc_purge(dep, frcn)
296 struct denode *dep;
297 u_int frcn;
298{
299 int i;
300 struct fatcache *fcp;
301
302 fcp = dep->de_fc;
303 for (i = 0; i < FC_SIZE; i++, fcp++) {
304 if (fcp->fc_frcn >= frcn)
305 fcp->fc_frcn = FCE_EMPTY;
306 }
307}
308
309/*
311 struct denode *dep;
312 u_int frcn;
313{
314 int i;
315 struct fatcache *fcp;
316
317 fcp = dep->de_fc;
318 for (i = 0; i < FC_SIZE; i++, fcp++) {
319 if (fcp->fc_frcn >= frcn)
320 fcp->fc_frcn = FCE_EMPTY;
321 }
322}
323
324/*
310 * Update all copies of the fat. The first copy is updated last.
325 * Update the fat.
326 * If mirroring the fat, update all copies, with the first copy as last.
327 * Else update only the current fat (ignoring the others).
311 *
312 * pmp - msdosfsmount structure for filesystem to update
313 * bp - addr of modified fat block
314 * fatbn - block number relative to begin of filesystem of the modified fat block.
315 */
316static void
317updatefats(pmp, bp, fatbn)
318 struct msdosfsmount *pmp;
319 struct buf *bp;
320 u_long fatbn;
321{
322 int i;
323 struct buf *bpn;
324
325#ifdef MSDOSFS_DEBUG
328 *
329 * pmp - msdosfsmount structure for filesystem to update
330 * bp - addr of modified fat block
331 * fatbn - block number relative to begin of filesystem of the modified fat block.
332 */
333static void
334updatefats(pmp, bp, fatbn)
335 struct msdosfsmount *pmp;
336 struct buf *bp;
337 u_long fatbn;
338{
339 int i;
340 struct buf *bpn;
341
342#ifdef MSDOSFS_DEBUG
326 printf("updatefats(pmp %p, bp %p, fatbn %ld)\n", pmp, bp, fatbn);
343 printf("updatefats(pmp %p, bp %p, fatbn %lu)\n", pmp, bp, fatbn);
327#endif
328
329 /*
344#endif
345
346 /*
330 * Now copy the block(s) of the modified fat to the other copies of
331 * the fat and write them out. This is faster than reading in the
332 * other fats and then writing them back out. This could tie up
333 * the fat for quite a while. Preventing others from accessing it.
334 * To prevent us from going after the fat quite so much we use
335 * delayed writes, unless they specfied "synchronous" when the
336 * filesystem was mounted. If synch is asked for then use
337 * bwrite()'s and really slow things down.
347 * If we have an FSInfo block, update it.
338 */
348 */
339 for (i = 1; i < pmp->pm_FATs; i++) {
340 fatbn += pmp->pm_FATsecs;
341 /* getblk() never fails */
342 bpn = getblk(pmp->pm_devvp, fatbn, bp->b_bcount, 0, 0);
343 bcopy(bp->b_data, bpn->b_data, bp->b_bcount);
344 if (pmp->pm_waitonfat)
345 bwrite(bpn);
346 else
347 bdwrite(bpn);
349 if (pmp->pm_fsinfo) {
350 u_long cn = pmp->pm_nxtfree;
351
352 if (pmp->pm_freeclustercount
353 && (pmp->pm_inusemap[cn / N_INUSEBITS]
354 & (1 << (cn % N_INUSEBITS)))) {
355 /*
356 * The cluster indicated in FSInfo isn't free
357 * any longer. Got get a new free one.
358 */
359 for (cn = 0; cn < pmp->pm_maxcluster;)
360 if (pmp->pm_inusemap[cn / N_INUSEBITS] != (u_int)-1)
361 break;
362 pmp->pm_nxtfree = cn
363 + ffs(pmp->pm_inusemap[cn / N_INUSEBITS]
364 ^ (u_int)-1) - 1;
365 }
366 if (bread(pmp->pm_devvp, pmp->pm_fsinfo, 1024, NOCRED, &bpn) != 0) {
367 /*
368 * Ignore the error, but turn off FSInfo update for the future.
369 */
370 pmp->pm_fsinfo = 0;
371 brelse(bpn);
372 } else {
373 struct fsinfo *fp = (struct fsinfo *)bpn->b_data;
374
375 putulong(fp->fsinfree, pmp->pm_freeclustercount);
376 putulong(fp->fsinxtfree, pmp->pm_nxtfree);
377 if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT)
378 bwrite(bpn);
379 else
380 bdwrite(bpn);
381 }
348 }
382 }
383
384 if (pmp->pm_flags & MSDOSFS_FATMIRROR) {
385 /*
386 * Now copy the block(s) of the modified fat to the other copies of
387 * the fat and write them out. This is faster than reading in the
388 * other fats and then writing them back out. This could tie up
389 * the fat for quite a while. Preventing others from accessing it.
390 * To prevent us from going after the fat quite so much we use
391 * delayed writes, unless they specfied "synchronous" when the
392 * filesystem was mounted. If synch is asked for then use
393 * bwrite()'s and really slow things down.
394 */
395 for (i = 1; i < pmp->pm_FATs; i++) {
396 fatbn += pmp->pm_FATsecs;
397 /* getblk() never fails */
398 bpn = getblk(pmp->pm_devvp, fatbn, bp->b_bcount, 0, 0);
399 bcopy(bp->b_data, bpn->b_data, bp->b_bcount);
400 if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT)
401 bwrite(bpn);
402 else
403 bdwrite(bpn);
404 }
405 }
406
349 /*
407 /*
350 * Write out the first fat last.
408 * Write out the first (or current) fat last.
351 */
409 */
352 if (pmp->pm_waitonfat)
410 if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT)
353 bwrite(bp);
354 else
355 bdwrite(bp);
411 bwrite(bp);
412 else
413 bdwrite(bp);
414 /*
415 * Maybe update fsinfo sector here?
416 */
356}
357
358/*
359 * Updating entries in 12 bit fats is a pain in the butt.
360 *
361 * The following picture shows where nibbles go when moving from a 12 bit
362 * cluster number into the appropriate bytes in the FAT.
363 *

--- 10 unchanged lines hidden (view full) ---

374 * Where n is even. m = n + (n >> 2)
375 *
376 */
377static inline void
378usemap_alloc(pmp, cn)
379 struct msdosfsmount *pmp;
380 u_long cn;
381{
417}
418
419/*
420 * Updating entries in 12 bit fats is a pain in the butt.
421 *
422 * The following picture shows where nibbles go when moving from a 12 bit
423 * cluster number into the appropriate bytes in the FAT.
424 *

--- 10 unchanged lines hidden (view full) ---

435 * Where n is even. m = n + (n >> 2)
436 *
437 */
438static inline void
439usemap_alloc(pmp, cn)
440 struct msdosfsmount *pmp;
441 u_long cn;
442{
382 pmp->pm_inusemap[cn / N_INUSEBITS]
383 |= 1 << (cn % N_INUSEBITS);
443
444 pmp->pm_inusemap[cn / N_INUSEBITS] |= 1 << (cn % N_INUSEBITS);
384 pmp->pm_freeclustercount--;
385}
386
387static inline void
388usemap_free(pmp, cn)
389 struct msdosfsmount *pmp;
390 u_long cn;
391{
445 pmp->pm_freeclustercount--;
446}
447
448static inline void
449usemap_free(pmp, cn)
450 struct msdosfsmount *pmp;
451 u_long cn;
452{
453
392 pmp->pm_freeclustercount++;
393 pmp->pm_inusemap[cn / N_INUSEBITS] &= ~(1 << (cn % N_INUSEBITS));
394}
395
396int
397clusterfree(pmp, cluster, oldcnp)
398 struct msdosfsmount *pmp;
399 u_long cluster;
400 u_long *oldcnp;
401{
402 int error;
403 u_long oldcn;
404
454 pmp->pm_freeclustercount++;
455 pmp->pm_inusemap[cn / N_INUSEBITS] &= ~(1 << (cn % N_INUSEBITS));
456}
457
458int
459clusterfree(pmp, cluster, oldcnp)
460 struct msdosfsmount *pmp;
461 u_long cluster;
462 u_long *oldcnp;
463{
464 int error;
465 u_long oldcn;
466
467 usemap_free(pmp, cluster);
405 error = fatentry(FAT_GET_AND_SET, pmp, cluster, &oldcn, MSDOSFSFREE);
468 error = fatentry(FAT_GET_AND_SET, pmp, cluster, &oldcn, MSDOSFSFREE);
406 if (error == 0) {
407 /*
408 * If the cluster was successfully marked free, then update
409 * the count of free clusters, and turn off the "allocated"
410 * bit in the "in use" cluster bit map.
411 */
412 usemap_free(pmp, cluster);
413 if (oldcnp)
414 *oldcnp = oldcn;
469 if (error) {
470 usemap_alloc(pmp, cluster);
471 return (error);
415 }
472 }
416 return error;
473 /*
474 * If the cluster was successfully marked free, then update
475 * the count of free clusters, and turn off the "allocated"
476 * bit in the "in use" cluster bit map.
477 */
478 if (oldcnp)
479 *oldcnp = oldcn;
480 return (0);
417}
418
419/*
420 * Get or Set or 'Get and Set' the cluster'th entry in the fat.
421 *
422 * function - whether to get or set a fat entry
423 * pmp - address of the msdosfsmount structure for the filesystem
424 * whose fat is to be manipulated.

--- 18 unchanged lines hidden (view full) ---

443 u_long *oldcontents;
444 u_long newcontents;
445{
446 int error;
447 u_long readcn;
448 u_long bn, bo, bsize, byteoffset;
449 struct buf *bp;
450
481}
482
483/*
484 * Get or Set or 'Get and Set' the cluster'th entry in the fat.
485 *
486 * function - whether to get or set a fat entry
487 * pmp - address of the msdosfsmount structure for the filesystem
488 * whose fat is to be manipulated.

--- 18 unchanged lines hidden (view full) ---

507 u_long *oldcontents;
508 u_long newcontents;
509{
510 int error;
511 u_long readcn;
512 u_long bn, bo, bsize, byteoffset;
513 struct buf *bp;
514
451 /*
452 * printf("fatentry(func %d, pmp %08x, clust %d, oldcon %08x, newcon %d)\n",
453 * function, pmp, cluster, oldcontents, newcontents);
454 */
515#ifdef MSDOSFS_DEBUG
516 printf("fatentry(func %d, pmp %p, clust %lu, oldcon %p, newcon %lx)\n",
517 function, pmp, cn, oldcontents, newcontents);
518#endif
455
456#ifdef DIAGNOSTIC
457 /*
458 * Be sure they asked us to do something.
459 */
460 if ((function & (FAT_SET | FAT_GET)) == 0) {
461 printf("fatentry(): function code doesn't specify get or set\n");
519
520#ifdef DIAGNOSTIC
521 /*
522 * Be sure they asked us to do something.
523 */
524 if ((function & (FAT_SET | FAT_GET)) == 0) {
525 printf("fatentry(): function code doesn't specify get or set\n");
462 return EINVAL;
526 return (EINVAL);
463 }
464
465 /*
466 * If they asked us to return a cluster number but didn't tell us
467 * where to put it, give them an error.
468 */
469 if ((function & FAT_GET) && oldcontents == NULL) {
470 printf("fatentry(): get function with no place to put result\n");
527 }
528
529 /*
530 * If they asked us to return a cluster number but didn't tell us
531 * where to put it, give them an error.
532 */
533 if ((function & FAT_GET) && oldcontents == NULL) {
534 printf("fatentry(): get function with no place to put result\n");
471 return EINVAL;
535 return (EINVAL);
472 }
473#endif
474
475 /*
476 * Be sure the requested cluster is in the filesystem.
477 */
478 if (cn < CLUST_FIRST || cn > pmp->pm_maxcluster)
536 }
537#endif
538
539 /*
540 * Be sure the requested cluster is in the filesystem.
541 */
542 if (cn < CLUST_FIRST || cn > pmp->pm_maxcluster)
479 return EINVAL;
543 return (EINVAL);
480
481 byteoffset = FATOFS(pmp, cn);
482 fatblock(pmp, byteoffset, &bn, &bsize, &bo);
483 error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
544
545 byteoffset = FATOFS(pmp, cn);
546 fatblock(pmp, byteoffset, &bn, &bsize, &bo);
547 error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
484 if (error)
485 return error;
548 if (error) {
549 brelse(bp);
550 return (error);
551 }
486
487 if (function & FAT_GET) {
552
553 if (function & FAT_GET) {
488 readcn = getushort(&bp->b_data[bo]);
489 if (FAT12(pmp)) {
490 if (cn & 1)
491 readcn >>= 4;
492 readcn &= 0x0fff;
493 /* map certain 12 bit fat entries to 16 bit */
494 if ((readcn & 0x0ff0) == 0x0ff0)
495 readcn |= 0xf000;
496 }
554 if (FAT32(pmp))
555 readcn = getulong(&bp->b_data[bo]);
556 else
557 readcn = getushort(&bp->b_data[bo]);
558 if (FAT12(pmp) & (cn & 1))
559 readcn >>= 4;
560 readcn &= pmp->pm_fatmask;
561 /* map reserved fat entries to same values for all fats */
562 if ((readcn | ~pmp->pm_fatmask) >= CLUST_RSRVD)
563 readcn |= ~pmp->pm_fatmask;
497 *oldcontents = readcn;
498 }
499 if (function & FAT_SET) {
564 *oldcontents = readcn;
565 }
566 if (function & FAT_SET) {
500 if (FAT12(pmp)) {
567 switch (pmp->pm_fatmask) {
568 case FAT12_MASK:
501 readcn = getushort(&bp->b_data[bo]);
502 if (cn & 1) {
503 readcn &= 0x000f;
504 readcn |= newcontents << 4;
505 } else {
506 readcn &= 0xf000;
507 readcn |= newcontents & 0xfff;
508 }
509 putushort(&bp->b_data[bo], readcn);
569 readcn = getushort(&bp->b_data[bo]);
570 if (cn & 1) {
571 readcn &= 0x000f;
572 readcn |= newcontents << 4;
573 } else {
574 readcn &= 0xf000;
575 readcn |= newcontents & 0xfff;
576 }
577 putushort(&bp->b_data[bo], readcn);
510 } else
578 break;
579 case FAT16_MASK:
511 putushort(&bp->b_data[bo], newcontents);
580 putushort(&bp->b_data[bo], newcontents);
581 break;
582 case FAT32_MASK:
583 /*
584 * According to spec we have to retain the
585 * high order bits of the fat entry.
586 */
587 readcn = getulong(&bp->b_data[bo]);
588 readcn &= ~FAT32_MASK;
589 readcn |= newcontents & FAT32_MASK;
590 putulong(&bp->b_data[bo], readcn);
591 break;
592 }
512 updatefats(pmp, bp, bn);
513 bp = NULL;
514 pmp->pm_fmod = 1;
515 }
516 if (bp)
517 brelse(bp);
593 updatefats(pmp, bp, bn);
594 bp = NULL;
595 pmp->pm_fmod = 1;
596 }
597 if (bp)
598 brelse(bp);
518 return 0;
599 return (0);
519}
520
521/*
522 * Update a contiguous cluster chain
523 *
524 * pmp - mount point
525 * start - first cluster of chain
526 * count - number of clusters in chain

--- 6 unchanged lines hidden (view full) ---

533 u_long count;
534 u_long fillwith;
535{
536 int error;
537 u_long bn, bo, bsize, byteoffset, readcn, newc;
538 struct buf *bp;
539
540#ifdef MSDOSFS_DEBUG
600}
601
602/*
603 * Update a contiguous cluster chain
604 *
605 * pmp - mount point
606 * start - first cluster of chain
607 * count - number of clusters in chain

--- 6 unchanged lines hidden (view full) ---

614 u_long count;
615 u_long fillwith;
616{
617 int error;
618 u_long bn, bo, bsize, byteoffset, readcn, newc;
619 struct buf *bp;
620
621#ifdef MSDOSFS_DEBUG
541 printf("fatchain(pmp %p, start %ld, count %ld, fillwith %ld)\n",
542 pmp, start, count, fillwith);
622 printf("fatchain(pmp %p, start %lu, count %lu, fillwith %lx)\n",
623 pmp, start, count, fillwith);
543#endif
544 /*
545 * Be sure the clusters are in the filesystem.
546 */
547 if (start < CLUST_FIRST || start + count - 1 > pmp->pm_maxcluster)
624#endif
625 /*
626 * Be sure the clusters are in the filesystem.
627 */
628 if (start < CLUST_FIRST || start + count - 1 > pmp->pm_maxcluster)
548 return EINVAL;
629 return (EINVAL);
549
550 while (count > 0) {
551 byteoffset = FATOFS(pmp, start);
552 fatblock(pmp, byteoffset, &bn, &bsize, &bo);
553 error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
630
631 while (count > 0) {
632 byteoffset = FATOFS(pmp, start);
633 fatblock(pmp, byteoffset, &bn, &bsize, &bo);
634 error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
554 if (error)
555 return error;
635 if (error) {
636 brelse(bp);
637 return (error);
638 }
556 while (count > 0) {
557 start++;
558 newc = --count > 0 ? start : fillwith;
639 while (count > 0) {
640 start++;
641 newc = --count > 0 ? start : fillwith;
559 if (FAT12(pmp)) {
642 switch (pmp->pm_fatmask) {
643 case FAT12_MASK:
560 readcn = getushort(&bp->b_data[bo]);
561 if (start & 1) {
562 readcn &= 0xf000;
563 readcn |= newc & 0xfff;
564 } else {
565 readcn &= 0x000f;
566 readcn |= newc << 4;
567 }
568 putushort(&bp->b_data[bo], readcn);
569 bo++;
570 if (!(start & 1))
571 bo++;
644 readcn = getushort(&bp->b_data[bo]);
645 if (start & 1) {
646 readcn &= 0xf000;
647 readcn |= newc & 0xfff;
648 } else {
649 readcn &= 0x000f;
650 readcn |= newc << 4;
651 }
652 putushort(&bp->b_data[bo], readcn);
653 bo++;
654 if (!(start & 1))
655 bo++;
572 } else {
656 break;
657 case FAT16_MASK:
573 putushort(&bp->b_data[bo], newc);
574 bo += 2;
658 putushort(&bp->b_data[bo], newc);
659 bo += 2;
660 break;
661 case FAT32_MASK:
662 readcn = getulong(&bp->b_data[bo]);
663 readcn &= ~pmp->pm_fatmask;
664 readcn |= newc & pmp->pm_fatmask;
665 putulong(&bp->b_data[bo], readcn);
666 bo += 4;
667 break;
575 }
576 if (bo >= bsize)
577 break;
578 }
579 updatefats(pmp, bp, bn);
580 }
581 pmp->pm_fmod = 1;
668 }
669 if (bo >= bsize)
670 break;
671 }
672 updatefats(pmp, bp, bn);
673 }
674 pmp->pm_fmod = 1;
582 return 0;
675 return (0);
583}
584
585/*
586 * Check the length of a free cluster chain starting at start.
587 *
588 * pmp - mount point
589 * start - start of chain
590 * count - maximum interesting length

--- 10 unchanged lines hidden (view full) ---

601
602 max_idx = pmp->pm_maxcluster / N_INUSEBITS;
603 idx = start / N_INUSEBITS;
604 start %= N_INUSEBITS;
605 map = pmp->pm_inusemap[idx];
606 map &= ~((1 << start) - 1);
607 if (map) {
608 len = ffs(map) - 1 - start;
676}
677
678/*
679 * Check the length of a free cluster chain starting at start.
680 *
681 * pmp - mount point
682 * start - start of chain
683 * count - maximum interesting length

--- 10 unchanged lines hidden (view full) ---

694
695 max_idx = pmp->pm_maxcluster / N_INUSEBITS;
696 idx = start / N_INUSEBITS;
697 start %= N_INUSEBITS;
698 map = pmp->pm_inusemap[idx];
699 map &= ~((1 << start) - 1);
700 if (map) {
701 len = ffs(map) - 1 - start;
609 return len > count ? count : len;
702 return (len > count ? count : len);
610 }
611 len = N_INUSEBITS - start;
612 if (len >= count)
703 }
704 len = N_INUSEBITS - start;
705 if (len >= count)
613 return count;
706 return (count);
614 while (++idx <= max_idx) {
615 if (len >= count)
616 break;
617 map = pmp->pm_inusemap[idx];
618 if (map) {
619 len += ffs(map) - 1;
620 break;
621 }
622 len += N_INUSEBITS;
623 }
707 while (++idx <= max_idx) {
708 if (len >= count)
709 break;
710 map = pmp->pm_inusemap[idx];
711 if (map) {
712 len += ffs(map) - 1;
713 break;
714 }
715 len += N_INUSEBITS;
716 }
624 return len > count ? count : len;
717 return (len > count ? count : len);
625}
626
627/*
628 * Allocate contigous free clusters.
629 *
630 * pmp - mount point.
631 * start - start of cluster chain.
632 * count - number of clusters to allocate.

--- 7 unchanged lines hidden (view full) ---

640 struct msdosfsmount *pmp;
641 u_long start;
642 u_long count;
643 u_long fillwith;
644 u_long *retcluster;
645 u_long *got;
646{
647 int error;
718}
719
720/*
721 * Allocate contigous free clusters.
722 *
723 * pmp - mount point.
724 * start - start of cluster chain.
725 * count - number of clusters to allocate.

--- 7 unchanged lines hidden (view full) ---

733 struct msdosfsmount *pmp;
734 u_long start;
735 u_long count;
736 u_long fillwith;
737 u_long *retcluster;
738 u_long *got;
739{
740 int error;
741 u_long cl, n;
648
742
743 for (cl = start, n = count; n-- > 0;)
744 usemap_alloc(pmp, cl++);
745
649 error = fatchain(pmp, start, count, fillwith);
746 error = fatchain(pmp, start, count, fillwith);
650 if (error == 0) {
747 if (error != 0)
748 return (error);
651#ifdef MSDOSFS_DEBUG
749#ifdef MSDOSFS_DEBUG
652 printf("clusteralloc(): allocated cluster chain at %ld (%ld clusters)\n",
653 start, count);
750 printf("clusteralloc(): allocated cluster chain at %lu (%lu clusters)\n",
751 start, count);
654#endif
752#endif
655 if (retcluster)
656 *retcluster = start;
657 if (got)
658 *got = count;
659 while (count-- > 0)
660 usemap_alloc(pmp, start++);
661 }
662 return error;
753 if (retcluster)
754 *retcluster = start;
755 if (got)
756 *got = count;
757 return (0);
663}
664
665/*
666 * Allocate contiguous free clusters.
667 *
668 * pmp - mount point.
669 * start - preferred start of cluster chain.
670 * count - number of clusters requested.

--- 7 unchanged lines hidden (view full) ---

678 struct msdosfsmount *pmp;
679 u_long start;
680 u_long count;
681 u_long fillwith;
682 u_long *retcluster;
683 u_long *got;
684{
685 u_long idx;
758}
759
760/*
761 * Allocate contiguous free clusters.
762 *
763 * pmp - mount point.
764 * start - preferred start of cluster chain.
765 * count - number of clusters requested.

--- 7 unchanged lines hidden (view full) ---

773 struct msdosfsmount *pmp;
774 u_long start;
775 u_long count;
776 u_long fillwith;
777 u_long *retcluster;
778 u_long *got;
779{
780 u_long idx;
686 u_long len, newst, foundcn, foundl, cn, l;
781 u_long len, newst, foundl, cn, l;
782 u_long foundcn = 0; /* XXX: foundcn could be used unititialized */
687 u_int map;
688
689#ifdef MSDOSFS_DEBUG
783 u_int map;
784
785#ifdef MSDOSFS_DEBUG
690 printf("clusteralloc(): find %d clusters\n",count);
786 printf("clusteralloc(): find %lu clusters\n",count);
691#endif
692 if (start) {
693 if ((len = chainlength(pmp, start, count)) >= count)
787#endif
788 if (start) {
789 if ((len = chainlength(pmp, start, count)) >= count)
694 return chainalloc(pmp, start, count, fillwith, retcluster, got);
790 return (chainalloc(pmp, start, count, fillwith, retcluster, got));
695 } else {
696 /*
697 * This is a new file, initialize start
698 */
699 struct timeval tv;
700
701 microtime(&tv);
791 } else {
792 /*
793 * This is a new file, initialize start
794 */
795 struct timeval tv;
796
797 microtime(&tv);
702 start = (tv.tv_usec >> 10)|tv.tv_usec;
798 start = (tv.tv_usec >> 10) | tv.tv_usec;
703 len = 0;
704 }
705
706 /*
707 * Start at a (pseudo) random place to maximize cluster runs
708 * under multiple writers.
709 */
799 len = 0;
800 }
801
802 /*
803 * Start at a (pseudo) random place to maximize cluster runs
804 * under multiple writers.
805 */
710 foundcn = newst = (start * 1103515245 + 12345) % (pmp->pm_maxcluster + 1);
806 newst = (start * 1103515245 + 12345) % (pmp->pm_maxcluster + 1);
711 foundl = 0;
712
713 for (cn = newst; cn <= pmp->pm_maxcluster;) {
714 idx = cn / N_INUSEBITS;
715 map = pmp->pm_inusemap[idx];
716 map |= (1 << (cn % N_INUSEBITS)) - 1;
717 if (map != (u_int)-1) {
718 cn = idx * N_INUSEBITS + ffs(map^(u_int)-1) - 1;
719 if ((l = chainlength(pmp, cn, count)) >= count)
807 foundl = 0;
808
809 for (cn = newst; cn <= pmp->pm_maxcluster;) {
810 idx = cn / N_INUSEBITS;
811 map = pmp->pm_inusemap[idx];
812 map |= (1 << (cn % N_INUSEBITS)) - 1;
813 if (map != (u_int)-1) {
814 cn = idx * N_INUSEBITS + ffs(map^(u_int)-1) - 1;
815 if ((l = chainlength(pmp, cn, count)) >= count)
720 return chainalloc(pmp, cn, count, fillwith, retcluster, got);
816 return (chainalloc(pmp, cn, count, fillwith, retcluster, got));
721 if (l > foundl) {
722 foundcn = cn;
723 foundl = l;
724 }
725 cn += l + 1;
726 continue;
727 }
728 cn += N_INUSEBITS - cn % N_INUSEBITS;
729 }
730 for (cn = 0; cn < newst;) {
731 idx = cn / N_INUSEBITS;
732 map = pmp->pm_inusemap[idx];
733 map |= (1 << (cn % N_INUSEBITS)) - 1;
734 if (map != (u_int)-1) {
735 cn = idx * N_INUSEBITS + ffs(map^(u_int)-1) - 1;
736 if ((l = chainlength(pmp, cn, count)) >= count)
817 if (l > foundl) {
818 foundcn = cn;
819 foundl = l;
820 }
821 cn += l + 1;
822 continue;
823 }
824 cn += N_INUSEBITS - cn % N_INUSEBITS;
825 }
826 for (cn = 0; cn < newst;) {
827 idx = cn / N_INUSEBITS;
828 map = pmp->pm_inusemap[idx];
829 map |= (1 << (cn % N_INUSEBITS)) - 1;
830 if (map != (u_int)-1) {
831 cn = idx * N_INUSEBITS + ffs(map^(u_int)-1) - 1;
832 if ((l = chainlength(pmp, cn, count)) >= count)
737 return chainalloc(pmp, cn, count, fillwith, retcluster, got);
833 return (chainalloc(pmp, cn, count, fillwith, retcluster, got));
738 if (l > foundl) {
739 foundcn = cn;
740 foundl = l;
741 }
742 cn += l + 1;
743 continue;
744 }
745 cn += N_INUSEBITS - cn % N_INUSEBITS;
746 }
747
748 if (!foundl)
834 if (l > foundl) {
835 foundcn = cn;
836 foundl = l;
837 }
838 cn += l + 1;
839 continue;
840 }
841 cn += N_INUSEBITS - cn % N_INUSEBITS;
842 }
843
844 if (!foundl)
749 return ENOSPC;
845 return (ENOSPC);
750
751 if (len)
846
847 if (len)
752 return chainalloc(pmp, start, len, fillwith, retcluster, got);
848 return (chainalloc(pmp, start, len, fillwith, retcluster, got));
753 else
849 else
754 return chainalloc(pmp, foundcn, foundl, fillwith, retcluster, got);
850 return (chainalloc(pmp, foundcn, foundl, fillwith, retcluster, got));
755}
756
757
758/*
759 * Free a chain of clusters.
760 *
761 * pmp - address of the msdosfs mount structure for the filesystem
762 * containing the cluster chain to be freed.
763 * startcluster - number of the 1st cluster in the chain of clusters to be
764 * freed.
765 */
766int
767freeclusterchain(pmp, cluster)
768 struct msdosfsmount *pmp;
769 u_long cluster;
770{
851}
852
853
854/*
855 * Free a chain of clusters.
856 *
857 * pmp - address of the msdosfs mount structure for the filesystem
858 * containing the cluster chain to be freed.
859 * startcluster - number of the 1st cluster in the chain of clusters to be
860 * freed.
861 */
862int
863freeclusterchain(pmp, cluster)
864 struct msdosfsmount *pmp;
865 u_long cluster;
866{
771 int error = 0;
867 int error;
772 struct buf *bp = NULL;
773 u_long bn, bo, bsize, byteoffset;
774 u_long readcn, lbn = -1;
775
776 while (cluster >= CLUST_FIRST && cluster <= pmp->pm_maxcluster) {
777 byteoffset = FATOFS(pmp, cluster);
778 fatblock(pmp, byteoffset, &bn, &bsize, &bo);
779 if (lbn != bn) {
780 if (bp)
781 updatefats(pmp, bp, lbn);
782 error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
868 struct buf *bp = NULL;
869 u_long bn, bo, bsize, byteoffset;
870 u_long readcn, lbn = -1;
871
872 while (cluster >= CLUST_FIRST && cluster <= pmp->pm_maxcluster) {
873 byteoffset = FATOFS(pmp, cluster);
874 fatblock(pmp, byteoffset, &bn, &bsize, &bo);
875 if (lbn != bn) {
876 if (bp)
877 updatefats(pmp, bp, lbn);
878 error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
783 if (error)
784 return error;
879 if (error) {
880 brelse(bp);
881 return (error);
882 }
785 lbn = bn;
786 }
787 usemap_free(pmp, cluster);
883 lbn = bn;
884 }
885 usemap_free(pmp, cluster);
788 readcn = getushort(&bp->b_data[bo]);
789 if (FAT12(pmp)) {
886 switch (pmp->pm_fatmask) {
887 case FAT12_MASK:
888 readcn = getushort(&bp->b_data[bo]);
790 if (cluster & 1) {
791 cluster = readcn >> 4;
792 readcn &= 0x000f;
793 readcn |= MSDOSFSFREE << 4;
794 } else {
795 cluster = readcn;
796 readcn &= 0xf000;
797 readcn |= MSDOSFSFREE & 0xfff;
798 }
799 putushort(&bp->b_data[bo], readcn);
889 if (cluster & 1) {
890 cluster = readcn >> 4;
891 readcn &= 0x000f;
892 readcn |= MSDOSFSFREE << 4;
893 } else {
894 cluster = readcn;
895 readcn &= 0xf000;
896 readcn |= MSDOSFSFREE & 0xfff;
897 }
898 putushort(&bp->b_data[bo], readcn);
800 cluster &= 0x0fff;
801 if ((cluster&0x0ff0) == 0x0ff0)
802 cluster |= 0xf000;
803 } else {
804 cluster = readcn;
899 break;
900 case FAT16_MASK:
901 cluster = getushort(&bp->b_data[bo]);
805 putushort(&bp->b_data[bo], MSDOSFSFREE);
902 putushort(&bp->b_data[bo], MSDOSFSFREE);
903 break;
904 case FAT32_MASK:
905 cluster = getulong(&bp->b_data[bo]);
906 putulong(&bp->b_data[bo],
907 (MSDOSFSFREE & FAT32_MASK) | (cluster & ~FAT32_MASK));
908 break;
806 }
909 }
910 cluster &= pmp->pm_fatmask;
911 if ((cluster | ~pmp->pm_fatmask) >= CLUST_RSRVD)
912 cluster |= pmp->pm_fatmask;
807 }
808 if (bp)
809 updatefats(pmp, bp, bn);
913 }
914 if (bp)
915 updatefats(pmp, bp, bn);
810 return error;
916 return (0);
811}
812
813/*
814 * Read in fat blocks looking for free clusters. For every free cluster
815 * found turn off its corresponding bit in the pm_inusemap.
816 */
817int
818fillinusemap(pmp)
819 struct msdosfsmount *pmp;
820{
821 struct buf *bp = NULL;
822 u_long cn, readcn;
823 int error;
917}
918
919/*
920 * Read in fat blocks looking for free clusters. For every free cluster
921 * found turn off its corresponding bit in the pm_inusemap.
922 */
923int
924fillinusemap(pmp)
925 struct msdosfsmount *pmp;
926{
927 struct buf *bp = NULL;
928 u_long cn, readcn;
929 int error;
824 int fat12 = FAT12(pmp);
825 u_long bn, bo, bsize, byteoffset;
826
827 /*
828 * Mark all clusters in use, we mark the free ones in the fat scan
829 * loop further down.
830 */
831 for (cn = 0; cn < (pmp->pm_maxcluster + N_INUSEBITS) / N_INUSEBITS; cn++)
832 pmp->pm_inusemap[cn] = (u_int)-1;

--- 8 unchanged lines hidden (view full) ---

841 byteoffset = FATOFS(pmp, cn);
842 bo = byteoffset % pmp->pm_fatblocksize;
843 if (!bo || !bp) {
844 /* Read new FAT block */
845 if (bp)
846 brelse(bp);
847 fatblock(pmp, byteoffset, &bn, &bsize, NULL);
848 error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
930 u_long bn, bo, bsize, byteoffset;
931
932 /*
933 * Mark all clusters in use, we mark the free ones in the fat scan
934 * loop further down.
935 */
936 for (cn = 0; cn < (pmp->pm_maxcluster + N_INUSEBITS) / N_INUSEBITS; cn++)
937 pmp->pm_inusemap[cn] = (u_int)-1;

--- 8 unchanged lines hidden (view full) ---

946 byteoffset = FATOFS(pmp, cn);
947 bo = byteoffset % pmp->pm_fatblocksize;
948 if (!bo || !bp) {
949 /* Read new FAT block */
950 if (bp)
951 brelse(bp);
952 fatblock(pmp, byteoffset, &bn, &bsize, NULL);
953 error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
849 if (error)
850 return error;
954 if (error) {
955 brelse(bp);
956 return (error);
957 }
851 }
958 }
852 readcn = getushort(&bp->b_data[bo]);
853 if (fat12) {
854 if (cn & 1)
855 readcn >>= 4;
856 readcn &= 0x0fff;
857 }
959 if (FAT32(pmp))
960 readcn = getulong(&bp->b_data[bo]);
961 else
962 readcn = getushort(&bp->b_data[bo]);
963 if (FAT12(pmp) && (cn & 1))
964 readcn >>= 4;
965 readcn &= pmp->pm_fatmask;
858
859 if (readcn == 0)
860 usemap_free(pmp, cn);
861 }
862 brelse(bp);
966
967 if (readcn == 0)
968 usemap_free(pmp, cn);
969 }
970 brelse(bp);
863 return 0;
971 return (0);
864}
865
866/*
867 * Allocate a new cluster and chain it onto the end of the file.
868 *
869 * dep - the file to extend
870 * count - number of clusters to allocate
871 * bpp - where to return the address of the buf header for the first new

--- 9 unchanged lines hidden (view full) ---

881int
882extendfile(dep, count, bpp, ncp, flags)
883 struct denode *dep;
884 u_long count;
885 struct buf **bpp;
886 u_long *ncp;
887 int flags;
888{
972}
973
974/*
975 * Allocate a new cluster and chain it onto the end of the file.
976 *
977 * dep - the file to extend
978 * count - number of clusters to allocate
979 * bpp - where to return the address of the buf header for the first new

--- 9 unchanged lines hidden (view full) ---

989int
990extendfile(dep, count, bpp, ncp, flags)
991 struct denode *dep;
992 u_long count;
993 struct buf **bpp;
994 u_long *ncp;
995 int flags;
996{
889 int error = 0;
997 int error;
890 u_long frcn;
891 u_long cn, got;
892 struct msdosfsmount *pmp = dep->de_pmp;
893 struct buf *bp;
894
895 /*
896 * Don't try to extend the root directory
897 */
998 u_long frcn;
999 u_long cn, got;
1000 struct msdosfsmount *pmp = dep->de_pmp;
1001 struct buf *bp;
1002
1003 /*
1004 * Don't try to extend the root directory
1005 */
898 if (DETOV(dep)->v_flag & VROOT) {
1006 if (dep->de_StartCluster == MSDOSFSROOT
1007 && (dep->de_Attributes & ATTR_DIRECTORY)) {
899 printf("extendfile(): attempt to extend root directory\n");
1008 printf("extendfile(): attempt to extend root directory\n");
900 return ENOSPC;
1009 return (ENOSPC);
901 }
902
903 /*
904 * If the "file's last cluster" cache entry is empty, and the file
905 * is not empty, then fill the cache entry by calling pcbmap().
906 */
907 fc_fileextends++;
908 if (dep->de_fc[FC_LASTFC].fc_frcn == FCE_EMPTY &&
909 dep->de_StartCluster != 0) {
910 fc_lfcempty++;
1010 }
1011
1012 /*
1013 * If the "file's last cluster" cache entry is empty, and the file
1014 * is not empty, then fill the cache entry by calling pcbmap().
1015 */
1016 fc_fileextends++;
1017 if (dep->de_fc[FC_LASTFC].fc_frcn == FCE_EMPTY &&
1018 dep->de_StartCluster != 0) {
1019 fc_lfcempty++;
911 error = pcbmap(dep, 0xffff, 0, &cn);
1020 error = pcbmap(dep, 0xffff, 0, &cn, 0);
912 /* we expect it to return E2BIG */
913 if (error != E2BIG)
1021 /* we expect it to return E2BIG */
1022 if (error != E2BIG)
914 return error;
915 error = 0;
1023 return (error);
916 }
917
918 while (count > 0) {
919 /*
1024 }
1025
1026 while (count > 0) {
1027 /*
920 * Allocate a new cluster chain and cat onto the end of the file.
921 * If the file is empty we make de_StartCluster point to the new
922 * block. Note that de_StartCluster being 0 is sufficient to be
923 * sure the file is empty since we exclude attempts to extend the
924 * root directory above, and the root dir is the only file with a
925 * startcluster of 0 that has blocks allocated (sort of).
1028 * Allocate a new cluster chain and cat onto the end of the
1029 * file. * If the file is empty we make de_StartCluster point
1030 * to the new block. Note that de_StartCluster being 0 is
1031 * sufficient to be sure the file is empty since we exclude
1032 * attempts to extend the root directory above, and the root
1033 * dir is the only file with a startcluster of 0 that has
1034 * blocks allocated (sort of).
926 */
927 if (dep->de_StartCluster == 0)
928 cn = 0;
929 else
930 cn = dep->de_fc[FC_LASTFC].fc_fsrcn + 1;
931 error = clusteralloc(pmp, cn, count, CLUST_EOFE, &cn, &got);
932 if (error)
1035 */
1036 if (dep->de_StartCluster == 0)
1037 cn = 0;
1038 else
1039 cn = dep->de_fc[FC_LASTFC].fc_fsrcn + 1;
1040 error = clusteralloc(pmp, cn, count, CLUST_EOFE, &cn, &got);
1041 if (error)
933 return error;
1042 return (error);
934
935 count -= got;
936
937 /*
938 * Give them the filesystem relative cluster number if they want
939 * it.
940 */
941 if (ncp) {
942 *ncp = cn;
943 ncp = NULL;
944 }
945
946 if (dep->de_StartCluster == 0) {
947 dep->de_StartCluster = cn;
948 frcn = 0;
949 } else {
1043
1044 count -= got;
1045
1046 /*
1047 * Give them the filesystem relative cluster number if they want
1048 * it.
1049 */
1050 if (ncp) {
1051 *ncp = cn;
1052 ncp = NULL;
1053 }
1054
1055 if (dep->de_StartCluster == 0) {
1056 dep->de_StartCluster = cn;
1057 frcn = 0;
1058 } else {
950 error = fatentry(FAT_SET, pmp, dep->de_fc[FC_LASTFC].fc_fsrcn,
1059 error = fatentry(FAT_SET, pmp,
1060 dep->de_fc[FC_LASTFC].fc_fsrcn,
951 0, cn);
952 if (error) {
953 clusterfree(pmp, cn, NULL);
1061 0, cn);
1062 if (error) {
1063 clusterfree(pmp, cn, NULL);
954 return error;
1064 return (error);
955 }
1065 }
956
957 frcn = dep->de_fc[FC_LASTFC].fc_frcn + 1;
958 }
959
960 /*
961 * Update the "last cluster of the file" entry in the denode's fat
962 * cache.
963 */
964 fc_setcache(dep, FC_LASTFC, frcn + got - 1, cn + got - 1);
965
966 if (flags & DE_CLEAR) {
967 while (got-- > 0) {
968 /*
969 * Get the buf header for the new block of the file.
970 */
971 if (dep->de_Attributes & ATTR_DIRECTORY)
972 bp = getblk(pmp->pm_devvp, cntobn(pmp, cn++),
973 pmp->pm_bpcluster, 0, 0);
974 else {
1066 frcn = dep->de_fc[FC_LASTFC].fc_frcn + 1;
1067 }
1068
1069 /*
1070 * Update the "last cluster of the file" entry in the denode's fat
1071 * cache.
1072 */
1073 fc_setcache(dep, FC_LASTFC, frcn + got - 1, cn + got - 1);
1074
1075 if (flags & DE_CLEAR) {
1076 while (got-- > 0) {
1077 /*
1078 * Get the buf header for the new block of the file.
1079 */
1080 if (dep->de_Attributes & ATTR_DIRECTORY)
1081 bp = getblk(pmp->pm_devvp, cntobn(pmp, cn++),
1082 pmp->pm_bpcluster, 0, 0);
1083 else {
975 bp = getblk(DETOV(dep), frcn++, pmp->pm_bpcluster, 0, 0);
1084 bp = getblk(DETOV(dep), de_cn2bn(pmp, frcn++),
1085 pmp->pm_bpcluster, 0, 0);
976 /*
977 * Do the bmap now, as in msdosfs_write
978 */
1086 /*
1087 * Do the bmap now, as in msdosfs_write
1088 */
979 if (pcbmap(dep, bp->b_lblkno, &bp->b_blkno, 0))
1089 if (pcbmap(dep,
1090 de_bn2cn(pmp, bp->b_lblkno),
1091 &bp->b_blkno, 0, 0))
980 bp->b_blkno = -1;
981 if (bp->b_blkno == -1)
982 panic("extendfile: pcbmap");
983 }
984 clrbuf(bp);
985 if (bpp) {
986 *bpp = bp;
987 bpp = NULL;
1092 bp->b_blkno = -1;
1093 if (bp->b_blkno == -1)
1094 panic("extendfile: pcbmap");
1095 }
1096 clrbuf(bp);
1097 if (bpp) {
1098 *bpp = bp;
1099 bpp = NULL;
988 } else {
989 bp->b_flags |= B_AGE;
990 bawrite(bp);
991 }
1100 } else
1101 bdwrite(bp);
992 }
993 }
994 }
995
1102 }
1103 }
1104 }
1105
996 return 0;
1106 return (0);
997}
1107}