#include "inode.h"
#include "super.h"
#include <minix/vfsif.h>
+#include <sys/param.h>
#define SAME 1000
*===========================================================================*/
int fs_rdlink()
{
- block_t b; /* block containing link text */
struct buf *bp; /* buffer containing link text */
register struct inode *rip; /* target inode */
register int r; /* return value */
if(!S_ISLNK(rip->i_mode))
r = EACCES;
- else if ((b = read_map(rip, (off_t) 0)) == NO_BLOCK)
- r = EIO;
else {
+ if(!(bp = get_block_map(rip, 0)))
+ return EIO;
/* Passed all checks */
/* We can safely cast to unsigned, because copylen is guaranteed to be
below max file size */
copylen = min( copylen, (unsigned) rip->i_size);
- bp = get_block(rip->i_dev, b, NORMAL);
r = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) fs_m_in.REQ_GRANT,
(vir_bytes) 0, (vir_bytes) b_data(bp),
(size_t) copylen);
{
/* Zero an arbitrary byte range in a zone, possibly spanning multiple blocks.
*/
- block_t b;
struct buf *bp;
off_t offset;
unsigned short block_size;
block_size = rip->i_sp->s_block_size;
if(!len) return; /* no zeroing to be done. */
- if( (b = read_map(rip, pos)) == NO_BLOCK) return;
+
while (len > 0) {
- if( (bp = get_block(rip->i_dev, b, NORMAL)) == NULL)
- panic("zerozone_range: no block");
+ if( (bp = get_block_map(rip, rounddown(pos, block_size))) == NULL)
+ return;
offset = pos % block_size;
bytes = block_size - offset;
if (bytes > (size_t) len)
pos += bytes;
len -= bytes;
- b++;
}
}
* new pathname.
*/
- block_t blink; /* block containing link text */
size_t llen; /* length of link */
size_t slen; /* length of suffix */
struct buf *bp; /* buffer containing link text */
char *sp; /* start of link text */
- if ((blink = read_map(rip, (off_t) 0)) == NO_BLOCK)
+ if(!(bp = get_block_map(rip, 0)))
return(EIO);
-
- bp = get_block(rip->i_dev, blink, NORMAL);
llen = (size_t) rip->i_size;
sp = b_data(bp);
slen = strlen(suffix);
mode_t bits;
off_t pos;
unsigned new_slots, old_slots;
- block_t b;
struct super_block *sp;
int extended = 0;
}
for (; pos < ldir_ptr->i_size; pos += ldir_ptr->i_sp->s_block_size) {
- b = read_map(ldir_ptr, pos); /* get block number */
+ assert(ldir_ptr->i_dev != NO_DEV);
/* Since directories don't have holes, 'b' cannot be NO_BLOCK. */
- bp = get_block(ldir_ptr->i_dev, b, NORMAL); /* get a dir block */
+ bp = get_block_map(ldir_ptr, pos);
+ assert(ldir_ptr->i_dev != NO_DEV);
assert(bp != NULL);
+ assert(lmfs_dev(bp) != NO_DEV);
/* Search a directory block. */
for (dp = &b_dir(bp)[0];
*numb = (ino_t) conv4(sp->s_native,
(int) dp->mfs_d_ino);
}
+ assert(lmfs_dev(bp) != NO_DEV);
put_block(bp, DIRECTORY_BLOCK);
return(r);
}
/* The whole block has been searched or ENTER has a free slot. */
if (e_hit) break; /* e_hit set if ENTER can be performed now */
+ assert(lmfs_dev(bp) != NO_DEV);
put_block(bp, DIRECTORY_BLOCK); /* otherwise, continue searching dir */
}
#include "inode.h"
#include "super.h"
#include <minix/vfsif.h>
+#include <sys/param.h>
#include <assert.h>
gid = (cp_grant_id_t) fs_m_in.REQ_GRANT;
position = (off_t) fs_m_in.REQ_SEEK_POS_LO;
nrbytes = (size_t) fs_m_in.REQ_NBYTES;
-
+
lmfs_reset_rdwt_err();
/* If this is file i/o, check we can write */
int n, block_spec;
block_t b;
dev_t dev;
+ ino_t ino = VMC_NO_INODE;
+ u64_t ino_off = rounddown(position, block_size);
/* rw_flag:
* READING: read from FS, copy to user
} else {
if (ex64hi(position) != 0)
panic("rw_chunk: position too high");
- b = read_map(rip, (off_t) ex64lo(position));
+ b = read_map(rip, (off_t) ex64lo(position), 0);
dev = rip->i_dev;
+ ino = rip->i_num;
+ assert(ino != VMC_NO_INODE);
}
if (!block_spec && b == NO_BLOCK) {
n = (chunk == block_size ? NO_READ : NORMAL);
if (!block_spec && off == 0 && (off_t) ex64lo(position) >= rip->i_size)
n = NO_READ;
- bp = get_block(dev, b, n);
+ if(block_spec) {
+ assert(ino == VMC_NO_INODE);
+ bp = get_block(dev, b, n);
+ } else {
+ assert(ino != VMC_NO_INODE);
+ assert(!(ino_off % block_size));
+ bp = lmfs_get_block_ino(dev, b, n, ino, ino_off);
+ }
}
/* In all cases, bp now points to a valid buffer. */
/*===========================================================================*
* read_map *
*===========================================================================*/
-block_t read_map(rip, position)
+block_t read_map(rip, position, opportunistic)
register struct inode *rip; /* ptr to inode to map from */
off_t position; /* position in file whose blk wanted */
+int opportunistic; /* if nonzero, only use cache for metadata */
{
/* Given an inode and a position within the corresponding file, locate the
* block (not zone) number in which that position is to be found and return it.
unsigned int dzones, nr_indirects;
block_t b;
unsigned long excess, zone, block_pos;
-
+ int iomode = NORMAL;
+
+ if(opportunistic) iomode = PREFETCH;
+
scale = rip->i_sp->s_log_zone_size; /* for block-zone conversion */
block_pos = position/rip->i_sp->s_block_size; /* relative blk # in file */
zone = block_pos >> scale; /* position's zone */
index = (int) (excess/nr_indirects);
if ((unsigned int) index > rip->i_nindirs)
return(NO_BLOCK); /* Can't go beyond double indirects */
- bp = get_block(rip->i_dev, b, NORMAL); /* get double indirect block */
+ bp = get_block(rip->i_dev, b, iomode); /* get double indirect block */
+ if(opportunistic && lmfs_dev(bp) == NO_DEV) {
+ put_block(bp, INDIRECT_BLOCK);
+ return NO_BLOCK;
+ }
ASSERT(lmfs_dev(bp) != NO_DEV);
ASSERT(lmfs_dev(bp) == rip->i_dev);
z = rd_indir(bp, index); /* z= zone for single*/
/* 'z' is zone num for single indirect block; 'excess' is index into it. */
if (z == NO_ZONE) return(NO_BLOCK);
b = (block_t) z << scale; /* b is blk # for single ind */
- bp = get_block(rip->i_dev, b, NORMAL); /* get single indirect block */
+ bp = get_block(rip->i_dev, b, iomode); /* get single indirect block */
+ if(opportunistic && lmfs_dev(bp) == NO_DEV) {
+ put_block(bp, INDIRECT_BLOCK);
+ return NO_BLOCK;
+ }
z = rd_indir(bp, (int) excess); /* get block pointed to */
put_block(bp, INDIRECT_BLOCK); /* release single indir blk */
if (z == NO_ZONE) return(NO_BLOCK);
return(b);
}
+struct buf *get_block_map(register struct inode *rip, u64_t position)
+{
+ block_t b = read_map(rip, position, 0); /* get block number */
+ int block_size = get_block_size(rip->i_dev);
+ if(b == NO_BLOCK)
+ return NULL;
+ position = rounddown(position, block_size);
+ assert(rip->i_num != VMC_NO_INODE);
+ return lmfs_get_block_ino(rip->i_dev, b, NORMAL, rip->i_num, position);
+}
/*===========================================================================*
* rd_indir *
struct buf *bp;
static unsigned int readqsize = 0;
static struct buf **read_q;
+ u64_t position_running;
if(readqsize != nr_bufs) {
if(readqsize > 0) {
dev = (dev_t) rip->i_zone[0];
else
dev = rip->i_dev;
+
+ assert(dev != NO_DEV);
block_size = get_block_size(dev);
block = baseblock;
- bp = get_block(dev, block, PREFETCH);
+
+ fragment = position % block_size;
+ position -= fragment;
+ position_running = position;
+ bytes_ahead += fragment;
+ blocks_ahead = (bytes_ahead + block_size - 1) / block_size;
+
+ if(block_spec)
+ bp = get_block(dev, block, PREFETCH);
+ else
+ bp = lmfs_get_block_ino(dev, block, PREFETCH, rip->i_num, position);
+
assert(bp != NULL);
if (lmfs_dev(bp) != NO_DEV) return(bp);
* indirect blocks (but don't call read_map!).
*/
- fragment = rem64u(position, block_size);
- position = sub64u(position, fragment);
- bytes_ahead += fragment;
-
- blocks_ahead = (bytes_ahead + block_size - 1) / block_size;
-
if (block_spec && rip->i_size == 0) {
blocks_left = (block_t) NR_IOREQS;
} else {
/* Acquire block buffers. */
for (;;) {
+ block_t thisblock;
read_q[read_q_size++] = bp;
if (--blocks_ahead == 0) break;
if (lmfs_bufs_in_use() >= nr_bufs - 4) break;
block++;
+ position_running += block_size;
- bp = get_block(dev, block, PREFETCH);
+ if(!block_spec &&
+ (thisblock = read_map(rip, (off_t) ex64lo(position_running), 1)) != NO_BLOCK) {
+ bp = lmfs_get_block_ino(dev, thisblock, PREFETCH, rip->i_num, position_running);
+ } else {
+ bp = get_block(dev, block, PREFETCH);
+ }
if (lmfs_dev(bp) != NO_DEV) {
/* Oops, block already in the cache, get out. */
put_block(bp, FULL_DATA_BLOCK);
}
}
lmfs_rw_scattered(dev, read_q, read_q_size, READING);
- return(get_block(dev, baseblock, NORMAL));
+
+ if(block_spec)
+ return get_block(dev, baseblock, NORMAL);
+ return(lmfs_get_block_ino(dev, baseblock, NORMAL, rip->i_num, position));
}
int o, r, done;
unsigned int block_size, len, reclen;
ino_t ino;
- block_t b;
cp_grant_id_t gid;
size_t size, tmpbuf_off, userbuf_off;
off_t pos, off, block_pos, new_pos, ent_pos;
new_pos = rip->i_size;
for(; block_pos < rip->i_size; block_pos += block_size) {
- b = read_map(rip, block_pos); /* get block number */
-
- /* Since directories don't have holes, 'b' cannot be NO_BLOCK. */
- bp = get_block(rip->i_dev, b, NORMAL); /* get a dir block */
-
+ /* Since directories don't have holes, 'bp' cannot be NULL. */
+ bp = get_block_map(rip, block_pos); /* get a dir block */
assert(bp != NULL);
/* Search a directory block. */
#include "fs.h"
#include <string.h>
+#include <assert.h>
+#include <sys/param.h>
#include "buf.h"
#include "inode.h"
#include "super.h"
z1 = NO_ZONE;
} else {
b = (block_t) z << scale;
- bp_dindir = get_block(rip->i_dev, b, (new_dbl?NO_READ:NORMAL));
+ bp_dindir = get_block(rip->i_dev, b,
+ (new_dbl?NO_READ:NORMAL));
if (new_dbl) zero_block(bp_dindir);
z1 = rd_indir(bp_dindir, ind_ex);
}
* a byte in the first block to be zeroed. Clearzone() is called from
* fs_readwrite(), truncate_inode(), and new_block().
*/
-
- struct buf *bp;
- block_t b, blo, bhi;
- off_t next;
- int scale, zone_size;
+ int scale;
/* If the block size and zone size are the same, clear_zone() not needed. */
scale = rip->i_sp->s_log_zone_size;
- if (scale == 0) return;
-
- zone_size = rip->i_sp->s_block_size << scale;
- if (flag == 1) pos = (off_t) ((pos/zone_size) * zone_size);
- next = pos + rip->i_sp->s_block_size - 1;
-
- /* If 'pos' is in the last block of a zone, do not clear the zone. */
- if (next/zone_size != pos/zone_size) return;
- if ( (blo = read_map(rip, next)) == NO_BLOCK) return;
- bhi = (block_t) ( ((blo>>scale)+1) << scale) - 1;
-
- /* Clear all the blocks between 'blo' and 'bhi'. */
- for (b = blo; b <= bhi; b++) {
- bp = get_block(rip->i_dev, b, NO_READ);
- zero_block(bp);
- put_block(bp, FULL_DATA_BLOCK);
- }
+ assert(scale == 0);
+ return;
}
int scale, r;
/* Is another block available in the current zone? */
- if ( (b = read_map(rip, position)) == NO_BLOCK) {
+ if ( (b = read_map(rip, position, 0)) == NO_BLOCK) {
if (rip->i_zsearch == NO_ZONE) {
/* First search for this file. Start looking from
* the file's first data zone to prevent fragmentation
b = base_block + (block_t)((position % zone_size)/rip->i_sp->s_block_size);
}
- bp = get_block(rip->i_dev, b, NO_READ);
+ bp = lmfs_get_block_ino(rip->i_dev, b, NO_READ, rip->i_num,
+ rounddown(position, rip->i_sp->s_block_size));
zero_block(bp);
return(bp);
}