From: Ben Gras Date: Thu, 25 Apr 2013 12:03:40 +0000 (+0000) Subject: ext2: annotate cache blocks with inode metadata X-Git-Tag: v3.3.0~1000 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zlib_tech.html?a=commitdiff_plain;h=f497d9b9c4007ce04a7b398d8c80de223aca5ed7;p=minix.git ext2: annotate cache blocks with inode metadata . allows mmap() to work on it Change-Id: I33af8b86ebb408d971478d00ed2caacf15afc7a5 --- diff --git a/sbin/newfs_ext2fs/newfs_ext2fs.c b/sbin/newfs_ext2fs/newfs_ext2fs.c index be9a99831..f3cc5ad89 100644 --- a/sbin/newfs_ext2fs/newfs_ext2fs.c +++ b/sbin/newfs_ext2fs/newfs_ext2fs.c @@ -82,9 +82,17 @@ static void usage(void) __dead; * L_DFL_*. */ #define SMALL_FSSIZE ((4 * 1024 * 1024) / sectorsize) /* 4MB */ +#ifdef __minix +#define S_DFL_BSIZE 4096 +#else #define S_DFL_BSIZE 1024 +#endif #define MEDIUM_FSSIZE ((512 * 1024 * 1024) / sectorsize) /* 512MB */ +#ifdef __minix +#define M_DFL_BSIZE 4096 +#else #define M_DFL_BSIZE 1024 +#endif #define L_DFL_BSIZE 4096 /* diff --git a/servers/ext2/link.c b/servers/ext2/link.c index b2e20ec74..939d9e9c0 100644 --- a/servers/ext2/link.c +++ b/servers/ext2/link.c @@ -10,6 +10,7 @@ #include "inode.h" #include "super.h" #include +#include #define SAME 1000 @@ -181,7 +182,6 @@ int fs_unlink() *===========================================================================*/ int fs_rdlink() { - block_t b; /* block containing link text */ struct buf *bp = NULL; /* buffer containing link text */ char* link_text; /* either bp->b_data or rip->i_block */ register struct inode *rip; /* target inode */ @@ -196,16 +196,11 @@ int fs_rdlink() if (rip->i_size >= MAX_FAST_SYMLINK_LENGTH) { /* normal symlink */ - if ((b = read_map(rip, (off_t) 0)) == NO_BLOCK) { + if(!(bp = get_block_map(rip, 0))) { r = EIO; } else { - bp = get_block(rip->i_dev, b, NORMAL); - if (bp != NULL) { - link_text = b_data(bp); - r = OK; - } else { - r = EIO; - } + link_text = b_data(bp); + r = OK; } } else { /* fast symlink, stored in inode */ @@ -715,13 +710,11 @@ off_t len; /* Zero a range in a block. * This function is used to zero a segment of a block. */ - block_t b; struct buf *bp; off_t offset; if (!len) return; /* no zeroing to be done. */ - if ( (b = read_map(rip, pos)) == NO_BLOCK) return; - if ( (bp = get_block(rip->i_dev, b, NORMAL)) == NULL) + if (!(bp = get_block_map(rip, rounddown(pos, rip->i_sp->s_block_size)))) panic("zeroblock_range: no block"); offset = pos % rip->i_sp->s_block_size; if (offset + len > rip->i_sp->s_block_size) diff --git a/servers/ext2/misc.c b/servers/ext2/misc.c index 430a1f602..f0127889d 100644 --- a/servers/ext2/misc.c +++ b/servers/ext2/misc.c @@ -90,3 +90,9 @@ int fs_new_driver(void) return(OK); } + +int fs_bpeek(void) +{ + return lmfs_do_bpeek(&fs_m_in); +} + diff --git a/servers/ext2/path.c b/servers/ext2/path.c index 724262872..54b7aa8ef 100644 --- a/servers/ext2/path.c +++ b/servers/ext2/path.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "buf.h" #include "inode.h" @@ -292,7 +293,6 @@ char *suffix; /* current remaining path. Has to point in the * 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 */ @@ -302,9 +302,8 @@ char *suffix; /* current remaining path. Has to point in the if (llen >= MAX_FAST_SYMLINK_LENGTH) { /* normal symlink */ - 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); sp = b_data(bp); } else { /* fast symlink, stored in inode */ @@ -507,7 +506,6 @@ int ftype; /* used when ENTER and mode_t bits; off_t pos; unsigned new_slots; - block_t b; int extended = 0; int required_space = 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) { - b = read_map(ldir_ptr, pos); /* get block number */ - /* Since directories don't have holes, 'b' cannot be NO_BLOCK. */ - bp = get_block(ldir_ptr->i_dev, b, NORMAL); /* get a dir block */ - prev_dp = NULL; /* New block - new first dentry, so no prev. */ - - if (bp == NO_BLOCK) + if(!(bp = get_block_map(ldir_ptr, + rounddown(pos, ldir_ptr->i_sp->s_block_size)))) panic("get_block returned NO_BLOCK"); - assert(bp != NULL); + + prev_dp = NULL; /* New block - new first dentry, so no prev. */ /* Search a directory block. * 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 */ *numb = (ino_t) conv4(le_CPU, dp->d_ino); } + assert(lmfs_dev(bp) != NO_DEV); put_block(bp, DIRECTORY_BLOCK); return(r); } @@ -661,6 +657,7 @@ int ftype; /* used when ENTER and } /* 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 */ put_block(bp, DIRECTORY_BLOCK); /* otherwise, continue searching dir */ } diff --git a/servers/ext2/proto.h b/servers/ext2/proto.h index 0a9f93ca1..46d285920 100644 --- a/servers/ext2/proto.h +++ b/servers/ext2/proto.h @@ -44,6 +44,7 @@ int truncate_inode(struct inode *rip, off_t len); int fs_flush(void); int fs_sync(void); int fs_new_driver(void); +int fs_bpeek(void); /* mount.c */ int fs_mountpoint(void); @@ -75,8 +76,9 @@ int read_only(struct inode *ip); int fs_breadwrite(void); int fs_readwrite(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 read_map(struct inode *rip, off_t pos, int opportunistic); +struct buf *get_block_map(register struct inode *rip, u64_t position); /* stadir.c */ int fs_fstatfs(void); diff --git a/servers/ext2/read.c b/servers/ext2/read.c index 50cc875cb..64935a1d4 100644 --- a/servers/ext2/read.c +++ b/servers/ext2/read.c @@ -12,6 +12,7 @@ #include "inode.h" #include "super.h" #include +#include #include #include @@ -224,6 +225,8 @@ int *completed; /* number of bytes copied */ 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 @@ -241,8 +244,10 @@ int *completed; /* number of bytes copied */ } 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) { @@ -272,7 +277,14 @@ int *completed; /* number of bytes copied */ 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. */ @@ -305,9 +317,10 @@ int *completed; /* number of bytes copied */ /*===========================================================================* * 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; { /* 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. @@ -323,6 +336,9 @@ off_t position; /* position in file whose blk wanted */ static long doub_ind_s; static long triple_ind_s; static long out_range_s; + int iomode = NORMAL; + + if(opportunistic) iomode = PREFETCH; if (first_time) { 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; } 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) == rip->i_dev); 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 */ } 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) == rip->i_dev); b = rd_indir(bp, index); @@ -382,6 +407,16 @@ off_t position; /* position in file whose blk wanted */ 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 * @@ -414,7 +449,7 @@ void read_ahead() rip = rdahed_inode; /* pointer to inode to read ahead from */ block_size = get_block_size(rip->i_dev); 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 */ @@ -450,6 +485,7 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */ struct buf *bp = NULL; static unsigned int readqsize = 0; static struct buf **read_q = NULL; + u64_t position_running; if(readqsize != nr_bufs) { if(readqsize > 0) { @@ -473,10 +509,23 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */ 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); @@ -500,12 +549,6 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */ * 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 { @@ -536,6 +579,7 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */ /* Acquire block buffers. */ for (;;) { + block_t thisblock; read_q[read_q_size++] = bp; 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; 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); @@ -553,7 +603,10 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */ } } 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; 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; @@ -604,9 +656,9 @@ int fs_getdents(void) for (; block_pos < rip->i_size; block_pos += block_size) { off_t temp_pos = block_pos; - 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); assert(bp != NULL); /* Search a directory block. */ diff --git a/servers/ext2/table.c b/servers/ext2/table.c index af77d746b..1d779a9a6 100644 --- a/servers/ext2/table.c +++ b/servers/ext2/table.c @@ -46,11 +46,6 @@ int (*fs_call_vec[])(void) = { fs_rdlink, /* 30 */ fs_getdents, /* 31 */ fs_statvfs, /* 32 */ -#if 0 fs_readwrite, /* 33 */ - no_sys, -#else - no_sys, - no_sys, -#endif + fs_bpeek, /* 34 */ }; diff --git a/servers/ext2/write.c b/servers/ext2/write.c index ffec057ff..fe53161e6 100644 --- a/servers/ext2/write.c +++ b/servers/ext2/write.c @@ -12,6 +12,8 @@ #include "fs.h" #include +#include +#include #include "buf.h" #include "inode.h" #include "super.h" @@ -316,7 +318,7 @@ off_t position; /* file pointer */ block_t b; /* 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 * 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); return(bp); }