summaryrefslogtreecommitdiffstats
path: root/fs/efs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/efs/inode.c')
-rw-r--r--fs/efs/inode.c86
1 files changed, 58 insertions, 28 deletions
diff --git a/fs/efs/inode.c b/fs/efs/inode.c
index 9e7da7934..81c8e81c7 100644
--- a/fs/efs/inode.c
+++ b/fs/efs/inode.c
@@ -7,14 +7,33 @@
* and from work (c) 1998 Mike Shaver.
*/
-#include <linux/efs.h>
+#include <linux/efs_fs.h>
+#include <linux/efs_fs_sb.h>
+
+static inline void extent_copy(efs_extent *src, efs_extent *dst) {
+ /*
+ * this is slightly evil. it doesn't just copy the
+ * efs_extent from src to dst, it also mangles the bits
+ * so that dst ends up in cpu byte-order.
+ */
+
+ dst->cooked.ex_magic = (unsigned int) src->raw[0];
+ dst->cooked.ex_bn = ((unsigned int) src->raw[1] << 16) |
+ ((unsigned int) src->raw[2] << 8) |
+ ((unsigned int) src->raw[3] << 0);
+ dst->cooked.ex_length = (unsigned int) src->raw[4];
+ dst->cooked.ex_offset = ((unsigned int) src->raw[5] << 16) |
+ ((unsigned int) src->raw[6] << 8) |
+ ((unsigned int) src->raw[7] << 0);
+ return;
+}
void efs_read_inode(struct inode *in) {
int i, extents, inode_index;
dev_t device;
struct buffer_head *bh;
- struct efs_spb *sbp = (struct efs_spb *)&in->i_sb->u.generic_sbp;
- struct efs_in_info *ini = (struct efs_in_info *)&in->u.generic_ip;
+ struct efs_sb_info *sbp = (struct efs_sb_info *)&in->i_sb->u.generic_sbp;
+ struct efs_inode_info *ini = (struct efs_inode_info *)&in->u.generic_ip;
efs_block_t block, offset;
struct efs_dinode *efs_inode;
@@ -70,10 +89,8 @@ void efs_read_inode(struct inode *in) {
/* copy the first 12 extents directly from the inode */
for(i = 0; i < EFS_DIRECTEXTENTS; i++) {
- /* ick. horrible (ab)use of union */
- ini->extents[i].u1.l = be32_to_cpu(efs_inode->di_u.di_extents[i].u1.l);
- ini->extents[i].u2.l = be32_to_cpu(efs_inode->di_u.di_extents[i].u2.l);
- if (i < extents && ini->extents[i].u1.s.ex_magic != 0) {
+ extent_copy(&(efs_inode->di_u.di_extents[i]), &(ini->extents[i]));
+ if (i < extents && ini->extents[i].cooked.ex_magic != 0) {
printk("EFS: extent %d has bad magic number in inode %lu\n", i, in->i_ino);
brelse(bh);
goto read_inode_error;
@@ -136,7 +153,7 @@ read_inode_error:
}
static inline efs_block_t
-efs_extent_check(efs_extent *ptr, efs_block_t block, struct efs_spb *sbi, struct efs_in_info *ini) {
+efs_extent_check(efs_extent *ptr, efs_block_t block, struct efs_sb_info *sbp, struct efs_inode_info *ini) {
efs_block_t start;
efs_block_t length;
efs_block_t offset;
@@ -145,12 +162,12 @@ efs_extent_check(efs_extent *ptr, efs_block_t block, struct efs_spb *sbi, struct
** given an extent and a logical block within a file,
** can this block be found within this extent ?
*/
- start = ptr->u1.s.ex_bn;
- length = ptr->u2.s.ex_length;
- offset = ptr->u2.s.ex_offset;
+ start = ptr->cooked.ex_bn;
+ length = ptr->cooked.ex_length;
+ offset = ptr->cooked.ex_offset;
if ((block >= offset) && (block < offset+length)) {
- return(sbi->fs_start + start + block - offset);
+ return(sbp->fs_start + start + block - offset);
} else {
return 0;
}
@@ -159,23 +176,23 @@ efs_extent_check(efs_extent *ptr, efs_block_t block, struct efs_spb *sbi, struct
/* find the disk block number for a given logical file block number */
efs_block_t efs_read_block(struct inode *inode, efs_block_t block) {
- struct efs_spb *sbi = (struct efs_spb *) &inode->i_sb->u.generic_sbp;
- struct efs_in_info *ini = (struct efs_in_info *) &inode->u.generic_ip;
+ struct efs_sb_info *sbp = (struct efs_sb_info *) &inode->i_sb->u.generic_sbp;
+ struct efs_inode_info *ini = (struct efs_inode_info *) &inode->u.generic_ip;
struct buffer_head *bh;
efs_block_t result = 0;
int indirexts, indirext, imagic;
efs_block_t istart, iblock, ilen;
- int i, last, total, checked;
+ int i, cur, last, total, checked;
efs_extent *exts;
- efs_extent tmp;
+ efs_extent ext;
last = ini->lastextent;
total = ini->numextents;
if (total <= EFS_DIRECTEXTENTS) {
/* first check the last extent we returned */
- if ((result = efs_extent_check(&ini->extents[last], block, sbi, ini)))
+ if ((result = efs_extent_check(&ini->extents[last], block, sbp, ini)))
return result;
/* if we only have one extent then nothing can be found */
@@ -186,8 +203,8 @@ efs_block_t efs_read_block(struct inode *inode, efs_block_t block) {
/* check the stored extents in the inode */
/* start with next extent and check forwards */
- for(i = 0; i < total - 1; i++) {
- if ((result = efs_extent_check(&ini->extents[(last + i) % total], block, sbi, ini))) {
+ for(i = 1; i < total; i++) {
+ if ((result = efs_extent_check(&ini->extents[(last + i) % total], block, sbp, ini))) {
ini->lastextent = i;
return result;
}
@@ -200,13 +217,19 @@ efs_block_t efs_read_block(struct inode *inode, efs_block_t block) {
#ifdef DEBUG
printk("EFS: indirect search for logical block %u\n", block);
#endif
- indirexts = ini->extents[0].u2.s.ex_offset;
+
+ /*
+ * OPT: this lot is inefficient.
+ */
+
+ indirexts = ini->extents[0].cooked.ex_offset;
checked = 0;
for(indirext = 0; indirext < indirexts; indirext++) {
- imagic = ini->extents[indirext].u1.s.ex_magic;
- istart = ini->extents[indirext].u1.s.ex_bn + sbi->fs_start;
- ilen = ini->extents[indirext].u2.s.ex_length;
+ cur = (last + indirext) % indirexts;
+ imagic = ini->extents[cur].cooked.ex_magic;
+ istart = ini->extents[cur].cooked.ex_bn + sbp->fs_start;
+ ilen = ini->extents[cur].cooked.ex_length;
for(iblock = istart; iblock < istart + ilen; iblock++) {
bh = bread(inode->i_dev, iblock, EFS_BLOCKSIZE);
@@ -214,20 +237,27 @@ efs_block_t efs_read_block(struct inode *inode, efs_block_t block) {
printk("EFS: bread() failed at block %d\n", block);
return 0;
}
+#ifdef DEBUG
+ printk("EFS: read indirect extent block %d\n", iblock-istart);
+#endif
- exts = (struct extent *) bh->b_data;
+ exts = (efs_extent *) bh->b_data;
for(i = 0; i < EFS_BLOCKSIZE / sizeof(efs_extent) && checked < total; i++, checked++) {
- tmp.u1.l = be32_to_cpu(exts[i].u1.l);
- tmp.u2.l = be32_to_cpu(exts[i].u2.l);
+ /*
+ * this block might be read-cached
+ * so fiddle the endianness in a private copy
+ */
+ extent_copy(&(exts[i]), &ext);
- if (tmp.u1.s.ex_magic != 0) {
+ if (ext.cooked.ex_magic != 0) {
printk("EFS: extent %d has bad magic number in block %d\n", i, iblock);
brelse(bh);
return 0;
}
- if ((result = efs_extent_check(&tmp, block, sbi, ini))) {
+ if ((result = efs_extent_check(&ext, block, sbp, ini))) {
brelse(bh);
+ ini->lastextent = cur;
return result;
}
}