diff options
Diffstat (limited to 'fs/freevxfs')
-rw-r--r-- | fs/freevxfs/Makefile | 8 | ||||
-rw-r--r-- | fs/freevxfs/vxfs.h | 264 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_bmap.c | 280 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_dir.h | 92 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_extern.h | 76 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_fshead.c | 202 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_fshead.h | 67 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_immed.c | 114 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_inode.c | 351 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_inode.h | 180 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_kcompat.h | 49 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_lookup.c | 328 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_olt.c | 132 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_olt.h | 145 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_subr.c | 190 | ||||
-rw-r--r-- | fs/freevxfs/vxfs_super.c | 278 |
16 files changed, 2756 insertions, 0 deletions
diff --git a/fs/freevxfs/Makefile b/fs/freevxfs/Makefile new file mode 100644 index 000000000000..87ad097440d6 --- /dev/null +++ b/fs/freevxfs/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # | ||
2 | # VxFS Makefile | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_VXFS_FS) += freevxfs.o | ||
6 | |||
7 | freevxfs-objs := vxfs_bmap.o vxfs_fshead.o vxfs_immed.o vxfs_inode.o \ | ||
8 | vxfs_lookup.o vxfs_olt.o vxfs_subr.o vxfs_super.o | ||
diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h new file mode 100644 index 000000000000..8da0252642a4 --- /dev/null +++ b/fs/freevxfs/vxfs.h | |||
@@ -0,0 +1,264 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * 1. Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions, and the following disclaimer, | ||
10 | * without modification. | ||
11 | * 2. The name of the author may not be used to endorse or promote products | ||
12 | * derived from this software without specific prior written permission. | ||
13 | * | ||
14 | * Alternatively, this software may be distributed under the terms of the | ||
15 | * GNU General Public License ("GPL"). | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
27 | * SUCH DAMAGE. | ||
28 | * | ||
29 | */ | ||
30 | #ifndef _VXFS_SUPER_H_ | ||
31 | #define _VXFS_SUPER_H_ | ||
32 | |||
33 | /* | ||
34 | * Veritas filesystem driver - superblock structure. | ||
35 | * | ||
36 | * This file contains the definition of the disk and core | ||
37 | * superblocks of the Veritas Filesystem. | ||
38 | */ | ||
39 | #include <linux/types.h> | ||
40 | #include "vxfs_kcompat.h" | ||
41 | |||
42 | |||
43 | /* | ||
44 | * Data types for use with the VxFS ondisk format. | ||
45 | */ | ||
46 | typedef int32_t vx_daddr_t; | ||
47 | typedef int32_t vx_ino_t; | ||
48 | |||
49 | /* | ||
50 | * Superblock magic number (vxfs_super->vs_magic). | ||
51 | */ | ||
52 | #define VXFS_SUPER_MAGIC 0xa501FCF5 | ||
53 | |||
54 | /* | ||
55 | * The root inode. | ||
56 | */ | ||
57 | #define VXFS_ROOT_INO 2 | ||
58 | |||
59 | /* | ||
60 | * Num of entries in free extent array | ||
61 | */ | ||
62 | #define VXFS_NEFREE 32 | ||
63 | |||
64 | |||
65 | /* | ||
66 | * VxFS superblock (disk). | ||
67 | */ | ||
68 | struct vxfs_sb { | ||
69 | /* | ||
70 | * Readonly fields for the version 1 superblock. | ||
71 | * | ||
72 | * Lots of this fields are no more used by version 2 | ||
73 | * and never filesystems. | ||
74 | */ | ||
75 | u_int32_t vs_magic; /* Magic number */ | ||
76 | int32_t vs_version; /* VxFS version */ | ||
77 | u_int32_t vs_ctime; /* create time - secs */ | ||
78 | u_int32_t vs_cutime; /* create time - usecs */ | ||
79 | int32_t __unused1; /* unused */ | ||
80 | int32_t __unused2; /* unused */ | ||
81 | vx_daddr_t vs_old_logstart; /* obsolete */ | ||
82 | vx_daddr_t vs_old_logend; /* obsolete */ | ||
83 | int32_t vs_bsize; /* block size */ | ||
84 | int32_t vs_size; /* number of blocks */ | ||
85 | int32_t vs_dsize; /* number of data blocks */ | ||
86 | u_int32_t vs_old_ninode; /* obsolete */ | ||
87 | int32_t vs_old_nau; /* obsolete */ | ||
88 | int32_t __unused3; /* unused */ | ||
89 | int32_t vs_old_defiextsize; /* obsolete */ | ||
90 | int32_t vs_old_ilbsize; /* obsolete */ | ||
91 | int32_t vs_immedlen; /* size of immediate data area */ | ||
92 | int32_t vs_ndaddr; /* number of direct extentes */ | ||
93 | vx_daddr_t vs_firstau; /* address of first AU */ | ||
94 | vx_daddr_t vs_emap; /* offset of extent map in AU */ | ||
95 | vx_daddr_t vs_imap; /* offset of inode map in AU */ | ||
96 | vx_daddr_t vs_iextop; /* offset of ExtOp. map in AU */ | ||
97 | vx_daddr_t vs_istart; /* offset of inode list in AU */ | ||
98 | vx_daddr_t vs_bstart; /* offset of fdblock in AU */ | ||
99 | vx_daddr_t vs_femap; /* aufirst + emap */ | ||
100 | vx_daddr_t vs_fimap; /* aufirst + imap */ | ||
101 | vx_daddr_t vs_fiextop; /* aufirst + iextop */ | ||
102 | vx_daddr_t vs_fistart; /* aufirst + istart */ | ||
103 | vx_daddr_t vs_fbstart; /* aufirst + bstart */ | ||
104 | int32_t vs_nindir; /* number of entries in indir */ | ||
105 | int32_t vs_aulen; /* length of AU in blocks */ | ||
106 | int32_t vs_auimlen; /* length of imap in blocks */ | ||
107 | int32_t vs_auemlen; /* length of emap in blocks */ | ||
108 | int32_t vs_auilen; /* length of ilist in blocks */ | ||
109 | int32_t vs_aupad; /* length of pad in blocks */ | ||
110 | int32_t vs_aublocks; /* data blocks in AU */ | ||
111 | int32_t vs_maxtier; /* log base 2 of aublocks */ | ||
112 | int32_t vs_inopb; /* number of inodes per blk */ | ||
113 | int32_t vs_old_inopau; /* obsolete */ | ||
114 | int32_t vs_old_inopilb; /* obsolete */ | ||
115 | int32_t vs_old_ndiripau; /* obsolete */ | ||
116 | int32_t vs_iaddrlen; /* size of indirect addr ext. */ | ||
117 | int32_t vs_bshift; /* log base 2 of bsize */ | ||
118 | int32_t vs_inoshift; /* log base 2 of inobp */ | ||
119 | int32_t vs_bmask; /* ~( bsize - 1 ) */ | ||
120 | int32_t vs_boffmask; /* bsize - 1 */ | ||
121 | int32_t vs_old_inomask; /* old_inopilb - 1 */ | ||
122 | int32_t vs_checksum; /* checksum of V1 data */ | ||
123 | |||
124 | /* | ||
125 | * Version 1, writable | ||
126 | */ | ||
127 | int32_t vs_free; /* number of free blocks */ | ||
128 | int32_t vs_ifree; /* number of free inodes */ | ||
129 | int32_t vs_efree[VXFS_NEFREE]; /* number of free extents by size */ | ||
130 | int32_t vs_flags; /* flags ?!? */ | ||
131 | u_int8_t vs_mod; /* filesystem has been changed */ | ||
132 | u_int8_t vs_clean; /* clean FS */ | ||
133 | u_int16_t __unused4; /* unused */ | ||
134 | u_int32_t vs_firstlogid; /* mount time log ID */ | ||
135 | u_int32_t vs_wtime; /* last time written - sec */ | ||
136 | u_int32_t vs_wutime; /* last time written - usec */ | ||
137 | u_int8_t vs_fname[6]; /* FS name */ | ||
138 | u_int8_t vs_fpack[6]; /* FS pack name */ | ||
139 | int32_t vs_logversion; /* log format version */ | ||
140 | int32_t __unused5; /* unused */ | ||
141 | |||
142 | /* | ||
143 | * Version 2, Read-only | ||
144 | */ | ||
145 | vx_daddr_t vs_oltext[2]; /* OLT extent and replica */ | ||
146 | int32_t vs_oltsize; /* OLT extent size */ | ||
147 | int32_t vs_iauimlen; /* size of inode map */ | ||
148 | int32_t vs_iausize; /* size of IAU in blocks */ | ||
149 | int32_t vs_dinosize; /* size of inode in bytes */ | ||
150 | int32_t vs_old_dniaddr; /* indir levels per inode */ | ||
151 | int32_t vs_checksum2; /* checksum of V2 RO */ | ||
152 | |||
153 | /* | ||
154 | * Actually much more... | ||
155 | */ | ||
156 | }; | ||
157 | |||
158 | |||
159 | /* | ||
160 | * In core superblock filesystem private data for VxFS. | ||
161 | */ | ||
162 | struct vxfs_sb_info { | ||
163 | struct vxfs_sb *vsi_raw; /* raw (on disk) supeblock */ | ||
164 | struct buffer_head *vsi_bp; /* buffer for raw superblock*/ | ||
165 | struct inode *vsi_fship; /* fileset header inode */ | ||
166 | struct inode *vsi_ilist; /* inode list inode */ | ||
167 | struct inode *vsi_stilist; /* structual inode list inode */ | ||
168 | u_long vsi_iext; /* initial inode list */ | ||
169 | ino_t vsi_fshino; /* fileset header inode */ | ||
170 | daddr_t vsi_oltext; /* OLT extent */ | ||
171 | daddr_t vsi_oltsize; /* OLT size */ | ||
172 | }; | ||
173 | |||
174 | |||
175 | /* | ||
176 | * File modes. File types above 0xf000 are vxfs internal only, they should | ||
177 | * not be passed back to higher levels of the system. vxfs file types must | ||
178 | * never have one of the regular file type bits set. | ||
179 | */ | ||
180 | enum vxfs_mode { | ||
181 | VXFS_ISUID = 0x00000800, /* setuid */ | ||
182 | VXFS_ISGID = 0x00000400, /* setgid */ | ||
183 | VXFS_ISVTX = 0x00000200, /* sticky bit */ | ||
184 | VXFS_IREAD = 0x00000100, /* read */ | ||
185 | VXFS_IWRITE = 0x00000080, /* write */ | ||
186 | VXFS_IEXEC = 0x00000040, /* exec */ | ||
187 | |||
188 | VXFS_IFIFO = 0x00001000, /* Named pipe */ | ||
189 | VXFS_IFCHR = 0x00002000, /* Character device */ | ||
190 | VXFS_IFDIR = 0x00004000, /* Directory */ | ||
191 | VXFS_IFNAM = 0x00005000, /* Xenix device ?? */ | ||
192 | VXFS_IFBLK = 0x00006000, /* Block device */ | ||
193 | VXFS_IFREG = 0x00008000, /* Regular file */ | ||
194 | VXFS_IFCMP = 0x00009000, /* Compressed file ?!? */ | ||
195 | VXFS_IFLNK = 0x0000a000, /* Symlink */ | ||
196 | VXFS_IFSOC = 0x0000c000, /* Socket */ | ||
197 | |||
198 | /* VxFS internal */ | ||
199 | VXFS_IFFSH = 0x10000000, /* Fileset header */ | ||
200 | VXFS_IFILT = 0x20000000, /* Inode list */ | ||
201 | VXFS_IFIAU = 0x30000000, /* Inode allocation unit */ | ||
202 | VXFS_IFCUT = 0x40000000, /* Current usage table */ | ||
203 | VXFS_IFATT = 0x50000000, /* Attr. inode */ | ||
204 | VXFS_IFLCT = 0x60000000, /* Link count table */ | ||
205 | VXFS_IFIAT = 0x70000000, /* Indirect attribute file */ | ||
206 | VXFS_IFEMR = 0x80000000, /* Extent map reorg file */ | ||
207 | VXFS_IFQUO = 0x90000000, /* BSD quota file */ | ||
208 | VXFS_IFPTI = 0xa0000000, /* "Pass through" inode */ | ||
209 | VXFS_IFLAB = 0x11000000, /* Device label file */ | ||
210 | VXFS_IFOLT = 0x12000000, /* OLT file */ | ||
211 | VXFS_IFLOG = 0x13000000, /* Log file */ | ||
212 | VXFS_IFEMP = 0x14000000, /* Extent map file */ | ||
213 | VXFS_IFEAU = 0x15000000, /* Extent AU file */ | ||
214 | VXFS_IFAUS = 0x16000000, /* Extent AU summary file */ | ||
215 | VXFS_IFDEV = 0x17000000, /* Device config file */ | ||
216 | |||
217 | }; | ||
218 | |||
219 | #define VXFS_TYPE_MASK 0xfffff000 | ||
220 | |||
221 | #define VXFS_IS_TYPE(ip,type) (((ip)->vii_mode & VXFS_TYPE_MASK) == (type)) | ||
222 | #define VXFS_ISFIFO(x) VXFS_IS_TYPE((x),VXFS_IFIFO) | ||
223 | #define VXFS_ISCHR(x) VXFS_IS_TYPE((x),VXFS_IFCHR) | ||
224 | #define VXFS_ISDIR(x) VXFS_IS_TYPE((x),VXFS_IFDIR) | ||
225 | #define VXFS_ISNAM(x) VXFS_IS_TYPE((x),VXFS_IFNAM) | ||
226 | #define VXFS_ISBLK(x) VXFS_IS_TYPE((x),VXFS_IFBLK) | ||
227 | #define VXFS_ISLNK(x) VXFS_IS_TYPE((x),VXFS_IFLNK) | ||
228 | #define VXFS_ISREG(x) VXFS_IS_TYPE((x),VXFS_IFREG) | ||
229 | #define VXFS_ISCMP(x) VXFS_IS_TYPE((x),VXFS_IFCMP) | ||
230 | #define VXFS_ISSOC(x) VXFS_IS_TYPE((x),VXFS_IFSOC) | ||
231 | |||
232 | #define VXFS_ISFSH(x) VXFS_IS_TYPE((x),VXFS_IFFSH) | ||
233 | #define VXFS_ISILT(x) VXFS_IS_TYPE((x),VXFS_IFILT) | ||
234 | |||
235 | /* | ||
236 | * Inmode organisation types. | ||
237 | */ | ||
238 | enum { | ||
239 | VXFS_ORG_NONE = 0, /* Inode has *no* format ?!? */ | ||
240 | VXFS_ORG_EXT4 = 1, /* Ext4 */ | ||
241 | VXFS_ORG_IMMED = 2, /* All data stored in inode */ | ||
242 | VXFS_ORG_TYPED = 3, /* Typed extents */ | ||
243 | }; | ||
244 | |||
245 | #define VXFS_IS_ORG(ip,org) ((ip)->vii_orgtype == (org)) | ||
246 | #define VXFS_ISNONE(ip) VXFS_IS_ORG((ip), VXFS_ORG_NONE) | ||
247 | #define VXFS_ISEXT4(ip) VXFS_IS_ORG((ip), VXFS_ORG_EXT4) | ||
248 | #define VXFS_ISIMMED(ip) VXFS_IS_ORG((ip), VXFS_ORG_IMMED) | ||
249 | #define VXFS_ISTYPED(ip) VXFS_IS_ORG((ip), VXFS_ORG_TYPED) | ||
250 | |||
251 | |||
252 | /* | ||
253 | * Get filesystem private data from VFS inode. | ||
254 | */ | ||
255 | #define VXFS_INO(ip) \ | ||
256 | ((struct vxfs_inode_info *)(ip)->u.generic_ip) | ||
257 | |||
258 | /* | ||
259 | * Get filesystem private data from VFS superblock. | ||
260 | */ | ||
261 | #define VXFS_SBI(sbp) \ | ||
262 | ((struct vxfs_sb_info *)(sbp)->s_fs_info) | ||
263 | |||
264 | #endif /* _VXFS_SUPER_H_ */ | ||
diff --git a/fs/freevxfs/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c new file mode 100644 index 000000000000..bc4b57da306a --- /dev/null +++ b/fs/freevxfs/vxfs_bmap.c | |||
@@ -0,0 +1,280 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * 1. Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions, and the following disclaimer, | ||
10 | * without modification. | ||
11 | * 2. The name of the author may not be used to endorse or promote products | ||
12 | * derived from this software without specific prior written permission. | ||
13 | * | ||
14 | * Alternatively, this software may be distributed under the terms of the | ||
15 | * GNU General Public License ("GPL"). | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
27 | * SUCH DAMAGE. | ||
28 | */ | ||
29 | |||
30 | /* | ||
31 | * Veritas filesystem driver - filesystem to disk block mapping. | ||
32 | */ | ||
33 | #include <linux/fs.h> | ||
34 | #include <linux/buffer_head.h> | ||
35 | #include <linux/kernel.h> | ||
36 | |||
37 | #include "vxfs.h" | ||
38 | #include "vxfs_inode.h" | ||
39 | |||
40 | |||
41 | #ifdef DIAGNOSTIC | ||
42 | static void | ||
43 | vxfs_typdump(struct vxfs_typed *typ) | ||
44 | { | ||
45 | printk(KERN_DEBUG "type=%Lu ", typ->vt_hdr >> VXFS_TYPED_TYPESHIFT); | ||
46 | printk("offset=%Lx ", typ->vt_hdr & VXFS_TYPED_OFFSETMASK); | ||
47 | printk("block=%x ", typ->vt_block); | ||
48 | printk("size=%x\n", typ->vt_size); | ||
49 | } | ||
50 | #endif | ||
51 | |||
52 | /** | ||
53 | * vxfs_bmap_ext4 - do bmap for ext4 extents | ||
54 | * @ip: pointer to the inode we do bmap for | ||
55 | * @iblock: logical block. | ||
56 | * | ||
57 | * Description: | ||
58 | * vxfs_bmap_ext4 performs the bmap operation for inodes with | ||
59 | * ext4-style extents (which are much like the traditional UNIX | ||
60 | * inode organisation). | ||
61 | * | ||
62 | * Returns: | ||
63 | * The physical block number on success, else Zero. | ||
64 | */ | ||
65 | static daddr_t | ||
66 | vxfs_bmap_ext4(struct inode *ip, long bn) | ||
67 | { | ||
68 | struct super_block *sb = ip->i_sb; | ||
69 | struct vxfs_inode_info *vip = VXFS_INO(ip); | ||
70 | unsigned long bsize = sb->s_blocksize; | ||
71 | u32 indsize = vip->vii_ext4.ve4_indsize; | ||
72 | int i; | ||
73 | |||
74 | if (indsize > sb->s_blocksize) | ||
75 | goto fail_size; | ||
76 | |||
77 | for (i = 0; i < VXFS_NDADDR; i++) { | ||
78 | struct direct *d = vip->vii_ext4.ve4_direct + i; | ||
79 | if (bn >= 0 && bn < d->size) | ||
80 | return (bn + d->extent); | ||
81 | bn -= d->size; | ||
82 | } | ||
83 | |||
84 | if ((bn / (indsize * indsize * bsize / 4)) == 0) { | ||
85 | struct buffer_head *buf; | ||
86 | daddr_t bno; | ||
87 | u32 *indir; | ||
88 | |||
89 | buf = sb_bread(sb, vip->vii_ext4.ve4_indir[0]); | ||
90 | if (!buf || !buffer_mapped(buf)) | ||
91 | goto fail_buf; | ||
92 | |||
93 | indir = (u32 *)buf->b_data; | ||
94 | bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize); | ||
95 | |||
96 | brelse(buf); | ||
97 | return bno; | ||
98 | } else | ||
99 | printk(KERN_WARNING "no matching indir?"); | ||
100 | |||
101 | return 0; | ||
102 | |||
103 | fail_size: | ||
104 | printk("vxfs: indirect extent to big!\n"); | ||
105 | fail_buf: | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * vxfs_bmap_indir - recursion for vxfs_bmap_typed | ||
111 | * @ip: pointer to the inode we do bmap for | ||
112 | * @indir: indirect block we start reading at | ||
113 | * @size: size of the typed area to search | ||
114 | * @block: partially result from further searches | ||
115 | * | ||
116 | * Description: | ||
117 | * vxfs_bmap_indir reads a &struct vxfs_typed at @indir | ||
118 | * and performs the type-defined action. | ||
119 | * | ||
120 | * Return Value: | ||
121 | * The physical block number on success, else Zero. | ||
122 | * | ||
123 | * Note: | ||
124 | * Kernelstack is rare. Unrecurse? | ||
125 | */ | ||
126 | static daddr_t | ||
127 | vxfs_bmap_indir(struct inode *ip, long indir, int size, long block) | ||
128 | { | ||
129 | struct buffer_head *bp = NULL; | ||
130 | daddr_t pblock = 0; | ||
131 | int i; | ||
132 | |||
133 | for (i = 0; i < size * VXFS_TYPED_PER_BLOCK(ip->i_sb); i++) { | ||
134 | struct vxfs_typed *typ; | ||
135 | int64_t off; | ||
136 | |||
137 | bp = sb_bread(ip->i_sb, | ||
138 | indir + (i / VXFS_TYPED_PER_BLOCK(ip->i_sb))); | ||
139 | if (!buffer_mapped(bp)) | ||
140 | return 0; | ||
141 | |||
142 | typ = ((struct vxfs_typed *)bp->b_data) + | ||
143 | (i % VXFS_TYPED_PER_BLOCK(ip->i_sb)); | ||
144 | off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK); | ||
145 | |||
146 | if (block < off) { | ||
147 | brelse(bp); | ||
148 | continue; | ||
149 | } | ||
150 | |||
151 | switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) { | ||
152 | case VXFS_TYPED_INDIRECT: | ||
153 | pblock = vxfs_bmap_indir(ip, typ->vt_block, | ||
154 | typ->vt_size, block - off); | ||
155 | if (pblock == -2) | ||
156 | break; | ||
157 | goto out; | ||
158 | case VXFS_TYPED_DATA: | ||
159 | if ((block - off) >= typ->vt_size) | ||
160 | break; | ||
161 | pblock = (typ->vt_block + block - off); | ||
162 | goto out; | ||
163 | case VXFS_TYPED_INDIRECT_DEV4: | ||
164 | case VXFS_TYPED_DATA_DEV4: { | ||
165 | struct vxfs_typed_dev4 *typ4 = | ||
166 | (struct vxfs_typed_dev4 *)typ; | ||
167 | |||
168 | printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n"); | ||
169 | printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n", | ||
170 | (unsigned long long) typ4->vd4_block, | ||
171 | (unsigned long long) typ4->vd4_size, | ||
172 | typ4->vd4_dev); | ||
173 | goto fail; | ||
174 | } | ||
175 | default: | ||
176 | BUG(); | ||
177 | } | ||
178 | brelse(bp); | ||
179 | } | ||
180 | |||
181 | fail: | ||
182 | pblock = 0; | ||
183 | out: | ||
184 | brelse(bp); | ||
185 | return (pblock); | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * vxfs_bmap_typed - bmap for typed extents | ||
190 | * @ip: pointer to the inode we do bmap for | ||
191 | * @iblock: logical block | ||
192 | * | ||
193 | * Description: | ||
194 | * Performs the bmap operation for typed extents. | ||
195 | * | ||
196 | * Return Value: | ||
197 | * The physical block number on success, else Zero. | ||
198 | */ | ||
199 | static daddr_t | ||
200 | vxfs_bmap_typed(struct inode *ip, long iblock) | ||
201 | { | ||
202 | struct vxfs_inode_info *vip = VXFS_INO(ip); | ||
203 | daddr_t pblock = 0; | ||
204 | int i; | ||
205 | |||
206 | for (i = 0; i < VXFS_NTYPED; i++) { | ||
207 | struct vxfs_typed *typ = vip->vii_org.typed + i; | ||
208 | int64_t off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK); | ||
209 | |||
210 | #ifdef DIAGNOSTIC | ||
211 | vxfs_typdump(typ); | ||
212 | #endif | ||
213 | if (iblock < off) | ||
214 | continue; | ||
215 | switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) { | ||
216 | case VXFS_TYPED_INDIRECT: | ||
217 | pblock = vxfs_bmap_indir(ip, typ->vt_block, | ||
218 | typ->vt_size, iblock - off); | ||
219 | if (pblock == -2) | ||
220 | break; | ||
221 | return (pblock); | ||
222 | case VXFS_TYPED_DATA: | ||
223 | if ((iblock - off) < typ->vt_size) | ||
224 | return (typ->vt_block + iblock - off); | ||
225 | break; | ||
226 | case VXFS_TYPED_INDIRECT_DEV4: | ||
227 | case VXFS_TYPED_DATA_DEV4: { | ||
228 | struct vxfs_typed_dev4 *typ4 = | ||
229 | (struct vxfs_typed_dev4 *)typ; | ||
230 | |||
231 | printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n"); | ||
232 | printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n", | ||
233 | (unsigned long long) typ4->vd4_block, | ||
234 | (unsigned long long) typ4->vd4_size, | ||
235 | typ4->vd4_dev); | ||
236 | return 0; | ||
237 | } | ||
238 | default: | ||
239 | BUG(); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | /** | ||
247 | * vxfs_bmap1 - vxfs-internal bmap operation | ||
248 | * @ip: pointer to the inode we do bmap for | ||
249 | * @iblock: logical block | ||
250 | * | ||
251 | * Description: | ||
252 | * vxfs_bmap1 perfoms a logical to physical block mapping | ||
253 | * for vxfs-internal purposes. | ||
254 | * | ||
255 | * Return Value: | ||
256 | * The physical block number on success, else Zero. | ||
257 | */ | ||
258 | daddr_t | ||
259 | vxfs_bmap1(struct inode *ip, long iblock) | ||
260 | { | ||
261 | struct vxfs_inode_info *vip = VXFS_INO(ip); | ||
262 | |||
263 | if (VXFS_ISEXT4(vip)) | ||
264 | return vxfs_bmap_ext4(ip, iblock); | ||
265 | if (VXFS_ISTYPED(vip)) | ||
266 | return vxfs_bmap_typed(ip, iblock); | ||
267 | if (VXFS_ISNONE(vip)) | ||
268 | goto unsupp; | ||
269 | if (VXFS_ISIMMED(vip)) | ||
270 | goto unsupp; | ||
271 | |||
272 | printk(KERN_WARNING "vxfs: inode %ld has no valid orgtype (%x)\n", | ||
273 | ip->i_ino, vip->vii_orgtype); | ||
274 | BUG(); | ||
275 | |||
276 | unsupp: | ||
277 | printk(KERN_WARNING "vxfs: inode %ld has an unsupported orgtype (%x)\n", | ||
278 | ip->i_ino, vip->vii_orgtype); | ||
279 | return 0; | ||
280 | } | ||
diff --git a/fs/freevxfs/vxfs_dir.h b/fs/freevxfs/vxfs_dir.h new file mode 100644 index 000000000000..8a4dfef1ddad --- /dev/null +++ b/fs/freevxfs/vxfs_dir.h | |||
@@ -0,0 +1,92 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * 1. Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions, and the following disclaimer, | ||
10 | * without modification. | ||
11 | * 2. The name of the author may not be used to endorse or promote products | ||
12 | * derived from this software without specific prior written permission. | ||
13 | * | ||
14 | * Alternatively, this software may be distributed under the terms of the | ||
15 | * GNU General Public License ("GPL"). | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
27 | * SUCH DAMAGE. | ||
28 | * | ||
29 | */ | ||
30 | #ifndef _VXFS_DIR_H_ | ||
31 | #define _VXFS_DIR_H_ | ||
32 | |||
33 | /* | ||
34 | * Veritas filesystem driver - directory structure. | ||
35 | * | ||
36 | * This file contains the definition of the vxfs directory format. | ||
37 | */ | ||
38 | |||
39 | |||
40 | /* | ||
41 | * VxFS directory block header. | ||
42 | * | ||
43 | * This entry is the head of every filesystem block in a directory. | ||
44 | * It is used for free space managment and additionally includes | ||
45 | * a hash for speeding up directory search (lookup). | ||
46 | * | ||
47 | * The hash may be empty and in fact we do not use it all in the | ||
48 | * Linux driver for now. | ||
49 | */ | ||
50 | struct vxfs_dirblk { | ||
51 | u_int16_t d_free; /* free space in dirblock */ | ||
52 | u_int16_t d_nhash; /* no of hash chains */ | ||
53 | u_int16_t d_hash[1]; /* hash chain */ | ||
54 | }; | ||
55 | |||
56 | /* | ||
57 | * VXFS_NAMELEN is the maximum length of the d_name field | ||
58 | * of an VxFS directory entry. | ||
59 | */ | ||
60 | #define VXFS_NAMELEN 256 | ||
61 | |||
62 | /* | ||
63 | * VxFS directory entry. | ||
64 | */ | ||
65 | struct vxfs_direct { | ||
66 | vx_ino_t d_ino; /* inode number */ | ||
67 | u_int16_t d_reclen; /* record length */ | ||
68 | u_int16_t d_namelen; /* d_name length */ | ||
69 | u_int16_t d_hashnext; /* next hash entry */ | ||
70 | char d_name[VXFS_NAMELEN]; /* name */ | ||
71 | }; | ||
72 | |||
73 | /* | ||
74 | * VXFS_DIRPAD defines the directory entry boundaries, is _must_ be | ||
75 | * a multiple of four. | ||
76 | * VXFS_NAMEMIN is the length of a directory entry with a NULL d_name. | ||
77 | * VXFS_DIRROUND is an internal macros that rounds a length to a value | ||
78 | * usable for directory sizes. | ||
79 | * VXFS_DIRLEN calculates the directory entry size for an entry with | ||
80 | * a d_name with size len. | ||
81 | */ | ||
82 | #define VXFS_DIRPAD 4 | ||
83 | #define VXFS_NAMEMIN ((int)((struct vxfs_direct *)0)->d_name) | ||
84 | #define VXFS_DIRROUND(len) ((VXFS_DIRPAD + (len) - 1) & ~(VXFS_DIRPAD -1)) | ||
85 | #define VXFS_DIRLEN(len) (VXFS_DIRROUND(VXFS_NAMEMIN + (len))) | ||
86 | |||
87 | /* | ||
88 | * VXFS_DIRBLKOV is the overhead of a specific dirblock. | ||
89 | */ | ||
90 | #define VXFS_DIRBLKOV(dbp) ((sizeof(short) * dbp->d_nhash) + 4) | ||
91 | |||
92 | #endif /* _VXFS_DIR_H_ */ | ||
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h new file mode 100644 index 000000000000..d8be917f9797 --- /dev/null +++ b/fs/freevxfs/vxfs_extern.h | |||
@@ -0,0 +1,76 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * 1. Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions, and the following disclaimer, | ||
10 | * without modification. | ||
11 | * 2. The name of the author may not be used to endorse or promote products | ||
12 | * derived from this software without specific prior written permission. | ||
13 | * | ||
14 | * Alternatively, this software may be distributed under the terms of the | ||
15 | * GNU General Public License ("GPL"). | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
27 | * SUCH DAMAGE. | ||
28 | * | ||
29 | */ | ||
30 | #ifndef _VXFS_EXTERN_H_ | ||
31 | #define _VXFS_EXTERN_H_ | ||
32 | |||
33 | /* | ||
34 | * Veritas filesystem driver - external prototypes. | ||
35 | * | ||
36 | * This file contains prototypes for all vxfs functions used | ||
37 | * outside their respective source files. | ||
38 | */ | ||
39 | |||
40 | |||
41 | struct kmem_cache_s; | ||
42 | struct super_block; | ||
43 | struct vxfs_inode_info; | ||
44 | struct inode; | ||
45 | |||
46 | |||
47 | /* vxfs_bmap.c */ | ||
48 | extern daddr_t vxfs_bmap1(struct inode *, long); | ||
49 | |||
50 | /* vxfs_fshead.c */ | ||
51 | extern int vxfs_read_fshead(struct super_block *); | ||
52 | |||
53 | /* vxfs_inode.c */ | ||
54 | extern struct kmem_cache_s *vxfs_inode_cachep; | ||
55 | extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t); | ||
56 | extern struct inode * vxfs_get_fake_inode(struct super_block *, | ||
57 | struct vxfs_inode_info *); | ||
58 | extern void vxfs_put_fake_inode(struct inode *); | ||
59 | extern struct vxfs_inode_info * vxfs_blkiget(struct super_block *, u_long, ino_t); | ||
60 | extern struct vxfs_inode_info * vxfs_stiget(struct super_block *, ino_t); | ||
61 | extern void vxfs_read_inode(struct inode *); | ||
62 | extern void vxfs_clear_inode(struct inode *); | ||
63 | |||
64 | /* vxfs_lookup.c */ | ||
65 | extern struct inode_operations vxfs_dir_inode_ops; | ||
66 | extern struct file_operations vxfs_dir_operations; | ||
67 | |||
68 | /* vxfs_olt.c */ | ||
69 | extern int vxfs_read_olt(struct super_block *, u_long); | ||
70 | |||
71 | /* vxfs_subr.c */ | ||
72 | extern struct page * vxfs_get_page(struct address_space *, u_long); | ||
73 | extern void vxfs_put_page(struct page *); | ||
74 | extern struct buffer_head * vxfs_bread(struct inode *, int); | ||
75 | |||
76 | #endif /* _VXFS_EXTERN_H_ */ | ||
diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c new file mode 100644 index 000000000000..05b19f70bf97 --- /dev/null +++ b/fs/freevxfs/vxfs_fshead.c | |||
@@ -0,0 +1,202 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * 1. Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions, and the following disclaimer, | ||
10 | * without modification. | ||
11 | * 2. The name of the author may not be used to endorse or promote products | ||
12 | * derived from this software without specific prior written permission. | ||
13 | * | ||
14 | * Alternatively, this software may be distributed under the terms of the | ||
15 | * GNU General Public License ("GPL"). | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
27 | * SUCH DAMAGE. | ||
28 | */ | ||
29 | |||
30 | /* | ||
31 | * Veritas filesystem driver - fileset header routines. | ||
32 | */ | ||
33 | #include <linux/fs.h> | ||
34 | #include <linux/buffer_head.h> | ||
35 | #include <linux/kernel.h> | ||
36 | #include <linux/slab.h> | ||
37 | #include <linux/string.h> | ||
38 | |||
39 | #include "vxfs.h" | ||
40 | #include "vxfs_inode.h" | ||
41 | #include "vxfs_extern.h" | ||
42 | #include "vxfs_fshead.h" | ||
43 | |||
44 | |||
45 | #ifdef DIAGNOSTIC | ||
46 | static void | ||
47 | vxfs_dumpfsh(struct vxfs_fsh *fhp) | ||
48 | { | ||
49 | printk("\n\ndumping fileset header:\n"); | ||
50 | printk("----------------------------\n"); | ||
51 | printk("version: %u\n", fhp->fsh_version); | ||
52 | printk("fsindex: %u\n", fhp->fsh_fsindex); | ||
53 | printk("iauino: %u\tninodes:%u\n", | ||
54 | fhp->fsh_iauino, fhp->fsh_ninodes); | ||
55 | printk("maxinode: %u\tlctino: %u\n", | ||
56 | fhp->fsh_maxinode, fhp->fsh_lctino); | ||
57 | printk("nau: %u\n", fhp->fsh_nau); | ||
58 | printk("ilistino[0]: %u\tilistino[1]: %u\n", | ||
59 | fhp->fsh_ilistino[0], fhp->fsh_ilistino[1]); | ||
60 | } | ||
61 | #endif | ||
62 | |||
63 | /** | ||
64 | * vxfs_getfsh - read fileset header into memory | ||
65 | * @ip: the (fake) fileset header inode | ||
66 | * @which: 0 for the structural, 1 for the primary fsh. | ||
67 | * | ||
68 | * Description: | ||
69 | * vxfs_getfsh reads either the structural or primary fileset header | ||
70 | * described by @ip into memory. | ||
71 | * | ||
72 | * Returns: | ||
73 | * The fileset header structure on success, else Zero. | ||
74 | */ | ||
75 | static struct vxfs_fsh * | ||
76 | vxfs_getfsh(struct inode *ip, int which) | ||
77 | { | ||
78 | struct buffer_head *bp; | ||
79 | |||
80 | bp = vxfs_bread(ip, which); | ||
81 | if (buffer_mapped(bp)) { | ||
82 | struct vxfs_fsh *fhp; | ||
83 | |||
84 | if (!(fhp = kmalloc(sizeof(*fhp), SLAB_KERNEL))) | ||
85 | return NULL; | ||
86 | memcpy(fhp, bp->b_data, sizeof(*fhp)); | ||
87 | |||
88 | brelse(bp); | ||
89 | return (fhp); | ||
90 | } | ||
91 | |||
92 | return NULL; | ||
93 | } | ||
94 | |||
95 | /** | ||
96 | * vxfs_read_fshead - read the fileset headers | ||
97 | * @sbp: superblock to which the fileset belongs | ||
98 | * | ||
99 | * Description: | ||
100 | * vxfs_read_fshead will fill the inode and structural inode list in @sb. | ||
101 | * | ||
102 | * Returns: | ||
103 | * Zero on success, else a negative error code (-EINVAL). | ||
104 | */ | ||
105 | int | ||
106 | vxfs_read_fshead(struct super_block *sbp) | ||
107 | { | ||
108 | struct vxfs_sb_info *infp = VXFS_SBI(sbp); | ||
109 | struct vxfs_fsh *pfp, *sfp; | ||
110 | struct vxfs_inode_info *vip, *tip; | ||
111 | |||
112 | vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino); | ||
113 | if (!vip) { | ||
114 | printk(KERN_ERR "vxfs: unabled to read fsh inode\n"); | ||
115 | return -EINVAL; | ||
116 | } | ||
117 | if (!VXFS_ISFSH(vip)) { | ||
118 | printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n", | ||
119 | vip->vii_mode & VXFS_TYPE_MASK); | ||
120 | goto out_free_fship; | ||
121 | } | ||
122 | |||
123 | |||
124 | #ifdef DIAGNOSTIC | ||
125 | printk("vxfs: fsh inode dump:\n"); | ||
126 | vxfs_dumpi(vip, infp->vsi_fshino); | ||
127 | #endif | ||
128 | |||
129 | infp->vsi_fship = vxfs_get_fake_inode(sbp, vip); | ||
130 | if (!infp->vsi_fship) { | ||
131 | printk(KERN_ERR "vxfs: unabled to get fsh inode\n"); | ||
132 | goto out_free_fship; | ||
133 | } | ||
134 | |||
135 | sfp = vxfs_getfsh(infp->vsi_fship, 0); | ||
136 | if (!sfp) { | ||
137 | printk(KERN_ERR "vxfs: unabled to get structural fsh\n"); | ||
138 | goto out_iput_fship; | ||
139 | } | ||
140 | |||
141 | #ifdef DIAGNOSTIC | ||
142 | vxfs_dumpfsh(sfp); | ||
143 | #endif | ||
144 | |||
145 | pfp = vxfs_getfsh(infp->vsi_fship, 1); | ||
146 | if (!pfp) { | ||
147 | printk(KERN_ERR "vxfs: unabled to get primary fsh\n"); | ||
148 | goto out_free_sfp; | ||
149 | } | ||
150 | |||
151 | #ifdef DIAGNOSTIC | ||
152 | vxfs_dumpfsh(pfp); | ||
153 | #endif | ||
154 | |||
155 | tip = vxfs_blkiget(sbp, infp->vsi_iext, sfp->fsh_ilistino[0]); | ||
156 | if (!tip) | ||
157 | goto out_free_pfp; | ||
158 | |||
159 | infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip); | ||
160 | if (!infp->vsi_stilist) { | ||
161 | printk(KERN_ERR "vxfs: unabled to get structual list inode\n"); | ||
162 | kfree(tip); | ||
163 | goto out_free_pfp; | ||
164 | } | ||
165 | if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) { | ||
166 | printk(KERN_ERR "vxfs: structual list inode is of wrong type (%x)\n", | ||
167 | VXFS_INO(infp->vsi_stilist)->vii_mode & VXFS_TYPE_MASK); | ||
168 | goto out_iput_stilist; | ||
169 | } | ||
170 | |||
171 | tip = vxfs_stiget(sbp, pfp->fsh_ilistino[0]); | ||
172 | if (!tip) | ||
173 | goto out_iput_stilist; | ||
174 | infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip); | ||
175 | if (!infp->vsi_ilist) { | ||
176 | printk(KERN_ERR "vxfs: unabled to get inode list inode\n"); | ||
177 | kfree(tip); | ||
178 | goto out_iput_stilist; | ||
179 | } | ||
180 | if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) { | ||
181 | printk(KERN_ERR "vxfs: inode list inode is of wrong type (%x)\n", | ||
182 | VXFS_INO(infp->vsi_ilist)->vii_mode & VXFS_TYPE_MASK); | ||
183 | goto out_iput_ilist; | ||
184 | } | ||
185 | |||
186 | return 0; | ||
187 | |||
188 | out_iput_ilist: | ||
189 | iput(infp->vsi_ilist); | ||
190 | out_iput_stilist: | ||
191 | iput(infp->vsi_stilist); | ||
192 | out_free_pfp: | ||
193 | kfree(pfp); | ||
194 | out_free_sfp: | ||
195 | kfree(sfp); | ||
196 | out_iput_fship: | ||
197 | iput(infp->vsi_fship); | ||
198 | return -EINVAL; | ||
199 | out_free_fship: | ||
200 | kfree(vip); | ||
201 | return -EINVAL; | ||
202 | } | ||
diff --git a/fs/freevxfs/vxfs_fshead.h b/fs/freevxfs/vxfs_fshead.h new file mode 100644 index 000000000000..ead0d640c181 --- /dev/null +++ b/fs/freevxfs/vxfs_fshead.h | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * 1. Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions, and the following disclaimer, | ||
10 | * without modification. | ||
11 | * 2. The name of the author may not be used to endorse or promote products | ||
12 | * derived from this software without specific prior written permission. | ||
13 | * | ||
14 | * Alternatively, this software may be distributed under the terms of the | ||
15 | * GNU General Public License ("GPL"). | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
27 | * SUCH DAMAGE. | ||
28 | * | ||
29 | */ | ||
30 | #ifndef _VXFS_FSHEAD_H_ | ||
31 | #define _VXFS_FSHEAD_H_ | ||
32 | |||
33 | /* | ||
34 | * Veritas filesystem driver - fileset header structures. | ||
35 | * | ||
36 | * This file contains the physical structure of the VxFS | ||
37 | * fileset header. | ||
38 | */ | ||
39 | |||
40 | |||
41 | /* | ||
42 | * Fileset header | ||
43 | */ | ||
44 | struct vxfs_fsh { | ||
45 | u_int32_t fsh_version; /* fileset header version */ | ||
46 | u_int32_t fsh_fsindex; /* fileset index */ | ||
47 | u_int32_t fsh_time; /* modification time - sec */ | ||
48 | u_int32_t fsh_utime; /* modification time - usec */ | ||
49 | u_int32_t fsh_extop; /* extop flags */ | ||
50 | vx_ino_t fsh_ninodes; /* allocated inodes */ | ||
51 | u_int32_t fsh_nau; /* number of IAUs */ | ||
52 | u_int32_t fsh_old_ilesize; /* old size of ilist */ | ||
53 | u_int32_t fsh_dflags; /* flags */ | ||
54 | u_int32_t fsh_quota; /* quota limit */ | ||
55 | vx_ino_t fsh_maxinode; /* maximum inode number */ | ||
56 | vx_ino_t fsh_iauino; /* IAU inode */ | ||
57 | vx_ino_t fsh_ilistino[2]; /* ilist inodes */ | ||
58 | vx_ino_t fsh_lctino; /* link count table inode */ | ||
59 | |||
60 | /* | ||
61 | * Slightly more fields follow, but they | ||
62 | * a) are not of any interest for us, and | ||
63 | * b) differ a lot in different vxfs versions/ports | ||
64 | */ | ||
65 | }; | ||
66 | |||
67 | #endif /* _VXFS_FSHEAD_H_ */ | ||
diff --git a/fs/freevxfs/vxfs_immed.c b/fs/freevxfs/vxfs_immed.c new file mode 100644 index 000000000000..ac677ab262b2 --- /dev/null +++ b/fs/freevxfs/vxfs_immed.c | |||
@@ -0,0 +1,114 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * 1. Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions, and the following disclaimer, | ||
10 | * without modification. | ||
11 | * 2. The name of the author may not be used to endorse or promote products | ||
12 | * derived from this software without specific prior written permission. | ||
13 | * | ||
14 | * Alternatively, this software may be distributed under the terms of the | ||
15 | * GNU General Public License ("GPL"). | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
27 | * SUCH DAMAGE. | ||
28 | */ | ||
29 | |||
30 | /* | ||
31 | * Veritas filesystem driver - support for 'immed' inodes. | ||
32 | */ | ||
33 | #include <linux/fs.h> | ||
34 | #include <linux/pagemap.h> | ||
35 | #include <linux/namei.h> | ||
36 | |||
37 | #include "vxfs.h" | ||
38 | #include "vxfs_inode.h" | ||
39 | |||
40 | |||
41 | static int vxfs_immed_follow_link(struct dentry *, struct nameidata *); | ||
42 | |||
43 | static int vxfs_immed_readpage(struct file *, struct page *); | ||
44 | |||
45 | /* | ||
46 | * Inode operations for immed symlinks. | ||
47 | * | ||
48 | * Unliked all other operations we do not go through the pagecache, | ||
49 | * but do all work directly on the inode. | ||
50 | */ | ||
51 | struct inode_operations vxfs_immed_symlink_iops = { | ||
52 | .readlink = generic_readlink, | ||
53 | .follow_link = vxfs_immed_follow_link, | ||
54 | }; | ||
55 | |||
56 | /* | ||
57 | * Adress space operations for immed files and directories. | ||
58 | */ | ||
59 | struct address_space_operations vxfs_immed_aops = { | ||
60 | .readpage = vxfs_immed_readpage, | ||
61 | }; | ||
62 | |||
63 | /** | ||
64 | * vxfs_immed_follow_link - follow immed symlink | ||
65 | * @dp: dentry for the link | ||
66 | * @np: pathname lookup data for the current path walk | ||
67 | * | ||
68 | * Description: | ||
69 | * vxfs_immed_follow_link restarts the pathname lookup with | ||
70 | * the data obtained from @dp. | ||
71 | * | ||
72 | * Returns: | ||
73 | * Zero on success, else a negative error code. | ||
74 | */ | ||
75 | static int | ||
76 | vxfs_immed_follow_link(struct dentry *dp, struct nameidata *np) | ||
77 | { | ||
78 | struct vxfs_inode_info *vip = VXFS_INO(dp->d_inode); | ||
79 | nd_set_link(np, vip->vii_immed.vi_immed); | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | /** | ||
84 | * vxfs_immed_readpage - read part of an immed inode into pagecache | ||
85 | * @file: file context (unused) | ||
86 | * @page: page frame to fill in. | ||
87 | * | ||
88 | * Description: | ||
89 | * vxfs_immed_readpage reads a part of the immed area of the | ||
90 | * file that hosts @pp into the pagecache. | ||
91 | * | ||
92 | * Returns: | ||
93 | * Zero on success, else a negative error code. | ||
94 | * | ||
95 | * Locking status: | ||
96 | * @page is locked and will be unlocked. | ||
97 | */ | ||
98 | static int | ||
99 | vxfs_immed_readpage(struct file *fp, struct page *pp) | ||
100 | { | ||
101 | struct vxfs_inode_info *vip = VXFS_INO(pp->mapping->host); | ||
102 | u_int64_t offset = pp->index << PAGE_CACHE_SHIFT; | ||
103 | caddr_t kaddr; | ||
104 | |||
105 | kaddr = kmap(pp); | ||
106 | memcpy(kaddr, vip->vii_immed.vi_immed + offset, PAGE_CACHE_SIZE); | ||
107 | kunmap(pp); | ||
108 | |||
109 | flush_dcache_page(pp); | ||
110 | SetPageUptodate(pp); | ||
111 | unlock_page(pp); | ||
112 | |||
113 | return 0; | ||
114 | } | ||
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c new file mode 100644 index 000000000000..9672d2facffe --- /dev/null +++ b/fs/freevxfs/vxfs_inode.c | |||
@@ -0,0 +1,351 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * 1. Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions, and the following disclaimer, | ||
10 | * without modification. | ||
11 | * 2. The name of the author may not be used to endorse or promote products | ||
12 | * derived from this software without specific prior written permission. | ||
13 | * | ||
14 | * Alternatively, this software may be distributed under the terms of the | ||
15 | * GNU General Public License ("GPL"). | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
27 | * SUCH DAMAGE. | ||
28 | */ | ||
29 | |||
30 | /* | ||
31 | * Veritas filesystem driver - inode routines. | ||
32 | */ | ||
33 | #include <linux/fs.h> | ||
34 | #include <linux/buffer_head.h> | ||
35 | #include <linux/pagemap.h> | ||
36 | #include <linux/kernel.h> | ||
37 | #include <linux/slab.h> | ||
38 | |||
39 | #include "vxfs.h" | ||
40 | #include "vxfs_inode.h" | ||
41 | #include "vxfs_extern.h" | ||
42 | |||
43 | |||
44 | extern struct address_space_operations vxfs_aops; | ||
45 | extern struct address_space_operations vxfs_immed_aops; | ||
46 | |||
47 | extern struct inode_operations vxfs_immed_symlink_iops; | ||
48 | |||
49 | static struct file_operations vxfs_file_operations = { | ||
50 | .open = generic_file_open, | ||
51 | .llseek = generic_file_llseek, | ||
52 | .read = generic_file_read, | ||
53 | .mmap = generic_file_mmap, | ||
54 | .sendfile = generic_file_sendfile, | ||
55 | }; | ||
56 | |||
57 | |||
58 | kmem_cache_t *vxfs_inode_cachep; | ||
59 | |||
60 | |||
61 | #ifdef DIAGNOSTIC | ||
62 | /* | ||
63 | * Dump inode contents (partially). | ||
64 | */ | ||
65 | void | ||
66 | vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino) | ||
67 | { | ||
68 | printk(KERN_DEBUG "\n\n"); | ||
69 | if (ino) | ||
70 | printk(KERN_DEBUG "dumping vxfs inode %ld\n", ino); | ||
71 | else | ||
72 | printk(KERN_DEBUG "dumping unknown vxfs inode\n"); | ||
73 | |||
74 | printk(KERN_DEBUG "---------------------------\n"); | ||
75 | printk(KERN_DEBUG "mode is %x\n", vip->vii_mode); | ||
76 | printk(KERN_DEBUG "nlink:%u, uid:%u, gid:%u\n", | ||
77 | vip->vii_nlink, vip->vii_uid, vip->vii_gid); | ||
78 | printk(KERN_DEBUG "size:%Lx, blocks:%u\n", | ||
79 | vip->vii_size, vip->vii_blocks); | ||
80 | printk(KERN_DEBUG "orgtype:%u\n", vip->vii_orgtype); | ||
81 | } | ||
82 | #endif | ||
83 | |||
84 | |||
85 | /** | ||
86 | * vxfs_blkiget - find inode based on extent # | ||
87 | * @sbp: superblock of the filesystem we search in | ||
88 | * @extent: number of the extent to search | ||
89 | * @ino: inode number to search | ||
90 | * | ||
91 | * Description: | ||
92 | * vxfs_blkiget searches inode @ino in the filesystem described by | ||
93 | * @sbp in the extent @extent. | ||
94 | * Returns the matching VxFS inode on success, else a NULL pointer. | ||
95 | * | ||
96 | * NOTE: | ||
97 | * While __vxfs_iget uses the pagecache vxfs_blkiget uses the | ||
98 | * buffercache. This function should not be used outside the | ||
99 | * read_super() method, otherwise the data may be incoherent. | ||
100 | */ | ||
101 | struct vxfs_inode_info * | ||
102 | vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino) | ||
103 | { | ||
104 | struct buffer_head *bp; | ||
105 | u_long block, offset; | ||
106 | |||
107 | block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize); | ||
108 | offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE); | ||
109 | bp = sb_bread(sbp, block); | ||
110 | |||
111 | if (buffer_mapped(bp)) { | ||
112 | struct vxfs_inode_info *vip; | ||
113 | struct vxfs_dinode *dip; | ||
114 | |||
115 | if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, SLAB_KERNEL))) | ||
116 | goto fail; | ||
117 | dip = (struct vxfs_dinode *)(bp->b_data + offset); | ||
118 | memcpy(vip, dip, sizeof(*vip)); | ||
119 | #ifdef DIAGNOSTIC | ||
120 | vxfs_dumpi(vip, ino); | ||
121 | #endif | ||
122 | brelse(bp); | ||
123 | return (vip); | ||
124 | } | ||
125 | |||
126 | fail: | ||
127 | printk(KERN_WARNING "vxfs: unable to read block %ld\n", block); | ||
128 | brelse(bp); | ||
129 | return NULL; | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * __vxfs_iget - generic find inode facility | ||
134 | * @sbp: VFS superblock | ||
135 | * @ino: inode number | ||
136 | * @ilistp: inode list | ||
137 | * | ||
138 | * Description: | ||
139 | * Search the for inode number @ino in the filesystem | ||
140 | * described by @sbp. Use the specified inode table (@ilistp). | ||
141 | * Returns the matching VxFS inode on success, else a NULL pointer. | ||
142 | */ | ||
143 | static struct vxfs_inode_info * | ||
144 | __vxfs_iget(ino_t ino, struct inode *ilistp) | ||
145 | { | ||
146 | struct page *pp; | ||
147 | u_long offset; | ||
148 | |||
149 | offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE; | ||
150 | pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE); | ||
151 | |||
152 | if (!IS_ERR(pp)) { | ||
153 | struct vxfs_inode_info *vip; | ||
154 | struct vxfs_dinode *dip; | ||
155 | caddr_t kaddr = (char *)page_address(pp); | ||
156 | |||
157 | if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, SLAB_KERNEL))) | ||
158 | goto fail; | ||
159 | dip = (struct vxfs_dinode *)(kaddr + offset); | ||
160 | memcpy(vip, dip, sizeof(*vip)); | ||
161 | #ifdef DIAGNOSTIC | ||
162 | vxfs_dumpi(vip, ino); | ||
163 | #endif | ||
164 | vxfs_put_page(pp); | ||
165 | return (vip); | ||
166 | } | ||
167 | |||
168 | printk(KERN_WARNING "vxfs: error on page %p\n", pp); | ||
169 | return NULL; | ||
170 | |||
171 | fail: | ||
172 | printk(KERN_WARNING "vxfs: unable to read inode %ld\n", (unsigned long)ino); | ||
173 | vxfs_put_page(pp); | ||
174 | return NULL; | ||
175 | } | ||
176 | |||
177 | /** | ||
178 | * vxfs_stiget - find inode using the structural inode list | ||
179 | * @sbp: VFS superblock | ||
180 | * @ino: inode # | ||
181 | * | ||
182 | * Description: | ||
183 | * Find inode @ino in the filesystem described by @sbp using | ||
184 | * the structural inode list. | ||
185 | * Returns the matching VxFS inode on success, else a NULL pointer. | ||
186 | */ | ||
187 | struct vxfs_inode_info * | ||
188 | vxfs_stiget(struct super_block *sbp, ino_t ino) | ||
189 | { | ||
190 | return __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_stilist); | ||
191 | } | ||
192 | |||
193 | /** | ||
194 | * vxfs_transmod - mode for a VxFS inode | ||
195 | * @vip: VxFS inode | ||
196 | * | ||
197 | * Description: | ||
198 | * vxfs_transmod returns a Linux mode_t for a given | ||
199 | * VxFS inode structure. | ||
200 | */ | ||
201 | static __inline__ mode_t | ||
202 | vxfs_transmod(struct vxfs_inode_info *vip) | ||
203 | { | ||
204 | mode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK; | ||
205 | |||
206 | if (VXFS_ISFIFO(vip)) | ||
207 | ret |= S_IFIFO; | ||
208 | if (VXFS_ISCHR(vip)) | ||
209 | ret |= S_IFCHR; | ||
210 | if (VXFS_ISDIR(vip)) | ||
211 | ret |= S_IFDIR; | ||
212 | if (VXFS_ISBLK(vip)) | ||
213 | ret |= S_IFBLK; | ||
214 | if (VXFS_ISLNK(vip)) | ||
215 | ret |= S_IFLNK; | ||
216 | if (VXFS_ISREG(vip)) | ||
217 | ret |= S_IFREG; | ||
218 | if (VXFS_ISSOC(vip)) | ||
219 | ret |= S_IFSOCK; | ||
220 | |||
221 | return (ret); | ||
222 | } | ||
223 | |||
224 | /** | ||
225 | * vxfs_iinit- helper to fill inode fields | ||
226 | * @ip: VFS inode | ||
227 | * @vip: VxFS inode | ||
228 | * | ||
229 | * Description: | ||
230 | * vxfs_instino is a helper function to fill in all relevant | ||
231 | * fields in @ip from @vip. | ||
232 | */ | ||
233 | static void | ||
234 | vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip) | ||
235 | { | ||
236 | |||
237 | ip->i_mode = vxfs_transmod(vip); | ||
238 | ip->i_uid = (uid_t)vip->vii_uid; | ||
239 | ip->i_gid = (gid_t)vip->vii_gid; | ||
240 | |||
241 | ip->i_nlink = vip->vii_nlink; | ||
242 | ip->i_size = vip->vii_size; | ||
243 | |||
244 | ip->i_atime.tv_sec = vip->vii_atime; | ||
245 | ip->i_ctime.tv_sec = vip->vii_ctime; | ||
246 | ip->i_mtime.tv_sec = vip->vii_mtime; | ||
247 | ip->i_atime.tv_nsec = 0; | ||
248 | ip->i_ctime.tv_nsec = 0; | ||
249 | ip->i_mtime.tv_nsec = 0; | ||
250 | |||
251 | ip->i_blksize = PAGE_SIZE; | ||
252 | ip->i_blocks = vip->vii_blocks; | ||
253 | ip->i_generation = vip->vii_gen; | ||
254 | |||
255 | ip->u.generic_ip = (void *)vip; | ||
256 | |||
257 | } | ||
258 | |||
259 | /** | ||
260 | * vxfs_get_fake_inode - get fake inode structure | ||
261 | * @sbp: filesystem superblock | ||
262 | * @vip: fspriv inode | ||
263 | * | ||
264 | * Description: | ||
265 | * vxfs_fake_inode gets a fake inode (not in the inode hash) for a | ||
266 | * superblock, vxfs_inode pair. | ||
267 | * Returns the filled VFS inode. | ||
268 | */ | ||
269 | struct inode * | ||
270 | vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip) | ||
271 | { | ||
272 | struct inode *ip = NULL; | ||
273 | |||
274 | if ((ip = new_inode(sbp))) { | ||
275 | vxfs_iinit(ip, vip); | ||
276 | ip->i_mapping->a_ops = &vxfs_aops; | ||
277 | } | ||
278 | return (ip); | ||
279 | } | ||
280 | |||
281 | /** | ||
282 | * vxfs_put_fake_inode - free faked inode | ||
283 | * *ip: VFS inode | ||
284 | * | ||
285 | * Description: | ||
286 | * vxfs_put_fake_inode frees all data asssociated with @ip. | ||
287 | */ | ||
288 | void | ||
289 | vxfs_put_fake_inode(struct inode *ip) | ||
290 | { | ||
291 | iput(ip); | ||
292 | } | ||
293 | |||
294 | /** | ||
295 | * vxfs_read_inode - fill in inode information | ||
296 | * @ip: inode pointer to fill | ||
297 | * | ||
298 | * Description: | ||
299 | * vxfs_read_inode reads the disk inode for @ip and fills | ||
300 | * in all relevant fields in @ip. | ||
301 | */ | ||
302 | void | ||
303 | vxfs_read_inode(struct inode *ip) | ||
304 | { | ||
305 | struct super_block *sbp = ip->i_sb; | ||
306 | struct vxfs_inode_info *vip; | ||
307 | struct address_space_operations *aops; | ||
308 | ino_t ino = ip->i_ino; | ||
309 | |||
310 | if (!(vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist))) | ||
311 | return; | ||
312 | |||
313 | vxfs_iinit(ip, vip); | ||
314 | |||
315 | if (VXFS_ISIMMED(vip)) | ||
316 | aops = &vxfs_immed_aops; | ||
317 | else | ||
318 | aops = &vxfs_aops; | ||
319 | |||
320 | if (S_ISREG(ip->i_mode)) { | ||
321 | ip->i_fop = &vxfs_file_operations; | ||
322 | ip->i_mapping->a_ops = aops; | ||
323 | } else if (S_ISDIR(ip->i_mode)) { | ||
324 | ip->i_op = &vxfs_dir_inode_ops; | ||
325 | ip->i_fop = &vxfs_dir_operations; | ||
326 | ip->i_mapping->a_ops = aops; | ||
327 | } else if (S_ISLNK(ip->i_mode)) { | ||
328 | if (!VXFS_ISIMMED(vip)) { | ||
329 | ip->i_op = &page_symlink_inode_operations; | ||
330 | ip->i_mapping->a_ops = &vxfs_aops; | ||
331 | } else | ||
332 | ip->i_op = &vxfs_immed_symlink_iops; | ||
333 | } else | ||
334 | init_special_inode(ip, ip->i_mode, old_decode_dev(vip->vii_rdev)); | ||
335 | |||
336 | return; | ||
337 | } | ||
338 | |||
339 | /** | ||
340 | * vxfs_clear_inode - remove inode from main memory | ||
341 | * @ip: inode to discard. | ||
342 | * | ||
343 | * Description: | ||
344 | * vxfs_clear_inode() is called on the final iput and frees the private | ||
345 | * inode area. | ||
346 | */ | ||
347 | void | ||
348 | vxfs_clear_inode(struct inode *ip) | ||
349 | { | ||
350 | kmem_cache_free(vxfs_inode_cachep, ip->u.generic_ip); | ||
351 | } | ||
diff --git a/fs/freevxfs/vxfs_inode.h b/fs/freevxfs/vxfs_inode.h new file mode 100644 index 000000000000..240aeb11263f --- /dev/null +++ b/fs/freevxfs/vxfs_inode.h | |||
@@ -0,0 +1,180 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * 1. Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions, and the following disclaimer, | ||
10 | * without modification. | ||
11 | * 2. The name of the author may not be used to endorse or promote products | ||
12 | * derived from this software without specific prior written permission. | ||
13 | * | ||
14 | * Alternatively, this software may be distributed under the terms of the | ||
15 | * GNU General Public License ("GPL"). | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
27 | * SUCH DAMAGE. | ||
28 | * | ||
29 | */ | ||
30 | #ifndef _VXFS_INODE_H_ | ||
31 | #define _VXFS_INODE_H_ | ||
32 | |||
33 | /* | ||
34 | * Veritas filesystem driver - inode structure. | ||
35 | * | ||
36 | * This file contains the definition of the disk and core | ||
37 | * inodes of the Veritas Filesystem. | ||
38 | */ | ||
39 | |||
40 | |||
41 | #define VXFS_ISIZE 0x100 /* Inode size */ | ||
42 | |||
43 | #define VXFS_NDADDR 10 /* Number of direct addrs in inode */ | ||
44 | #define VXFS_NIADDR 2 /* Number of indirect addrs in inode */ | ||
45 | #define VXFS_NIMMED 96 /* Size of immediate data in inode */ | ||
46 | #define VXFS_NTYPED 6 /* Num of typed extents */ | ||
47 | |||
48 | #define VXFS_TYPED_OFFSETMASK (0x00FFFFFFFFFFFFFFULL) | ||
49 | #define VXFS_TYPED_TYPEMASK (0xFF00000000000000ULL) | ||
50 | #define VXFS_TYPED_TYPESHIFT 56 | ||
51 | |||
52 | #define VXFS_TYPED_PER_BLOCK(sbp) \ | ||
53 | ((sbp)->s_blocksize / sizeof(struct vxfs_typed)) | ||
54 | |||
55 | /* | ||
56 | * Possible extent descriptor types for %VXFS_ORG_TYPED extents. | ||
57 | */ | ||
58 | enum { | ||
59 | VXFS_TYPED_INDIRECT = 1, | ||
60 | VXFS_TYPED_DATA = 2, | ||
61 | VXFS_TYPED_INDIRECT_DEV4 = 3, | ||
62 | VXFS_TYPED_DATA_DEV4 = 4, | ||
63 | }; | ||
64 | |||
65 | /* | ||
66 | * Data stored immediately in the inode. | ||
67 | */ | ||
68 | struct vxfs_immed { | ||
69 | u_int8_t vi_immed[VXFS_NIMMED]; | ||
70 | }; | ||
71 | |||
72 | struct vxfs_ext4 { | ||
73 | u_int32_t ve4_spare; /* ?? */ | ||
74 | u_int32_t ve4_indsize; /* Indirect extent size */ | ||
75 | vx_daddr_t ve4_indir[VXFS_NIADDR]; /* Indirect extents */ | ||
76 | struct direct { /* Direct extents */ | ||
77 | vx_daddr_t extent; /* Extent number */ | ||
78 | int32_t size; /* Size of extent */ | ||
79 | } ve4_direct[VXFS_NDADDR]; | ||
80 | }; | ||
81 | |||
82 | struct vxfs_typed { | ||
83 | u_int64_t vt_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */ | ||
84 | vx_daddr_t vt_block; /* Extent block */ | ||
85 | int32_t vt_size; /* Size in blocks */ | ||
86 | }; | ||
87 | |||
88 | struct vxfs_typed_dev4 { | ||
89 | u_int64_t vd4_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */ | ||
90 | u_int64_t vd4_block; /* Extent block */ | ||
91 | u_int64_t vd4_size; /* Size in blocks */ | ||
92 | int32_t vd4_dev; /* Device ID */ | ||
93 | u_int32_t __pad1; | ||
94 | }; | ||
95 | |||
96 | /* | ||
97 | * The inode as contained on the physical device. | ||
98 | */ | ||
99 | struct vxfs_dinode { | ||
100 | int32_t vdi_mode; | ||
101 | u_int32_t vdi_nlink; /* Link count */ | ||
102 | u_int32_t vdi_uid; /* UID */ | ||
103 | u_int32_t vdi_gid; /* GID */ | ||
104 | u_int64_t vdi_size; /* Inode size in bytes */ | ||
105 | u_int32_t vdi_atime; /* Last time accessed - sec */ | ||
106 | u_int32_t vdi_autime; /* Last time accessed - usec */ | ||
107 | u_int32_t vdi_mtime; /* Last modify time - sec */ | ||
108 | u_int32_t vdi_mutime; /* Last modify time - usec */ | ||
109 | u_int32_t vdi_ctime; /* Create time - sec */ | ||
110 | u_int32_t vdi_cutime; /* Create time - usec */ | ||
111 | u_int8_t vdi_aflags; /* Allocation flags */ | ||
112 | u_int8_t vdi_orgtype; /* Organisation type */ | ||
113 | u_int16_t vdi_eopflags; | ||
114 | u_int32_t vdi_eopdata; | ||
115 | union { | ||
116 | u_int32_t rdev; | ||
117 | u_int32_t dotdot; | ||
118 | struct { | ||
119 | u_int32_t reserved; | ||
120 | u_int32_t fixextsize; | ||
121 | } i_regular; | ||
122 | struct { | ||
123 | u_int32_t matchino; | ||
124 | u_int32_t fsetindex; | ||
125 | } i_vxspec; | ||
126 | u_int64_t align; | ||
127 | } vdi_ftarea; | ||
128 | u_int32_t vdi_blocks; /* How much blocks does inode occupy */ | ||
129 | u_int32_t vdi_gen; /* Inode generation */ | ||
130 | u_int64_t vdi_version; /* Version */ | ||
131 | union { | ||
132 | struct vxfs_immed immed; | ||
133 | struct vxfs_ext4 ext4; | ||
134 | struct vxfs_typed typed[VXFS_NTYPED]; | ||
135 | } vdi_org; | ||
136 | u_int32_t vdi_iattrino; | ||
137 | }; | ||
138 | |||
139 | #define vdi_rdev vdi_ftarea.rdev | ||
140 | #define vdi_dotdot vdi_ftarea.dotdot | ||
141 | #define vdi_fixextsize vdi_ftarea.regular.fixextsize | ||
142 | #define vdi_matchino vdi_ftarea.vxspec.matchino | ||
143 | #define vdi_fsetindex vdi_ftarea.vxspec.fsetindex | ||
144 | |||
145 | #define vdi_immed vdi_org.immed | ||
146 | #define vdi_ext4 vdi_org.ext4 | ||
147 | #define vdi_typed vdi_org.typed | ||
148 | |||
149 | |||
150 | /* | ||
151 | * The inode as represented in the main memory. | ||
152 | * | ||
153 | * TBD: This should become a separate structure... | ||
154 | */ | ||
155 | #define vxfs_inode_info vxfs_dinode | ||
156 | |||
157 | #define vii_mode vdi_mode | ||
158 | #define vii_uid vdi_uid | ||
159 | #define vii_gid vdi_gid | ||
160 | #define vii_nlink vdi_nlink | ||
161 | #define vii_size vdi_size | ||
162 | #define vii_atime vdi_atime | ||
163 | #define vii_ctime vdi_ctime | ||
164 | #define vii_mtime vdi_mtime | ||
165 | #define vii_blocks vdi_blocks | ||
166 | #define vii_org vdi_org | ||
167 | #define vii_orgtype vdi_orgtype | ||
168 | #define vii_gen vdi_gen | ||
169 | |||
170 | #define vii_rdev vdi_ftarea.rdev | ||
171 | #define vii_dotdot vdi_ftarea.dotdot | ||
172 | #define vii_fixextsize vdi_ftarea.regular.fixextsize | ||
173 | #define vii_matchino vdi_ftarea.vxspec.matchino | ||
174 | #define vii_fsetindex vdi_ftarea.vxspec.fsetindex | ||
175 | |||
176 | #define vii_immed vdi_org.immed | ||
177 | #define vii_ext4 vdi_org.ext4 | ||
178 | #define vii_typed vdi_org.typed | ||
179 | |||
180 | #endif /* _VXFS_INODE_H_ */ | ||
diff --git a/fs/freevxfs/vxfs_kcompat.h b/fs/freevxfs/vxfs_kcompat.h new file mode 100644 index 000000000000..342a4cc860f4 --- /dev/null +++ b/fs/freevxfs/vxfs_kcompat.h | |||
@@ -0,0 +1,49 @@ | |||
1 | #ifndef _VXFS_KCOMPAT_H | ||
2 | #define _VXFS_KCOMPAT_H | ||
3 | |||
4 | #include <linux/version.h> | ||
5 | |||
6 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) | ||
7 | |||
8 | #include <linux/blkdev.h> | ||
9 | |||
10 | typedef long sector_t; | ||
11 | |||
12 | /* From include/linux/fs.h (Linux 2.5.2-pre3) */ | ||
13 | static inline struct buffer_head * sb_bread(struct super_block *sb, int block) | ||
14 | { | ||
15 | return bread(sb->s_dev, block, sb->s_blocksize); | ||
16 | } | ||
17 | |||
18 | /* Dito. */ | ||
19 | static inline void map_bh(struct buffer_head *bh, struct super_block *sb, int block) | ||
20 | { | ||
21 | bh->b_state |= 1 << BH_Mapped; | ||
22 | bh->b_dev = sb->s_dev; | ||
23 | bh->b_blocknr = block; | ||
24 | } | ||
25 | |||
26 | /* From fs/block_dev.c (Linux 2.5.2-pre2) */ | ||
27 | static inline int sb_set_blocksize(struct super_block *sb, int size) | ||
28 | { | ||
29 | int bits; | ||
30 | if (set_blocksize(sb->s_dev, size) < 0) | ||
31 | return 0; | ||
32 | sb->s_blocksize = size; | ||
33 | for (bits = 9, size >>= 9; size >>= 1; bits++) | ||
34 | ; | ||
35 | sb->s_blocksize_bits = bits; | ||
36 | return sb->s_blocksize; | ||
37 | } | ||
38 | |||
39 | /* Dito. */ | ||
40 | static inline int sb_min_blocksize(struct super_block *sb, int size) | ||
41 | { | ||
42 | int minsize = get_hardsect_size(sb->s_dev); | ||
43 | if (size < minsize) | ||
44 | size = minsize; | ||
45 | return sb_set_blocksize(sb, size); | ||
46 | } | ||
47 | |||
48 | #endif /* Kernel 2.4 */ | ||
49 | #endif /* _VXFS_KCOMPAT_H */ | ||
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c new file mode 100644 index 000000000000..506ae251d2c0 --- /dev/null +++ b/fs/freevxfs/vxfs_lookup.c | |||
@@ -0,0 +1,328 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * 1. Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions, and the following disclaimer, | ||
10 | * without modification. | ||
11 | * 2. The name of the author may not be used to endorse or promote products | ||
12 | * derived from this software without specific prior written permission. | ||
13 | * | ||
14 | * Alternatively, this software may be distributed under the terms of the | ||
15 | * GNU General Public License ("GPL"). | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
27 | * SUCH DAMAGE. | ||
28 | */ | ||
29 | |||
30 | /* | ||
31 | * Veritas filesystem driver - lookup and other directory related code. | ||
32 | */ | ||
33 | #include <linux/fs.h> | ||
34 | #include <linux/time.h> | ||
35 | #include <linux/mm.h> | ||
36 | #include <linux/highmem.h> | ||
37 | #include <linux/kernel.h> | ||
38 | #include <linux/pagemap.h> | ||
39 | #include <linux/smp_lock.h> | ||
40 | |||
41 | #include "vxfs.h" | ||
42 | #include "vxfs_dir.h" | ||
43 | #include "vxfs_inode.h" | ||
44 | #include "vxfs_extern.h" | ||
45 | |||
46 | /* | ||
47 | * Number of VxFS blocks per page. | ||
48 | */ | ||
49 | #define VXFS_BLOCK_PER_PAGE(sbp) ((PAGE_CACHE_SIZE / (sbp)->s_blocksize)) | ||
50 | |||
51 | |||
52 | static struct dentry * vxfs_lookup(struct inode *, struct dentry *, struct nameidata *); | ||
53 | static int vxfs_readdir(struct file *, void *, filldir_t); | ||
54 | |||
55 | struct inode_operations vxfs_dir_inode_ops = { | ||
56 | .lookup = vxfs_lookup, | ||
57 | }; | ||
58 | |||
59 | struct file_operations vxfs_dir_operations = { | ||
60 | .readdir = vxfs_readdir, | ||
61 | }; | ||
62 | |||
63 | |||
64 | static __inline__ u_long | ||
65 | dir_pages(struct inode *inode) | ||
66 | { | ||
67 | return (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | ||
68 | } | ||
69 | |||
70 | static __inline__ u_long | ||
71 | dir_blocks(struct inode *ip) | ||
72 | { | ||
73 | u_long bsize = ip->i_sb->s_blocksize; | ||
74 | return (ip->i_size + bsize - 1) & ~(bsize - 1); | ||
75 | } | ||
76 | |||
77 | /* | ||
78 | * NOTE! unlike strncmp, vxfs_match returns 1 for success, 0 for failure. | ||
79 | * | ||
80 | * len <= VXFS_NAMELEN and de != NULL are guaranteed by caller. | ||
81 | */ | ||
82 | static __inline__ int | ||
83 | vxfs_match(int len, const char * const name, struct vxfs_direct *de) | ||
84 | { | ||
85 | if (len != de->d_namelen) | ||
86 | return 0; | ||
87 | if (!de->d_ino) | ||
88 | return 0; | ||
89 | return !memcmp(name, de->d_name, len); | ||
90 | } | ||
91 | |||
92 | static __inline__ struct vxfs_direct * | ||
93 | vxfs_next_entry(struct vxfs_direct *de) | ||
94 | { | ||
95 | return ((struct vxfs_direct *)((char*)de + de->d_reclen)); | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * vxfs_find_entry - find a mathing directory entry for a dentry | ||
100 | * @ip: directory inode | ||
101 | * @dp: dentry for which we want to find a direct | ||
102 | * @ppp: gets filled with the page the return value sits in | ||
103 | * | ||
104 | * Description: | ||
105 | * vxfs_find_entry finds a &struct vxfs_direct for the VFS directory | ||
106 | * cache entry @dp. @ppp will be filled with the page the return | ||
107 | * value resides in. | ||
108 | * | ||
109 | * Returns: | ||
110 | * The wanted direct on success, else a NULL pointer. | ||
111 | */ | ||
112 | static struct vxfs_direct * | ||
113 | vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp) | ||
114 | { | ||
115 | u_long npages, page, nblocks, pblocks, block; | ||
116 | u_long bsize = ip->i_sb->s_blocksize; | ||
117 | const char *name = dp->d_name.name; | ||
118 | int namelen = dp->d_name.len; | ||
119 | |||
120 | npages = dir_pages(ip); | ||
121 | nblocks = dir_blocks(ip); | ||
122 | pblocks = VXFS_BLOCK_PER_PAGE(ip->i_sb); | ||
123 | |||
124 | for (page = 0; page < npages; page++) { | ||
125 | caddr_t kaddr; | ||
126 | struct page *pp; | ||
127 | |||
128 | pp = vxfs_get_page(ip->i_mapping, page); | ||
129 | if (IS_ERR(pp)) | ||
130 | continue; | ||
131 | kaddr = (caddr_t)page_address(pp); | ||
132 | |||
133 | for (block = 0; block <= nblocks && block <= pblocks; block++) { | ||
134 | caddr_t baddr, limit; | ||
135 | struct vxfs_dirblk *dbp; | ||
136 | struct vxfs_direct *de; | ||
137 | |||
138 | baddr = kaddr + (block * bsize); | ||
139 | limit = baddr + bsize - VXFS_DIRLEN(1); | ||
140 | |||
141 | dbp = (struct vxfs_dirblk *)baddr; | ||
142 | de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp)); | ||
143 | |||
144 | for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) { | ||
145 | if (!de->d_reclen) | ||
146 | break; | ||
147 | if (!de->d_ino) | ||
148 | continue; | ||
149 | if (vxfs_match(namelen, name, de)) { | ||
150 | *ppp = pp; | ||
151 | return (de); | ||
152 | } | ||
153 | } | ||
154 | } | ||
155 | vxfs_put_page(pp); | ||
156 | } | ||
157 | |||
158 | return NULL; | ||
159 | } | ||
160 | |||
161 | /** | ||
162 | * vxfs_inode_by_name - find inode number for dentry | ||
163 | * @dip: directory to search in | ||
164 | * @dp: dentry we seach for | ||
165 | * | ||
166 | * Description: | ||
167 | * vxfs_inode_by_name finds out the inode number of | ||
168 | * the path component described by @dp in @dip. | ||
169 | * | ||
170 | * Returns: | ||
171 | * The wanted inode number on success, else Zero. | ||
172 | */ | ||
173 | static ino_t | ||
174 | vxfs_inode_by_name(struct inode *dip, struct dentry *dp) | ||
175 | { | ||
176 | struct vxfs_direct *de; | ||
177 | struct page *pp; | ||
178 | ino_t ino = 0; | ||
179 | |||
180 | de = vxfs_find_entry(dip, dp, &pp); | ||
181 | if (de) { | ||
182 | ino = de->d_ino; | ||
183 | kunmap(pp); | ||
184 | page_cache_release(pp); | ||
185 | } | ||
186 | |||
187 | return (ino); | ||
188 | } | ||
189 | |||
190 | /** | ||
191 | * vxfs_lookup - lookup pathname component | ||
192 | * @dip: dir in which we lookup | ||
193 | * @dp: dentry we lookup | ||
194 | * @nd: lookup nameidata | ||
195 | * | ||
196 | * Description: | ||
197 | * vxfs_lookup tries to lookup the pathname component described | ||
198 | * by @dp in @dip. | ||
199 | * | ||
200 | * Returns: | ||
201 | * A NULL-pointer on success, else an negative error code encoded | ||
202 | * in the return pointer. | ||
203 | */ | ||
204 | static struct dentry * | ||
205 | vxfs_lookup(struct inode *dip, struct dentry *dp, struct nameidata *nd) | ||
206 | { | ||
207 | struct inode *ip = NULL; | ||
208 | ino_t ino; | ||
209 | |||
210 | if (dp->d_name.len > VXFS_NAMELEN) | ||
211 | return ERR_PTR(-ENAMETOOLONG); | ||
212 | |||
213 | lock_kernel(); | ||
214 | ino = vxfs_inode_by_name(dip, dp); | ||
215 | if (ino) { | ||
216 | ip = iget(dip->i_sb, ino); | ||
217 | if (!ip) { | ||
218 | unlock_kernel(); | ||
219 | return ERR_PTR(-EACCES); | ||
220 | } | ||
221 | } | ||
222 | unlock_kernel(); | ||
223 | d_add(dp, ip); | ||
224 | return NULL; | ||
225 | } | ||
226 | |||
227 | /** | ||
228 | * vxfs_readdir - read a directory | ||
229 | * @fp: the directory to read | ||
230 | * @retp: return buffer | ||
231 | * @filler: filldir callback | ||
232 | * | ||
233 | * Description: | ||
234 | * vxfs_readdir fills @retp with directory entries from @fp | ||
235 | * using the VFS supplied callback @filler. | ||
236 | * | ||
237 | * Returns: | ||
238 | * Zero. | ||
239 | */ | ||
240 | static int | ||
241 | vxfs_readdir(struct file *fp, void *retp, filldir_t filler) | ||
242 | { | ||
243 | struct inode *ip = fp->f_dentry->d_inode; | ||
244 | struct super_block *sbp = ip->i_sb; | ||
245 | u_long bsize = sbp->s_blocksize; | ||
246 | u_long page, npages, block, pblocks, nblocks, offset; | ||
247 | loff_t pos; | ||
248 | |||
249 | switch ((long)fp->f_pos) { | ||
250 | case 0: | ||
251 | if (filler(retp, ".", 1, fp->f_pos, ip->i_ino, DT_DIR) < 0) | ||
252 | goto out; | ||
253 | fp->f_pos++; | ||
254 | /* fallthrough */ | ||
255 | case 1: | ||
256 | if (filler(retp, "..", 2, fp->f_pos, VXFS_INO(ip)->vii_dotdot, DT_DIR) < 0) | ||
257 | goto out; | ||
258 | fp->f_pos++; | ||
259 | /* fallthrough */ | ||
260 | } | ||
261 | |||
262 | pos = fp->f_pos - 2; | ||
263 | |||
264 | if (pos > VXFS_DIRROUND(ip->i_size)) { | ||
265 | unlock_kernel(); | ||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | npages = dir_pages(ip); | ||
270 | nblocks = dir_blocks(ip); | ||
271 | pblocks = VXFS_BLOCK_PER_PAGE(sbp); | ||
272 | |||
273 | page = pos >> PAGE_CACHE_SHIFT; | ||
274 | offset = pos & ~PAGE_CACHE_MASK; | ||
275 | block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks; | ||
276 | |||
277 | for (; page < npages; page++, block = 0) { | ||
278 | caddr_t kaddr; | ||
279 | struct page *pp; | ||
280 | |||
281 | pp = vxfs_get_page(ip->i_mapping, page); | ||
282 | if (IS_ERR(pp)) | ||
283 | continue; | ||
284 | kaddr = (caddr_t)page_address(pp); | ||
285 | |||
286 | for (; block <= nblocks && block <= pblocks; block++) { | ||
287 | caddr_t baddr, limit; | ||
288 | struct vxfs_dirblk *dbp; | ||
289 | struct vxfs_direct *de; | ||
290 | |||
291 | baddr = kaddr + (block * bsize); | ||
292 | limit = baddr + bsize - VXFS_DIRLEN(1); | ||
293 | |||
294 | dbp = (struct vxfs_dirblk *)baddr; | ||
295 | de = (struct vxfs_direct *) | ||
296 | (offset ? | ||
297 | (kaddr + offset) : | ||
298 | (baddr + VXFS_DIRBLKOV(dbp))); | ||
299 | |||
300 | for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) { | ||
301 | int over; | ||
302 | |||
303 | if (!de->d_reclen) | ||
304 | break; | ||
305 | if (!de->d_ino) | ||
306 | continue; | ||
307 | |||
308 | offset = (caddr_t)de - kaddr; | ||
309 | over = filler(retp, de->d_name, de->d_namelen, | ||
310 | ((page << PAGE_CACHE_SHIFT) | offset) + 2, | ||
311 | de->d_ino, DT_UNKNOWN); | ||
312 | if (over) { | ||
313 | vxfs_put_page(pp); | ||
314 | goto done; | ||
315 | } | ||
316 | } | ||
317 | offset = 0; | ||
318 | } | ||
319 | vxfs_put_page(pp); | ||
320 | offset = 0; | ||
321 | } | ||
322 | |||
323 | done: | ||
324 | fp->f_pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2; | ||
325 | out: | ||
326 | unlock_kernel(); | ||
327 | return 0; | ||
328 | } | ||
diff --git a/fs/freevxfs/vxfs_olt.c b/fs/freevxfs/vxfs_olt.c new file mode 100644 index 000000000000..7a204e31aad9 --- /dev/null +++ b/fs/freevxfs/vxfs_olt.c | |||
@@ -0,0 +1,132 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * 1. Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions, and the following disclaimer, | ||
10 | * without modification. | ||
11 | * 2. The name of the author may not be used to endorse or promote products | ||
12 | * derived from this software without specific prior written permission. | ||
13 | * | ||
14 | * Alternatively, this software may be distributed under the terms of the | ||
15 | * GNU General Public License ("GPL"). | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
27 | * SUCH DAMAGE. | ||
28 | */ | ||
29 | |||
30 | /* | ||
31 | * Veritas filesystem driver - object location table support. | ||
32 | */ | ||
33 | #include <linux/fs.h> | ||
34 | #include <linux/buffer_head.h> | ||
35 | #include <linux/kernel.h> | ||
36 | |||
37 | #include "vxfs.h" | ||
38 | #include "vxfs_olt.h" | ||
39 | |||
40 | |||
41 | static __inline__ void | ||
42 | vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp) | ||
43 | { | ||
44 | if (infp->vsi_fshino) | ||
45 | BUG(); | ||
46 | infp->vsi_fshino = fshp->olt_fsino[0]; | ||
47 | } | ||
48 | |||
49 | static __inline__ void | ||
50 | vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp) | ||
51 | { | ||
52 | if (infp->vsi_iext) | ||
53 | BUG(); | ||
54 | infp->vsi_iext = ilistp->olt_iext[0]; | ||
55 | } | ||
56 | |||
57 | static __inline__ u_long | ||
58 | vxfs_oblock(struct super_block *sbp, daddr_t block, u_long bsize) | ||
59 | { | ||
60 | if (sbp->s_blocksize % bsize) | ||
61 | BUG(); | ||
62 | return (block * (sbp->s_blocksize / bsize)); | ||
63 | } | ||
64 | |||
65 | |||
66 | /** | ||
67 | * vxfs_read_olt - read olt | ||
68 | * @sbp: superblock of the filesystem | ||
69 | * @bsize: blocksize of the filesystem | ||
70 | * | ||
71 | * Description: | ||
72 | * vxfs_read_olt reads the olt of the filesystem described by @sbp | ||
73 | * into main memory and does some basic setup. | ||
74 | * | ||
75 | * Returns: | ||
76 | * Zero on success, else a negative error code. | ||
77 | */ | ||
78 | int | ||
79 | vxfs_read_olt(struct super_block *sbp, u_long bsize) | ||
80 | { | ||
81 | struct vxfs_sb_info *infp = VXFS_SBI(sbp); | ||
82 | struct buffer_head *bp; | ||
83 | struct vxfs_olt *op; | ||
84 | char *oaddr, *eaddr; | ||
85 | |||
86 | |||
87 | bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize)); | ||
88 | if (!bp || !bp->b_data) | ||
89 | goto fail; | ||
90 | |||
91 | op = (struct vxfs_olt *)bp->b_data; | ||
92 | if (op->olt_magic != VXFS_OLT_MAGIC) { | ||
93 | printk(KERN_NOTICE "vxfs: ivalid olt magic number\n"); | ||
94 | goto fail; | ||
95 | } | ||
96 | |||
97 | /* | ||
98 | * It is in theory possible that vsi_oltsize is > 1. | ||
99 | * I've not seen any such filesystem yet and I'm lazy.. --hch | ||
100 | */ | ||
101 | if (infp->vsi_oltsize > 1) { | ||
102 | printk(KERN_NOTICE "vxfs: oltsize > 1 detected.\n"); | ||
103 | printk(KERN_NOTICE "vxfs: please notify hch@infradead.org\n"); | ||
104 | goto fail; | ||
105 | } | ||
106 | |||
107 | oaddr = (char *)bp->b_data + op->olt_size; | ||
108 | eaddr = (char *)bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize); | ||
109 | |||
110 | while (oaddr < eaddr) { | ||
111 | struct vxfs_oltcommon *ocp = | ||
112 | (struct vxfs_oltcommon *)oaddr; | ||
113 | |||
114 | switch (ocp->olt_type) { | ||
115 | case VXFS_OLT_FSHEAD: | ||
116 | vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp); | ||
117 | break; | ||
118 | case VXFS_OLT_ILIST: | ||
119 | vxfs_get_ilist((struct vxfs_oltilist *)oaddr, infp); | ||
120 | break; | ||
121 | } | ||
122 | |||
123 | oaddr += ocp->olt_size; | ||
124 | } | ||
125 | |||
126 | brelse(bp); | ||
127 | return 0; | ||
128 | |||
129 | fail: | ||
130 | brelse(bp); | ||
131 | return -EINVAL; | ||
132 | } | ||
diff --git a/fs/freevxfs/vxfs_olt.h b/fs/freevxfs/vxfs_olt.h new file mode 100644 index 000000000000..d8324296486f --- /dev/null +++ b/fs/freevxfs/vxfs_olt.h | |||
@@ -0,0 +1,145 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * 1. Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions, and the following disclaimer, | ||
10 | * without modification. | ||
11 | * 2. The name of the author may not be used to endorse or promote products | ||
12 | * derived from this software without specific prior written permission. | ||
13 | * | ||
14 | * Alternatively, this software may be distributed under the terms of the | ||
15 | * GNU General Public License ("GPL"). | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
27 | * SUCH DAMAGE. | ||
28 | * | ||
29 | */ | ||
30 | #ifndef _VXFS_OLT_H_ | ||
31 | #define _VXFS_OLT_H_ | ||
32 | |||
33 | /* | ||
34 | * Veritas filesystem driver - Object Location Table data structures. | ||
35 | * | ||
36 | * This file contains definitions for the Object Location Table used | ||
37 | * by the Veritas Filesystem version 2 and newer. | ||
38 | */ | ||
39 | |||
40 | |||
41 | /* | ||
42 | * OLT magic number (vxfs_olt->olt_magic). | ||
43 | */ | ||
44 | #define VXFS_OLT_MAGIC 0xa504FCF5 | ||
45 | |||
46 | /* | ||
47 | * VxFS OLT entry types. | ||
48 | */ | ||
49 | enum { | ||
50 | VXFS_OLT_FREE = 1, | ||
51 | VXFS_OLT_FSHEAD = 2, | ||
52 | VXFS_OLT_CUT = 3, | ||
53 | VXFS_OLT_ILIST = 4, | ||
54 | VXFS_OLT_DEV = 5, | ||
55 | VXFS_OLT_SB = 6 | ||
56 | }; | ||
57 | |||
58 | /* | ||
59 | * VxFS OLT header. | ||
60 | * | ||
61 | * The Object Location Table header is placed at the beginning of each | ||
62 | * OLT extent. It is used to fing certain filesystem-wide metadata, e.g. | ||
63 | * the inital inode list, the fileset header or the device configuration. | ||
64 | */ | ||
65 | struct vxfs_olt { | ||
66 | u_int32_t olt_magic; /* magic number */ | ||
67 | u_int32_t olt_size; /* size of this entry */ | ||
68 | u_int32_t olt_checksum; /* checksum of extent */ | ||
69 | u_int32_t __unused1; /* ??? */ | ||
70 | u_int32_t olt_mtime; /* time of last mod. (sec) */ | ||
71 | u_int32_t olt_mutime; /* time of last mod. (usec) */ | ||
72 | u_int32_t olt_totfree; /* free space in OLT extent */ | ||
73 | vx_daddr_t olt_extents[2]; /* addr of this extent, replica */ | ||
74 | u_int32_t olt_esize; /* size of this extent */ | ||
75 | vx_daddr_t olt_next[2]; /* addr of next extent, replica */ | ||
76 | u_int32_t olt_nsize; /* size of next extent */ | ||
77 | u_int32_t __unused2; /* align to 8 byte boundary */ | ||
78 | }; | ||
79 | |||
80 | /* | ||
81 | * VxFS common OLT entry (on disk). | ||
82 | */ | ||
83 | struct vxfs_oltcommon { | ||
84 | u_int32_t olt_type; /* type of this record */ | ||
85 | u_int32_t olt_size; /* size of this record */ | ||
86 | }; | ||
87 | |||
88 | /* | ||
89 | * VxFS free OLT entry (on disk). | ||
90 | */ | ||
91 | struct vxfs_oltfree { | ||
92 | u_int32_t olt_type; /* type of this record */ | ||
93 | u_int32_t olt_fsize; /* size of this free record */ | ||
94 | }; | ||
95 | |||
96 | /* | ||
97 | * VxFS initial-inode list (on disk). | ||
98 | */ | ||
99 | struct vxfs_oltilist { | ||
100 | u_int32_t olt_type; /* type of this record */ | ||
101 | u_int32_t olt_size; /* size of this record */ | ||
102 | vx_ino_t olt_iext[2]; /* initial inode list, replica */ | ||
103 | }; | ||
104 | |||
105 | /* | ||
106 | * Current Usage Table | ||
107 | */ | ||
108 | struct vxfs_oltcut { | ||
109 | u_int32_t olt_type; /* type of this record */ | ||
110 | u_int32_t olt_size; /* size of this record */ | ||
111 | vx_ino_t olt_cutino; /* inode of current usage table */ | ||
112 | u_int32_t __pad; /* unused, 8 byte align */ | ||
113 | }; | ||
114 | |||
115 | /* | ||
116 | * Inodes containing Superblock, Intent log and OLTs | ||
117 | */ | ||
118 | struct vxfs_oltsb { | ||
119 | u_int32_t olt_type; /* type of this record */ | ||
120 | u_int32_t olt_size; /* size of this record */ | ||
121 | vx_ino_t olt_sbino; /* inode of superblock file */ | ||
122 | u_int32_t __unused1; /* ??? */ | ||
123 | vx_ino_t olt_logino[2]; /* inode of log file,replica */ | ||
124 | vx_ino_t olt_oltino[2]; /* inode of OLT, replica */ | ||
125 | }; | ||
126 | |||
127 | /* | ||
128 | * Inode containing device configuration + it's replica | ||
129 | */ | ||
130 | struct vxfs_oltdev { | ||
131 | u_int32_t olt_type; /* type of this record */ | ||
132 | u_int32_t olt_size; /* size of this record */ | ||
133 | vx_ino_t olt_devino[2]; /* inode of device config files */ | ||
134 | }; | ||
135 | |||
136 | /* | ||
137 | * Fileset header | ||
138 | */ | ||
139 | struct vxfs_oltfshead { | ||
140 | u_int32_t olt_type; /* type number */ | ||
141 | u_int32_t olt_size; /* size of this record */ | ||
142 | vx_ino_t olt_fsino[2]; /* inodes of fileset header */ | ||
143 | }; | ||
144 | |||
145 | #endif /* _VXFS_OLT_H_ */ | ||
diff --git a/fs/freevxfs/vxfs_subr.c b/fs/freevxfs/vxfs_subr.c new file mode 100644 index 000000000000..5e305612054a --- /dev/null +++ b/fs/freevxfs/vxfs_subr.c | |||
@@ -0,0 +1,190 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * 1. Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions, and the following disclaimer, | ||
10 | * without modification. | ||
11 | * 2. The name of the author may not be used to endorse or promote products | ||
12 | * derived from this software without specific prior written permission. | ||
13 | * | ||
14 | * Alternatively, this software may be distributed under the terms of the | ||
15 | * GNU General Public License ("GPL"). | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
27 | * SUCH DAMAGE. | ||
28 | */ | ||
29 | |||
30 | /* | ||
31 | * Veritas filesystem driver - shared subroutines. | ||
32 | */ | ||
33 | #include <linux/fs.h> | ||
34 | #include <linux/buffer_head.h> | ||
35 | #include <linux/kernel.h> | ||
36 | #include <linux/slab.h> | ||
37 | #include <linux/pagemap.h> | ||
38 | |||
39 | #include "vxfs_kcompat.h" | ||
40 | #include "vxfs_extern.h" | ||
41 | |||
42 | |||
43 | static int vxfs_readpage(struct file *, struct page *); | ||
44 | static sector_t vxfs_bmap(struct address_space *, sector_t); | ||
45 | |||
46 | struct address_space_operations vxfs_aops = { | ||
47 | .readpage = vxfs_readpage, | ||
48 | .bmap = vxfs_bmap, | ||
49 | .sync_page = block_sync_page, | ||
50 | }; | ||
51 | |||
52 | inline void | ||
53 | vxfs_put_page(struct page *pp) | ||
54 | { | ||
55 | kunmap(pp); | ||
56 | page_cache_release(pp); | ||
57 | } | ||
58 | |||
59 | /** | ||
60 | * vxfs_get_page - read a page into memory. | ||
61 | * @ip: inode to read from | ||
62 | * @n: page number | ||
63 | * | ||
64 | * Description: | ||
65 | * vxfs_get_page reads the @n th page of @ip into the pagecache. | ||
66 | * | ||
67 | * Returns: | ||
68 | * The wanted page on success, else a NULL pointer. | ||
69 | */ | ||
70 | struct page * | ||
71 | vxfs_get_page(struct address_space *mapping, u_long n) | ||
72 | { | ||
73 | struct page * pp; | ||
74 | |||
75 | pp = read_cache_page(mapping, n, | ||
76 | (filler_t*)mapping->a_ops->readpage, NULL); | ||
77 | |||
78 | if (!IS_ERR(pp)) { | ||
79 | wait_on_page_locked(pp); | ||
80 | kmap(pp); | ||
81 | if (!PageUptodate(pp)) | ||
82 | goto fail; | ||
83 | /** if (!PageChecked(pp)) **/ | ||
84 | /** vxfs_check_page(pp); **/ | ||
85 | if (PageError(pp)) | ||
86 | goto fail; | ||
87 | } | ||
88 | |||
89 | return (pp); | ||
90 | |||
91 | fail: | ||
92 | vxfs_put_page(pp); | ||
93 | return ERR_PTR(-EIO); | ||
94 | } | ||
95 | |||
96 | /** | ||
97 | * vxfs_bread - read buffer for a give inode,block tuple | ||
98 | * @ip: inode | ||
99 | * @block: logical block | ||
100 | * | ||
101 | * Description: | ||
102 | * The vxfs_bread function reads block no @block of | ||
103 | * @ip into the buffercache. | ||
104 | * | ||
105 | * Returns: | ||
106 | * The resulting &struct buffer_head. | ||
107 | */ | ||
108 | struct buffer_head * | ||
109 | vxfs_bread(struct inode *ip, int block) | ||
110 | { | ||
111 | struct buffer_head *bp; | ||
112 | daddr_t pblock; | ||
113 | |||
114 | pblock = vxfs_bmap1(ip, block); | ||
115 | bp = sb_bread(ip->i_sb, pblock); | ||
116 | |||
117 | return (bp); | ||
118 | } | ||
119 | |||
120 | /** | ||
121 | * vxfs_get_block - locate buffer for given inode,block tuple | ||
122 | * @ip: inode | ||
123 | * @iblock: logical block | ||
124 | * @bp: buffer skeleton | ||
125 | * @create: %TRUE if blocks may be newly allocated. | ||
126 | * | ||
127 | * Description: | ||
128 | * The vxfs_get_block function fills @bp with the right physical | ||
129 | * block and device number to perform a lowlevel read/write on | ||
130 | * it. | ||
131 | * | ||
132 | * Returns: | ||
133 | * Zero on success, else a negativ error code (-EIO). | ||
134 | */ | ||
135 | static int | ||
136 | vxfs_getblk(struct inode *ip, sector_t iblock, | ||
137 | struct buffer_head *bp, int create) | ||
138 | { | ||
139 | daddr_t pblock; | ||
140 | |||
141 | pblock = vxfs_bmap1(ip, iblock); | ||
142 | if (pblock != 0) { | ||
143 | map_bh(bp, ip->i_sb, pblock); | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | return -EIO; | ||
148 | } | ||
149 | |||
150 | /** | ||
151 | * vxfs_readpage - read one page synchronously into the pagecache | ||
152 | * @file: file context (unused) | ||
153 | * @page: page frame to fill in. | ||
154 | * | ||
155 | * Description: | ||
156 | * The vxfs_readpage routine reads @page synchronously into the | ||
157 | * pagecache. | ||
158 | * | ||
159 | * Returns: | ||
160 | * Zero on success, else a negative error code. | ||
161 | * | ||
162 | * Locking status: | ||
163 | * @page is locked and will be unlocked. | ||
164 | */ | ||
165 | static int | ||
166 | vxfs_readpage(struct file *file, struct page *page) | ||
167 | { | ||
168 | return block_read_full_page(page, vxfs_getblk); | ||
169 | } | ||
170 | |||
171 | /** | ||
172 | * vxfs_bmap - perform logical to physical block mapping | ||
173 | * @mapping: logical to physical mapping to use | ||
174 | * @block: logical block (relative to @mapping). | ||
175 | * | ||
176 | * Description: | ||
177 | * Vxfs_bmap find out the corresponding phsical block to the | ||
178 | * @mapping, @block pair. | ||
179 | * | ||
180 | * Returns: | ||
181 | * Physical block number on success, else Zero. | ||
182 | * | ||
183 | * Locking status: | ||
184 | * We are under the bkl. | ||
185 | */ | ||
186 | static sector_t | ||
187 | vxfs_bmap(struct address_space *mapping, sector_t block) | ||
188 | { | ||
189 | return generic_block_bmap(mapping, block, vxfs_getblk); | ||
190 | } | ||
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c new file mode 100644 index 000000000000..0ae2c7b8182a --- /dev/null +++ b/fs/freevxfs/vxfs_super.c | |||
@@ -0,0 +1,278 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2001 Christoph Hellwig. | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * 1. Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions, and the following disclaimer, | ||
10 | * without modification. | ||
11 | * 2. The name of the author may not be used to endorse or promote products | ||
12 | * derived from this software without specific prior written permission. | ||
13 | * | ||
14 | * Alternatively, this software may be distributed under the terms of the | ||
15 | * GNU General Public License ("GPL"). | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
27 | * SUCH DAMAGE. | ||
28 | */ | ||
29 | |||
30 | /* | ||
31 | * Veritas filesystem driver - superblock related routines. | ||
32 | */ | ||
33 | #include <linux/init.h> | ||
34 | #include <linux/module.h> | ||
35 | |||
36 | #include <linux/blkdev.h> | ||
37 | #include <linux/fs.h> | ||
38 | #include <linux/buffer_head.h> | ||
39 | #include <linux/kernel.h> | ||
40 | #include <linux/slab.h> | ||
41 | #include <linux/stat.h> | ||
42 | #include <linux/vfs.h> | ||
43 | |||
44 | #include "vxfs.h" | ||
45 | #include "vxfs_extern.h" | ||
46 | #include "vxfs_dir.h" | ||
47 | #include "vxfs_inode.h" | ||
48 | |||
49 | |||
50 | MODULE_AUTHOR("Christoph Hellwig"); | ||
51 | MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver"); | ||
52 | MODULE_LICENSE("Dual BSD/GPL"); | ||
53 | |||
54 | MODULE_ALIAS("vxfs"); /* makes mount -t vxfs autoload the module */ | ||
55 | |||
56 | |||
57 | static void vxfs_put_super(struct super_block *); | ||
58 | static int vxfs_statfs(struct super_block *, struct kstatfs *); | ||
59 | static int vxfs_remount(struct super_block *, int *, char *); | ||
60 | |||
61 | static struct super_operations vxfs_super_ops = { | ||
62 | .read_inode = vxfs_read_inode, | ||
63 | .clear_inode = vxfs_clear_inode, | ||
64 | .put_super = vxfs_put_super, | ||
65 | .statfs = vxfs_statfs, | ||
66 | .remount_fs = vxfs_remount, | ||
67 | }; | ||
68 | |||
69 | /** | ||
70 | * vxfs_put_super - free superblock resources | ||
71 | * @sbp: VFS superblock. | ||
72 | * | ||
73 | * Description: | ||
74 | * vxfs_put_super frees all resources allocated for @sbp | ||
75 | * after the last instance of the filesystem is unmounted. | ||
76 | */ | ||
77 | |||
78 | static void | ||
79 | vxfs_put_super(struct super_block *sbp) | ||
80 | { | ||
81 | struct vxfs_sb_info *infp = VXFS_SBI(sbp); | ||
82 | |||
83 | vxfs_put_fake_inode(infp->vsi_fship); | ||
84 | vxfs_put_fake_inode(infp->vsi_ilist); | ||
85 | vxfs_put_fake_inode(infp->vsi_stilist); | ||
86 | |||
87 | brelse(infp->vsi_bp); | ||
88 | kfree(infp); | ||
89 | } | ||
90 | |||
91 | /** | ||
92 | * vxfs_statfs - get filesystem information | ||
93 | * @sbp: VFS superblock | ||
94 | * @bufp: output buffer | ||
95 | * | ||
96 | * Description: | ||
97 | * vxfs_statfs fills the statfs buffer @bufp with information | ||
98 | * about the filesystem described by @sbp. | ||
99 | * | ||
100 | * Returns: | ||
101 | * Zero. | ||
102 | * | ||
103 | * Locking: | ||
104 | * No locks held. | ||
105 | * | ||
106 | * Notes: | ||
107 | * This is everything but complete... | ||
108 | */ | ||
109 | static int | ||
110 | vxfs_statfs(struct super_block *sbp, struct kstatfs *bufp) | ||
111 | { | ||
112 | struct vxfs_sb_info *infp = VXFS_SBI(sbp); | ||
113 | |||
114 | bufp->f_type = VXFS_SUPER_MAGIC; | ||
115 | bufp->f_bsize = sbp->s_blocksize; | ||
116 | bufp->f_blocks = infp->vsi_raw->vs_dsize; | ||
117 | bufp->f_bfree = infp->vsi_raw->vs_free; | ||
118 | bufp->f_bavail = 0; | ||
119 | bufp->f_files = 0; | ||
120 | bufp->f_ffree = infp->vsi_raw->vs_ifree; | ||
121 | bufp->f_namelen = VXFS_NAMELEN; | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static int vxfs_remount(struct super_block *sb, int *flags, char *data) | ||
127 | { | ||
128 | *flags |= MS_RDONLY; | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * vxfs_read_super - read superblock into memory and initalize filesystem | ||
134 | * @sbp: VFS superblock (to fill) | ||
135 | * @dp: fs private mount data | ||
136 | * @silent: do not complain loudly when sth is wrong | ||
137 | * | ||
138 | * Description: | ||
139 | * We are called on the first mount of a filesystem to read the | ||
140 | * superblock into memory and do some basic setup. | ||
141 | * | ||
142 | * Returns: | ||
143 | * The superblock on success, else %NULL. | ||
144 | * | ||
145 | * Locking: | ||
146 | * We are under the bkl and @sbp->s_lock. | ||
147 | */ | ||
148 | static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent) | ||
149 | { | ||
150 | struct vxfs_sb_info *infp; | ||
151 | struct vxfs_sb *rsbp; | ||
152 | struct buffer_head *bp = NULL; | ||
153 | u_long bsize; | ||
154 | struct inode *root; | ||
155 | |||
156 | sbp->s_flags |= MS_RDONLY; | ||
157 | |||
158 | infp = kmalloc(sizeof(*infp), GFP_KERNEL); | ||
159 | if (!infp) { | ||
160 | printk(KERN_WARNING "vxfs: unable to allocate incore superblock\n"); | ||
161 | return -ENOMEM; | ||
162 | } | ||
163 | memset(infp, 0, sizeof(*infp)); | ||
164 | |||
165 | bsize = sb_min_blocksize(sbp, BLOCK_SIZE); | ||
166 | if (!bsize) { | ||
167 | printk(KERN_WARNING "vxfs: unable to set blocksize\n"); | ||
168 | goto out; | ||
169 | } | ||
170 | |||
171 | bp = sb_bread(sbp, 1); | ||
172 | if (!bp || !buffer_mapped(bp)) { | ||
173 | if (!silent) { | ||
174 | printk(KERN_WARNING | ||
175 | "vxfs: unable to read disk superblock\n"); | ||
176 | } | ||
177 | goto out; | ||
178 | } | ||
179 | |||
180 | rsbp = (struct vxfs_sb *)bp->b_data; | ||
181 | if (rsbp->vs_magic != VXFS_SUPER_MAGIC) { | ||
182 | if (!silent) | ||
183 | printk(KERN_NOTICE "vxfs: WRONG superblock magic\n"); | ||
184 | goto out; | ||
185 | } | ||
186 | |||
187 | if ((rsbp->vs_version < 2 || rsbp->vs_version > 4) && !silent) { | ||
188 | printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", | ||
189 | rsbp->vs_version); | ||
190 | goto out; | ||
191 | } | ||
192 | |||
193 | #ifdef DIAGNOSTIC | ||
194 | printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", rsbp->vs_version); | ||
195 | printk(KERN_DEBUG "vxfs: blocksize: %d\n", rsbp->vs_bsize); | ||
196 | #endif | ||
197 | |||
198 | sbp->s_magic = rsbp->vs_magic; | ||
199 | sbp->s_fs_info = (void *)infp; | ||
200 | |||
201 | infp->vsi_raw = rsbp; | ||
202 | infp->vsi_bp = bp; | ||
203 | infp->vsi_oltext = rsbp->vs_oltext[0]; | ||
204 | infp->vsi_oltsize = rsbp->vs_oltsize; | ||
205 | |||
206 | if (!sb_set_blocksize(sbp, rsbp->vs_bsize)) { | ||
207 | printk(KERN_WARNING "vxfs: unable to set final block size\n"); | ||
208 | goto out; | ||
209 | } | ||
210 | |||
211 | if (vxfs_read_olt(sbp, bsize)) { | ||
212 | printk(KERN_WARNING "vxfs: unable to read olt\n"); | ||
213 | goto out; | ||
214 | } | ||
215 | |||
216 | if (vxfs_read_fshead(sbp)) { | ||
217 | printk(KERN_WARNING "vxfs: unable to read fshead\n"); | ||
218 | goto out; | ||
219 | } | ||
220 | |||
221 | sbp->s_op = &vxfs_super_ops; | ||
222 | root = iget(sbp, VXFS_ROOT_INO); | ||
223 | sbp->s_root = d_alloc_root(root); | ||
224 | if (!sbp->s_root) { | ||
225 | iput(root); | ||
226 | printk(KERN_WARNING "vxfs: unable to get root dentry.\n"); | ||
227 | goto out_free_ilist; | ||
228 | } | ||
229 | |||
230 | return 0; | ||
231 | |||
232 | out_free_ilist: | ||
233 | vxfs_put_fake_inode(infp->vsi_fship); | ||
234 | vxfs_put_fake_inode(infp->vsi_ilist); | ||
235 | vxfs_put_fake_inode(infp->vsi_stilist); | ||
236 | out: | ||
237 | brelse(bp); | ||
238 | kfree(infp); | ||
239 | return -EINVAL; | ||
240 | } | ||
241 | |||
242 | /* | ||
243 | * The usual module blurb. | ||
244 | */ | ||
245 | static struct super_block *vxfs_get_sb(struct file_system_type *fs_type, | ||
246 | int flags, const char *dev_name, void *data) | ||
247 | { | ||
248 | return get_sb_bdev(fs_type, flags, dev_name, data, vxfs_fill_super); | ||
249 | } | ||
250 | |||
251 | static struct file_system_type vxfs_fs_type = { | ||
252 | .owner = THIS_MODULE, | ||
253 | .name = "vxfs", | ||
254 | .get_sb = vxfs_get_sb, | ||
255 | .kill_sb = kill_block_super, | ||
256 | .fs_flags = FS_REQUIRES_DEV, | ||
257 | }; | ||
258 | |||
259 | static int __init | ||
260 | vxfs_init(void) | ||
261 | { | ||
262 | vxfs_inode_cachep = kmem_cache_create("vxfs_inode", | ||
263 | sizeof(struct vxfs_inode_info), 0, | ||
264 | SLAB_RECLAIM_ACCOUNT, NULL, NULL); | ||
265 | if (vxfs_inode_cachep) | ||
266 | return (register_filesystem(&vxfs_fs_type)); | ||
267 | return -ENOMEM; | ||
268 | } | ||
269 | |||
270 | static void __exit | ||
271 | vxfs_cleanup(void) | ||
272 | { | ||
273 | unregister_filesystem(&vxfs_fs_type); | ||
274 | kmem_cache_destroy(vxfs_inode_cachep); | ||
275 | } | ||
276 | |||
277 | module_init(vxfs_init); | ||
278 | module_exit(vxfs_cleanup); | ||