ext2: annotate cache blocks with inode metadata

. allows mmap() to work on it

Change-Id: I33af8b86ebb408d971478d00ed2caacf15afc7a5
This commit is contained in:
Ben Gras 2013-04-25 12:03:40 +00:00
parent f0cc010614
commit f497d9b9c4
8 changed files with 107 additions and 51 deletions

View file

@ -82,9 +82,17 @@ static void usage(void) __dead;
* L_DFL_*. * L_DFL_*.
*/ */
#define SMALL_FSSIZE ((4 * 1024 * 1024) / sectorsize) /* 4MB */ #define SMALL_FSSIZE ((4 * 1024 * 1024) / sectorsize) /* 4MB */
#ifdef __minix
#define S_DFL_BSIZE 4096
#else
#define S_DFL_BSIZE 1024 #define S_DFL_BSIZE 1024
#endif
#define MEDIUM_FSSIZE ((512 * 1024 * 1024) / sectorsize) /* 512MB */ #define MEDIUM_FSSIZE ((512 * 1024 * 1024) / sectorsize) /* 512MB */
#ifdef __minix
#define M_DFL_BSIZE 4096
#else
#define M_DFL_BSIZE 1024 #define M_DFL_BSIZE 1024
#endif
#define L_DFL_BSIZE 4096 #define L_DFL_BSIZE 4096
/* /*

View file

@ -10,6 +10,7 @@
#include "inode.h" #include "inode.h"
#include "super.h" #include "super.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
#include <sys/param.h>
#define SAME 1000 #define SAME 1000
@ -181,7 +182,6 @@ int fs_unlink()
*===========================================================================*/ *===========================================================================*/
int fs_rdlink() int fs_rdlink()
{ {
block_t b; /* block containing link text */
struct buf *bp = NULL; /* buffer containing link text */ struct buf *bp = NULL; /* buffer containing link text */
char* link_text; /* either bp->b_data or rip->i_block */ char* link_text; /* either bp->b_data or rip->i_block */
register struct inode *rip; /* target inode */ register struct inode *rip; /* target inode */
@ -196,16 +196,11 @@ int fs_rdlink()
if (rip->i_size >= MAX_FAST_SYMLINK_LENGTH) { if (rip->i_size >= MAX_FAST_SYMLINK_LENGTH) {
/* normal symlink */ /* normal symlink */
if ((b = read_map(rip, (off_t) 0)) == NO_BLOCK) { if(!(bp = get_block_map(rip, 0))) {
r = EIO; r = EIO;
} else { } else {
bp = get_block(rip->i_dev, b, NORMAL);
if (bp != NULL) {
link_text = b_data(bp); link_text = b_data(bp);
r = OK; r = OK;
} else {
r = EIO;
}
} }
} else { } else {
/* fast symlink, stored in inode */ /* fast symlink, stored in inode */
@ -715,13 +710,11 @@ off_t len;
/* Zero a range in a block. /* Zero a range in a block.
* This function is used to zero a segment of a block. * This function is used to zero a segment of a block.
*/ */
block_t b;
struct buf *bp; struct buf *bp;
off_t offset; off_t offset;
if (!len) return; /* no zeroing to be done. */ if (!len) return; /* no zeroing to be done. */
if ( (b = read_map(rip, pos)) == NO_BLOCK) return; if (!(bp = get_block_map(rip, rounddown(pos, rip->i_sp->s_block_size))))
if ( (bp = get_block(rip->i_dev, b, NORMAL)) == NULL)
panic("zeroblock_range: no block"); panic("zeroblock_range: no block");
offset = pos % rip->i_sp->s_block_size; offset = pos % rip->i_sp->s_block_size;
if (offset + len > rip->i_sp->s_block_size) if (offset + len > rip->i_sp->s_block_size)

View file

@ -90,3 +90,9 @@ int fs_new_driver(void)
return(OK); return(OK);
} }
int fs_bpeek(void)
{
return lmfs_do_bpeek(&fs_m_in);
}

View file

@ -16,6 +16,7 @@
#include <string.h> #include <string.h>
#include <minix/endpoint.h> #include <minix/endpoint.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/param.h>
#include <sys/types.h> #include <sys/types.h>
#include "buf.h" #include "buf.h"
#include "inode.h" #include "inode.h"
@ -292,7 +293,6 @@ char *suffix; /* current remaining path. Has to point in the
* new pathname. * new pathname.
*/ */
block_t blink; /* block containing link text */
size_t llen; /* length of link */ size_t llen; /* length of link */
size_t slen; /* length of suffix */ size_t slen; /* length of suffix */
struct buf *bp; /* buffer containing link text */ struct buf *bp; /* buffer containing link text */
@ -302,9 +302,8 @@ char *suffix; /* current remaining path. Has to point in the
if (llen >= MAX_FAST_SYMLINK_LENGTH) { if (llen >= MAX_FAST_SYMLINK_LENGTH) {
/* normal symlink */ /* normal symlink */
if ((blink = read_map(rip, (off_t) 0)) == NO_BLOCK) if(!(bp = get_block_map(rip, 0)))
return(EIO); return(EIO);
bp = get_block(rip->i_dev, blink, NORMAL);
sp = b_data(bp); sp = b_data(bp);
} else { } else {
/* fast symlink, stored in inode */ /* fast symlink, stored in inode */
@ -507,7 +506,6 @@ int ftype; /* used when ENTER and
mode_t bits; mode_t bits;
off_t pos; off_t pos;
unsigned new_slots; unsigned new_slots;
block_t b;
int extended = 0; int extended = 0;
int required_space = 0; int required_space = 0;
int string_len = 0; int string_len = 0;
@ -548,15 +546,12 @@ int ftype; /* used when ENTER and
} }
for (; pos < ldir_ptr->i_size; pos += ldir_ptr->i_sp->s_block_size) { for (; pos < ldir_ptr->i_size; pos += ldir_ptr->i_sp->s_block_size) {
b = read_map(ldir_ptr, pos); /* get block number */
/* Since directories don't have holes, 'b' cannot be NO_BLOCK. */ /* Since directories don't have holes, 'b' cannot be NO_BLOCK. */
bp = get_block(ldir_ptr->i_dev, b, NORMAL); /* get a dir block */ if(!(bp = get_block_map(ldir_ptr,
prev_dp = NULL; /* New block - new first dentry, so no prev. */ rounddown(pos, ldir_ptr->i_sp->s_block_size))))
if (bp == NO_BLOCK)
panic("get_block returned NO_BLOCK"); panic("get_block returned NO_BLOCK");
assert(bp != NULL);
prev_dp = NULL; /* New block - new first dentry, so no prev. */
/* Search a directory block. /* Search a directory block.
* Note, we set prev_dp at the end of the loop. * Note, we set prev_dp at the end of the loop.
@ -627,6 +622,7 @@ int ftype; /* used when ENTER and
/* 'flag' is LOOK_UP */ /* 'flag' is LOOK_UP */
*numb = (ino_t) conv4(le_CPU, dp->d_ino); *numb = (ino_t) conv4(le_CPU, dp->d_ino);
} }
assert(lmfs_dev(bp) != NO_DEV);
put_block(bp, DIRECTORY_BLOCK); put_block(bp, DIRECTORY_BLOCK);
return(r); return(r);
} }
@ -661,6 +657,7 @@ int ftype; /* used when ENTER and
} }
/* The whole block has been searched or ENTER has a free slot. */ /* The whole block has been searched or ENTER has a free slot. */
assert(lmfs_dev(bp) != NO_DEV);
if (e_hit) break; /* e_hit set if ENTER can be performed now */ if (e_hit) break; /* e_hit set if ENTER can be performed now */
put_block(bp, DIRECTORY_BLOCK); /* otherwise, continue searching dir */ put_block(bp, DIRECTORY_BLOCK); /* otherwise, continue searching dir */
} }

View file

@ -44,6 +44,7 @@ int truncate_inode(struct inode *rip, off_t len);
int fs_flush(void); int fs_flush(void);
int fs_sync(void); int fs_sync(void);
int fs_new_driver(void); int fs_new_driver(void);
int fs_bpeek(void);
/* mount.c */ /* mount.c */
int fs_mountpoint(void); int fs_mountpoint(void);
@ -75,8 +76,9 @@ int read_only(struct inode *ip);
int fs_breadwrite(void); int fs_breadwrite(void);
int fs_readwrite(void); int fs_readwrite(void);
void read_ahead(void); void read_ahead(void);
block_t read_map(struct inode *rip, off_t pos);
block_t rd_indir(struct buf *bp, int index); block_t rd_indir(struct buf *bp, int index);
block_t read_map(struct inode *rip, off_t pos, int opportunistic);
struct buf *get_block_map(register struct inode *rip, u64_t position);
/* stadir.c */ /* stadir.c */
int fs_fstatfs(void); int fs_fstatfs(void);

View file

@ -12,6 +12,7 @@
#include "inode.h" #include "inode.h"
#include "super.h" #include "super.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
#include <sys/param.h>
#include <assert.h> #include <assert.h>
#include <sys/param.h> #include <sys/param.h>
@ -224,6 +225,8 @@ int *completed; /* number of bytes copied */
int n, block_spec; int n, block_spec;
block_t b; block_t b;
dev_t dev; dev_t dev;
ino_t ino = VMC_NO_INODE;
u64_t ino_off = rounddown(position, block_size);
/* rw_flag: /* rw_flag:
* READING: read from FS, copy to user * READING: read from FS, copy to user
@ -241,8 +244,10 @@ int *completed; /* number of bytes copied */
} else { } else {
if (ex64hi(position) != 0) if (ex64hi(position) != 0)
panic("rw_chunk: position too high"); 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; dev = rip->i_dev;
ino = rip->i_num;
assert(ino != VMC_NO_INODE);
} }
if (!block_spec && b == NO_BLOCK) { if (!block_spec && b == NO_BLOCK) {
@ -272,7 +277,14 @@ int *completed; /* number of bytes copied */
n = (chunk == block_size ? NO_READ : NORMAL); n = (chunk == block_size ? NO_READ : NORMAL);
if (!block_spec && off == 0 && (off_t) ex64lo(position) >= rip->i_size) if (!block_spec && off == 0 && (off_t) ex64lo(position) >= rip->i_size)
n = NO_READ; n = NO_READ;
if(block_spec) {
assert(ino == VMC_NO_INODE);
bp = get_block(dev, b, n); 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. */ /* In all cases, bp now points to a valid buffer. */
@ -305,9 +317,10 @@ int *completed; /* number of bytes copied */
/*===========================================================================* /*===========================================================================*
* read_map * * 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 */ register struct inode *rip; /* ptr to inode to map from */
off_t position; /* position in file whose blk wanted */ off_t position; /* position in file whose blk wanted */
int opportunistic;
{ {
/* Given an inode and a position within the corresponding file, locate the /* Given an inode and a position within the corresponding file, locate the
* block number in which that position is to be found and return it. * block number in which that position is to be found and return it.
@ -323,6 +336,9 @@ off_t position; /* position in file whose blk wanted */
static long doub_ind_s; static long doub_ind_s;
static long triple_ind_s; static long triple_ind_s;
static long out_range_s; static long out_range_s;
int iomode = NORMAL;
if(opportunistic) iomode = PREFETCH;
if (first_time) { if (first_time) {
addr_in_block = rip->i_sp->s_block_size / BLOCK_ADDRESS_BYTES; addr_in_block = rip->i_sp->s_block_size / BLOCK_ADDRESS_BYTES;
@ -364,7 +380,11 @@ off_t position; /* position in file whose blk wanted */
excess = excess % addr_in_block2; excess = excess % addr_in_block2;
} }
if (b == NO_BLOCK) return(NO_BLOCK); if (b == NO_BLOCK) return(NO_BLOCK);
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) != NO_DEV);
ASSERT(lmfs_dev(bp) == rip->i_dev); ASSERT(lmfs_dev(bp) == rip->i_dev);
index = excess / addr_in_block; index = excess / addr_in_block;
@ -373,7 +393,12 @@ off_t position; /* position in file whose blk wanted */
index = excess % addr_in_block; /* index into single ind blk */ index = excess % addr_in_block; /* index into single ind blk */
} }
if (b == NO_BLOCK) return(NO_BLOCK); if (b == NO_BLOCK) return(NO_BLOCK);
bp = get_block(rip->i_dev, b, NORMAL); 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;
}
ASSERT(lmfs_dev(bp) != NO_DEV); ASSERT(lmfs_dev(bp) != NO_DEV);
ASSERT(lmfs_dev(bp) == rip->i_dev); ASSERT(lmfs_dev(bp) == rip->i_dev);
b = rd_indir(bp, index); b = rd_indir(bp, index);
@ -382,6 +407,16 @@ off_t position; /* position in file whose blk wanted */
return(b); 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 * * rd_indir *
@ -414,7 +449,7 @@ void read_ahead()
rip = rdahed_inode; /* pointer to inode to read ahead from */ rip = rdahed_inode; /* pointer to inode to read ahead from */
block_size = get_block_size(rip->i_dev); block_size = get_block_size(rip->i_dev);
rdahed_inode = NULL; /* turn off read ahead */ rdahed_inode = NULL; /* turn off read ahead */
if ( (b = read_map(rip, rdahedpos)) == NO_BLOCK) return; /* at EOF */ if ( (b = read_map(rip, rdahedpos, 1)) == NO_BLOCK) return; /* at EOF */
assert(rdahedpos >= 0); /* So we can safely cast it to unsigned below */ assert(rdahedpos >= 0); /* So we can safely cast it to unsigned below */
@ -450,6 +485,7 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */
struct buf *bp = NULL; struct buf *bp = NULL;
static unsigned int readqsize = 0; static unsigned int readqsize = 0;
static struct buf **read_q = NULL; static struct buf **read_q = NULL;
u64_t position_running;
if(readqsize != nr_bufs) { if(readqsize != nr_bufs) {
if(readqsize > 0) { if(readqsize > 0) {
@ -473,10 +509,23 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */
else else
dev = rip->i_dev; dev = rip->i_dev;
assert(dev != NO_DEV);
block_size = get_block_size(dev); block_size = get_block_size(dev);
block = baseblock; block = baseblock;
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); bp = get_block(dev, block, PREFETCH);
else
bp = lmfs_get_block_ino(dev, block, PREFETCH, rip->i_num, position);
assert(bp != NULL); assert(bp != NULL);
if (lmfs_dev(bp) != NO_DEV) return(bp); if (lmfs_dev(bp) != NO_DEV) return(bp);
@ -500,12 +549,6 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */
* indirect blocks (but don't call read_map!). * 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) { if (block_spec && rip->i_size == 0) {
blocks_left = (block_t) NR_IOREQS; blocks_left = (block_t) NR_IOREQS;
} else { } else {
@ -536,6 +579,7 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */
/* Acquire block buffers. */ /* Acquire block buffers. */
for (;;) { for (;;) {
block_t thisblock;
read_q[read_q_size++] = bp; read_q[read_q_size++] = bp;
if (--blocks_ahead == 0) break; if (--blocks_ahead == 0) break;
@ -544,8 +588,14 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */
if (lmfs_bufs_in_use() >= nr_bufs - 4) break; if (lmfs_bufs_in_use() >= nr_bufs - 4) break;
block++; block++;
position_running += block_size;
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); bp = get_block(dev, block, PREFETCH);
}
if (lmfs_dev(bp) != NO_DEV) { if (lmfs_dev(bp) != NO_DEV) {
/* Oops, block already in the cache, get out. */ /* Oops, block already in the cache, get out. */
put_block(bp, FULL_DATA_BLOCK); put_block(bp, FULL_DATA_BLOCK);
@ -553,7 +603,10 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */
} }
} }
lmfs_rw_scattered(dev, read_q, read_q_size, READING); 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));
} }
@ -569,7 +622,6 @@ int fs_getdents(void)
int o, r, done; int o, r, done;
unsigned int block_size, len, reclen; unsigned int block_size, len, reclen;
ino_t ino; ino_t ino;
block_t b;
cp_grant_id_t gid; cp_grant_id_t gid;
size_t size, tmpbuf_off, userbuf_off; size_t size, tmpbuf_off, userbuf_off;
off_t pos, off, block_pos, new_pos, ent_pos; off_t pos, off, block_pos, new_pos, ent_pos;
@ -604,9 +656,9 @@ int fs_getdents(void)
for (; block_pos < rip->i_size; block_pos += block_size) { for (; block_pos < rip->i_size; block_pos += block_size) {
off_t temp_pos = block_pos; off_t temp_pos = block_pos;
b = read_map(rip, block_pos); /* get block number */ /* Since directories don't have holes, 'bp' cannot be NULL. */
/* Since directories don't have holes, 'b' cannot be NO_BLOCK. */ bp = get_block_map(rip, block_pos); /* get a dir block */
bp = get_block(rip->i_dev, b, NORMAL); /* get a dir block */ assert(bp != NULL);
assert(bp != NULL); assert(bp != NULL);
/* Search a directory block. */ /* Search a directory block. */

View file

@ -46,11 +46,6 @@ int (*fs_call_vec[])(void) = {
fs_rdlink, /* 30 */ fs_rdlink, /* 30 */
fs_getdents, /* 31 */ fs_getdents, /* 31 */
fs_statvfs, /* 32 */ fs_statvfs, /* 32 */
#if 0
fs_readwrite, /* 33 */ fs_readwrite, /* 33 */
no_sys, fs_bpeek, /* 34 */
#else
no_sys,
no_sys,
#endif
}; };

View file

@ -12,6 +12,8 @@
#include "fs.h" #include "fs.h"
#include <string.h> #include <string.h>
#include <assert.h>
#include <sys/param.h>
#include "buf.h" #include "buf.h"
#include "inode.h" #include "inode.h"
#include "super.h" #include "super.h"
@ -316,7 +318,7 @@ off_t position; /* file pointer */
block_t b; block_t b;
/* Is another block available? */ /* Is another block available? */
if ( (b = read_map(rip, position)) == NO_BLOCK) { if ( (b = read_map(rip, position, 0)) == NO_BLOCK) {
/* Check if this position follows last allocated /* Check if this position follows last allocated
* block. * block.
*/ */
@ -359,7 +361,8 @@ off_t position; /* file pointer */
} }
} }
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); zero_block(bp);
return(bp); return(bp);
} }