Mercurial > hvf > hvf-old
changeset 512:cb3926aac584
cp/fs: rewrite the EDF code to use the block cache
Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Mon, 25 Apr 2011 09:15:29 -0400 |
parents | 162125ad17ee |
children | c5b9bc302571 |
files | cp/fs/edf.c cp/include/edf.h cp/nucleus/config.c |
diffstat | 3 files changed, 183 insertions(+), 109 deletions(-) [+] |
line wrap: on
line diff
--- a/cp/fs/edf.c Mon Apr 25 09:15:18 2011 -0400 +++ b/cp/fs/edf.c Mon Apr 25 09:15:29 2011 -0400 @@ -12,10 +12,80 @@ #include <bdev.h> #include <ebcdic.h> #include <edf.h> +#include <bcache.h> static LOCK_CLASS(edf_fs); +static LOCK_CLASS(edf_dir); static LOCK_CLASS(edf_file); +/* assumes that fs->lock is held */ +struct file *__alloc_file(struct fs *fs, struct FST *fst) +{ + struct file *file; + + file = malloc(sizeof(struct file), ZONE_NORMAL); + if (!file) + return ERR_PTR(-ENOMEM); + + memset(file, 0, sizeof(struct file)); + + if (fst) + memcpy(&file->FST, fst, sizeof(struct FST)); + + INIT_LIST_HEAD(&file->files); + INIT_LIST_HEAD(&file->bcache); + mutex_init(&file->lock, &edf_file); + + file->fs = fs; + + list_add_tail(&file->files, &fs->files); + + return file; +} + +/* assumes that fs->lock is held */ +void __free_file(struct file *file) +{ + list_del(&file->files); + free(file); +} + +int __init_dir(struct fs *fs, void *tmp) +{ + struct FST *fst = tmp; + struct file *file; + int ret; + + ret = bdev_read_block(fs->dev, tmp, fs->ADT.DOP); + if (ret) + return ret; + + if (memcmp(fst[0].FNAME, DIRECTOR_FN, 8) || + memcmp(fst[0].FTYPE, DIRECTOR_FT, 8) || + (fst[0].RECFM != FSTDFIX) || + memcmp(fst[1].FNAME, ALLOCMAP_FN, 8) || + memcmp(fst[1].FTYPE, ALLOCMAP_FT, 8) || + (fst[1].RECFM != FSTDFIX)) + return -ECORRUPT; + + file = __alloc_file(fs, &fst[0]); + if (IS_ERR(file)) + return PTR_ERR(file); + + /* need to override the default lock class */ + mutex_init(&file->lock, &edf_dir); + + ret = bcache_add(file, 0, 0, fs->ADT.DOP); + if (ret) { + __free_file(file); + return ret; + } + + fs->dir = file; + + return 0; +} + struct fs *edf_mount(struct device *dev) { struct page *page; @@ -41,17 +111,23 @@ mutex_init(&fs->lock, &edf_fs); INIT_LIST_HEAD(&fs->files); fs->dev = dev; - fs->tmp_buf = tmp; memcpy(&fs->ADT, tmp, sizeof(struct ADT)); ret = -EINVAL; - if ((fs->ADT.ADTIDENT != __ADTIDENT) || - (fs->ADT.ADTDBSIZ != EDF_SUPPORTED_BLOCK_SIZE) || - (fs->ADT.ADTOFFST != 0) || - (fs->ADT.ADTFSTSZ != sizeof(struct FST))) + if ((fs->ADT.IDENT != __ADTIDENT) || + (fs->ADT.DBSIZ != EDF_SUPPORTED_BLOCK_SIZE) || + (fs->ADT.OFFST != 0) || + (fs->ADT.FSTSZ != sizeof(struct FST))) goto out_free; + ret = __init_dir(fs, tmp); + if (ret) + goto out_free; + + /* FIXME: init the ALLOCMAP */ + + free_pages(tmp, 0); return fs; out_free: @@ -60,26 +136,16 @@ return ERR_PTR(ret); } -extern struct console *oper_con; struct file *edf_lookup(struct fs *fs, char *fn, char *ft) { char __fn[8]; char __ft[8]; - struct page *page; struct file *file; - struct file *tmpf; struct FST *fst; - long ret; - int found; + u32 blk; + int ret; int i; - file = malloc(sizeof(struct file), ZONE_NORMAL); - if (!file) - return ERR_PTR(-ENOMEM); - - file->fs = fs; - file->buf = NULL; - memcpy(__fn, fn, 8); memcpy(__ft, ft, 8); ascii2ebcdic((u8 *) __fn, 8); @@ -88,43 +154,39 @@ mutex_lock(&fs->lock); /* first, check the cache */ - list_for_each_entry(tmpf, &fs->files, files) { - if (!memcmp((char*) tmpf->FST.FSTFNAME, __fn, 8) && - !memcmp((char*) tmpf->FST.FSTFTYPE, __ft, 8)) { + list_for_each_entry(file, &fs->files, files) { + if (!memcmp((char*) file->FST.FNAME, __fn, 8) && + !memcmp((char*) file->FST.FTYPE, __ft, 8)) { mutex_unlock(&fs->lock); - free(file); - return tmpf; + return file; } } - page = alloc_pages(0, ZONE_NORMAL); - if (!page) { - ret = -ENOMEM; - goto out_unlock; + /* the slow path */ + file = __alloc_file(fs, NULL); + if (IS_ERR(file)) { + ret = PTR_ERR(file); + goto out; } - file->buf = page_to_addr(page); - /* oh well, must do it the hard way ... read from disk */ - ret = bdev_read_block(fs->dev, fs->tmp_buf, fs->ADT.ADTDOP); - if (ret) - goto out_unlock; - - fst = fs->tmp_buf; + for(blk=0; blk<fs->dir->FST.ADBC; blk++) { + fst = bcache_read(fs->dir, 0, blk); + if (IS_ERR(fst)) + goto out_free; - for(i=0,found=0; i<fs->ADT.ADTNFST; i++) { - if ((!memcmp(fst[i].FSTFNAME, __fn, 8)) && - (!memcmp(fst[i].FSTFTYPE, __ft, 8))) { - memcpy(&file->FST, &fst[i], sizeof(struct FST)); - found = 1; - break; + for(i=0; i<fs->ADT.NFST; i++) { + if ((!memcmp(fst[i].FNAME, __fn, 8)) && + (!memcmp(fst[i].FTYPE, __ft, 8))) { + memcpy(&file->FST, &fst[i], sizeof(struct FST)); + goto found; + } } } - if (!found) { - ret = -ENOENT; - goto out_unlock; - } + ret = -ENOENT; + goto out_free; +found: mutex_init(&file->lock, &edf_file); list_add_tail(&file->files, &fs->files); @@ -132,36 +194,43 @@ return file; -out_unlock: - if (file && file->buf) - free_pages(file->buf, 0); +out_free: + __free_file(file); + +out: mutex_unlock(&fs->lock); - free(file); return ERR_PTR(ret); } int edf_read_rec(struct file *file, char *buf, u32 recno) { struct fs *fs = file->fs; - u32 fop, lrecl; - int ret; - - if (file->FST.FSTNLVL != 0 || - file->FST.FSTPTRSZ != 4 || - file->FST.FSTLRECL > fs->ADT.ADTDBSIZ || - file->FST.FSTRECFM != FSTDFIX) - return -EINVAL; + u32 blk, off; + char *dbuf; + int ret = -EINVAL; mutex_lock(&file->lock); - fop = file->FST.FSTFOP; - lrecl = file->FST.FSTLRECL; - - ret = bdev_read_block(fs->dev, file->buf, fop); - if (ret) + if (file->FST.NLVL != 0 || + file->FST.PTRSZ != 4 || + file->FST.LRECL > fs->ADT.DBSIZ || + file->FST.RECFM != FSTDFIX) goto out; - memcpy(buf, file->buf + (recno * lrecl), lrecl); + blk = (recno * file->FST.LRECL) / fs->ADT.DBSIZ; + off = (recno * file->FST.LRECL) % fs->ADT.DBSIZ; + + dbuf = bcache_read(file, 0, blk); + if (IS_ERR(dbuf)) { + ret = PTR_ERR(dbuf); + goto out; + } + + BUG_ON((off + file->FST.LRECL) > fs->ADT.DBSIZ); + + memcpy(buf, dbuf + off, file->FST.LRECL); + + ret = 0; out: mutex_unlock(&file->lock); @@ -174,8 +243,6 @@ struct fs *fs = file->fs; mutex_lock(&fs->lock); - list_del(&file->files); + __free_file(file); mutex_unlock(&fs->lock); - - free(file); }
--- a/cp/include/edf.h Mon Apr 25 09:15:18 2011 -0400 +++ b/cp/include/edf.h Mon Apr 25 09:15:29 2011 -0400 @@ -12,45 +12,45 @@ #include <device.h> struct ADT { - u32 ADTIDENT; /* VOL START / LABEL IDENTIFIER */ + u32 IDENT; /* VOL START / LABEL IDENTIFIER */ #define __ADTIDENT 0xC3D4E2F1 /* 'CMS1' in EBCDIC */ - u8 ADTID[6]; /* VOL START / VOL IDENTIFIER */ - u8 ADTVER[2]; /* VERSION LEVEL */ - u32 ADTDBSIZ; /* DISK BLOCK SIZE */ - u32 ADTDOP; /* DISK ORIGIN POINTER */ - u32 ADTCYL; /* NUM OF FORMATTED CYL ON DISK */ - u32 ADTMCYL; /* MAX NUM FORMATTED CYL ON DISK */ - u32 ADTNUM; /* Number of Blocks on disk */ - u32 ADTUSED; /* Number of Blocks used */ - u32 ADTFSTSZ; /* SIZE OF FST */ - u32 ADTNFST; /* NUMBER OF FST'S PER BLOCK */ - u8 ADTDCRED[6]; /* DISK CREATION DATE (YYMMDDHHMMSS) */ - u8 ADTFLGL; /* LABEL FLAG BYTE (ADTFLGL) */ + u8 ID[6]; /* VOL START / VOL IDENTIFIER */ + u8 VER[2]; /* VERSION LEVEL */ + u32 DBSIZ; /* DISK BLOCK SIZE */ + u32 DOP; /* DISK ORIGIN POINTER */ + u32 CYL; /* NUM OF FORMATTED CYL ON DISK */ + u32 MCYL; /* MAX NUM FORMATTED CYL ON DISK */ + u32 NUM; /* Number of Blocks on disk */ + u32 USED; /* Number of Blocks used */ + u32 FSTSZ; /* SIZE OF FST */ + u32 NFST; /* NUMBER OF FST'S PER BLOCK */ + u8 DCRED[6]; /* DISK CREATION DATE (YYMMDDHHMMSS) */ + u8 FLGL; /* LABEL FLAG BYTE (ADTFLGL) */ #define ADTCNTRY 0x01 /* Century for disk creation date (0=19, 1=20), * corresponds to ADTDCRED. */ u8 reserved[1]; - u32 ADTOFFST; /* DISK OFFSET WHEN RESERVED */ - u32 ADTAMNB; /* ALLOC MAP BLOCK WITH NEXT HOLE */ - u32 ADTAMND; /* DISP INTO HBLK DATA OF NEXT HOLE */ - u32 ADTAMUP; /* DISP INTO USER PART OF ALLOC MAP */ - u32 ADTOFCNT; /* Count of SFS open files for this ADT */ - u8 ADTSFNAM[8]; /* NAME OF SHARED SEGMENT */ + u32 OFFST; /* DISK OFFSET WHEN RESERVED */ + u32 AMNB; /* ALLOC MAP BLOCK WITH NEXT HOLE */ + u32 AMND; /* DISP INTO HBLK DATA OF NEXT HOLE */ + u32 AMUP; /* DISP INTO USER PART OF ALLOC MAP */ + u32 OFCNT; /* Count of SFS open files for this ADT */ + u8 SFNAM[8]; /* NAME OF SHARED SEGMENT */ }; struct FST { - u8 FSTFNAME[8]; /* filename */ - u8 FSTFTYPE[8]; /* filetype */ - u8 FSTDATEW[2]; /* DATE LAST WRITTEN - MMDD */ - u8 FSTTIMEW[2]; /* TIME LAST WRITTEN - HHMM */ - u16 FSTWRPNT; /* WRITE POINTER - ITEM NUMBER */ - u16 FSTRDPNT; /* READ POINTER - ITEM NUMBER */ - u8 FSTFMODE[2]; /* FILE MODE - LETTER AND NUMBER */ - u16 FSTRECCT; /* NUMBER OF LOGICAL RECORDS */ - u16 FSTFCLPT; /* FIRST CHAIN LINK POINTER */ - u8 FSTRECFM; /* F*1 - RECORD FORMAT - F OR V */ + u8 FNAME[8]; /* filename */ + u8 FTYPE[8]; /* filetype */ + u8 DATEW[2]; /* DATE LAST WRITTEN - MMDD */ + u8 TIMEW[2]; /* TIME LAST WRITTEN - HHMM */ + u16 WRPNT; /* WRITE POINTER - ITEM NUMBER */ + u16 RDPNT; /* READ POINTER - ITEM NUMBER */ + u8 FMODE[2]; /* FILE MODE - LETTER AND NUMBER */ + u16 RECCT; /* NUMBER OF LOGICAL RECORDS */ + u16 FCLPT; /* FIRST CHAIN LINK POINTER */ + u8 RECFM; /* F*1 - RECORD FORMAT - F OR V */ #define FSTDFIX 0xC6 /* Fixed record format (EBCDIC 'F') */ #define FSTDVAR 0xE5 /* Variable record format (EBCDIC 'V') */ - u8 FSTFLAGS; /* F*2 - FST FLAG BYTE */ + u8 FLAGS; /* F*2 - FST FLAG BYTE */ #define FSTRWDSK 0x80 /* READ/WRITE DISK */ #define FSTRODSK 0x00 /* READ/ONLY DISK */ #define FSTDSFS 0x10 /* Shared File FST */ @@ -65,17 +65,17 @@ #define FSTACTWR 0x02 /* ACTIVE FOR WRITING */ #define FSTACTPT 0x01 /* ACTIVE FROM A POINT */ #define FSTFILEA 0x07 /* THE FILE IS ACTIVE */ - u32 FSTLRECL; /* LOGICAL RECORD LENGTH */ - u16 FSTBLKCT; /* NUMBER OF 800 BYTE BLOCKS */ - u16 FSTYEARW; /* YEAR LAST WRITTEN */ - u32 FSTFOP; /* ALT. FILE ORIGIN POINTER */ - u32 FSTADBC; /* ALT. NUMBER OF DATA BLOCKS */ - u32 FSTAIC; /* ALT. ITEM COUNT */ - u8 FSTNLVL; /* NUMBER OF POINTER BLOCK LEVELS */ - u8 FSTPTRSZ; /* LENGTH OF A POINTER ELEMENT */ - u8 FSTADATI[6]; /* ALT. DATE/TIME(YY MM DD HH MM SS) */ - u8 FSTREALM; /* Real filemode */ - u8 FSTFLAG2; /* F*3 - FST FLAG BYTE 2 FSTFLAG2 */ + u32 LRECL; /* LOGICAL RECORD LENGTH */ + u16 BLKCT; /* NUMBER OF 800 BYTE BLOCKS */ + u16 YEARW; /* YEAR LAST WRITTEN */ + u32 FOP; /* ALT. FILE ORIGIN POINTER */ + u32 ADBC; /* ALT. NUMBER OF DATA BLOCKS */ + u32 AIC; /* ALT. ITEM COUNT */ + u8 NLVL; /* NUMBER OF POINTER BLOCK LEVELS */ + u8 PTRSZ; /* LENGTH OF A POINTER ELEMENT */ + u8 ADATI[6]; /* ALT. DATE/TIME(YY MM DD HH MM SS) */ + u8 REALM; /* Real filemode */ + u8 FLAG2; /* F*3 - FST FLAG BYTE 2 FSTFLAG2 */ #define FSTPIPEU 0x10 /* Reserved for CMS PIPELINES usage */ u8 reserved[2]; }; @@ -84,20 +84,27 @@ #define EDF_SUPPORTED_BLOCK_SIZE 4096 +#define DIRECTOR_FN ((u8*) "\x00\x00\x00\x01\x00\x00\x00\x00") +#define DIRECTOR_FT ((u8*) "\xc4\xc9\xd9\xc5\xc3\xe3\xd6\xd9") +#define ALLOCMAP_FN ((u8*) "\x00\x00\x00\x02\x00\x00\x00\x00") +#define ALLOCMAP_FT ((u8*) "\xc1\xd3\xd3\xd6\xc3\xd4\xc1\xd7") + +struct file; + struct fs { struct ADT ADT; struct list_head files; mutex_t lock; struct device *dev; - void *tmp_buf; + struct file *dir; }; struct file { struct FST FST; - struct list_head files; + struct list_head files; /* fs->files */ + struct list_head bcache; mutex_t lock; struct fs *fs; - char *buf; }; extern struct fs *edf_mount(struct device *dev);
--- a/cp/nucleus/config.c Mon Apr 25 09:15:18 2011 -0400 +++ b/cp/nucleus/config.c Mon Apr 25 09:15:29 2011 -0400 @@ -176,7 +176,7 @@ return PTR_ERR(file); /* parse each record in the config file */ - for(i=0; i<file->FST.FSTAIC; i++) { + for(i=0; i<file->FST.AIC; i++) { ret = edf_read_rec(file, buf, i); if (ret) return ret;