Commit 45254b4fb2aef51c94a7397df1e481c4137b4b97

Authored by Christoph Hellwig
Committed by Linus Torvalds
1 parent 48f15b93b2

efs: move headers out of include/linux/

Merge include/linux/efs_fs{_i,_dir}.h into fs/efs/efs.h.  efs_vh.h remains
there because this is the IRIX volume header and shouldn't really be
handled by efs but by the partitioning code.  efs_sb.h remains there for
now because it's exported to userspace.  Of course this wrong and aboot
should have a copy of it's own, but I'll leave that to a separate patch to
avoid any contention.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 10 changed files with 150 additions and 175 deletions Inline Diff

1 /* 1 /*
2 * dir.c 2 * dir.c
3 * 3 *
4 * Copyright (c) 1999 Al Smith 4 * Copyright (c) 1999 Al Smith
5 */ 5 */
6 6
7 #include <linux/buffer_head.h> 7 #include <linux/buffer_head.h>
8 #include <linux/efs_fs.h>
9 #include <linux/smp_lock.h> 8 #include <linux/smp_lock.h>
9 #include "efs.h"
10 10
11 static int efs_readdir(struct file *, void *, filldir_t); 11 static int efs_readdir(struct file *, void *, filldir_t);
12 12
13 const struct file_operations efs_dir_operations = { 13 const struct file_operations efs_dir_operations = {
14 .read = generic_read_dir, 14 .read = generic_read_dir,
15 .readdir = efs_readdir, 15 .readdir = efs_readdir,
16 }; 16 };
17 17
18 const struct inode_operations efs_dir_inode_operations = { 18 const struct inode_operations efs_dir_inode_operations = {
19 .lookup = efs_lookup, 19 .lookup = efs_lookup,
20 }; 20 };
21 21
22 static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) { 22 static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) {
23 struct inode *inode = filp->f_path.dentry->d_inode; 23 struct inode *inode = filp->f_path.dentry->d_inode;
24 struct buffer_head *bh; 24 struct buffer_head *bh;
25 25
26 struct efs_dir *dirblock; 26 struct efs_dir *dirblock;
27 struct efs_dentry *dirslot; 27 struct efs_dentry *dirslot;
28 efs_ino_t inodenum; 28 efs_ino_t inodenum;
29 efs_block_t block; 29 efs_block_t block;
30 int slot, namelen; 30 int slot, namelen;
31 char *nameptr; 31 char *nameptr;
32 32
33 if (inode->i_size & (EFS_DIRBSIZE-1)) 33 if (inode->i_size & (EFS_DIRBSIZE-1))
34 printk(KERN_WARNING "EFS: WARNING: readdir(): directory size not a multiple of EFS_DIRBSIZE\n"); 34 printk(KERN_WARNING "EFS: WARNING: readdir(): directory size not a multiple of EFS_DIRBSIZE\n");
35 35
36 lock_kernel(); 36 lock_kernel();
37 37
38 /* work out where this entry can be found */ 38 /* work out where this entry can be found */
39 block = filp->f_pos >> EFS_DIRBSIZE_BITS; 39 block = filp->f_pos >> EFS_DIRBSIZE_BITS;
40 40
41 /* each block contains at most 256 slots */ 41 /* each block contains at most 256 slots */
42 slot = filp->f_pos & 0xff; 42 slot = filp->f_pos & 0xff;
43 43
44 /* look at all blocks */ 44 /* look at all blocks */
45 while (block < inode->i_blocks) { 45 while (block < inode->i_blocks) {
46 /* read the dir block */ 46 /* read the dir block */
47 bh = sb_bread(inode->i_sb, efs_bmap(inode, block)); 47 bh = sb_bread(inode->i_sb, efs_bmap(inode, block));
48 48
49 if (!bh) { 49 if (!bh) {
50 printk(KERN_ERR "EFS: readdir(): failed to read dir block %d\n", block); 50 printk(KERN_ERR "EFS: readdir(): failed to read dir block %d\n", block);
51 break; 51 break;
52 } 52 }
53 53
54 dirblock = (struct efs_dir *) bh->b_data; 54 dirblock = (struct efs_dir *) bh->b_data;
55 55
56 if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) { 56 if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) {
57 printk(KERN_ERR "EFS: readdir(): invalid directory block\n"); 57 printk(KERN_ERR "EFS: readdir(): invalid directory block\n");
58 brelse(bh); 58 brelse(bh);
59 break; 59 break;
60 } 60 }
61 61
62 while (slot < dirblock->slots) { 62 while (slot < dirblock->slots) {
63 if (dirblock->space[slot] == 0) { 63 if (dirblock->space[slot] == 0) {
64 slot++; 64 slot++;
65 continue; 65 continue;
66 } 66 }
67 67
68 dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot)); 68 dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot));
69 69
70 inodenum = be32_to_cpu(dirslot->inode); 70 inodenum = be32_to_cpu(dirslot->inode);
71 namelen = dirslot->namelen; 71 namelen = dirslot->namelen;
72 nameptr = dirslot->name; 72 nameptr = dirslot->name;
73 73
74 #ifdef DEBUG 74 #ifdef DEBUG
75 printk(KERN_DEBUG "EFS: readdir(): block %d slot %d/%d: inode %u, name \"%s\", namelen %u\n", block, slot, dirblock->slots-1, inodenum, nameptr, namelen); 75 printk(KERN_DEBUG "EFS: readdir(): block %d slot %d/%d: inode %u, name \"%s\", namelen %u\n", block, slot, dirblock->slots-1, inodenum, nameptr, namelen);
76 #endif 76 #endif
77 if (namelen > 0) { 77 if (namelen > 0) {
78 /* found the next entry */ 78 /* found the next entry */
79 filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot; 79 filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot;
80 80
81 /* copy filename and data in dirslot */ 81 /* copy filename and data in dirslot */
82 filldir(dirent, nameptr, namelen, filp->f_pos, inodenum, DT_UNKNOWN); 82 filldir(dirent, nameptr, namelen, filp->f_pos, inodenum, DT_UNKNOWN);
83 83
84 /* sanity check */ 84 /* sanity check */
85 if (nameptr - (char *) dirblock + namelen > EFS_DIRBSIZE) { 85 if (nameptr - (char *) dirblock + namelen > EFS_DIRBSIZE) {
86 printk(KERN_WARNING "EFS: directory entry %d exceeds directory block\n", slot); 86 printk(KERN_WARNING "EFS: directory entry %d exceeds directory block\n", slot);
87 slot++; 87 slot++;
88 continue; 88 continue;
89 } 89 }
90 90
91 /* store position of next slot */ 91 /* store position of next slot */
92 if (++slot == dirblock->slots) { 92 if (++slot == dirblock->slots) {
93 slot = 0; 93 slot = 0;
94 block++; 94 block++;
95 } 95 }
96 brelse(bh); 96 brelse(bh);
97 filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot; 97 filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot;
98 goto out; 98 goto out;
99 } 99 }
100 slot++; 100 slot++;
101 } 101 }
102 brelse(bh); 102 brelse(bh);
103 103
104 slot = 0; 104 slot = 0;
105 block++; 105 block++;
106 } 106 }
107 107
108 filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot; 108 filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot;
109 out: 109 out:
110 unlock_kernel(); 110 unlock_kernel();
111 return 0; 111 return 0;
112 } 112 }
113 113
File was created 1 /*
2 * Copyright (c) 1999 Al Smith
3 *
4 * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
5 * Portions derived from IRIX header files (c) 1988 Silicon Graphics
6 */
7 #ifndef _EFS_EFS_H_
8 #define _EFS_EFS_H_
9
10 #include <linux/fs.h>
11 #include <asm/uaccess.h>
12
13 #define EFS_VERSION "1.0a"
14
15 static const char cprt[] = "EFS: "EFS_VERSION" - (c) 1999 Al Smith <Al.Smith@aeschi.ch.eu.org>";
16
17
18 /* 1 block is 512 bytes */
19 #define EFS_BLOCKSIZE_BITS 9
20 #define EFS_BLOCKSIZE (1 << EFS_BLOCKSIZE_BITS)
21
22 typedef int32_t efs_block_t;
23 typedef uint32_t efs_ino_t;
24
25 #define EFS_DIRECTEXTENTS 12
26
27 /*
28 * layout of an extent, in memory and on disk. 8 bytes exactly.
29 */
30 typedef union extent_u {
31 unsigned char raw[8];
32 struct extent_s {
33 unsigned int ex_magic:8; /* magic # (zero) */
34 unsigned int ex_bn:24; /* basic block */
35 unsigned int ex_length:8; /* numblocks in this extent */
36 unsigned int ex_offset:24; /* logical offset into file */
37 } cooked;
38 } efs_extent;
39
40 typedef struct edevs {
41 __be16 odev;
42 __be32 ndev;
43 } efs_devs;
44
45 /*
46 * extent based filesystem inode as it appears on disk. The efs inode
47 * is exactly 128 bytes long.
48 */
49 struct efs_dinode {
50 __be16 di_mode; /* mode and type of file */
51 __be16 di_nlink; /* number of links to file */
52 __be16 di_uid; /* owner's user id */
53 __be16 di_gid; /* owner's group id */
54 __be32 di_size; /* number of bytes in file */
55 __be32 di_atime; /* time last accessed */
56 __be32 di_mtime; /* time last modified */
57 __be32 di_ctime; /* time created */
58 __be32 di_gen; /* generation number */
59 __be16 di_numextents; /* # of extents */
60 u_char di_version; /* version of inode */
61 u_char di_spare; /* spare - used by AFS */
62 union di_addr {
63 efs_extent di_extents[EFS_DIRECTEXTENTS];
64 efs_devs di_dev; /* device for IFCHR/IFBLK */
65 } di_u;
66 };
67
68 /* efs inode storage in memory */
69 struct efs_inode_info {
70 int numextents;
71 int lastextent;
72
73 efs_extent extents[EFS_DIRECTEXTENTS];
74 struct inode vfs_inode;
75 };
76
77 #include <linux/efs_fs_sb.h>
78
79 #define EFS_DIRBSIZE_BITS EFS_BLOCKSIZE_BITS
80 #define EFS_DIRBSIZE (1 << EFS_DIRBSIZE_BITS)
81
82 struct efs_dentry {
83 __be32 inode;
84 unsigned char namelen;
85 char name[3];
86 };
87
88 #define EFS_DENTSIZE (sizeof(struct efs_dentry) - 3 + 1)
89 #define EFS_MAXNAMELEN ((1 << (sizeof(char) * 8)) - 1)
90
91 #define EFS_DIRBLK_HEADERSIZE 4
92 #define EFS_DIRBLK_MAGIC 0xbeef /* moo */
93
94 struct efs_dir {
95 __be16 magic;
96 unsigned char firstused;
97 unsigned char slots;
98
99 unsigned char space[EFS_DIRBSIZE - EFS_DIRBLK_HEADERSIZE];
100 };
101
102 #define EFS_MAXENTS \
103 ((EFS_DIRBSIZE - EFS_DIRBLK_HEADERSIZE) / \
104 (EFS_DENTSIZE + sizeof(char)))
105
106 #define EFS_SLOTAT(dir, slot) EFS_REALOFF((dir)->space[slot])
107
108 #define EFS_REALOFF(offset) ((offset << 1))
109
110
111 static inline struct efs_inode_info *INODE_INFO(struct inode *inode)
112 {
113 return container_of(inode, struct efs_inode_info, vfs_inode);
114 }
115
116 static inline struct efs_sb_info *SUPER_INFO(struct super_block *sb)
117 {
118 return sb->s_fs_info;
119 }
120
121 struct statfs;
122 struct fid;
123
124 extern const struct inode_operations efs_dir_inode_operations;
125 extern const struct file_operations efs_dir_operations;
126 extern const struct address_space_operations efs_symlink_aops;
127
128 extern struct inode *efs_iget(struct super_block *, unsigned long);
129 extern efs_block_t efs_map_block(struct inode *, efs_block_t);
130 extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int);
131
132 extern struct dentry *efs_lookup(struct inode *, struct dentry *, struct nameidata *);
133 extern struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid,
134 int fh_len, int fh_type);
135 extern struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid,
136 int fh_len, int fh_type);
137 extern struct dentry *efs_get_parent(struct dentry *);
138 extern int efs_bmap(struct inode *, int);
139
140 #endif /* _EFS_EFS_H_ */
141
1 /* 1 /*
2 * file.c 2 * file.c
3 * 3 *
4 * Copyright (c) 1999 Al Smith 4 * Copyright (c) 1999 Al Smith
5 * 5 *
6 * Portions derived from work (c) 1995,1996 Christian Vogelgsang. 6 * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
7 */ 7 */
8 8
9 #include <linux/buffer_head.h> 9 #include <linux/buffer_head.h>
10 #include <linux/efs_fs.h> 10 #include "efs.h"
11 11
12 int efs_get_block(struct inode *inode, sector_t iblock, 12 int efs_get_block(struct inode *inode, sector_t iblock,
13 struct buffer_head *bh_result, int create) 13 struct buffer_head *bh_result, int create)
14 { 14 {
15 int error = -EROFS; 15 int error = -EROFS;
16 long phys; 16 long phys;
17 17
18 if (create) 18 if (create)
19 return error; 19 return error;
20 if (iblock >= inode->i_blocks) { 20 if (iblock >= inode->i_blocks) {
21 #ifdef DEBUG 21 #ifdef DEBUG
22 /* 22 /*
23 * i have no idea why this happens as often as it does 23 * i have no idea why this happens as often as it does
24 */ 24 */
25 printk(KERN_WARNING "EFS: bmap(): block %d >= %ld (filesize %ld)\n", 25 printk(KERN_WARNING "EFS: bmap(): block %d >= %ld (filesize %ld)\n",
26 block, 26 block,
27 inode->i_blocks, 27 inode->i_blocks,
28 inode->i_size); 28 inode->i_size);
29 #endif 29 #endif
30 return 0; 30 return 0;
31 } 31 }
32 phys = efs_map_block(inode, iblock); 32 phys = efs_map_block(inode, iblock);
33 if (phys) 33 if (phys)
34 map_bh(bh_result, inode->i_sb, phys); 34 map_bh(bh_result, inode->i_sb, phys);
35 return 0; 35 return 0;
36 } 36 }
37 37
38 int efs_bmap(struct inode *inode, efs_block_t block) { 38 int efs_bmap(struct inode *inode, efs_block_t block) {
39 39
40 if (block < 0) { 40 if (block < 0) {
41 printk(KERN_WARNING "EFS: bmap(): block < 0\n"); 41 printk(KERN_WARNING "EFS: bmap(): block < 0\n");
42 return 0; 42 return 0;
43 } 43 }
44 44
45 /* are we about to read past the end of a file ? */ 45 /* are we about to read past the end of a file ? */
46 if (!(block < inode->i_blocks)) { 46 if (!(block < inode->i_blocks)) {
47 #ifdef DEBUG 47 #ifdef DEBUG
48 /* 48 /*
49 * i have no idea why this happens as often as it does 49 * i have no idea why this happens as often as it does
50 */ 50 */
51 printk(KERN_WARNING "EFS: bmap(): block %d >= %ld (filesize %ld)\n", 51 printk(KERN_WARNING "EFS: bmap(): block %d >= %ld (filesize %ld)\n",
52 block, 52 block,
53 inode->i_blocks, 53 inode->i_blocks,
54 inode->i_size); 54 inode->i_size);
55 #endif 55 #endif
56 return 0; 56 return 0;
57 } 57 }
58 58
59 return efs_map_block(inode, block); 59 return efs_map_block(inode, block);
60 } 60 }
61 61
1 /* 1 /*
2 * inode.c 2 * inode.c
3 * 3 *
4 * Copyright (c) 1999 Al Smith 4 * Copyright (c) 1999 Al Smith
5 * 5 *
6 * Portions derived from work (c) 1995,1996 Christian Vogelgsang, 6 * Portions derived from work (c) 1995,1996 Christian Vogelgsang,
7 * and from work (c) 1998 Mike Shaver. 7 * and from work (c) 1998 Mike Shaver.
8 */ 8 */
9 9
10 #include <linux/efs_fs.h>
11 #include <linux/efs_fs_sb.h>
12 #include <linux/buffer_head.h> 10 #include <linux/buffer_head.h>
13 #include <linux/module.h> 11 #include <linux/module.h>
14 #include <linux/fs.h> 12 #include <linux/fs.h>
13 #include "efs.h"
14 #include <linux/efs_fs_sb.h>
15 15
16 static int efs_readpage(struct file *file, struct page *page) 16 static int efs_readpage(struct file *file, struct page *page)
17 { 17 {
18 return block_read_full_page(page,efs_get_block); 18 return block_read_full_page(page,efs_get_block);
19 } 19 }
20 static sector_t _efs_bmap(struct address_space *mapping, sector_t block) 20 static sector_t _efs_bmap(struct address_space *mapping, sector_t block)
21 { 21 {
22 return generic_block_bmap(mapping,block,efs_get_block); 22 return generic_block_bmap(mapping,block,efs_get_block);
23 } 23 }
24 static const struct address_space_operations efs_aops = { 24 static const struct address_space_operations efs_aops = {
25 .readpage = efs_readpage, 25 .readpage = efs_readpage,
26 .sync_page = block_sync_page, 26 .sync_page = block_sync_page,
27 .bmap = _efs_bmap 27 .bmap = _efs_bmap
28 }; 28 };
29 29
30 static inline void extent_copy(efs_extent *src, efs_extent *dst) { 30 static inline void extent_copy(efs_extent *src, efs_extent *dst) {
31 /* 31 /*
32 * this is slightly evil. it doesn't just copy 32 * this is slightly evil. it doesn't just copy
33 * efs_extent from src to dst, it also mangles 33 * efs_extent from src to dst, it also mangles
34 * the bits so that dst ends up in cpu byte-order. 34 * the bits so that dst ends up in cpu byte-order.
35 */ 35 */
36 36
37 dst->cooked.ex_magic = (unsigned int) src->raw[0]; 37 dst->cooked.ex_magic = (unsigned int) src->raw[0];
38 dst->cooked.ex_bn = ((unsigned int) src->raw[1] << 16) | 38 dst->cooked.ex_bn = ((unsigned int) src->raw[1] << 16) |
39 ((unsigned int) src->raw[2] << 8) | 39 ((unsigned int) src->raw[2] << 8) |
40 ((unsigned int) src->raw[3] << 0); 40 ((unsigned int) src->raw[3] << 0);
41 dst->cooked.ex_length = (unsigned int) src->raw[4]; 41 dst->cooked.ex_length = (unsigned int) src->raw[4];
42 dst->cooked.ex_offset = ((unsigned int) src->raw[5] << 16) | 42 dst->cooked.ex_offset = ((unsigned int) src->raw[5] << 16) |
43 ((unsigned int) src->raw[6] << 8) | 43 ((unsigned int) src->raw[6] << 8) |
44 ((unsigned int) src->raw[7] << 0); 44 ((unsigned int) src->raw[7] << 0);
45 return; 45 return;
46 } 46 }
47 47
48 struct inode *efs_iget(struct super_block *super, unsigned long ino) 48 struct inode *efs_iget(struct super_block *super, unsigned long ino)
49 { 49 {
50 int i, inode_index; 50 int i, inode_index;
51 dev_t device; 51 dev_t device;
52 u32 rdev; 52 u32 rdev;
53 struct buffer_head *bh; 53 struct buffer_head *bh;
54 struct efs_sb_info *sb = SUPER_INFO(super); 54 struct efs_sb_info *sb = SUPER_INFO(super);
55 struct efs_inode_info *in; 55 struct efs_inode_info *in;
56 efs_block_t block, offset; 56 efs_block_t block, offset;
57 struct efs_dinode *efs_inode; 57 struct efs_dinode *efs_inode;
58 struct inode *inode; 58 struct inode *inode;
59 59
60 inode = iget_locked(super, ino); 60 inode = iget_locked(super, ino);
61 if (IS_ERR(inode)) 61 if (IS_ERR(inode))
62 return ERR_PTR(-ENOMEM); 62 return ERR_PTR(-ENOMEM);
63 if (!(inode->i_state & I_NEW)) 63 if (!(inode->i_state & I_NEW))
64 return inode; 64 return inode;
65 65
66 in = INODE_INFO(inode); 66 in = INODE_INFO(inode);
67 67
68 /* 68 /*
69 ** EFS layout: 69 ** EFS layout:
70 ** 70 **
71 ** | cylinder group | cylinder group | cylinder group ..etc 71 ** | cylinder group | cylinder group | cylinder group ..etc
72 ** |inodes|data |inodes|data |inodes|data ..etc 72 ** |inodes|data |inodes|data |inodes|data ..etc
73 ** 73 **
74 ** work out the inode block index, (considering initially that the 74 ** work out the inode block index, (considering initially that the
75 ** inodes are stored as consecutive blocks). then work out the block 75 ** inodes are stored as consecutive blocks). then work out the block
76 ** number of that inode given the above layout, and finally the 76 ** number of that inode given the above layout, and finally the
77 ** offset of the inode within that block. 77 ** offset of the inode within that block.
78 */ 78 */
79 79
80 inode_index = inode->i_ino / 80 inode_index = inode->i_ino /
81 (EFS_BLOCKSIZE / sizeof(struct efs_dinode)); 81 (EFS_BLOCKSIZE / sizeof(struct efs_dinode));
82 82
83 block = sb->fs_start + sb->first_block + 83 block = sb->fs_start + sb->first_block +
84 (sb->group_size * (inode_index / sb->inode_blocks)) + 84 (sb->group_size * (inode_index / sb->inode_blocks)) +
85 (inode_index % sb->inode_blocks); 85 (inode_index % sb->inode_blocks);
86 86
87 offset = (inode->i_ino % 87 offset = (inode->i_ino %
88 (EFS_BLOCKSIZE / sizeof(struct efs_dinode))) * 88 (EFS_BLOCKSIZE / sizeof(struct efs_dinode))) *
89 sizeof(struct efs_dinode); 89 sizeof(struct efs_dinode);
90 90
91 bh = sb_bread(inode->i_sb, block); 91 bh = sb_bread(inode->i_sb, block);
92 if (!bh) { 92 if (!bh) {
93 printk(KERN_WARNING "EFS: bread() failed at block %d\n", block); 93 printk(KERN_WARNING "EFS: bread() failed at block %d\n", block);
94 goto read_inode_error; 94 goto read_inode_error;
95 } 95 }
96 96
97 efs_inode = (struct efs_dinode *) (bh->b_data + offset); 97 efs_inode = (struct efs_dinode *) (bh->b_data + offset);
98 98
99 inode->i_mode = be16_to_cpu(efs_inode->di_mode); 99 inode->i_mode = be16_to_cpu(efs_inode->di_mode);
100 inode->i_nlink = be16_to_cpu(efs_inode->di_nlink); 100 inode->i_nlink = be16_to_cpu(efs_inode->di_nlink);
101 inode->i_uid = (uid_t)be16_to_cpu(efs_inode->di_uid); 101 inode->i_uid = (uid_t)be16_to_cpu(efs_inode->di_uid);
102 inode->i_gid = (gid_t)be16_to_cpu(efs_inode->di_gid); 102 inode->i_gid = (gid_t)be16_to_cpu(efs_inode->di_gid);
103 inode->i_size = be32_to_cpu(efs_inode->di_size); 103 inode->i_size = be32_to_cpu(efs_inode->di_size);
104 inode->i_atime.tv_sec = be32_to_cpu(efs_inode->di_atime); 104 inode->i_atime.tv_sec = be32_to_cpu(efs_inode->di_atime);
105 inode->i_mtime.tv_sec = be32_to_cpu(efs_inode->di_mtime); 105 inode->i_mtime.tv_sec = be32_to_cpu(efs_inode->di_mtime);
106 inode->i_ctime.tv_sec = be32_to_cpu(efs_inode->di_ctime); 106 inode->i_ctime.tv_sec = be32_to_cpu(efs_inode->di_ctime);
107 inode->i_atime.tv_nsec = inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0; 107 inode->i_atime.tv_nsec = inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0;
108 108
109 /* this is the number of blocks in the file */ 109 /* this is the number of blocks in the file */
110 if (inode->i_size == 0) { 110 if (inode->i_size == 0) {
111 inode->i_blocks = 0; 111 inode->i_blocks = 0;
112 } else { 112 } else {
113 inode->i_blocks = ((inode->i_size - 1) >> EFS_BLOCKSIZE_BITS) + 1; 113 inode->i_blocks = ((inode->i_size - 1) >> EFS_BLOCKSIZE_BITS) + 1;
114 } 114 }
115 115
116 rdev = be16_to_cpu(efs_inode->di_u.di_dev.odev); 116 rdev = be16_to_cpu(efs_inode->di_u.di_dev.odev);
117 if (rdev == 0xffff) { 117 if (rdev == 0xffff) {
118 rdev = be32_to_cpu(efs_inode->di_u.di_dev.ndev); 118 rdev = be32_to_cpu(efs_inode->di_u.di_dev.ndev);
119 if (sysv_major(rdev) > 0xfff) 119 if (sysv_major(rdev) > 0xfff)
120 device = 0; 120 device = 0;
121 else 121 else
122 device = MKDEV(sysv_major(rdev), sysv_minor(rdev)); 122 device = MKDEV(sysv_major(rdev), sysv_minor(rdev));
123 } else 123 } else
124 device = old_decode_dev(rdev); 124 device = old_decode_dev(rdev);
125 125
126 /* get the number of extents for this object */ 126 /* get the number of extents for this object */
127 in->numextents = be16_to_cpu(efs_inode->di_numextents); 127 in->numextents = be16_to_cpu(efs_inode->di_numextents);
128 in->lastextent = 0; 128 in->lastextent = 0;
129 129
130 /* copy the extents contained within the inode to memory */ 130 /* copy the extents contained within the inode to memory */
131 for(i = 0; i < EFS_DIRECTEXTENTS; i++) { 131 for(i = 0; i < EFS_DIRECTEXTENTS; i++) {
132 extent_copy(&(efs_inode->di_u.di_extents[i]), &(in->extents[i])); 132 extent_copy(&(efs_inode->di_u.di_extents[i]), &(in->extents[i]));
133 if (i < in->numextents && in->extents[i].cooked.ex_magic != 0) { 133 if (i < in->numextents && in->extents[i].cooked.ex_magic != 0) {
134 printk(KERN_WARNING "EFS: extent %d has bad magic number in inode %lu\n", i, inode->i_ino); 134 printk(KERN_WARNING "EFS: extent %d has bad magic number in inode %lu\n", i, inode->i_ino);
135 brelse(bh); 135 brelse(bh);
136 goto read_inode_error; 136 goto read_inode_error;
137 } 137 }
138 } 138 }
139 139
140 brelse(bh); 140 brelse(bh);
141 141
142 #ifdef DEBUG 142 #ifdef DEBUG
143 printk(KERN_DEBUG "EFS: read_inode(): inode %lu, extents %d, mode %o\n", 143 printk(KERN_DEBUG "EFS: read_inode(): inode %lu, extents %d, mode %o\n",
144 inode->i_ino, in->numextents, inode->i_mode); 144 inode->i_ino, in->numextents, inode->i_mode);
145 #endif 145 #endif
146 146
147 switch (inode->i_mode & S_IFMT) { 147 switch (inode->i_mode & S_IFMT) {
148 case S_IFDIR: 148 case S_IFDIR:
149 inode->i_op = &efs_dir_inode_operations; 149 inode->i_op = &efs_dir_inode_operations;
150 inode->i_fop = &efs_dir_operations; 150 inode->i_fop = &efs_dir_operations;
151 break; 151 break;
152 case S_IFREG: 152 case S_IFREG:
153 inode->i_fop = &generic_ro_fops; 153 inode->i_fop = &generic_ro_fops;
154 inode->i_data.a_ops = &efs_aops; 154 inode->i_data.a_ops = &efs_aops;
155 break; 155 break;
156 case S_IFLNK: 156 case S_IFLNK:
157 inode->i_op = &page_symlink_inode_operations; 157 inode->i_op = &page_symlink_inode_operations;
158 inode->i_data.a_ops = &efs_symlink_aops; 158 inode->i_data.a_ops = &efs_symlink_aops;
159 break; 159 break;
160 case S_IFCHR: 160 case S_IFCHR:
161 case S_IFBLK: 161 case S_IFBLK:
162 case S_IFIFO: 162 case S_IFIFO:
163 init_special_inode(inode, inode->i_mode, device); 163 init_special_inode(inode, inode->i_mode, device);
164 break; 164 break;
165 default: 165 default:
166 printk(KERN_WARNING "EFS: unsupported inode mode %o\n", inode->i_mode); 166 printk(KERN_WARNING "EFS: unsupported inode mode %o\n", inode->i_mode);
167 goto read_inode_error; 167 goto read_inode_error;
168 break; 168 break;
169 } 169 }
170 170
171 unlock_new_inode(inode); 171 unlock_new_inode(inode);
172 return inode; 172 return inode;
173 173
174 read_inode_error: 174 read_inode_error:
175 printk(KERN_WARNING "EFS: failed to read inode %lu\n", inode->i_ino); 175 printk(KERN_WARNING "EFS: failed to read inode %lu\n", inode->i_ino);
176 iget_failed(inode); 176 iget_failed(inode);
177 return ERR_PTR(-EIO); 177 return ERR_PTR(-EIO);
178 } 178 }
179 179
180 static inline efs_block_t 180 static inline efs_block_t
181 efs_extent_check(efs_extent *ptr, efs_block_t block, struct efs_sb_info *sb) { 181 efs_extent_check(efs_extent *ptr, efs_block_t block, struct efs_sb_info *sb) {
182 efs_block_t start; 182 efs_block_t start;
183 efs_block_t length; 183 efs_block_t length;
184 efs_block_t offset; 184 efs_block_t offset;
185 185
186 /* 186 /*
187 * given an extent and a logical block within a file, 187 * given an extent and a logical block within a file,
188 * can this block be found within this extent ? 188 * can this block be found within this extent ?
189 */ 189 */
190 start = ptr->cooked.ex_bn; 190 start = ptr->cooked.ex_bn;
191 length = ptr->cooked.ex_length; 191 length = ptr->cooked.ex_length;
192 offset = ptr->cooked.ex_offset; 192 offset = ptr->cooked.ex_offset;
193 193
194 if ((block >= offset) && (block < offset+length)) { 194 if ((block >= offset) && (block < offset+length)) {
195 return(sb->fs_start + start + block - offset); 195 return(sb->fs_start + start + block - offset);
196 } else { 196 } else {
197 return 0; 197 return 0;
198 } 198 }
199 } 199 }
200 200
201 efs_block_t efs_map_block(struct inode *inode, efs_block_t block) { 201 efs_block_t efs_map_block(struct inode *inode, efs_block_t block) {
202 struct efs_sb_info *sb = SUPER_INFO(inode->i_sb); 202 struct efs_sb_info *sb = SUPER_INFO(inode->i_sb);
203 struct efs_inode_info *in = INODE_INFO(inode); 203 struct efs_inode_info *in = INODE_INFO(inode);
204 struct buffer_head *bh = NULL; 204 struct buffer_head *bh = NULL;
205 205
206 int cur, last, first = 1; 206 int cur, last, first = 1;
207 int ibase, ioffset, dirext, direxts, indext, indexts; 207 int ibase, ioffset, dirext, direxts, indext, indexts;
208 efs_block_t iblock, result = 0, lastblock = 0; 208 efs_block_t iblock, result = 0, lastblock = 0;
209 efs_extent ext, *exts; 209 efs_extent ext, *exts;
210 210
211 last = in->lastextent; 211 last = in->lastextent;
212 212
213 if (in->numextents <= EFS_DIRECTEXTENTS) { 213 if (in->numextents <= EFS_DIRECTEXTENTS) {
214 /* first check the last extent we returned */ 214 /* first check the last extent we returned */
215 if ((result = efs_extent_check(&in->extents[last], block, sb))) 215 if ((result = efs_extent_check(&in->extents[last], block, sb)))
216 return result; 216 return result;
217 217
218 /* if we only have one extent then nothing can be found */ 218 /* if we only have one extent then nothing can be found */
219 if (in->numextents == 1) { 219 if (in->numextents == 1) {
220 printk(KERN_ERR "EFS: map_block() failed to map (1 extent)\n"); 220 printk(KERN_ERR "EFS: map_block() failed to map (1 extent)\n");
221 return 0; 221 return 0;
222 } 222 }
223 223
224 direxts = in->numextents; 224 direxts = in->numextents;
225 225
226 /* 226 /*
227 * check the stored extents in the inode 227 * check the stored extents in the inode
228 * start with next extent and check forwards 228 * start with next extent and check forwards
229 */ 229 */
230 for(dirext = 1; dirext < direxts; dirext++) { 230 for(dirext = 1; dirext < direxts; dirext++) {
231 cur = (last + dirext) % in->numextents; 231 cur = (last + dirext) % in->numextents;
232 if ((result = efs_extent_check(&in->extents[cur], block, sb))) { 232 if ((result = efs_extent_check(&in->extents[cur], block, sb))) {
233 in->lastextent = cur; 233 in->lastextent = cur;
234 return result; 234 return result;
235 } 235 }
236 } 236 }
237 237
238 printk(KERN_ERR "EFS: map_block() failed to map block %u (dir)\n", block); 238 printk(KERN_ERR "EFS: map_block() failed to map block %u (dir)\n", block);
239 return 0; 239 return 0;
240 } 240 }
241 241
242 #ifdef DEBUG 242 #ifdef DEBUG
243 printk(KERN_DEBUG "EFS: map_block(): indirect search for logical block %u\n", block); 243 printk(KERN_DEBUG "EFS: map_block(): indirect search for logical block %u\n", block);
244 #endif 244 #endif
245 direxts = in->extents[0].cooked.ex_offset; 245 direxts = in->extents[0].cooked.ex_offset;
246 indexts = in->numextents; 246 indexts = in->numextents;
247 247
248 for(indext = 0; indext < indexts; indext++) { 248 for(indext = 0; indext < indexts; indext++) {
249 cur = (last + indext) % indexts; 249 cur = (last + indext) % indexts;
250 250
251 /* 251 /*
252 * work out which direct extent contains `cur'. 252 * work out which direct extent contains `cur'.
253 * 253 *
254 * also compute ibase: i.e. the number of the first 254 * also compute ibase: i.e. the number of the first
255 * indirect extent contained within direct extent `cur'. 255 * indirect extent contained within direct extent `cur'.
256 * 256 *
257 */ 257 */
258 ibase = 0; 258 ibase = 0;
259 for(dirext = 0; cur < ibase && dirext < direxts; dirext++) { 259 for(dirext = 0; cur < ibase && dirext < direxts; dirext++) {
260 ibase += in->extents[dirext].cooked.ex_length * 260 ibase += in->extents[dirext].cooked.ex_length *
261 (EFS_BLOCKSIZE / sizeof(efs_extent)); 261 (EFS_BLOCKSIZE / sizeof(efs_extent));
262 } 262 }
263 263
264 if (dirext == direxts) { 264 if (dirext == direxts) {
265 /* should never happen */ 265 /* should never happen */
266 printk(KERN_ERR "EFS: couldn't find direct extent for indirect extent %d (block %u)\n", cur, block); 266 printk(KERN_ERR "EFS: couldn't find direct extent for indirect extent %d (block %u)\n", cur, block);
267 if (bh) brelse(bh); 267 if (bh) brelse(bh);
268 return 0; 268 return 0;
269 } 269 }
270 270
271 /* work out block number and offset of this indirect extent */ 271 /* work out block number and offset of this indirect extent */
272 iblock = sb->fs_start + in->extents[dirext].cooked.ex_bn + 272 iblock = sb->fs_start + in->extents[dirext].cooked.ex_bn +
273 (cur - ibase) / 273 (cur - ibase) /
274 (EFS_BLOCKSIZE / sizeof(efs_extent)); 274 (EFS_BLOCKSIZE / sizeof(efs_extent));
275 ioffset = (cur - ibase) % 275 ioffset = (cur - ibase) %
276 (EFS_BLOCKSIZE / sizeof(efs_extent)); 276 (EFS_BLOCKSIZE / sizeof(efs_extent));
277 277
278 if (first || lastblock != iblock) { 278 if (first || lastblock != iblock) {
279 if (bh) brelse(bh); 279 if (bh) brelse(bh);
280 280
281 bh = sb_bread(inode->i_sb, iblock); 281 bh = sb_bread(inode->i_sb, iblock);
282 if (!bh) { 282 if (!bh) {
283 printk(KERN_ERR "EFS: bread() failed at block %d\n", iblock); 283 printk(KERN_ERR "EFS: bread() failed at block %d\n", iblock);
284 return 0; 284 return 0;
285 } 285 }
286 #ifdef DEBUG 286 #ifdef DEBUG
287 printk(KERN_DEBUG "EFS: map_block(): read indirect extent block %d\n", iblock); 287 printk(KERN_DEBUG "EFS: map_block(): read indirect extent block %d\n", iblock);
288 #endif 288 #endif
289 first = 0; 289 first = 0;
290 lastblock = iblock; 290 lastblock = iblock;
291 } 291 }
292 292
293 exts = (efs_extent *) bh->b_data; 293 exts = (efs_extent *) bh->b_data;
294 294
295 extent_copy(&(exts[ioffset]), &ext); 295 extent_copy(&(exts[ioffset]), &ext);
296 296
297 if (ext.cooked.ex_magic != 0) { 297 if (ext.cooked.ex_magic != 0) {
298 printk(KERN_ERR "EFS: extent %d has bad magic number in block %d\n", cur, iblock); 298 printk(KERN_ERR "EFS: extent %d has bad magic number in block %d\n", cur, iblock);
299 if (bh) brelse(bh); 299 if (bh) brelse(bh);
300 return 0; 300 return 0;
301 } 301 }
302 302
303 if ((result = efs_extent_check(&ext, block, sb))) { 303 if ((result = efs_extent_check(&ext, block, sb))) {
304 if (bh) brelse(bh); 304 if (bh) brelse(bh);
305 in->lastextent = cur; 305 in->lastextent = cur;
306 return result; 306 return result;
307 } 307 }
308 } 308 }
309 if (bh) brelse(bh); 309 if (bh) brelse(bh);
310 printk(KERN_ERR "EFS: map_block() failed to map block %u (indir)\n", block); 310 printk(KERN_ERR "EFS: map_block() failed to map block %u (indir)\n", block);
311 return 0; 311 return 0;
312 } 312 }
313 313
1 /* 1 /*
2 * namei.c 2 * namei.c
3 * 3 *
4 * Copyright (c) 1999 Al Smith 4 * Copyright (c) 1999 Al Smith
5 * 5 *
6 * Portions derived from work (c) 1995,1996 Christian Vogelgsang. 6 * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
7 */ 7 */
8 8
9 #include <linux/buffer_head.h> 9 #include <linux/buffer_head.h>
10 #include <linux/string.h> 10 #include <linux/string.h>
11 #include <linux/efs_fs.h>
12 #include <linux/smp_lock.h> 11 #include <linux/smp_lock.h>
13 #include <linux/exportfs.h> 12 #include <linux/exportfs.h>
13 #include "efs.h"
14 14
15 15
16 static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) { 16 static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) {
17 struct buffer_head *bh; 17 struct buffer_head *bh;
18 18
19 int slot, namelen; 19 int slot, namelen;
20 char *nameptr; 20 char *nameptr;
21 struct efs_dir *dirblock; 21 struct efs_dir *dirblock;
22 struct efs_dentry *dirslot; 22 struct efs_dentry *dirslot;
23 efs_ino_t inodenum; 23 efs_ino_t inodenum;
24 efs_block_t block; 24 efs_block_t block;
25 25
26 if (inode->i_size & (EFS_DIRBSIZE-1)) 26 if (inode->i_size & (EFS_DIRBSIZE-1))
27 printk(KERN_WARNING "EFS: WARNING: find_entry(): directory size not a multiple of EFS_DIRBSIZE\n"); 27 printk(KERN_WARNING "EFS: WARNING: find_entry(): directory size not a multiple of EFS_DIRBSIZE\n");
28 28
29 for(block = 0; block < inode->i_blocks; block++) { 29 for(block = 0; block < inode->i_blocks; block++) {
30 30
31 bh = sb_bread(inode->i_sb, efs_bmap(inode, block)); 31 bh = sb_bread(inode->i_sb, efs_bmap(inode, block));
32 if (!bh) { 32 if (!bh) {
33 printk(KERN_ERR "EFS: find_entry(): failed to read dir block %d\n", block); 33 printk(KERN_ERR "EFS: find_entry(): failed to read dir block %d\n", block);
34 return 0; 34 return 0;
35 } 35 }
36 36
37 dirblock = (struct efs_dir *) bh->b_data; 37 dirblock = (struct efs_dir *) bh->b_data;
38 38
39 if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) { 39 if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) {
40 printk(KERN_ERR "EFS: find_entry(): invalid directory block\n"); 40 printk(KERN_ERR "EFS: find_entry(): invalid directory block\n");
41 brelse(bh); 41 brelse(bh);
42 return(0); 42 return(0);
43 } 43 }
44 44
45 for(slot = 0; slot < dirblock->slots; slot++) { 45 for(slot = 0; slot < dirblock->slots; slot++) {
46 dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot)); 46 dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot));
47 47
48 namelen = dirslot->namelen; 48 namelen = dirslot->namelen;
49 nameptr = dirslot->name; 49 nameptr = dirslot->name;
50 50
51 if ((namelen == len) && (!memcmp(name, nameptr, len))) { 51 if ((namelen == len) && (!memcmp(name, nameptr, len))) {
52 inodenum = be32_to_cpu(dirslot->inode); 52 inodenum = be32_to_cpu(dirslot->inode);
53 brelse(bh); 53 brelse(bh);
54 return(inodenum); 54 return(inodenum);
55 } 55 }
56 } 56 }
57 brelse(bh); 57 brelse(bh);
58 } 58 }
59 return(0); 59 return(0);
60 } 60 }
61 61
62 struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { 62 struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) {
63 efs_ino_t inodenum; 63 efs_ino_t inodenum;
64 struct inode * inode = NULL; 64 struct inode * inode = NULL;
65 65
66 lock_kernel(); 66 lock_kernel();
67 inodenum = efs_find_entry(dir, dentry->d_name.name, dentry->d_name.len); 67 inodenum = efs_find_entry(dir, dentry->d_name.name, dentry->d_name.len);
68 if (inodenum) { 68 if (inodenum) {
69 inode = efs_iget(dir->i_sb, inodenum); 69 inode = efs_iget(dir->i_sb, inodenum);
70 if (IS_ERR(inode)) { 70 if (IS_ERR(inode)) {
71 unlock_kernel(); 71 unlock_kernel();
72 return ERR_CAST(inode); 72 return ERR_CAST(inode);
73 } 73 }
74 } 74 }
75 unlock_kernel(); 75 unlock_kernel();
76 76
77 d_add(dentry, inode); 77 d_add(dentry, inode);
78 return NULL; 78 return NULL;
79 } 79 }
80 80
81 static struct inode *efs_nfs_get_inode(struct super_block *sb, u64 ino, 81 static struct inode *efs_nfs_get_inode(struct super_block *sb, u64 ino,
82 u32 generation) 82 u32 generation)
83 { 83 {
84 struct inode *inode; 84 struct inode *inode;
85 85
86 if (ino == 0) 86 if (ino == 0)
87 return ERR_PTR(-ESTALE); 87 return ERR_PTR(-ESTALE);
88 inode = efs_iget(sb, ino); 88 inode = efs_iget(sb, ino);
89 if (IS_ERR(inode)) 89 if (IS_ERR(inode))
90 return ERR_CAST(inode); 90 return ERR_CAST(inode);
91 91
92 if (generation && inode->i_generation != generation) { 92 if (generation && inode->i_generation != generation) {
93 iput(inode); 93 iput(inode);
94 return ERR_PTR(-ESTALE); 94 return ERR_PTR(-ESTALE);
95 } 95 }
96 96
97 return inode; 97 return inode;
98 } 98 }
99 99
100 struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid, 100 struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid,
101 int fh_len, int fh_type) 101 int fh_len, int fh_type)
102 { 102 {
103 return generic_fh_to_dentry(sb, fid, fh_len, fh_type, 103 return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
104 efs_nfs_get_inode); 104 efs_nfs_get_inode);
105 } 105 }
106 106
107 struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid, 107 struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid,
108 int fh_len, int fh_type) 108 int fh_len, int fh_type)
109 { 109 {
110 return generic_fh_to_parent(sb, fid, fh_len, fh_type, 110 return generic_fh_to_parent(sb, fid, fh_len, fh_type,
111 efs_nfs_get_inode); 111 efs_nfs_get_inode);
112 } 112 }
113 113
114 struct dentry *efs_get_parent(struct dentry *child) 114 struct dentry *efs_get_parent(struct dentry *child)
115 { 115 {
116 struct dentry *parent; 116 struct dentry *parent;
117 struct inode *inode; 117 struct inode *inode;
118 efs_ino_t ino; 118 efs_ino_t ino;
119 long error; 119 long error;
120 120
121 lock_kernel(); 121 lock_kernel();
122 122
123 error = -ENOENT; 123 error = -ENOENT;
124 ino = efs_find_entry(child->d_inode, "..", 2); 124 ino = efs_find_entry(child->d_inode, "..", 2);
125 if (!ino) 125 if (!ino)
126 goto fail; 126 goto fail;
127 127
128 inode = efs_iget(child->d_inode->i_sb, ino); 128 inode = efs_iget(child->d_inode->i_sb, ino);
129 if (IS_ERR(inode)) { 129 if (IS_ERR(inode)) {
130 error = PTR_ERR(inode); 130 error = PTR_ERR(inode);
131 goto fail; 131 goto fail;
132 } 132 }
133 133
134 error = -ENOMEM; 134 error = -ENOMEM;
135 parent = d_alloc_anon(inode); 135 parent = d_alloc_anon(inode);
136 if (!parent) 136 if (!parent)
137 goto fail_iput; 137 goto fail_iput;
138 138
139 unlock_kernel(); 139 unlock_kernel();
140 return parent; 140 return parent;
141 141
142 fail_iput: 142 fail_iput:
143 iput(inode); 143 iput(inode);
144 fail: 144 fail:
145 unlock_kernel(); 145 unlock_kernel();
146 return ERR_PTR(error); 146 return ERR_PTR(error);
147 } 147 }
1 /* 1 /*
2 * super.c 2 * super.c
3 * 3 *
4 * Copyright (c) 1999 Al Smith 4 * Copyright (c) 1999 Al Smith
5 * 5 *
6 * Portions derived from work (c) 1995,1996 Christian Vogelgsang. 6 * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
7 */ 7 */
8 8
9 #include <linux/init.h> 9 #include <linux/init.h>
10 #include <linux/module.h> 10 #include <linux/module.h>
11 #include <linux/efs_fs.h>
12 #include <linux/efs_vh.h>
13 #include <linux/efs_fs_sb.h>
14 #include <linux/exportfs.h> 11 #include <linux/exportfs.h>
15 #include <linux/slab.h> 12 #include <linux/slab.h>
16 #include <linux/buffer_head.h> 13 #include <linux/buffer_head.h>
17 #include <linux/vfs.h> 14 #include <linux/vfs.h>
15
16 #include "efs.h"
17 #include <linux/efs_vh.h>
18 #include <linux/efs_fs_sb.h>
18 19
19 static int efs_statfs(struct dentry *dentry, struct kstatfs *buf); 20 static int efs_statfs(struct dentry *dentry, struct kstatfs *buf);
20 static int efs_fill_super(struct super_block *s, void *d, int silent); 21 static int efs_fill_super(struct super_block *s, void *d, int silent);
21 22
22 static int efs_get_sb(struct file_system_type *fs_type, 23 static int efs_get_sb(struct file_system_type *fs_type,
23 int flags, const char *dev_name, void *data, struct vfsmount *mnt) 24 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
24 { 25 {
25 return get_sb_bdev(fs_type, flags, dev_name, data, efs_fill_super, mnt); 26 return get_sb_bdev(fs_type, flags, dev_name, data, efs_fill_super, mnt);
26 } 27 }
27 28
28 static struct file_system_type efs_fs_type = { 29 static struct file_system_type efs_fs_type = {
29 .owner = THIS_MODULE, 30 .owner = THIS_MODULE,
30 .name = "efs", 31 .name = "efs",
31 .get_sb = efs_get_sb, 32 .get_sb = efs_get_sb,
32 .kill_sb = kill_block_super, 33 .kill_sb = kill_block_super,
33 .fs_flags = FS_REQUIRES_DEV, 34 .fs_flags = FS_REQUIRES_DEV,
34 }; 35 };
35 36
36 static struct pt_types sgi_pt_types[] = { 37 static struct pt_types sgi_pt_types[] = {
37 {0x00, "SGI vh"}, 38 {0x00, "SGI vh"},
38 {0x01, "SGI trkrepl"}, 39 {0x01, "SGI trkrepl"},
39 {0x02, "SGI secrepl"}, 40 {0x02, "SGI secrepl"},
40 {0x03, "SGI raw"}, 41 {0x03, "SGI raw"},
41 {0x04, "SGI bsd"}, 42 {0x04, "SGI bsd"},
42 {SGI_SYSV, "SGI sysv"}, 43 {SGI_SYSV, "SGI sysv"},
43 {0x06, "SGI vol"}, 44 {0x06, "SGI vol"},
44 {SGI_EFS, "SGI efs"}, 45 {SGI_EFS, "SGI efs"},
45 {0x08, "SGI lv"}, 46 {0x08, "SGI lv"},
46 {0x09, "SGI rlv"}, 47 {0x09, "SGI rlv"},
47 {0x0A, "SGI xfs"}, 48 {0x0A, "SGI xfs"},
48 {0x0B, "SGI xfslog"}, 49 {0x0B, "SGI xfslog"},
49 {0x0C, "SGI xlv"}, 50 {0x0C, "SGI xlv"},
50 {0x82, "Linux swap"}, 51 {0x82, "Linux swap"},
51 {0x83, "Linux native"}, 52 {0x83, "Linux native"},
52 {0, NULL} 53 {0, NULL}
53 }; 54 };
54 55
55 56
56 static struct kmem_cache * efs_inode_cachep; 57 static struct kmem_cache * efs_inode_cachep;
57 58
58 static struct inode *efs_alloc_inode(struct super_block *sb) 59 static struct inode *efs_alloc_inode(struct super_block *sb)
59 { 60 {
60 struct efs_inode_info *ei; 61 struct efs_inode_info *ei;
61 ei = (struct efs_inode_info *)kmem_cache_alloc(efs_inode_cachep, GFP_KERNEL); 62 ei = (struct efs_inode_info *)kmem_cache_alloc(efs_inode_cachep, GFP_KERNEL);
62 if (!ei) 63 if (!ei)
63 return NULL; 64 return NULL;
64 return &ei->vfs_inode; 65 return &ei->vfs_inode;
65 } 66 }
66 67
67 static void efs_destroy_inode(struct inode *inode) 68 static void efs_destroy_inode(struct inode *inode)
68 { 69 {
69 kmem_cache_free(efs_inode_cachep, INODE_INFO(inode)); 70 kmem_cache_free(efs_inode_cachep, INODE_INFO(inode));
70 } 71 }
71 72
72 static void init_once(struct kmem_cache *cachep, void *foo) 73 static void init_once(struct kmem_cache *cachep, void *foo)
73 { 74 {
74 struct efs_inode_info *ei = (struct efs_inode_info *) foo; 75 struct efs_inode_info *ei = (struct efs_inode_info *) foo;
75 76
76 inode_init_once(&ei->vfs_inode); 77 inode_init_once(&ei->vfs_inode);
77 } 78 }
78 79
79 static int init_inodecache(void) 80 static int init_inodecache(void)
80 { 81 {
81 efs_inode_cachep = kmem_cache_create("efs_inode_cache", 82 efs_inode_cachep = kmem_cache_create("efs_inode_cache",
82 sizeof(struct efs_inode_info), 83 sizeof(struct efs_inode_info),
83 0, SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, 84 0, SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,
84 init_once); 85 init_once);
85 if (efs_inode_cachep == NULL) 86 if (efs_inode_cachep == NULL)
86 return -ENOMEM; 87 return -ENOMEM;
87 return 0; 88 return 0;
88 } 89 }
89 90
90 static void destroy_inodecache(void) 91 static void destroy_inodecache(void)
91 { 92 {
92 kmem_cache_destroy(efs_inode_cachep); 93 kmem_cache_destroy(efs_inode_cachep);
93 } 94 }
94 95
95 static void efs_put_super(struct super_block *s) 96 static void efs_put_super(struct super_block *s)
96 { 97 {
97 kfree(s->s_fs_info); 98 kfree(s->s_fs_info);
98 s->s_fs_info = NULL; 99 s->s_fs_info = NULL;
99 } 100 }
100 101
101 static int efs_remount(struct super_block *sb, int *flags, char *data) 102 static int efs_remount(struct super_block *sb, int *flags, char *data)
102 { 103 {
103 *flags |= MS_RDONLY; 104 *flags |= MS_RDONLY;
104 return 0; 105 return 0;
105 } 106 }
106 107
107 static const struct super_operations efs_superblock_operations = { 108 static const struct super_operations efs_superblock_operations = {
108 .alloc_inode = efs_alloc_inode, 109 .alloc_inode = efs_alloc_inode,
109 .destroy_inode = efs_destroy_inode, 110 .destroy_inode = efs_destroy_inode,
110 .put_super = efs_put_super, 111 .put_super = efs_put_super,
111 .statfs = efs_statfs, 112 .statfs = efs_statfs,
112 .remount_fs = efs_remount, 113 .remount_fs = efs_remount,
113 }; 114 };
114 115
115 static const struct export_operations efs_export_ops = { 116 static const struct export_operations efs_export_ops = {
116 .fh_to_dentry = efs_fh_to_dentry, 117 .fh_to_dentry = efs_fh_to_dentry,
117 .fh_to_parent = efs_fh_to_parent, 118 .fh_to_parent = efs_fh_to_parent,
118 .get_parent = efs_get_parent, 119 .get_parent = efs_get_parent,
119 }; 120 };
120 121
121 static int __init init_efs_fs(void) { 122 static int __init init_efs_fs(void) {
122 int err; 123 int err;
123 printk("EFS: "EFS_VERSION" - http://aeschi.ch.eu.org/efs/\n"); 124 printk("EFS: "EFS_VERSION" - http://aeschi.ch.eu.org/efs/\n");
124 err = init_inodecache(); 125 err = init_inodecache();
125 if (err) 126 if (err)
126 goto out1; 127 goto out1;
127 err = register_filesystem(&efs_fs_type); 128 err = register_filesystem(&efs_fs_type);
128 if (err) 129 if (err)
129 goto out; 130 goto out;
130 return 0; 131 return 0;
131 out: 132 out:
132 destroy_inodecache(); 133 destroy_inodecache();
133 out1: 134 out1:
134 return err; 135 return err;
135 } 136 }
136 137
137 static void __exit exit_efs_fs(void) { 138 static void __exit exit_efs_fs(void) {
138 unregister_filesystem(&efs_fs_type); 139 unregister_filesystem(&efs_fs_type);
139 destroy_inodecache(); 140 destroy_inodecache();
140 } 141 }
141 142
142 module_init(init_efs_fs) 143 module_init(init_efs_fs)
143 module_exit(exit_efs_fs) 144 module_exit(exit_efs_fs)
144 145
145 static efs_block_t efs_validate_vh(struct volume_header *vh) { 146 static efs_block_t efs_validate_vh(struct volume_header *vh) {
146 int i; 147 int i;
147 __be32 cs, *ui; 148 __be32 cs, *ui;
148 int csum; 149 int csum;
149 efs_block_t sblock = 0; /* shuts up gcc */ 150 efs_block_t sblock = 0; /* shuts up gcc */
150 struct pt_types *pt_entry; 151 struct pt_types *pt_entry;
151 int pt_type, slice = -1; 152 int pt_type, slice = -1;
152 153
153 if (be32_to_cpu(vh->vh_magic) != VHMAGIC) { 154 if (be32_to_cpu(vh->vh_magic) != VHMAGIC) {
154 /* 155 /*
155 * assume that we're dealing with a partition and allow 156 * assume that we're dealing with a partition and allow
156 * read_super() to try and detect a valid superblock 157 * read_super() to try and detect a valid superblock
157 * on the next block. 158 * on the next block.
158 */ 159 */
159 return 0; 160 return 0;
160 } 161 }
161 162
162 ui = ((__be32 *) (vh + 1)) - 1; 163 ui = ((__be32 *) (vh + 1)) - 1;
163 for(csum = 0; ui >= ((__be32 *) vh);) { 164 for(csum = 0; ui >= ((__be32 *) vh);) {
164 cs = *ui--; 165 cs = *ui--;
165 csum += be32_to_cpu(cs); 166 csum += be32_to_cpu(cs);
166 } 167 }
167 if (csum) { 168 if (csum) {
168 printk(KERN_INFO "EFS: SGI disklabel: checksum bad, label corrupted\n"); 169 printk(KERN_INFO "EFS: SGI disklabel: checksum bad, label corrupted\n");
169 return 0; 170 return 0;
170 } 171 }
171 172
172 #ifdef DEBUG 173 #ifdef DEBUG
173 printk(KERN_DEBUG "EFS: bf: \"%16s\"\n", vh->vh_bootfile); 174 printk(KERN_DEBUG "EFS: bf: \"%16s\"\n", vh->vh_bootfile);
174 175
175 for(i = 0; i < NVDIR; i++) { 176 for(i = 0; i < NVDIR; i++) {
176 int j; 177 int j;
177 char name[VDNAMESIZE+1]; 178 char name[VDNAMESIZE+1];
178 179
179 for(j = 0; j < VDNAMESIZE; j++) { 180 for(j = 0; j < VDNAMESIZE; j++) {
180 name[j] = vh->vh_vd[i].vd_name[j]; 181 name[j] = vh->vh_vd[i].vd_name[j];
181 } 182 }
182 name[j] = (char) 0; 183 name[j] = (char) 0;
183 184
184 if (name[0]) { 185 if (name[0]) {
185 printk(KERN_DEBUG "EFS: vh: %8s block: 0x%08x size: 0x%08x\n", 186 printk(KERN_DEBUG "EFS: vh: %8s block: 0x%08x size: 0x%08x\n",
186 name, 187 name,
187 (int) be32_to_cpu(vh->vh_vd[i].vd_lbn), 188 (int) be32_to_cpu(vh->vh_vd[i].vd_lbn),
188 (int) be32_to_cpu(vh->vh_vd[i].vd_nbytes)); 189 (int) be32_to_cpu(vh->vh_vd[i].vd_nbytes));
189 } 190 }
190 } 191 }
191 #endif 192 #endif
192 193
193 for(i = 0; i < NPARTAB; i++) { 194 for(i = 0; i < NPARTAB; i++) {
194 pt_type = (int) be32_to_cpu(vh->vh_pt[i].pt_type); 195 pt_type = (int) be32_to_cpu(vh->vh_pt[i].pt_type);
195 for(pt_entry = sgi_pt_types; pt_entry->pt_name; pt_entry++) { 196 for(pt_entry = sgi_pt_types; pt_entry->pt_name; pt_entry++) {
196 if (pt_type == pt_entry->pt_type) break; 197 if (pt_type == pt_entry->pt_type) break;
197 } 198 }
198 #ifdef DEBUG 199 #ifdef DEBUG
199 if (be32_to_cpu(vh->vh_pt[i].pt_nblks)) { 200 if (be32_to_cpu(vh->vh_pt[i].pt_nblks)) {
200 printk(KERN_DEBUG "EFS: pt %2d: start: %08d size: %08d type: 0x%02x (%s)\n", 201 printk(KERN_DEBUG "EFS: pt %2d: start: %08d size: %08d type: 0x%02x (%s)\n",
201 i, 202 i,
202 (int) be32_to_cpu(vh->vh_pt[i].pt_firstlbn), 203 (int) be32_to_cpu(vh->vh_pt[i].pt_firstlbn),
203 (int) be32_to_cpu(vh->vh_pt[i].pt_nblks), 204 (int) be32_to_cpu(vh->vh_pt[i].pt_nblks),
204 pt_type, 205 pt_type,
205 (pt_entry->pt_name) ? pt_entry->pt_name : "unknown"); 206 (pt_entry->pt_name) ? pt_entry->pt_name : "unknown");
206 } 207 }
207 #endif 208 #endif
208 if (IS_EFS(pt_type)) { 209 if (IS_EFS(pt_type)) {
209 sblock = be32_to_cpu(vh->vh_pt[i].pt_firstlbn); 210 sblock = be32_to_cpu(vh->vh_pt[i].pt_firstlbn);
210 slice = i; 211 slice = i;
211 } 212 }
212 } 213 }
213 214
214 if (slice == -1) { 215 if (slice == -1) {
215 printk(KERN_NOTICE "EFS: partition table contained no EFS partitions\n"); 216 printk(KERN_NOTICE "EFS: partition table contained no EFS partitions\n");
216 #ifdef DEBUG 217 #ifdef DEBUG
217 } else { 218 } else {
218 printk(KERN_INFO "EFS: using slice %d (type %s, offset 0x%x)\n", 219 printk(KERN_INFO "EFS: using slice %d (type %s, offset 0x%x)\n",
219 slice, 220 slice,
220 (pt_entry->pt_name) ? pt_entry->pt_name : "unknown", 221 (pt_entry->pt_name) ? pt_entry->pt_name : "unknown",
221 sblock); 222 sblock);
222 #endif 223 #endif
223 } 224 }
224 return sblock; 225 return sblock;
225 } 226 }
226 227
227 static int efs_validate_super(struct efs_sb_info *sb, struct efs_super *super) { 228 static int efs_validate_super(struct efs_sb_info *sb, struct efs_super *super) {
228 229
229 if (!IS_EFS_MAGIC(be32_to_cpu(super->fs_magic))) 230 if (!IS_EFS_MAGIC(be32_to_cpu(super->fs_magic)))
230 return -1; 231 return -1;
231 232
232 sb->fs_magic = be32_to_cpu(super->fs_magic); 233 sb->fs_magic = be32_to_cpu(super->fs_magic);
233 sb->total_blocks = be32_to_cpu(super->fs_size); 234 sb->total_blocks = be32_to_cpu(super->fs_size);
234 sb->first_block = be32_to_cpu(super->fs_firstcg); 235 sb->first_block = be32_to_cpu(super->fs_firstcg);
235 sb->group_size = be32_to_cpu(super->fs_cgfsize); 236 sb->group_size = be32_to_cpu(super->fs_cgfsize);
236 sb->data_free = be32_to_cpu(super->fs_tfree); 237 sb->data_free = be32_to_cpu(super->fs_tfree);
237 sb->inode_free = be32_to_cpu(super->fs_tinode); 238 sb->inode_free = be32_to_cpu(super->fs_tinode);
238 sb->inode_blocks = be16_to_cpu(super->fs_cgisize); 239 sb->inode_blocks = be16_to_cpu(super->fs_cgisize);
239 sb->total_groups = be16_to_cpu(super->fs_ncg); 240 sb->total_groups = be16_to_cpu(super->fs_ncg);
240 241
241 return 0; 242 return 0;
242 } 243 }
243 244
244 static int efs_fill_super(struct super_block *s, void *d, int silent) 245 static int efs_fill_super(struct super_block *s, void *d, int silent)
245 { 246 {
246 struct efs_sb_info *sb; 247 struct efs_sb_info *sb;
247 struct buffer_head *bh; 248 struct buffer_head *bh;
248 struct inode *root; 249 struct inode *root;
249 int ret = -EINVAL; 250 int ret = -EINVAL;
250 251
251 sb = kzalloc(sizeof(struct efs_sb_info), GFP_KERNEL); 252 sb = kzalloc(sizeof(struct efs_sb_info), GFP_KERNEL);
252 if (!sb) 253 if (!sb)
253 return -ENOMEM; 254 return -ENOMEM;
254 s->s_fs_info = sb; 255 s->s_fs_info = sb;
255 256
256 s->s_magic = EFS_SUPER_MAGIC; 257 s->s_magic = EFS_SUPER_MAGIC;
257 if (!sb_set_blocksize(s, EFS_BLOCKSIZE)) { 258 if (!sb_set_blocksize(s, EFS_BLOCKSIZE)) {
258 printk(KERN_ERR "EFS: device does not support %d byte blocks\n", 259 printk(KERN_ERR "EFS: device does not support %d byte blocks\n",
259 EFS_BLOCKSIZE); 260 EFS_BLOCKSIZE);
260 goto out_no_fs_ul; 261 goto out_no_fs_ul;
261 } 262 }
262 263
263 /* read the vh (volume header) block */ 264 /* read the vh (volume header) block */
264 bh = sb_bread(s, 0); 265 bh = sb_bread(s, 0);
265 266
266 if (!bh) { 267 if (!bh) {
267 printk(KERN_ERR "EFS: cannot read volume header\n"); 268 printk(KERN_ERR "EFS: cannot read volume header\n");
268 goto out_no_fs_ul; 269 goto out_no_fs_ul;
269 } 270 }
270 271
271 /* 272 /*
272 * if this returns zero then we didn't find any partition table. 273 * if this returns zero then we didn't find any partition table.
273 * this isn't (yet) an error - just assume for the moment that 274 * this isn't (yet) an error - just assume for the moment that
274 * the device is valid and go on to search for a superblock. 275 * the device is valid and go on to search for a superblock.
275 */ 276 */
276 sb->fs_start = efs_validate_vh((struct volume_header *) bh->b_data); 277 sb->fs_start = efs_validate_vh((struct volume_header *) bh->b_data);
277 brelse(bh); 278 brelse(bh);
278 279
279 if (sb->fs_start == -1) { 280 if (sb->fs_start == -1) {
280 goto out_no_fs_ul; 281 goto out_no_fs_ul;
281 } 282 }
282 283
283 bh = sb_bread(s, sb->fs_start + EFS_SUPER); 284 bh = sb_bread(s, sb->fs_start + EFS_SUPER);
284 if (!bh) { 285 if (!bh) {
285 printk(KERN_ERR "EFS: cannot read superblock\n"); 286 printk(KERN_ERR "EFS: cannot read superblock\n");
286 goto out_no_fs_ul; 287 goto out_no_fs_ul;
287 } 288 }
288 289
289 if (efs_validate_super(sb, (struct efs_super *) bh->b_data)) { 290 if (efs_validate_super(sb, (struct efs_super *) bh->b_data)) {
290 #ifdef DEBUG 291 #ifdef DEBUG
291 printk(KERN_WARNING "EFS: invalid superblock at block %u\n", sb->fs_start + EFS_SUPER); 292 printk(KERN_WARNING "EFS: invalid superblock at block %u\n", sb->fs_start + EFS_SUPER);
292 #endif 293 #endif
293 brelse(bh); 294 brelse(bh);
294 goto out_no_fs_ul; 295 goto out_no_fs_ul;
295 } 296 }
296 brelse(bh); 297 brelse(bh);
297 298
298 if (!(s->s_flags & MS_RDONLY)) { 299 if (!(s->s_flags & MS_RDONLY)) {
299 #ifdef DEBUG 300 #ifdef DEBUG
300 printk(KERN_INFO "EFS: forcing read-only mode\n"); 301 printk(KERN_INFO "EFS: forcing read-only mode\n");
301 #endif 302 #endif
302 s->s_flags |= MS_RDONLY; 303 s->s_flags |= MS_RDONLY;
303 } 304 }
304 s->s_op = &efs_superblock_operations; 305 s->s_op = &efs_superblock_operations;
305 s->s_export_op = &efs_export_ops; 306 s->s_export_op = &efs_export_ops;
306 root = efs_iget(s, EFS_ROOTINODE); 307 root = efs_iget(s, EFS_ROOTINODE);
307 if (IS_ERR(root)) { 308 if (IS_ERR(root)) {
308 printk(KERN_ERR "EFS: get root inode failed\n"); 309 printk(KERN_ERR "EFS: get root inode failed\n");
309 ret = PTR_ERR(root); 310 ret = PTR_ERR(root);
310 goto out_no_fs; 311 goto out_no_fs;
311 } 312 }
312 313
313 s->s_root = d_alloc_root(root); 314 s->s_root = d_alloc_root(root);
314 if (!(s->s_root)) { 315 if (!(s->s_root)) {
315 printk(KERN_ERR "EFS: get root dentry failed\n"); 316 printk(KERN_ERR "EFS: get root dentry failed\n");
316 iput(root); 317 iput(root);
317 ret = -ENOMEM; 318 ret = -ENOMEM;
318 goto out_no_fs; 319 goto out_no_fs;
319 } 320 }
320 321
321 return 0; 322 return 0;
322 323
323 out_no_fs_ul: 324 out_no_fs_ul:
324 out_no_fs: 325 out_no_fs:
325 s->s_fs_info = NULL; 326 s->s_fs_info = NULL;
326 kfree(sb); 327 kfree(sb);
327 return ret; 328 return ret;
328 } 329 }
329 330
330 static int efs_statfs(struct dentry *dentry, struct kstatfs *buf) { 331 static int efs_statfs(struct dentry *dentry, struct kstatfs *buf) {
331 struct efs_sb_info *sb = SUPER_INFO(dentry->d_sb); 332 struct efs_sb_info *sb = SUPER_INFO(dentry->d_sb);
332 333
333 buf->f_type = EFS_SUPER_MAGIC; /* efs magic number */ 334 buf->f_type = EFS_SUPER_MAGIC; /* efs magic number */
334 buf->f_bsize = EFS_BLOCKSIZE; /* blocksize */ 335 buf->f_bsize = EFS_BLOCKSIZE; /* blocksize */
335 buf->f_blocks = sb->total_groups * /* total data blocks */ 336 buf->f_blocks = sb->total_groups * /* total data blocks */
336 (sb->group_size - sb->inode_blocks); 337 (sb->group_size - sb->inode_blocks);
337 buf->f_bfree = sb->data_free; /* free data blocks */ 338 buf->f_bfree = sb->data_free; /* free data blocks */
338 buf->f_bavail = sb->data_free; /* free blocks for non-root */ 339 buf->f_bavail = sb->data_free; /* free blocks for non-root */
339 buf->f_files = sb->total_groups * /* total inodes */ 340 buf->f_files = sb->total_groups * /* total inodes */
340 sb->inode_blocks * 341 sb->inode_blocks *
341 (EFS_BLOCKSIZE / sizeof(struct efs_dinode)); 342 (EFS_BLOCKSIZE / sizeof(struct efs_dinode));
342 buf->f_ffree = sb->inode_free; /* free inodes */ 343 buf->f_ffree = sb->inode_free; /* free inodes */
343 buf->f_fsid.val[0] = (sb->fs_magic >> 16) & 0xffff; /* fs ID */ 344 buf->f_fsid.val[0] = (sb->fs_magic >> 16) & 0xffff; /* fs ID */
344 buf->f_fsid.val[1] = sb->fs_magic & 0xffff; /* fs ID */ 345 buf->f_fsid.val[1] = sb->fs_magic & 0xffff; /* fs ID */
345 buf->f_namelen = EFS_MAXNAMELEN; /* max filename length */ 346 buf->f_namelen = EFS_MAXNAMELEN; /* max filename length */
346 347
347 return 0; 348 return 0;
1 /* 1 /*
2 * symlink.c 2 * symlink.c
3 * 3 *
4 * Copyright (c) 1999 Al Smith 4 * Copyright (c) 1999 Al Smith
5 * 5 *
6 * Portions derived from work (c) 1995,1996 Christian Vogelgsang. 6 * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
7 */ 7 */
8 8
9 #include <linux/string.h> 9 #include <linux/string.h>
10 #include <linux/efs_fs.h>
11 #include <linux/pagemap.h> 10 #include <linux/pagemap.h>
12 #include <linux/buffer_head.h> 11 #include <linux/buffer_head.h>
13 #include <linux/smp_lock.h> 12 #include <linux/smp_lock.h>
13 #include "efs.h"
14 14
15 static int efs_symlink_readpage(struct file *file, struct page *page) 15 static int efs_symlink_readpage(struct file *file, struct page *page)
16 { 16 {
17 char *link = kmap(page); 17 char *link = kmap(page);
18 struct buffer_head * bh; 18 struct buffer_head * bh;
19 struct inode * inode = page->mapping->host; 19 struct inode * inode = page->mapping->host;
20 efs_block_t size = inode->i_size; 20 efs_block_t size = inode->i_size;
21 int err; 21 int err;
22 22
23 err = -ENAMETOOLONG; 23 err = -ENAMETOOLONG;
24 if (size > 2 * EFS_BLOCKSIZE) 24 if (size > 2 * EFS_BLOCKSIZE)
25 goto fail_notlocked; 25 goto fail_notlocked;
26 26
27 lock_kernel(); 27 lock_kernel();
28 /* read first 512 bytes of link target */ 28 /* read first 512 bytes of link target */
29 err = -EIO; 29 err = -EIO;
30 bh = sb_bread(inode->i_sb, efs_bmap(inode, 0)); 30 bh = sb_bread(inode->i_sb, efs_bmap(inode, 0));
31 if (!bh) 31 if (!bh)
32 goto fail; 32 goto fail;
33 memcpy(link, bh->b_data, (size > EFS_BLOCKSIZE) ? EFS_BLOCKSIZE : size); 33 memcpy(link, bh->b_data, (size > EFS_BLOCKSIZE) ? EFS_BLOCKSIZE : size);
34 brelse(bh); 34 brelse(bh);
35 if (size > EFS_BLOCKSIZE) { 35 if (size > EFS_BLOCKSIZE) {
36 bh = sb_bread(inode->i_sb, efs_bmap(inode, 1)); 36 bh = sb_bread(inode->i_sb, efs_bmap(inode, 1));
37 if (!bh) 37 if (!bh)
38 goto fail; 38 goto fail;
39 memcpy(link + EFS_BLOCKSIZE, bh->b_data, size - EFS_BLOCKSIZE); 39 memcpy(link + EFS_BLOCKSIZE, bh->b_data, size - EFS_BLOCKSIZE);
40 brelse(bh); 40 brelse(bh);
41 } 41 }
42 link[size] = '\0'; 42 link[size] = '\0';
43 unlock_kernel(); 43 unlock_kernel();
44 SetPageUptodate(page); 44 SetPageUptodate(page);
45 kunmap(page); 45 kunmap(page);
46 unlock_page(page); 46 unlock_page(page);
47 return 0; 47 return 0;
48 fail: 48 fail:
49 unlock_kernel(); 49 unlock_kernel();
50 fail_notlocked: 50 fail_notlocked:
51 SetPageError(page); 51 SetPageError(page);
52 kunmap(page); 52 kunmap(page);
53 unlock_page(page); 53 unlock_page(page);
54 return err; 54 return err;
55 } 55 }
56 56
57 const struct address_space_operations efs_symlink_aops = { 57 const struct address_space_operations efs_symlink_aops = {
58 .readpage = efs_symlink_readpage 58 .readpage = efs_symlink_readpage
59 }; 59 };
include/linux/efs_dir.h
1 /* File was deleted
2 * efs_dir.h
3 *
4 * Copyright (c) 1999 Al Smith
5 */
6
7 #ifndef __EFS_DIR_H__
8 #define __EFS_DIR_H__
9
10 #define EFS_DIRBSIZE_BITS EFS_BLOCKSIZE_BITS
11 #define EFS_DIRBSIZE (1 << EFS_DIRBSIZE_BITS)
12
13 struct efs_dentry {
14 __be32 inode;
15 unsigned char namelen;
16 char name[3];
17 };
18
19 #define EFS_DENTSIZE (sizeof(struct efs_dentry) - 3 + 1)
20 #define EFS_MAXNAMELEN ((1 << (sizeof(char) * 8)) - 1)
21
22 #define EFS_DIRBLK_HEADERSIZE 4
23 #define EFS_DIRBLK_MAGIC 0xbeef /* moo */
24
25 struct efs_dir {
26 __be16 magic;
27 unsigned char firstused;
28 unsigned char slots;
29
30 unsigned char space[EFS_DIRBSIZE - EFS_DIRBLK_HEADERSIZE];
31 };
32
33 #define EFS_MAXENTS \
34 ((EFS_DIRBSIZE - EFS_DIRBLK_HEADERSIZE) / \
35 (EFS_DENTSIZE + sizeof(char)))
36
37 #define EFS_SLOTAT(dir, slot) EFS_REALOFF((dir)->space[slot])
38
39 #define EFS_REALOFF(offset) ((offset << 1))
40
41 #endif /* __EFS_DIR_H__ */
42 1 /*
43 2 * efs_dir.h
include/linux/efs_fs.h
1 /* File was deleted
2 * efs_fs.h
3 *
4 * Copyright (c) 1999 Al Smith
5 *
6 * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
7 */
8
9 #ifndef __EFS_FS_H__
10 #define __EFS_FS_H__
11
12 #define EFS_VERSION "1.0a"
13
14 static const char cprt[] = "EFS: "EFS_VERSION" - (c) 1999 Al Smith <Al.Smith@aeschi.ch.eu.org>";
15
16 #include <asm/uaccess.h>
17
18 /* 1 block is 512 bytes */
19 #define EFS_BLOCKSIZE_BITS 9
20 #define EFS_BLOCKSIZE (1 << EFS_BLOCKSIZE_BITS)
21
22 #include <linux/fs.h>
23 #include <linux/efs_fs_i.h>
24 #include <linux/efs_fs_sb.h>
25 #include <linux/efs_dir.h>
26
27 static inline struct efs_inode_info *INODE_INFO(struct inode *inode)
28 {
29 return container_of(inode, struct efs_inode_info, vfs_inode);
30 }
31
32 static inline struct efs_sb_info *SUPER_INFO(struct super_block *sb)
33 {
34 return sb->s_fs_info;
35 }
36
37 struct statfs;
38 struct fid;
39
40 extern const struct inode_operations efs_dir_inode_operations;
41 extern const struct file_operations efs_dir_operations;
42 extern const struct address_space_operations efs_symlink_aops;
43
44 extern struct inode *efs_iget(struct super_block *, unsigned long);
45 extern efs_block_t efs_map_block(struct inode *, efs_block_t);
46 extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int);
47
48 extern struct dentry *efs_lookup(struct inode *, struct dentry *, struct nameidata *);
49 extern struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid,
50 int fh_len, int fh_type);
51 extern struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid,
52 int fh_len, int fh_type);
53 extern struct dentry *efs_get_parent(struct dentry *);
54 extern int efs_bmap(struct inode *, int);
55
56 #endif /* __EFS_FS_H__ */
57 1 /*
include/linux/efs_fs_i.h
1 /* File was deleted
2 * efs_fs_i.h
3 *
4 * Copyright (c) 1999 Al Smith
5 *
6 * Portions derived from IRIX header files (c) 1988 Silicon Graphics
7 */
8
9 #ifndef __EFS_FS_I_H__
10 #define __EFS_FS_I_H__
11
12 typedef int32_t efs_block_t;
13 typedef uint32_t efs_ino_t;
14
15 #define EFS_DIRECTEXTENTS 12
16
17 /*
18 * layout of an extent, in memory and on disk. 8 bytes exactly.
19 */
20 typedef union extent_u {
21 unsigned char raw[8];
22 struct extent_s {
23 unsigned int ex_magic:8; /* magic # (zero) */
24 unsigned int ex_bn:24; /* basic block */
25 unsigned int ex_length:8; /* numblocks in this extent */
26 unsigned int ex_offset:24; /* logical offset into file */
27 } cooked;
28 } efs_extent;
29
30 typedef struct edevs {
31 __be16 odev;
32 __be32 ndev;
33 } efs_devs;
34
35 /*
36 * extent based filesystem inode as it appears on disk. The efs inode
37 * is exactly 128 bytes long.
38 */
39 struct efs_dinode {
40 __be16 di_mode; /* mode and type of file */
41 __be16 di_nlink; /* number of links to file */
42 __be16 di_uid; /* owner's user id */
43 __be16 di_gid; /* owner's group id */
44 __be32 di_size; /* number of bytes in file */
45 __be32 di_atime; /* time last accessed */
46 __be32 di_mtime; /* time last modified */
47 __be32 di_ctime; /* time created */
48 __be32 di_gen; /* generation number */
49 __be16 di_numextents; /* # of extents */
50 u_char di_version; /* version of inode */
51 u_char di_spare; /* spare - used by AFS */
52 union di_addr {
53 efs_extent di_extents[EFS_DIRECTEXTENTS];
54 efs_devs di_dev; /* device for IFCHR/IFBLK */
55 } di_u;
56 };
57
58 /* efs inode storage in memory */
59 struct efs_inode_info {
60 int numextents;
61 int lastextent;
62
63 efs_extent extents[EFS_DIRECTEXTENTS];
64 struct inode vfs_inode;
65 };
66
67 #endif /* __EFS_FS_I_H__ */
68 1 /*
69 2 * efs_fs_i.h