2005-04-21 16:53:53 +02:00
|
|
|
/* The file system maintains a buffer cache to reduce the number of disk
|
|
|
|
* accesses needed. Whenever a read or write to the disk is done, a check is
|
|
|
|
* first made to see if the block is in the cache. This file manages the
|
|
|
|
* cache.
|
|
|
|
*
|
|
|
|
* The entry points into this file are:
|
|
|
|
* get_block: request to fetch a block for reading or writing from cache
|
|
|
|
* put_block: return a block previously requested with get_block
|
|
|
|
* alloc_zone: allocate a new zone (to increase the length of a file)
|
|
|
|
* free_zone: release a zone (when a file is removed)
|
|
|
|
* invalidate: remove all the cache blocks on some device
|
2005-10-12 17:06:47 +02:00
|
|
|
*
|
|
|
|
* Private functions:
|
2011-12-22 01:29:27 +01:00
|
|
|
* read_block: read or write a block from the disk itself
|
2005-04-21 16:53:53 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "fs.h"
|
2006-11-27 15:21:43 +01:00
|
|
|
#include <minix/u64.h>
|
2011-11-09 14:29:12 +01:00
|
|
|
#include <minix/bdev.h>
|
2011-02-28 15:19:19 +01:00
|
|
|
#include <sys/param.h>
|
2010-05-05 13:35:04 +02:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <assert.h>
|
2011-09-08 18:49:54 +02:00
|
|
|
#include <minix/libminixfs.h>
|
2011-02-28 15:19:19 +01:00
|
|
|
#include <math.h>
|
2005-04-21 16:53:53 +02:00
|
|
|
#include "buf.h"
|
|
|
|
#include "super.h"
|
2008-11-19 13:26:10 +01:00
|
|
|
#include "inode.h"
|
2005-04-21 16:53:53 +02:00
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* alloc_zone *
|
|
|
|
*===========================================================================*/
|
2012-03-25 20:25:53 +02:00
|
|
|
zone_t alloc_zone(
|
2010-04-13 12:58:41 +02:00
|
|
|
dev_t dev, /* device where zone wanted */
|
|
|
|
zone_t z /* try to allocate new zone near this one */
|
|
|
|
)
|
2005-04-21 16:53:53 +02:00
|
|
|
{
|
|
|
|
/* Allocate a new zone on the indicated device and return its number. */
|
|
|
|
|
|
|
|
bit_t b, bit;
|
|
|
|
struct super_block *sp;
|
2011-12-16 10:17:37 +01:00
|
|
|
static int print_oos_msg = 1;
|
2005-04-21 16:53:53 +02:00
|
|
|
|
|
|
|
/* Note that the routine alloc_bit() returns 1 for the lowest possible
|
|
|
|
* zone, which corresponds to sp->s_firstdatazone. To convert a value
|
|
|
|
* between the bit number, 'b', used by alloc_bit() and the zone number, 'z',
|
|
|
|
* stored in the inode, use the formula:
|
|
|
|
* z = b + sp->s_firstdatazone - 1
|
|
|
|
* Alloc_bit() never returns 0, since this is used for NO_BIT (failure).
|
|
|
|
*/
|
|
|
|
sp = get_super(dev);
|
|
|
|
|
|
|
|
/* If z is 0, skip initial part of the map known to be fully in use. */
|
|
|
|
if (z == sp->s_firstdatazone) {
|
|
|
|
bit = sp->s_zsearch;
|
|
|
|
} else {
|
2010-06-01 14:35:33 +02:00
|
|
|
bit = (bit_t) (z - (sp->s_firstdatazone - 1));
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
|
|
|
b = alloc_bit(sp, ZMAP, bit);
|
|
|
|
if (b == NO_BIT) {
|
|
|
|
err_code = ENOSPC;
|
2011-12-16 10:17:37 +01:00
|
|
|
if (print_oos_msg)
|
|
|
|
printf("No space on device %d/%d\n", major(sp->s_dev),
|
|
|
|
minor(sp->s_dev));
|
|
|
|
print_oos_msg = 0; /* Don't repeat message */
|
2005-04-21 16:53:53 +02:00
|
|
|
return(NO_ZONE);
|
|
|
|
}
|
2011-12-16 10:17:37 +01:00
|
|
|
print_oos_msg = 1;
|
2005-04-21 16:53:53 +02:00
|
|
|
if (z == sp->s_firstdatazone) sp->s_zsearch = b; /* for next time */
|
2010-06-01 14:35:33 +02:00
|
|
|
return( (zone_t) (sp->s_firstdatazone - 1) + (zone_t) b);
|
2005-04-21 16:53:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* free_zone *
|
|
|
|
*===========================================================================*/
|
2012-03-25 20:25:53 +02:00
|
|
|
void free_zone(
|
2010-04-13 12:58:41 +02:00
|
|
|
dev_t dev, /* device where zone located */
|
|
|
|
zone_t numb /* zone to be returned */
|
|
|
|
)
|
2005-04-21 16:53:53 +02:00
|
|
|
{
|
|
|
|
/* Return a zone. */
|
|
|
|
|
|
|
|
register struct super_block *sp;
|
|
|
|
bit_t bit;
|
|
|
|
|
|
|
|
/* Locate the appropriate super_block and return bit. */
|
|
|
|
sp = get_super(dev);
|
|
|
|
if (numb < sp->s_firstdatazone || numb >= sp->s_zones) return;
|
2010-06-01 14:35:33 +02:00
|
|
|
bit = (bit_t) (numb - (zone_t) (sp->s_firstdatazone - 1));
|
2005-04-21 16:53:53 +02:00
|
|
|
free_bit(sp, ZMAP, bit);
|
|
|
|
if (bit < sp->s_zsearch) sp->s_zsearch = bit;
|
|
|
|
}
|
|
|
|
|
2008-11-19 13:26:10 +01:00
|
|
|
|