Mercurial > hvf > hvf-old
view cp/fs/edf.c @ 618:535aec703236
cp: define a FIXME macro that leaves a sclp message
There are far too many fixmes in the code. Sadly, the compiler simply
discards them. This usually isn't an issue until one accidentally hits a
"weird" bug which just turns out to be an unhandled (but documented) case in
another part of the code. Using a macro instead of a comment will let the
compiler string-ify the text, and then at runtime use SCLP to print it out.
This will immediatelly point at problem areas. So, keep an eye on SCLP from
now on :)
Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Tue, 13 Dec 2011 22:20:50 -0500 |
parents | 59c264b5fef0 |
children |
line wrap: on
line source
/* * (C) Copyright 2007-2011 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * This file is released under the GPLv2. See the COPYING file for more * details. */ #include <mutex.h> #include <buddy.h> #include <slab.h> #include <device.h> #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 */ static 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 */ static void __free_file(struct file *file) { list_del(&file->files); free(file); } static 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; void *tmp; struct fs *fs; long ret; page = alloc_pages(0, ZONE_NORMAL); if (!page) return ERR_PTR(-ENOMEM); tmp = page_to_addr(page); ret = -ENOMEM; fs = malloc(sizeof(struct fs), ZONE_NORMAL); if (!fs) goto out_free; /* First, read & verify the label */ ret = bdev_read_block(dev, tmp, EDF_LABEL_BLOCK_NO); if (ret) goto out_free; mutex_init(&fs->lock, &edf_fs); INIT_LIST_HEAD(&fs->files); fs->dev = dev; memcpy(&fs->ADT, tmp, sizeof(struct ADT)); ret = -EINVAL; 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: free(fs); free_pages(tmp, 0); return ERR_PTR(ret); } struct file *edf_lookup(struct fs *fs, char *fn, char *ft) { char __fn[8]; char __ft[8]; struct file *file; struct FST *fst; u32 blk; int ret; int i; memcpy(__fn, fn, 8); memcpy(__ft, ft, 8); ascii2ebcdic((u8 *) __fn, 8); ascii2ebcdic((u8 *) __ft, 8); mutex_lock(&fs->lock); /* first, check the cache */ 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); return file; } } /* the slow path */ file = __alloc_file(fs, NULL); if (IS_ERR(file)) { ret = PTR_ERR(file); goto out; } for(blk=0; blk<fs->dir->FST.ADBC; blk++) { fst = bcache_read(fs->dir, 0, blk); if (IS_ERR(fst)) { ret = PTR_ERR(fst); goto out_free; } 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)); mutex_unlock(&fs->lock); return file; } } } ret = -ENOENT; out_free: __free_file(file); out: mutex_unlock(&fs->lock); return ERR_PTR(ret); } int edf_read_rec(struct file *file, char *buf, u32 recno) { struct fs *fs = file->fs; u32 blk, off; char *dbuf; int ret = -EINVAL; mutex_lock(&file->lock); /* check for unsupported geometry */ if (file->FST.NLVL != 0 || file->FST.PTRSZ != 4 || file->FST.LRECL > fs->ADT.DBSIZ || file->FST.RECFM != FSTDFIX) goto out; /* reading past the end of file? */ if (recno >= file->FST.AIC) goto out; blk = (recno * file->FST.LRECL) / fs->ADT.DBSIZ; off = (recno * file->FST.LRECL) % fs->ADT.DBSIZ; if ((off + file->FST.LRECL) > fs->ADT.DBSIZ) { int flen = fs->ADT.DBSIZ - off; int slen = file->FST.LRECL - flen; assert(flen < file->FST.LRECL); assert(slen < file->FST.LRECL); /* the first part of the record */ dbuf = bcache_read(file, 0, blk); if (IS_ERR(dbuf)) { ret = PTR_ERR(dbuf); goto out; } memcpy(buf, dbuf + off, flen); /* the second part of the record */ blk++; dbuf = bcache_read(file, 0, blk); if (IS_ERR(dbuf)) { ret = PTR_ERR(dbuf); goto out; } memcpy(buf + flen, dbuf, slen); } else { /* the whole record */ dbuf = bcache_read(file, 0, blk); if (IS_ERR(dbuf)) { ret = PTR_ERR(dbuf); goto out; } memcpy(buf, dbuf + off, file->FST.LRECL); } ret = 0; out: mutex_unlock(&file->lock); return ret; } void edf_file_free(struct file *file) { struct fs *fs = file->fs; mutex_lock(&fs->lock); __free_file(file); mutex_unlock(&fs->lock); }