aboutsummaryrefslogtreecommitdiffstats
path: root/fs/befs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /fs/befs
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'fs/befs')
-rw-r--r--fs/befs/ChangeLog417
-rw-r--r--fs/befs/Makefile7
-rw-r--r--fs/befs/TODO14
-rw-r--r--fs/befs/attribute.c117
-rw-r--r--fs/befs/befs.h154
-rw-r--r--fs/befs/befs_fs_types.h213
-rw-r--r--fs/befs/btree.c788
-rw-r--r--fs/befs/btree.h13
-rw-r--r--fs/befs/datastream.c528
-rw-r--r--fs/befs/datastream.h19
-rw-r--r--fs/befs/debug.c283
-rw-r--r--fs/befs/endian.h126
-rw-r--r--fs/befs/inode.c53
-rw-r--r--fs/befs/inode.h8
-rw-r--r--fs/befs/io.c83
-rw-r--r--fs/befs/io.h9
-rw-r--r--fs/befs/linuxvfs.c964
-rw-r--r--fs/befs/super.c112
-rw-r--r--fs/befs/super.h8
19 files changed, 3916 insertions, 0 deletions
diff --git a/fs/befs/ChangeLog b/fs/befs/ChangeLog
new file mode 100644
index 000000000000..ce8c787916be
--- /dev/null
+++ b/fs/befs/ChangeLog
@@ -0,0 +1,417 @@
1Version 0.92 (2002-03-29)
2==========
3* Minor cleanup. Ran Lindent on the sources.
4
5Version 0.92 (2002-03-27)
6==========
7* Fixed module makefile problem. It was not compiling all the correct
8 source files!
9* Removed duplicated function definition
10* Fixed potential null pointer dereference when reporting an error
11
12Version 0.91 (2002-03-26)
13==========
14* Oy! Fixed stupid bug that would cause an unresolved symbol error.
15 Thanks to Laszlo Boszormenyi for pointing this out to me.
16
17Version 0.9 (2002-03-14)
18==========
19* Added Sergey S. Kostyliov's patch to eliminate memcpy() overhead
20 from b+tree operations. Changes the befs_read_datastream() interface.
21
22* Segregated the functions that interface directly with the linux vfs
23 interface into their own file called linuxvfs.c. [WD]
24
25Version 0.64 (2002-02-07)
26==========
27* Did the string comparision really right this time (btree.c) [WD]
28
29* Fixed up some places where I assumed that a long int could hold
30 a pointer value. (btree.c) [WD]
31
32* Andrew Farnham <andrewfarnham@uq.net.au> pointed out that the module
33 wouldn't work on older (<2.4.10) kernels due to an unresolved symbol.
34 This is bad, since 2.4.9 is still the current RedHat kernel. I added
35 a workaround for this problem (compatibility.h) [WD]
36
37* Sergey S. Kostyliov made befs_find_key() use a binary search to find
38 keys within btree nodes, rather than the linear search we were using
39 before. (btree.c) [Sergey S. Kostyliov <rathamahata@php4.ru>]
40
41* Made a debian package of the source for use with kernel-package. [WD]
42
43
44Version 0.63 (2002-01-31)
45==========
46* Fixed bug in befs_find_brun_indirect() that would result in the wrong
47 block being read. It was introduced when adding byteswapping in
48 0.61. (datastream.c) [WD]
49
50* Fixed a longstanding bug in befs_find_key() that would result in it
51 finding the first key that is a substring of the string it is searching
52 for. For example, this would cause files in the same directory with
53 names like file1 and file2 to mysteriously be duplicates of each other
54 (because they have the same inode number). Many thanks to Pavel Roskin
55 for reporting this serious bug!!!
56 (btree.c) [WD]
57
58* Added support for long symlinks, after Axel Dorfler explained up how
59 they work. I had forgotten all about them. (inode.c, symlink.c) [WD]
60
61* Documentation improvements in source. [WD]
62
63* Makefile fix for independent module when CONFIG_MODVERSION is set in
64 kernel config [Pavel Roskin <proski@gnu.org>]
65
66* Compile warning fix for namei.c. [Sergey S. Kostyliov <rathamahata@php4.ru>]
67
68
69Version 0.62
70==========
71* Fixed makefile for module install [WD]
72
73
74Version 0.61 (2002-01-20)
75==========
76* Made functions in endian.h to do the correct byteswapping, no matter
77 the arch. [WD]
78
79* Abbandoned silly checks for a NULL superblock pointer in debug.c. [WD]
80
81* Misc code cleanups. Also cleanup of this changelog file. [WD]
82
83* Added byteswapping to all metadata reads from disk.
84 Uses the functions from endian.h [WD]
85
86* Remove the typedef of struct super_block to vfs_sb, as it offended
87 certain peoples' aesthetic sense. [WD]
88
89* Ditto with the befs_read_block() interface. [WD]
90
91
92Version 0.6 (2001-12-15)
93==========
94* Cleanup of NLS functions (util.c) [WD]
95
96* Make directory lookup/read use the NLS if an iocharset is provided. [WD]
97
98* Fixed stupid bug where specifying the uid or gid mount options as '0'
99 would result in the filesystem using the on-disk uid and gid. [WD]
100
101* Added mount option to control debug printing.
102 The option is, simply enough, 'debug'.
103 (super.c, debug.c) [WD]
104
105* Removed notion of btree handle from btree.c. It was unnecessary, as the
106 linux VFS doesn't allow us to keep any state between calls. Updated
107 dir.c, namei.c befs_fs.h to account for it. [WD]
108
109* Improved handleing of overflow nodes when listing directories.
110 Now works for overflow nodes hanging off of nodes other than the root
111 node. This is the cleaner solution to Brent Miszalaski's problem. [WD]
112
113* Added new debug/warning/error print functions in debug.c.
114 More flexible. Will soon be controllable at mount time
115 (see TODO). [WD]
116
117* Rewrote datastream positon lookups.
118 (datastream.c) [WD]
119
120* Moved the TODO list to its own file.
121
122
123Version 0.50 (2001-11-13)
124==========
125* Added workaround for mis-understanding of the nature of the b+trees used
126 in directories. A cleaner solution will come after I've thought about it
127 for a while. Thanks to Brent Miszalaski for finding and reporting this bug.
128 (btree.c) [WD]
129
130* Minor cleanups
131
132* Added test for "impossible" condition of empty internal nodes in
133 seekleaf() in btree.c [WD]
134
135* Implemented the abstracted read_block() in io.c [WD]
136
137* Cleaned up the inode validation in inode.c [WD]
138
139* Anton Altaparmakov figured out (by asking Linus :) ) what was causing the
140 hanging disk io problem. It turns out you need to have the sync_pages
141 callback defined in your address_space_ops, even if it just uses the
142 default linux-supplied implementation. Fixed. Works now.
143 (file.c) [WD]
144
145* Anton Altaparmakov and Christoph Hellwig alerted me to the fact that
146 filesystem code should be using GFP_NOFS instead of GFP_KERNEL as the
147 priority parameter to kmalloc(). Fixed.
148 (datastream.c, btree.c super.c inode.c) [WD]
149
150* Anton also told me that the blocksize is not allowed to be larger than
151 the page size in linux, which is 4k i386. Oops. Added a test for
152 (blocksize > PAGE_SIZE), and refuse to mount in that case. What this
153 practicaly means is that 8k blocksize volumes won't work without a major
154 restructuring of the driver (or an alpha or other 64bit hardware). [WD]
155
156* Cleaned up the befs_count_blocks() function. Much smarter now.
157 And somewhat smaller too. [WD]
158
159* Made inode allocations use a slab cache
160 (super.c inode.c) [WD]
161
162* Moved the freeing of the private inode section from put_inode() to
163 clear_inode(). This fixes a potential free twice type bug. Put_inode()
164 can be called multiple times for each inode struct. [WD]
165
166* Converted all non vfs-callback functions to use befs_sb_info as the
167 superblock type, rather than struct super_block. This is for
168 portablity. [WD]
169
170* Fixed a couple of compile warnings due to use of malloc.h, when slab.h
171 is the new way. (inode.c, super.c) [WD]
172
173* Fixed erronous includes of linux/befs_fs_i.h and linux/befs_fs_sb.h
174 in inode.c [WD]
175
176Version 0.45 (2001-10-29)
177==========
178* Added functions to get the private superblock and inode structures from
179 their enclosing public structures. Switched all references to the
180 private portions to use them. (many files) [WD]
181
182* Made read_super and read_inode allocate the private portions of those
183 structures into the generic pointer fields of the public structures
184 with kmalloc(). put_super and put_inode free them. This allows us not
185 to have to touch the definitions of the public structures in
186 include/linux/fs.h. Also, befs_inode_info is huge (becuase of the
187 symlink string). (super.c, inode.c, befs_fs.h) [WD]
188
189* Fixed a thinko that was corrupting file reads after the first block_run
190 is done being read. (datastream.c) [WD]
191
192* Removed fsync() hooks, since a read-only filesystem doesn't need them.
193 [Christoph Hellwig].
194
195* Fixed befs_readlink() (symlink.c) [Christoph Hellwig].
196
197* Removed all the Read-Write stuff. I'll redo it when it is time to add
198 write support (various files) [WD].
199
200* Removed prototypes for functions who's definitions have been removed
201 (befs_fs.h) [WD].
202
203
204Version 0.4 (2001-10-28)
205==========
206* Made it an option to use the old non-pagecache befs_file_read() for
207 testing purposes. (fs/Config.in)
208
209* Fixed unused variable warnings when compiling without debugging.
210
211* Fixed a bug where the inode and super_block didn't get their blockbits
212 fields set (inode.c and super.c).
213
214* Release patch version 11. AKA befs-driver version 0.4.
215
216* Thats right. New versioning scheme.
217 I've done some serious testing on it now (on my box anyhow), and it
218 seems stable and not outragously slow. Existing features are more-or-less
219 correct (see TODO list). But it isn't 1.0 yet. I think 0.4 gives me some
220 headroom before the big 1.0.
221
222
2232001-10-26
224==========
225* Fixed date format in this file. Was I smoking crack?
226
227* Removed old datastream code from file.c, since it is nolonger used.
228
229* Generic_read_file() is now used to read regular file data.
230 It doesn't chew up the buffer cache (it does page io instead), and seems
231 to be about as fast (even though it has to look up each file block
232 indivdualy). And it knows about doing readahead, which is a major plus.
233 So it does i/o in much larger chunks. It is the correct linux way. It
234 uses befs_get_block() by way of befs_readpage() to find the disk offsets
235 of blocks, which in turn calls befs_fpos2brun() in datastream.c to do
236 the hard work of finding the disk block number.
237
238* Changed method of checking for a dirty filesystem in befs_read_super
239 (super.c). Now we check to see if log_start and log_end differ. If so,
240 the journal needs to be replayed, and the filesystem cannot be mounted.
241
242* Fixed an extra instance of MOD_DEC_USE_COUNT in super.c
243
244* Fixed a problem with reading the superblock on devices with large sector
245 sizes (such as cdroms) on linux 2.4.10 and up.
246
2472001-10-24
248==========
249* Fix nasty bug in converting block numbers to struct befs_inode_addr.
250 Subtle, because the old version was only sometimes wrong.
251 Probably responsible for lots of problems. (inode.c)
252
253* Fix bug with reading an empty directory. (btree.c and dir.c)
254
255* This one looks good. Release patch version 10
256
2572001-10-23
258==========
259* Added btree searching function.
260
261* Use befs_btree_find in befs_lookup (namei.c)
262
263* Additional comments in btree.c
264
2652001-10-22
266==========
267* Added B+tree reading functions (in btree.c).
268 Made befs_readdir() use them them instead of the cruft in index.c.
269
2702001-09-11
271==========
272* Converted befs_read_file() to use the new datastream code.
273
274* Finally updated the README file.
275
276* Added many comments.
277
278* Posted version 6
279
280* Removed byte-order conversion code.
281 I have no intention of supporting it, and it was very ugly.
282 Flow control with #ifdef (ugh). Maybe I'll redo it once
283 native byteorder works 100%.
284
2852001-09-10
286==========
287* Finished implementing read_datastream()
288
289* made befs_read_brun() more general
290 Supports an offset to start at and a max bytes to read
291 Added a wrapper function to give the old call
292
2932001-09-30
294==========
295* Discovered that the datastream handleing code in file.c is quite deficient
296 in several respects. For one thing, it doesn't deal with indirect blocks
297
298* Rewrote datastream handleing.
299
300* Created io.c, for io related functions.
301 Previously, the befs_bread() funtions lived in file.c
302 Created the befs_read_brun() function.
303
304
3052001-09-07
306==========
307* Made a function to actually count the number of fs blocks used by a file.
308 And helper functions.
309 (fs/befs/inode.c)
310
3112001-09-05
312==========
313* Fixed a misunderstanding of the inode fields.
314 This fixed the problmem with wrong file sizes from du and others.
315 The i_blocks field of the inode struct is not the number of blocks for the
316 inode, it is the number of blocks for the file. Also, i_blksize is not
317 necessarily the size of the inode, although in practice it works out.
318 Changed to blocksize of filesystem.
319 (fs/befs/inode.c)
320
321* Permanently removed code that had been provisionally ifdefed out of befs_fs.h
322
323* Since we don't support access time, make that field zero, instead of
324 copying m_time.
325 (fs/befs/inode.c)
326
327* Added sanity check for inode reading
328 Make sure inode we got was the one we asked for.
329 (fs/befs/inode.c)
330
331* Code cleanup
332 Local pointers to commonly used structures in inode.c.
333 Got rid of abominations befs_iaddr2inode() and befs_inode2ino().
334 Replaced with single function iaddr2blockno().
335 (fs/befs/super.c) (fs/befs/inode.c)
336
3372001-09-01
338==========
339* Fixed the problem with statfs where it would always claim the disk was
340 half full, due to improper understanding of the statfs fields.
341 (fs/befs/super.c)
342
343* Posted verion 4 of the patch
344
3452001-09-01
346==========
347* Changed the macros in befs_fs.h to inline functions.
348 More readable. Typesafe. Better
349 (include/linux/befs_fs.h)
350
351* Moved type definitions from befs_fs.h to a new file, befs_fs_types.h
352 Because befs_fs_i.h and befs_fs_sb.h were including befs_fs.h for the
353 typedefs, and they are inlcuded in <linux/fs.h>, which has definitions
354 that I want the inline functions in befs_fs.h to be able to see. Nasty
355 circularity.
356 (include/linux/befs_fs.h)
357
3582001-08-30
359==========
360* Cleaned up some wording.
361
362* Added additional consitency checks on mount
363 Check block_size agrees with block_shift
364 Check flags == BEFS_CLEAN
365 (fs/befs/super.c)
366
367* Tell the kernel to only mount befs read-only.
368 By setting the MS_RDONLY flag in befs_read_super().
369 Not that it was possible to write before. But now the kernel won't even try.
370 (fs/befs/super.c)
371
372* Got rid of kernel warning on mount.
373 The kernel doesn't like it if you call set_blocksize() on a device when
374 you have some of its blocks open. Moved the second set_blocksize() to the
375 very end of befs_read_super(), after we are done with the disk superblock.
376 (fs/befs/super.c)
377
378* Fixed wrong number of args bug in befs_dump_inode
379 (fs/befs/debug.c)
380
381* Solved lots of type mismatches in kprint()s
382 (everwhere)
383
3842001-08-27
385==========
386* Cleaned up the fs/Config.in entries a bit, now slightly more descriptive.
387
388* BeFS depends on NLS, so I made activating BeFS enable the NLS questions
389 (fs/nls/Config.in)
390
391* Added Configure.help entries for CONFIG_BEFS_FS and CONFIG_DEBUG_BEFS
392 (Documentation/Configure.help)
393
3942001-08-??
395==========
396* Removed superblock locking calls in befs_read_super(). In 2.4, the VFS
397 hands us a super_block struct that is already locked.
398
3992001-08-13
400==========
401* Will Dyson <will_dyson@pobox.com> is now attempting to maintain this module
402 Makoto Kato <m_kato@ga2.so-net.ne.jp> is original author.Daniel Berlin
403 also did some work on it (fixing it up for the later 2.3.x kernels, IIRC).
404
405* Fixed compile errors on 2.4.1 kernel (WD)
406 Resolve rejected patches
407 Accomodate changed NLS interface (util.h)
408 Needed to include <linux/slab.h> in most files
409 Makefile changes
410 fs/Config.in changes
411
412* Tried to niceify the code using the ext2 fs as a guide
413 Declare befs_fs_type using the DECLARE_FSTYPE_DEV() macro
414
415* Made it a configure option to turn on debugging (fs/Config.in)
416
417* Compiles on 2.4.7
diff --git a/fs/befs/Makefile b/fs/befs/Makefile
new file mode 100644
index 000000000000..2f370bd7a50d
--- /dev/null
+++ b/fs/befs/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for the linux BeOS filesystem routines.
3#
4
5obj-$(CONFIG_BEFS_FS) += befs.o
6
7befs-objs := datastream.o btree.o super.o inode.o debug.o io.o linuxvfs.o
diff --git a/fs/befs/TODO b/fs/befs/TODO
new file mode 100644
index 000000000000..3250921aa2e6
--- /dev/null
+++ b/fs/befs/TODO
@@ -0,0 +1,14 @@
1TODO
2==========
3
4* Convert comments to the Kernel-Doc format.
5
6* Befs_fs.h has gotten big and messy. No reason not to break it up into
7 smaller peices.
8
9* See if Alexander Viro's option parser made it into the kernel tree.
10 Use that if we can. (include/linux/parser.h)
11
12* See if we really need separate types for on-disk and in-memory
13 representations of the superblock and inode.
14
diff --git a/fs/befs/attribute.c b/fs/befs/attribute.c
new file mode 100644
index 000000000000..e329d727053e
--- /dev/null
+++ b/fs/befs/attribute.c
@@ -0,0 +1,117 @@
1/*
2 * linux/fs/befs/attribute.c
3 *
4 * Copyright (C) 2002 Will Dyson <will_dyson@pobox.com>
5 *
6 * Many thanks to Dominic Giampaolo, author of "Practical File System
7 * Design with the Be File System", for such a helpful book.
8 *
9 */
10
11#include <linux/fs.h>
12#include <linux/kernel.h>
13#include <linux/string.h>
14
15#include "befs.h"
16#include "endian.h"
17
18#define SD_DATA(sd)\
19 (void*)((char*)sd + sizeof(*sd) + (sd->name_size - sizeof(sd->name)))
20
21#define SD_NEXT(sd)\
22 (befs_small_data*)((char*)sd + sizeof(*sd) + (sd->name_size - \
23 sizeof(sd->name) + sd->data_size))
24
25int
26list_small_data(struct super_block *sb, befs_inode * inode, filldir_t filldir);
27
28befs_small_data *
29find_small_data(struct super_block *sb, befs_inode * inode,
30 const char *name);
31int
32read_small_data(struct super_block *sb, befs_inode * inode,
33 befs_small_data * sdata, void *buf, size_t bufsize);
34
35/**
36 *
37 *
38 *
39 *
40 *
41 */
42befs_small_data *
43find_small_data(struct super_block *sb, befs_inode * inode, const char *name)
44{
45 befs_small_data *sdata = inode->small_data;
46
47 while (sdata->type != 0) {
48 if (strcmp(name, sdata->name) != 0) {
49 return sdata;
50 }
51 sdata = SD_NEXT(sdata);
52 }
53 return NULL;
54}
55
56/**
57 *
58 *
59 *
60 *
61 *
62 */
63int
64read_small_data(struct super_block *sb, befs_inode * inode,
65 const char *name, void *buf, size_t bufsize)
66{
67 befs_small_data *sdata;
68
69 sdata = find_small_data(sb, inode, name);
70 if (sdata == NULL)
71 return BEFS_ERR;
72 else if (sdata->data_size > bufsize)
73 return BEFS_ERR;
74
75 memcpy(buf, SD_DATA(sdata), sdata->data_size);
76
77 return BEFS_OK;
78}
79
80/**
81 *
82 *
83 *
84 *
85 *
86 */
87int
88list_small_data(struct super_block *sb, befs_inode * inode)
89{
90
91}
92
93/**
94 *
95 *
96 *
97 *
98 *
99 */
100int
101list_attr(struct super_block *sb, befs_inode * inode)
102{
103
104}
105
106/**
107 *
108 *
109 *
110 *
111 *
112 */
113int
114read_attr(struct super_block *sb, befs_inode * inode)
115{
116
117}
diff --git a/fs/befs/befs.h b/fs/befs/befs.h
new file mode 100644
index 000000000000..057a2c3d73b7
--- /dev/null
+++ b/fs/befs/befs.h
@@ -0,0 +1,154 @@
1/*
2 * befs.h
3 *
4 * Copyright (C) 2001-2002 Will Dyson <will_dyson@pobox.com>
5 * Copyright (C) 1999 Makoto Kato (m_kato@ga2.so-net.ne.jp)
6 */
7
8#ifndef _LINUX_BEFS_H
9#define _LINUX_BEFS_H
10
11#include "befs_fs_types.h"
12
13/* used in debug.c */
14#define BEFS_VERSION "0.9.3"
15
16
17typedef u64 befs_blocknr_t;
18/*
19 * BeFS in memory structures
20 */
21
22typedef struct befs_mount_options {
23 gid_t gid;
24 uid_t uid;
25 int use_gid;
26 int use_uid;
27 int debug;
28 char *iocharset;
29} befs_mount_options;
30
31typedef struct befs_sb_info {
32 u32 magic1;
33 u32 block_size;
34 u32 block_shift;
35 int byte_order;
36 befs_off_t num_blocks;
37 befs_off_t used_blocks;
38 u32 inode_size;
39 u32 magic2;
40
41 /* Allocation group information */
42 u32 blocks_per_ag;
43 u32 ag_shift;
44 u32 num_ags;
45
46 /* jornal log entry */
47 befs_block_run log_blocks;
48 befs_off_t log_start;
49 befs_off_t log_end;
50
51 befs_inode_addr root_dir;
52 befs_inode_addr indices;
53 u32 magic3;
54
55 befs_mount_options mount_opts;
56 struct nls_table *nls;
57
58} befs_sb_info;
59
60typedef struct befs_inode_info {
61 u32 i_flags;
62 u32 i_type;
63
64 befs_inode_addr i_inode_num;
65 befs_inode_addr i_parent;
66 befs_inode_addr i_attribute;
67
68 union {
69 befs_data_stream ds;
70 char symlink[BEFS_SYMLINK_LEN];
71 } i_data;
72
73 struct inode vfs_inode;
74
75} befs_inode_info;
76
77enum befs_err {
78 BEFS_OK,
79 BEFS_ERR,
80 BEFS_BAD_INODE,
81 BEFS_BT_END,
82 BEFS_BT_EMPTY,
83 BEFS_BT_MATCH,
84 BEFS_BT_PARMATCH,
85 BEFS_BT_NOT_FOUND
86};
87
88
89/****************************/
90/* debug.c */
91void befs_error(const struct super_block *sb, const char *fmt, ...);
92void befs_warning(const struct super_block *sb, const char *fmt, ...);
93void befs_debug(const struct super_block *sb, const char *fmt, ...);
94
95void befs_dump_super_block(const struct super_block *sb, befs_super_block *);
96void befs_dump_inode(const struct super_block *sb, befs_inode *);
97void befs_dump_index_entry(const struct super_block *sb, befs_btree_super *);
98void befs_dump_index_node(const struct super_block *sb, befs_btree_nodehead *);
99/****************************/
100
101
102/* Gets a pointer to the private portion of the super_block
103 * structure from the public part
104 */
105static inline befs_sb_info *
106BEFS_SB(const struct super_block *super)
107{
108 return (befs_sb_info *) super->s_fs_info;
109}
110
111static inline befs_inode_info *
112BEFS_I(const struct inode *inode)
113{
114 return list_entry(inode, struct befs_inode_info, vfs_inode);
115}
116
117static inline befs_blocknr_t
118iaddr2blockno(struct super_block *sb, befs_inode_addr * iaddr)
119{
120 return ((iaddr->allocation_group << BEFS_SB(sb)->ag_shift) +
121 iaddr->start);
122}
123
124static inline befs_inode_addr
125blockno2iaddr(struct super_block *sb, befs_blocknr_t blockno)
126{
127 befs_inode_addr iaddr;
128 iaddr.allocation_group = blockno >> BEFS_SB(sb)->ag_shift;
129 iaddr.start =
130 blockno - (iaddr.allocation_group << BEFS_SB(sb)->ag_shift);
131 iaddr.len = 1;
132
133 return iaddr;
134}
135
136static inline unsigned int
137befs_iaddrs_per_block(struct super_block *sb)
138{
139 return BEFS_SB(sb)->block_size / sizeof (befs_inode_addr);
140}
141
142static inline int
143befs_iaddr_is_empty(befs_inode_addr * iaddr)
144{
145 return (!iaddr->allocation_group) && (!iaddr->start) && (!iaddr->len);
146}
147
148static inline size_t
149befs_brun_size(struct super_block *sb, befs_block_run run)
150{
151 return BEFS_SB(sb)->block_size * run.len;
152}
153
154#endif /* _LINUX_BEFS_H */
diff --git a/fs/befs/befs_fs_types.h b/fs/befs/befs_fs_types.h
new file mode 100644
index 000000000000..9095518e918d
--- /dev/null
+++ b/fs/befs/befs_fs_types.h
@@ -0,0 +1,213 @@
1/*
2 * include/linux/befs_fs_types.h
3 *
4 * Copyright (C) 2001 Will Dyson (will@cs.earlham.edu)
5 *
6 *
7 *
8 * from linux/include/linux/befs_fs.h
9 *
10 * Copyright (C) 1999 Makoto Kato (m_kato@ga2.so-net.ne.jp)
11 *
12 */
13
14#ifndef _LINUX_BEFS_FS_TYPES
15#define _LINUX_BEFS_FS_TYPES
16
17#ifdef __KERNEL__
18#include <linux/types.h>
19#endif /*__KERNEL__*/
20
21#define PACKED __attribute__ ((__packed__))
22
23/*
24 * Max name lengths of BFS
25 */
26
27#define BEFS_NAME_LEN 255
28
29#define BEFS_SYMLINK_LEN 144
30#define BEFS_NUM_DIRECT_BLOCKS 12
31#define B_OS_NAME_LENGTH 32
32
33/* The datastream blocks mapped by the double-indirect
34 * block are always 4 fs blocks long.
35 * This eliminates the need for linear searches among
36 * the potentially huge number of indirect blocks
37 *
38 * Err. Should that be 4 fs blocks or 4k???
39 * It matters on large blocksize volumes
40 */
41#define BEFS_DBLINDIR_BRUN_LEN 4
42
43/*
44 * Flags of superblock
45 */
46
47enum super_flags {
48 BEFS_BYTESEX_BE,
49 BEFS_BYTESEX_LE,
50 BEFS_CLEAN = 0x434c454e,
51 BEFS_DIRTY = 0x44495254,
52 BEFS_SUPER_MAGIC1 = 0x42465331, /* BFS1 */
53 BEFS_SUPER_MAGIC2 = 0xdd121031,
54 BEFS_SUPER_MAGIC3 = 0x15b6830e,
55};
56
57#define BEFS_BYTEORDER_NATIVE 0x42494745
58
59#define BEFS_SUPER_MAGIC BEFS_SUPER_MAGIC1
60
61/*
62 * Flags of inode
63 */
64
65#define BEFS_INODE_MAGIC1 0x3bbe0ad9
66
67enum inode_flags {
68 BEFS_INODE_IN_USE = 0x00000001,
69 BEFS_ATTR_INODE = 0x00000004,
70 BEFS_INODE_LOGGED = 0x00000008,
71 BEFS_INODE_DELETED = 0x00000010,
72 BEFS_LONG_SYMLINK = 0x00000040,
73 BEFS_PERMANENT_FLAG = 0x0000ffff,
74 BEFS_INODE_NO_CREATE = 0x00010000,
75 BEFS_INODE_WAS_WRITTEN = 0x00020000,
76 BEFS_NO_TRANSACTION = 0x00040000,
77};
78/*
79 * On-Disk datastructures of BeFS
80 */
81
82typedef u64 befs_off_t;
83typedef u64 befs_time_t;
84typedef void befs_binode_etc;
85
86/* Block runs */
87typedef struct {
88 u32 allocation_group;
89 u16 start;
90 u16 len;
91} PACKED befs_block_run;
92
93typedef befs_block_run befs_inode_addr;
94
95/*
96 * The Superblock Structure
97 */
98typedef struct {
99 char name[B_OS_NAME_LENGTH];
100 u32 magic1;
101 u32 fs_byte_order;
102
103 u32 block_size;
104 u32 block_shift;
105
106 befs_off_t num_blocks;
107 befs_off_t used_blocks;
108
109 u32 inode_size;
110
111 u32 magic2;
112 u32 blocks_per_ag;
113 u32 ag_shift;
114 u32 num_ags;
115
116 u32 flags;
117
118 befs_block_run log_blocks;
119 befs_off_t log_start;
120 befs_off_t log_end;
121
122 u32 magic3;
123 befs_inode_addr root_dir;
124 befs_inode_addr indices;
125
126} PACKED befs_super_block;
127
128/*
129 * Note: the indirect and dbl_indir block_runs may
130 * be longer than one block!
131 */
132typedef struct {
133 befs_block_run direct[BEFS_NUM_DIRECT_BLOCKS];
134 befs_off_t max_direct_range;
135 befs_block_run indirect;
136 befs_off_t max_indirect_range;
137 befs_block_run double_indirect;
138 befs_off_t max_double_indirect_range;
139 befs_off_t size;
140} PACKED befs_data_stream;
141
142/* Attribute */
143typedef struct {
144 u32 type;
145 u16 name_size;
146 u16 data_size;
147 char name[1];
148} PACKED befs_small_data;
149
150/* Inode structure */
151typedef struct {
152 u32 magic1;
153 befs_inode_addr inode_num;
154 u32 uid;
155 u32 gid;
156 u32 mode;
157 u32 flags;
158 befs_time_t create_time;
159 befs_time_t last_modified_time;
160 befs_inode_addr parent;
161 befs_inode_addr attributes;
162 u32 type;
163
164 u32 inode_size;
165 u32 etc; /* not use */
166
167 union {
168 befs_data_stream datastream;
169 char symlink[BEFS_SYMLINK_LEN];
170 } data;
171
172 u32 pad[4]; /* not use */
173 befs_small_data small_data[1];
174} PACKED befs_inode;
175
176/*
177 * B+tree superblock
178 */
179
180#define BEFS_BTREE_MAGIC 0x69f6c2e8
181
182enum btree_types {
183 BTREE_STRING_TYPE = 0,
184 BTREE_INT32_TYPE = 1,
185 BTREE_UINT32_TYPE = 2,
186 BTREE_INT64_TYPE = 3,
187 BTREE_UINT64_TYPE = 4,
188 BTREE_FLOAT_TYPE = 5,
189 BTREE_DOUBLE_TYPE = 6
190};
191
192typedef struct {
193 u32 magic;
194 u32 node_size;
195 u32 max_depth;
196 u32 data_type;
197 befs_off_t root_node_ptr;
198 befs_off_t free_node_ptr;
199 befs_off_t max_size;
200} PACKED befs_btree_super;
201
202/*
203 * Header stucture of each btree node
204 */
205typedef struct {
206 befs_off_t left;
207 befs_off_t right;
208 befs_off_t overflow;
209 u16 all_key_count;
210 u16 all_key_length;
211} PACKED befs_btree_nodehead;
212
213#endif /* _LINUX_BEFS_FS_TYPES */
diff --git a/fs/befs/btree.c b/fs/befs/btree.c
new file mode 100644
index 000000000000..76e219799409
--- /dev/null
+++ b/fs/befs/btree.c
@@ -0,0 +1,788 @@
1/*
2 * linux/fs/befs/btree.c
3 *
4 * Copyright (C) 2001-2002 Will Dyson <will_dyson@pobox.com>
5 *
6 * Licensed under the GNU GPL. See the file COPYING for details.
7 *
8 * 2002-02-05: Sergey S. Kostyliov added binary search withing
9 * btree nodes.
10 *
11 * Many thanks to:
12 *
13 * Dominic Giampaolo, author of "Practical File System
14 * Design with the Be File System", for such a helpful book.
15 *
16 * Marcus J. Ranum, author of the b+tree package in
17 * comp.sources.misc volume 10. This code is not copied from that
18 * work, but it is partially based on it.
19 *
20 * Makoto Kato, author of the original BeFS for linux filesystem
21 * driver.
22 */
23
24#include <linux/kernel.h>
25#include <linux/string.h>
26#include <linux/slab.h>
27#include <linux/mm.h>
28#include <linux/buffer_head.h>
29
30#include "befs.h"
31#include "btree.h"
32#include "datastream.h"
33#include "endian.h"
34
35/*
36 * The btree functions in this file are built on top of the
37 * datastream.c interface, which is in turn built on top of the
38 * io.c interface.
39 */
40
41/* Befs B+tree structure:
42 *
43 * The first thing in the tree is the tree superblock. It tells you
44 * all kinds of useful things about the tree, like where the rootnode
45 * is located, and the size of the nodes (always 1024 with current version
46 * of BeOS).
47 *
48 * The rest of the tree consists of a series of nodes. Nodes contain a header
49 * (struct befs_btree_nodehead), the packed key data, an array of shorts
50 * containing the ending offsets for each of the keys, and an array of
51 * befs_off_t values. In interior nodes, the keys are the ending keys for
52 * the childnode they point to, and the values are offsets into the
53 * datastream containing the tree.
54 */
55
56/* Note:
57 *
58 * The book states 2 confusing things about befs b+trees. First,
59 * it states that the overflow field of node headers is used by internal nodes
60 * to point to another node that "effectively continues this one". Here is what
61 * I believe that means. Each key in internal nodes points to another node that
62 * contains key values less than itself. Inspection reveals that the last key
63 * in the internal node is not the last key in the index. Keys that are
64 * greater than the last key in the internal node go into the overflow node.
65 * I imagine there is a performance reason for this.
66 *
67 * Second, it states that the header of a btree node is sufficient to
68 * distinguish internal nodes from leaf nodes. Without saying exactly how.
69 * After figuring out the first, it becomes obvious that internal nodes have
70 * overflow nodes and leafnodes do not.
71 */
72
73/*
74 * Currently, this code is only good for directory B+trees.
75 * In order to be used for other BFS indexes, it needs to be extended to handle
76 * duplicate keys and non-string keytypes (int32, int64, float, double).
77 */
78
79/*
80 * In memory structure of each btree node
81 */
82typedef struct {
83 befs_btree_nodehead head; /* head of node converted to cpu byteorder */
84 struct buffer_head *bh;
85 befs_btree_nodehead *od_node; /* on disk node */
86} befs_btree_node;
87
88/* local constants */
89static const befs_off_t befs_bt_inval = 0xffffffffffffffffULL;
90
91/* local functions */
92static int befs_btree_seekleaf(struct super_block *sb, befs_data_stream * ds,
93 befs_btree_super * bt_super,
94 befs_btree_node * this_node,
95 befs_off_t * node_off);
96
97static int befs_bt_read_super(struct super_block *sb, befs_data_stream * ds,
98 befs_btree_super * sup);
99
100static int befs_bt_read_node(struct super_block *sb, befs_data_stream * ds,
101 befs_btree_node * node, befs_off_t node_off);
102
103static int befs_leafnode(befs_btree_node * node);
104
105static u16 *befs_bt_keylen_index(befs_btree_node * node);
106
107static befs_off_t *befs_bt_valarray(befs_btree_node * node);
108
109static char *befs_bt_keydata(befs_btree_node * node);
110
111static int befs_find_key(struct super_block *sb, befs_btree_node * node,
112 const char *findkey, befs_off_t * value);
113
114static char *befs_bt_get_key(struct super_block *sb, befs_btree_node * node,
115 int index, u16 * keylen);
116
117static int befs_compare_strings(const void *key1, int keylen1,
118 const void *key2, int keylen2);
119
120/**
121 * befs_bt_read_super - read in btree superblock convert to cpu byteorder
122 * @sb: Filesystem superblock
123 * @ds: Datastream to read from
124 * @sup: Buffer in which to place the btree superblock
125 *
126 * Calls befs_read_datastream to read in the btree superblock and
127 * makes sure it is in cpu byteorder, byteswapping if necessary.
128 *
129 * On success, returns BEFS_OK and *@sup contains the btree superblock,
130 * in cpu byte order.
131 *
132 * On failure, BEFS_ERR is returned.
133 */
134static int
135befs_bt_read_super(struct super_block *sb, befs_data_stream * ds,
136 befs_btree_super * sup)
137{
138 struct buffer_head *bh = NULL;
139 befs_btree_super *od_sup = NULL;
140
141 befs_debug(sb, "---> befs_btree_read_super()");
142
143 bh = befs_read_datastream(sb, ds, 0, NULL);
144
145 if (!bh) {
146 befs_error(sb, "Couldn't read index header.");
147 goto error;
148 }
149 od_sup = (befs_btree_super *) bh->b_data;
150 befs_dump_index_entry(sb, od_sup);
151
152 sup->magic = fs32_to_cpu(sb, od_sup->magic);
153 sup->node_size = fs32_to_cpu(sb, od_sup->node_size);
154 sup->max_depth = fs32_to_cpu(sb, od_sup->max_depth);
155 sup->data_type = fs32_to_cpu(sb, od_sup->data_type);
156 sup->root_node_ptr = fs64_to_cpu(sb, od_sup->root_node_ptr);
157 sup->free_node_ptr = fs64_to_cpu(sb, od_sup->free_node_ptr);
158 sup->max_size = fs64_to_cpu(sb, od_sup->max_size);
159
160 brelse(bh);
161 if (sup->magic != BEFS_BTREE_MAGIC) {
162 befs_error(sb, "Index header has bad magic.");
163 goto error;
164 }
165
166 befs_debug(sb, "<--- befs_btree_read_super()");
167 return BEFS_OK;
168
169 error:
170 befs_debug(sb, "<--- befs_btree_read_super() ERROR");
171 return BEFS_ERR;
172}
173
174/**
175 * befs_bt_read_node - read in btree node and convert to cpu byteorder
176 * @sb: Filesystem superblock
177 * @ds: Datastream to read from
178 * @node: Buffer in which to place the btree node
179 * @node_off: Starting offset (in bytes) of the node in @ds
180 *
181 * Calls befs_read_datastream to read in the indicated btree node and
182 * makes sure its header fields are in cpu byteorder, byteswapping if
183 * necessary.
184 * Note: node->bh must be NULL when this function called first
185 * time. Don't forget brelse(node->bh) after last call.
186 *
187 * On success, returns BEFS_OK and *@node contains the btree node that
188 * starts at @node_off, with the node->head fields in cpu byte order.
189 *
190 * On failure, BEFS_ERR is returned.
191 */
192
193static int
194befs_bt_read_node(struct super_block *sb, befs_data_stream * ds,
195 befs_btree_node * node, befs_off_t node_off)
196{
197 uint off = 0;
198
199 befs_debug(sb, "---> befs_bt_read_node()");
200
201 if (node->bh)
202 brelse(node->bh);
203
204 node->bh = befs_read_datastream(sb, ds, node_off, &off);
205 if (!node->bh) {
206 befs_error(sb, "befs_bt_read_node() failed to read "
207 "node at %Lu", node_off);
208 befs_debug(sb, "<--- befs_bt_read_node() ERROR");
209
210 return BEFS_ERR;
211 }
212 node->od_node =
213 (befs_btree_nodehead *) ((void *) node->bh->b_data + off);
214
215 befs_dump_index_node(sb, node->od_node);
216
217 node->head.left = fs64_to_cpu(sb, node->od_node->left);
218 node->head.right = fs64_to_cpu(sb, node->od_node->right);
219 node->head.overflow = fs64_to_cpu(sb, node->od_node->overflow);
220 node->head.all_key_count =
221 fs16_to_cpu(sb, node->od_node->all_key_count);
222 node->head.all_key_length =
223 fs16_to_cpu(sb, node->od_node->all_key_length);
224
225 befs_debug(sb, "<--- befs_btree_read_node()");
226 return BEFS_OK;
227}
228
229/**
230 * befs_btree_find - Find a key in a befs B+tree
231 * @sb: Filesystem superblock
232 * @ds: Datastream containing btree
233 * @key: Key string to lookup in btree
234 * @value: Value stored with @key
235 *
236 * On sucess, returns BEFS_OK and sets *@value to the value stored
237 * with @key (usually the disk block number of an inode).
238 *
239 * On failure, returns BEFS_ERR or BEFS_BT_NOT_FOUND.
240 *
241 * Algorithm:
242 * Read the superblock and rootnode of the b+tree.
243 * Drill down through the interior nodes using befs_find_key().
244 * Once at the correct leaf node, use befs_find_key() again to get the
245 * actuall value stored with the key.
246 */
247int
248befs_btree_find(struct super_block *sb, befs_data_stream * ds,
249 const char *key, befs_off_t * value)
250{
251 befs_btree_node *this_node = NULL;
252 befs_btree_super bt_super;
253 befs_off_t node_off;
254 int res;
255
256 befs_debug(sb, "---> befs_btree_find() Key: %s", key);
257
258 if (befs_bt_read_super(sb, ds, &bt_super) != BEFS_OK) {
259 befs_error(sb,
260 "befs_btree_find() failed to read index superblock");
261 goto error;
262 }
263
264 this_node = (befs_btree_node *) kmalloc(sizeof (befs_btree_node),
265 GFP_NOFS);
266 if (!this_node) {
267 befs_error(sb, "befs_btree_find() failed to allocate %u "
268 "bytes of memory", sizeof (befs_btree_node));
269 goto error;
270 }
271
272 this_node->bh = NULL;
273
274 /* read in root node */
275 node_off = bt_super.root_node_ptr;
276 if (befs_bt_read_node(sb, ds, this_node, node_off) != BEFS_OK) {
277 befs_error(sb, "befs_btree_find() failed to read "
278 "node at %Lu", node_off);
279 goto error_alloc;
280 }
281
282 while (!befs_leafnode(this_node)) {
283 res = befs_find_key(sb, this_node, key, &node_off);
284 if (res == BEFS_BT_NOT_FOUND)
285 node_off = this_node->head.overflow;
286 /* if no match, go to overflow node */
287 if (befs_bt_read_node(sb, ds, this_node, node_off) != BEFS_OK) {
288 befs_error(sb, "befs_btree_find() failed to read "
289 "node at %Lu", node_off);
290 goto error_alloc;
291 }
292 }
293
294 /* at the correct leaf node now */
295
296 res = befs_find_key(sb, this_node, key, value);
297
298 brelse(this_node->bh);
299 kfree(this_node);
300
301 if (res != BEFS_BT_MATCH) {
302 befs_debug(sb, "<--- befs_btree_find() Key %s not found", key);
303 *value = 0;
304 return BEFS_BT_NOT_FOUND;
305 }
306 befs_debug(sb, "<--- befs_btree_find() Found key %s, value %Lu",
307 key, *value);
308 return BEFS_OK;
309
310 error_alloc:
311 kfree(this_node);
312 error:
313 *value = 0;
314 befs_debug(sb, "<--- befs_btree_find() ERROR");
315 return BEFS_ERR;
316}
317
318/**
319 * befs_find_key - Search for a key within a node
320 * @sb: Filesystem superblock
321 * @node: Node to find the key within
322 * @key: Keystring to search for
323 * @value: If key is found, the value stored with the key is put here
324 *
325 * finds exact match if one exists, and returns BEFS_BT_MATCH
326 * If no exact match, finds first key in node that is greater
327 * (alphabetically) than the search key and returns BEFS_BT_PARMATCH
328 * (for partial match, I guess). Can you think of something better to
329 * call it?
330 *
331 * If no key was a match or greater than the search key, return
332 * BEFS_BT_NOT_FOUND.
333 *
334 * Use binary search instead of a linear.
335 */
336static int
337befs_find_key(struct super_block *sb, befs_btree_node * node,
338 const char *findkey, befs_off_t * value)
339{
340 int first, last, mid;
341 int eq;
342 u16 keylen;
343 int findkey_len;
344 char *thiskey;
345 befs_off_t *valarray;
346
347 befs_debug(sb, "---> befs_find_key() %s", findkey);
348
349 *value = 0;
350
351 findkey_len = strlen(findkey);
352
353 /* if node can not contain key, just skeep this node */
354 last = node->head.all_key_count - 1;
355 thiskey = befs_bt_get_key(sb, node, last, &keylen);
356
357 eq = befs_compare_strings(thiskey, keylen, findkey, findkey_len);
358 if (eq < 0) {
359 befs_debug(sb, "<--- befs_find_key() %s not found", findkey);
360 return BEFS_BT_NOT_FOUND;
361 }
362
363 valarray = befs_bt_valarray(node);
364
365 /* simple binary search */
366 first = 0;
367 mid = 0;
368 while (last >= first) {
369 mid = (last + first) / 2;
370 befs_debug(sb, "first: %d, last: %d, mid: %d", first, last,
371 mid);
372 thiskey = befs_bt_get_key(sb, node, mid, &keylen);
373 eq = befs_compare_strings(thiskey, keylen, findkey,
374 findkey_len);
375
376 if (eq == 0) {
377 befs_debug(sb, "<--- befs_find_key() found %s at %d",
378 thiskey, mid);
379
380 *value = fs64_to_cpu(sb, valarray[mid]);
381 return BEFS_BT_MATCH;
382 }
383 if (eq > 0)
384 last = mid - 1;
385 else
386 first = mid + 1;
387 }
388 if (eq < 0)
389 *value = fs64_to_cpu(sb, valarray[mid + 1]);
390 else
391 *value = fs64_to_cpu(sb, valarray[mid]);
392 befs_debug(sb, "<--- befs_find_key() found %s at %d", thiskey, mid);
393 return BEFS_BT_PARMATCH;
394}
395
396/**
397 * befs_btree_read - Traverse leafnodes of a btree
398 * @sb: Filesystem superblock
399 * @ds: Datastream containing btree
400 * @key_no: Key number (alphabetical order) of key to read
401 * @bufsize: Size of the buffer to return key in
402 * @keybuf: Pointer to a buffer to put the key in
403 * @keysize: Length of the returned key
404 * @value: Value stored with the returned key
405 *
406 * Heres how it works: Key_no is the index of the key/value pair to
407 * return in keybuf/value.
408 * Bufsize is the size of keybuf (BEFS_NAME_LEN+1 is a good size). Keysize is
409 * the number of charecters in the key (just a convenience).
410 *
411 * Algorithm:
412 * Get the first leafnode of the tree. See if the requested key is in that
413 * node. If not, follow the node->right link to the next leafnode. Repeat
414 * until the (key_no)th key is found or the tree is out of keys.
415 */
416int
417befs_btree_read(struct super_block *sb, befs_data_stream * ds,
418 loff_t key_no, size_t bufsize, char *keybuf, size_t * keysize,
419 befs_off_t * value)
420{
421 befs_btree_node *this_node;
422 befs_btree_super bt_super;
423 befs_off_t node_off = 0;
424 int cur_key;
425 befs_off_t *valarray;
426 char *keystart;
427 u16 keylen;
428 int res;
429
430 uint key_sum = 0;
431
432 befs_debug(sb, "---> befs_btree_read()");
433
434 if (befs_bt_read_super(sb, ds, &bt_super) != BEFS_OK) {
435 befs_error(sb,
436 "befs_btree_read() failed to read index superblock");
437 goto error;
438 }
439
440 if ((this_node = (befs_btree_node *)
441 kmalloc(sizeof (befs_btree_node), GFP_NOFS)) == NULL) {
442 befs_error(sb, "befs_btree_read() failed to allocate %u "
443 "bytes of memory", sizeof (befs_btree_node));
444 goto error;
445 }
446
447 node_off = bt_super.root_node_ptr;
448 this_node->bh = NULL;
449
450 /* seeks down to first leafnode, reads it into this_node */
451 res = befs_btree_seekleaf(sb, ds, &bt_super, this_node, &node_off);
452 if (res == BEFS_BT_EMPTY) {
453 brelse(this_node->bh);
454 kfree(this_node);
455 *value = 0;
456 *keysize = 0;
457 befs_debug(sb, "<--- befs_btree_read() Tree is EMPTY");
458 return BEFS_BT_EMPTY;
459 } else if (res == BEFS_ERR) {
460 goto error_alloc;
461 }
462
463 /* find the leaf node containing the key_no key */
464
465 while (key_sum + this_node->head.all_key_count <= key_no) {
466
467 /* no more nodes to look in: key_no is too large */
468 if (this_node->head.right == befs_bt_inval) {
469 *keysize = 0;
470 *value = 0;
471 befs_debug(sb,
472 "<--- befs_btree_read() END of keys at %Lu",
473 key_sum + this_node->head.all_key_count);
474 brelse(this_node->bh);
475 kfree(this_node);
476 return BEFS_BT_END;
477 }
478
479 key_sum += this_node->head.all_key_count;
480 node_off = this_node->head.right;
481
482 if (befs_bt_read_node(sb, ds, this_node, node_off) != BEFS_OK) {
483 befs_error(sb, "befs_btree_read() failed to read "
484 "node at %Lu", node_off);
485 goto error_alloc;
486 }
487 }
488
489 /* how many keys into this_node is key_no */
490 cur_key = key_no - key_sum;
491
492 /* get pointers to datastructures within the node body */
493 valarray = befs_bt_valarray(this_node);
494
495 keystart = befs_bt_get_key(sb, this_node, cur_key, &keylen);
496
497 befs_debug(sb, "Read [%Lu,%d]: keysize %d", node_off, cur_key, keylen);
498
499 if (bufsize < keylen + 1) {
500 befs_error(sb, "befs_btree_read() keybuf too small (%u) "
501 "for key of size %d", bufsize, keylen);
502 brelse(this_node->bh);
503 goto error_alloc;
504 };
505
506 strncpy(keybuf, keystart, keylen);
507 *value = fs64_to_cpu(sb, valarray[cur_key]);
508 *keysize = keylen;
509 keybuf[keylen] = '\0';
510
511 befs_debug(sb, "Read [%Lu,%d]: Key \"%.*s\", Value %Lu", node_off,
512 cur_key, keylen, keybuf, *value);
513
514 brelse(this_node->bh);
515 kfree(this_node);
516
517 befs_debug(sb, "<--- befs_btree_read()");
518
519 return BEFS_OK;
520
521 error_alloc:
522 kfree(this_node);
523
524 error:
525 *keysize = 0;
526 *value = 0;
527 befs_debug(sb, "<--- befs_btree_read() ERROR");
528 return BEFS_ERR;
529}
530
531/**
532 * befs_btree_seekleaf - Find the first leafnode in the btree
533 * @sb: Filesystem superblock
534 * @ds: Datastream containing btree
535 * @bt_super: Pointer to the superblock of the btree
536 * @this_node: Buffer to return the leafnode in
537 * @node_off: Pointer to offset of current node within datastream. Modified
538 * by the function.
539 *
540 *
541 * Helper function for btree traverse. Moves the current position to the
542 * start of the first leaf node.
543 *
544 * Also checks for an empty tree. If there are no keys, returns BEFS_BT_EMPTY.
545 */
546static int
547befs_btree_seekleaf(struct super_block *sb, befs_data_stream * ds,
548 befs_btree_super * bt_super, befs_btree_node * this_node,
549 befs_off_t * node_off)
550{
551
552 befs_debug(sb, "---> befs_btree_seekleaf()");
553
554 if (befs_bt_read_node(sb, ds, this_node, *node_off) != BEFS_OK) {
555 befs_error(sb, "befs_btree_seekleaf() failed to read "
556 "node at %Lu", *node_off);
557 goto error;
558 }
559 befs_debug(sb, "Seekleaf to root node %Lu", *node_off);
560
561 if (this_node->head.all_key_count == 0 && befs_leafnode(this_node)) {
562 befs_debug(sb, "<--- befs_btree_seekleaf() Tree is EMPTY");
563 return BEFS_BT_EMPTY;
564 }
565
566 while (!befs_leafnode(this_node)) {
567
568 if (this_node->head.all_key_count == 0) {
569 befs_debug(sb, "befs_btree_seekleaf() encountered "
570 "an empty interior node: %Lu. Using Overflow "
571 "node: %Lu", *node_off,
572 this_node->head.overflow);
573 *node_off = this_node->head.overflow;
574 } else {
575 befs_off_t *valarray = befs_bt_valarray(this_node);
576 *node_off = fs64_to_cpu(sb, valarray[0]);
577 }
578 if (befs_bt_read_node(sb, ds, this_node, *node_off) != BEFS_OK) {
579 befs_error(sb, "befs_btree_seekleaf() failed to read "
580 "node at %Lu", *node_off);
581 goto error;
582 }
583
584 befs_debug(sb, "Seekleaf to child node %Lu", *node_off);
585 }
586 befs_debug(sb, "Node %Lu is a leaf node", *node_off);
587
588 return BEFS_OK;
589
590 error:
591 befs_debug(sb, "<--- befs_btree_seekleaf() ERROR");
592 return BEFS_ERR;
593}
594
595/**
596 * befs_leafnode - Determine if the btree node is a leaf node or an
597 * interior node
598 * @node: Pointer to node structure to test
599 *
600 * Return 1 if leaf, 0 if interior
601 */
602static int
603befs_leafnode(befs_btree_node * node)
604{
605 /* all interior nodes (and only interior nodes) have an overflow node */
606 if (node->head.overflow == befs_bt_inval)
607 return 1;
608 else
609 return 0;
610}
611
612/**
613 * befs_bt_keylen_index - Finds start of keylen index in a node
614 * @node: Pointer to the node structure to find the keylen index within
615 *
616 * Returns a pointer to the start of the key length index array
617 * of the B+tree node *@node
618 *
619 * "The length of all the keys in the node is added to the size of the
620 * header and then rounded up to a multiple of four to get the beginning
621 * of the key length index" (p.88, practical filesystem design).
622 *
623 * Except that rounding up to 8 works, and rounding up to 4 doesn't.
624 */
625static u16 *
626befs_bt_keylen_index(befs_btree_node * node)
627{
628 const int keylen_align = 8;
629 unsigned long int off =
630 (sizeof (befs_btree_nodehead) + node->head.all_key_length);
631 ulong tmp = off % keylen_align;
632
633 if (tmp)
634 off += keylen_align - tmp;
635
636 return (u16 *) ((void *) node->od_node + off);
637}
638
639/**
640 * befs_bt_valarray - Finds the start of value array in a node
641 * @node: Pointer to the node structure to find the value array within
642 *
643 * Returns a pointer to the start of the value array
644 * of the node pointed to by the node header
645 */
646static befs_off_t *
647befs_bt_valarray(befs_btree_node * node)
648{
649 void *keylen_index_start = (void *) befs_bt_keylen_index(node);
650 size_t keylen_index_size = node->head.all_key_count * sizeof (u16);
651
652 return (befs_off_t *) (keylen_index_start + keylen_index_size);
653}
654
655/**
656 * befs_bt_keydata - Finds start of keydata array in a node
657 * @node: Pointer to the node structure to find the keydata array within
658 *
659 * Returns a pointer to the start of the keydata array
660 * of the node pointed to by the node header
661 */
662static char *
663befs_bt_keydata(befs_btree_node * node)
664{
665 return (char *) ((void *) node->od_node + sizeof (befs_btree_nodehead));
666}
667
668/**
669 * befs_bt_get_key - returns a pointer to the start of a key
670 * @sb: filesystem superblock
671 * @node: node in which to look for the key
672 * @index: the index of the key to get
673 * @keylen: modified to be the length of the key at @index
674 *
675 * Returns a valid pointer into @node on success.
676 * Returns NULL on failure (bad input) and sets *@keylen = 0
677 */
678static char *
679befs_bt_get_key(struct super_block *sb, befs_btree_node * node,
680 int index, u16 * keylen)
681{
682 int prev_key_end;
683 char *keystart;
684 u16 *keylen_index;
685
686 if (index < 0 || index > node->head.all_key_count) {
687 *keylen = 0;
688 return NULL;
689 }
690
691 keystart = befs_bt_keydata(node);
692 keylen_index = befs_bt_keylen_index(node);
693
694 if (index == 0)
695 prev_key_end = 0;
696 else
697 prev_key_end = fs16_to_cpu(sb, keylen_index[index - 1]);
698
699 *keylen = fs16_to_cpu(sb, keylen_index[index]) - prev_key_end;
700
701 return keystart + prev_key_end;
702}
703
704/**
705 * befs_compare_strings - compare two strings
706 * @key1: pointer to the first key to be compared
707 * @keylen1: length in bytes of key1
708 * @key2: pointer to the second key to be compared
709 * @kelen2: length in bytes of key2
710 *
711 * Returns 0 if @key1 and @key2 are equal.
712 * Returns >0 if @key1 is greater.
713 * Returns <0 if @key2 is greater..
714 */
715static int
716befs_compare_strings(const void *key1, int keylen1,
717 const void *key2, int keylen2)
718{
719 int len = min_t(int, keylen1, keylen2);
720 int result = strncmp(key1, key2, len);
721 if (result == 0)
722 result = keylen1 - keylen2;
723 return result;
724}
725
726/* These will be used for non-string keyed btrees */
727#if 0
728static int
729btree_compare_int32(cont void *key1, int keylen1, const void *key2, int keylen2)
730{
731 return *(int32_t *) key1 - *(int32_t *) key2;
732}
733
734static int
735btree_compare_uint32(cont void *key1, int keylen1,
736 const void *key2, int keylen2)
737{
738 if (*(u_int32_t *) key1 == *(u_int32_t *) key2)
739 return 0;
740 else if (*(u_int32_t *) key1 > *(u_int32_t *) key2)
741 return 1;
742
743 return -1;
744}
745static int
746btree_compare_int64(cont void *key1, int keylen1, const void *key2, int keylen2)
747{
748 if (*(int64_t *) key1 == *(int64_t *) key2)
749 return 0;
750 else if (*(int64_t *) key1 > *(int64_t *) key2)
751 return 1;
752
753 return -1;
754}
755
756static int
757btree_compare_uint64(cont void *key1, int keylen1,
758 const void *key2, int keylen2)
759{
760 if (*(u_int64_t *) key1 == *(u_int64_t *) key2)
761 return 0;
762 else if (*(u_int64_t *) key1 > *(u_int64_t *) key2)
763 return 1;
764
765 return -1;
766}
767
768static int
769btree_compare_float(cont void *key1, int keylen1, const void *key2, int keylen2)
770{
771 float result = *(float *) key1 - *(float *) key2;
772 if (result == 0.0f)
773 return 0;
774
775 return (result < 0.0f) ? -1 : 1;
776}
777
778static int
779btree_compare_double(cont void *key1, int keylen1,
780 const void *key2, int keylen2)
781{
782 double result = *(double *) key1 - *(double *) key2;
783 if (result == 0.0)
784 return 0;
785
786 return (result < 0.0) ? -1 : 1;
787}
788#endif //0
diff --git a/fs/befs/btree.h b/fs/befs/btree.h
new file mode 100644
index 000000000000..92e781e5f30e
--- /dev/null
+++ b/fs/befs/btree.h
@@ -0,0 +1,13 @@
1/*
2 * btree.h
3 *
4 */
5
6
7int befs_btree_find(struct super_block *sb, befs_data_stream * ds,
8 const char *key, befs_off_t * value);
9
10int befs_btree_read(struct super_block *sb, befs_data_stream * ds,
11 loff_t key_no, size_t bufsize, char *keybuf,
12 size_t * keysize, befs_off_t * value);
13
diff --git a/fs/befs/datastream.c b/fs/befs/datastream.c
new file mode 100644
index 000000000000..785f6b2d5d10
--- /dev/null
+++ b/fs/befs/datastream.c
@@ -0,0 +1,528 @@
1/*
2 * linux/fs/befs/datastream.c
3 *
4 * Copyright (C) 2001 Will Dyson <will_dyson@pobox.com>
5 *
6 * Based on portions of file.c by Makoto Kato <m_kato@ga2.so-net.ne.jp>
7 *
8 * Many thanks to Dominic Giampaolo, author of "Practical File System
9 * Design with the Be File System", for such a helpful book.
10 *
11 */
12
13#include <linux/kernel.h>
14#include <linux/slab.h>
15#include <linux/buffer_head.h>
16#include <linux/string.h>
17
18#include "befs.h"
19#include "datastream.h"
20#include "io.h"
21#include "endian.h"
22
23const befs_inode_addr BAD_IADDR = { 0, 0, 0 };
24
25static int befs_find_brun_direct(struct super_block *sb,
26 befs_data_stream * data,
27 befs_blocknr_t blockno, befs_block_run * run);
28
29static int befs_find_brun_indirect(struct super_block *sb,
30 befs_data_stream * data,
31 befs_blocknr_t blockno,
32 befs_block_run * run);
33
34static int befs_find_brun_dblindirect(struct super_block *sb,
35 befs_data_stream * data,
36 befs_blocknr_t blockno,
37 befs_block_run * run);
38
39/**
40 * befs_read_datastream - get buffer_head containing data, starting from pos.
41 * @sb: Filesystem superblock
42 * @ds: datastrem to find data with
43 * @pos: start of data
44 * @off: offset of data in buffer_head->b_data
45 *
46 * Returns pointer to buffer_head containing data starting with offset @off,
47 * if you don't need to know offset just set @off = NULL.
48 */
49struct buffer_head *
50befs_read_datastream(struct super_block *sb, befs_data_stream * ds,
51 befs_off_t pos, uint * off)
52{
53 struct buffer_head *bh = NULL;
54 befs_block_run run;
55 befs_blocknr_t block; /* block coresponding to pos */
56
57 befs_debug(sb, "---> befs_read_datastream() %Lu", pos);
58 block = pos >> BEFS_SB(sb)->block_shift;
59 if (off)
60 *off = pos - (block << BEFS_SB(sb)->block_shift);
61
62 if (befs_fblock2brun(sb, ds, block, &run) != BEFS_OK) {
63 befs_error(sb, "BeFS: Error finding disk addr of block %lu",
64 block);
65 befs_debug(sb, "<--- befs_read_datastream() ERROR");
66 return NULL;
67 }
68 bh = befs_bread_iaddr(sb, run);
69 if (!bh) {
70 befs_error(sb, "BeFS: Error reading block %lu from datastream",
71 block);
72 return NULL;
73 }
74
75 befs_debug(sb, "<--- befs_read_datastream() read data, starting at %Lu",
76 pos);
77
78 return bh;
79}
80
81/*
82 * Takes a file position and gives back a brun who's starting block
83 * is block number fblock of the file.
84 *
85 * Returns BEFS_OK or BEFS_ERR.
86 *
87 * Calls specialized functions for each of the three possible
88 * datastream regions.
89 *
90 * 2001-11-15 Will Dyson
91 */
92int
93befs_fblock2brun(struct super_block *sb, befs_data_stream * data,
94 befs_blocknr_t fblock, befs_block_run * run)
95{
96 int err;
97 befs_off_t pos = fblock << BEFS_SB(sb)->block_shift;
98
99 if (pos < data->max_direct_range) {
100 err = befs_find_brun_direct(sb, data, fblock, run);
101
102 } else if (pos < data->max_indirect_range) {
103 err = befs_find_brun_indirect(sb, data, fblock, run);
104
105 } else if (pos < data->max_double_indirect_range) {
106 err = befs_find_brun_dblindirect(sb, data, fblock, run);
107
108 } else {
109 befs_error(sb,
110 "befs_fblock2brun() was asked to find block %lu, "
111 "which is not mapped by the datastream\n", fblock);
112 err = BEFS_ERR;
113 }
114 return err;
115}
116
117/**
118 * befs_read_lsmylink - read long symlink from datastream.
119 * @sb: Filesystem superblock
120 * @ds: Datastrem to read from
121 * @buf: Buffer in wich to place long symlink data
122 * @len: Length of the long symlink in bytes
123 *
124 * Returns the number of bytes read
125 */
126size_t
127befs_read_lsymlink(struct super_block * sb, befs_data_stream * ds, void *buff,
128 befs_off_t len)
129{
130 befs_off_t bytes_read = 0; /* bytes readed */
131 u16 plen;
132 struct buffer_head *bh = NULL;
133 befs_debug(sb, "---> befs_read_lsymlink() length: %Lu", len);
134
135 while (bytes_read < len) {
136 bh = befs_read_datastream(sb, ds, bytes_read, NULL);
137 if (!bh) {
138 befs_error(sb, "BeFS: Error reading datastream block "
139 "starting from %Lu", bytes_read);
140 befs_debug(sb, "<--- befs_read_lsymlink() ERROR");
141 return bytes_read;
142
143 }
144 plen = ((bytes_read + BEFS_SB(sb)->block_size) < len) ?
145 BEFS_SB(sb)->block_size : len - bytes_read;
146 memcpy(buff + bytes_read, bh->b_data, plen);
147 brelse(bh);
148 bytes_read += plen;
149 }
150
151 befs_debug(sb, "<--- befs_read_lsymlink() read %u bytes", bytes_read);
152 return bytes_read;
153}
154
155/**
156 * befs_count_blocks - blocks used by a file
157 * @sb: Filesystem superblock
158 * @ds: Datastream of the file
159 *
160 * Counts the number of fs blocks that the file represented by
161 * inode occupies on the filesystem, counting both regular file
162 * data and filesystem metadata (and eventually attribute data
163 * when we support attributes)
164*/
165
166befs_blocknr_t
167befs_count_blocks(struct super_block * sb, befs_data_stream * ds)
168{
169 befs_blocknr_t blocks;
170 befs_blocknr_t datablocks; /* File data blocks */
171 befs_blocknr_t metablocks; /* FS metadata blocks */
172 befs_sb_info *befs_sb = BEFS_SB(sb);
173
174 befs_debug(sb, "---> befs_count_blocks()");
175
176 datablocks = ds->size >> befs_sb->block_shift;
177 if (ds->size & (befs_sb->block_size - 1))
178 datablocks += 1;
179
180 metablocks = 1; /* Start with 1 block for inode */
181
182 /* Size of indirect block */
183 if (ds->size > ds->max_direct_range)
184 metablocks += ds->indirect.len;
185
186 /*
187 Double indir block, plus all the indirect blocks it mapps
188 In the double-indirect range, all block runs of data are
189 BEFS_DBLINDIR_BRUN_LEN blocks long. Therefore, we know
190 how many data block runs are in the double-indirect region,
191 and from that we know how many indirect blocks it takes to
192 map them. We assume that the indirect blocks are also
193 BEFS_DBLINDIR_BRUN_LEN blocks long.
194 */
195 if (ds->size > ds->max_indirect_range && ds->max_indirect_range != 0) {
196 uint dbl_bytes;
197 uint dbl_bruns;
198 uint indirblocks;
199
200 dbl_bytes =
201 ds->max_double_indirect_range - ds->max_indirect_range;
202 dbl_bruns =
203 dbl_bytes / (befs_sb->block_size * BEFS_DBLINDIR_BRUN_LEN);
204 indirblocks = dbl_bruns / befs_iaddrs_per_block(sb);
205
206 metablocks += ds->double_indirect.len;
207 metablocks += indirblocks;
208 }
209
210 blocks = datablocks + metablocks;
211 befs_debug(sb, "<--- befs_count_blocks() %u blocks", blocks);
212
213 return blocks;
214}
215
216/*
217 Finds the block run that starts at file block number blockno
218 in the file represented by the datastream data, if that
219 blockno is in the direct region of the datastream.
220
221 sb: the superblock
222 data: the datastream
223 blockno: the blocknumber to find
224 run: The found run is passed back through this pointer
225
226 Return value is BEFS_OK if the blockrun is found, BEFS_ERR
227 otherwise.
228
229 Algorithm:
230 Linear search. Checks each element of array[] to see if it
231 contains the blockno-th filesystem block. This is necessary
232 because the block runs map variable amounts of data. Simply
233 keeps a count of the number of blocks searched so far (sum),
234 incrementing this by the length of each block run as we come
235 across it. Adds sum to *count before returning (this is so
236 you can search multiple arrays that are logicaly one array,
237 as in the indirect region code).
238
239 When/if blockno is found, if blockno is inside of a block
240 run as stored on disk, we offset the start and lenght members
241 of the block run, so that blockno is the start and len is
242 still valid (the run ends in the same place).
243
244 2001-11-15 Will Dyson
245*/
246static int
247befs_find_brun_direct(struct super_block *sb, befs_data_stream * data,
248 befs_blocknr_t blockno, befs_block_run * run)
249{
250 int i;
251 befs_block_run *array = data->direct;
252 befs_blocknr_t sum;
253 befs_blocknr_t max_block =
254 data->max_direct_range >> BEFS_SB(sb)->block_shift;
255
256 befs_debug(sb, "---> befs_find_brun_direct(), find %lu", blockno);
257
258 if (blockno > max_block) {
259 befs_error(sb, "befs_find_brun_direct() passed block outside of"
260 "direct region");
261 return BEFS_ERR;
262 }
263
264 for (i = 0, sum = 0; i < BEFS_NUM_DIRECT_BLOCKS;
265 sum += array[i].len, i++) {
266 if (blockno >= sum && blockno < sum + (array[i].len)) {
267 int offset = blockno - sum;
268 run->allocation_group = array[i].allocation_group;
269 run->start = array[i].start + offset;
270 run->len = array[i].len - offset;
271
272 befs_debug(sb, "---> befs_find_brun_direct(), "
273 "found %lu at direct[%d]", blockno, i);
274 return BEFS_OK;
275 }
276 }
277
278 befs_debug(sb, "---> befs_find_brun_direct() ERROR");
279 return BEFS_ERR;
280}
281
282/*
283 Finds the block run that starts at file block number blockno
284 in the file represented by the datastream data, if that
285 blockno is in the indirect region of the datastream.
286
287 sb: the superblock
288 data: the datastream
289 blockno: the blocknumber to find
290 run: The found run is passed back through this pointer
291
292 Return value is BEFS_OK if the blockrun is found, BEFS_ERR
293 otherwise.
294
295 Algorithm:
296 For each block in the indirect run of the datastream, read
297 it in and search through it for search_blk.
298
299 XXX:
300 Really should check to make sure blockno is inside indirect
301 region.
302
303 2001-11-15 Will Dyson
304*/
305static int
306befs_find_brun_indirect(struct super_block *sb,
307 befs_data_stream * data, befs_blocknr_t blockno,
308 befs_block_run * run)
309{
310 int i, j;
311 befs_blocknr_t sum = 0;
312 befs_blocknr_t indir_start_blk;
313 befs_blocknr_t search_blk;
314 struct buffer_head *indirblock;
315 befs_block_run *array;
316
317 befs_block_run indirect = data->indirect;
318 befs_blocknr_t indirblockno = iaddr2blockno(sb, &indirect);
319 int arraylen = befs_iaddrs_per_block(sb);
320
321 befs_debug(sb, "---> befs_find_brun_indirect(), find %lu", blockno);
322
323 indir_start_blk = data->max_direct_range >> BEFS_SB(sb)->block_shift;
324 search_blk = blockno - indir_start_blk;
325
326 /* Examine blocks of the indirect run one at a time */
327 for (i = 0; i < indirect.len; i++) {
328 indirblock = befs_bread(sb, indirblockno + i);
329 if (indirblock == NULL) {
330 befs_debug(sb,
331 "---> befs_find_brun_indirect() failed to "
332 "read disk block %lu from the indirect brun",
333 indirblockno + i);
334 return BEFS_ERR;
335 }
336
337 array = (befs_block_run *) indirblock->b_data;
338
339 for (j = 0; j < arraylen; ++j) {
340 int len = fs16_to_cpu(sb, array[j].len);
341
342 if (search_blk >= sum && search_blk < sum + len) {
343 int offset = search_blk - sum;
344 run->allocation_group =
345 fs32_to_cpu(sb, array[j].allocation_group);
346 run->start =
347 fs16_to_cpu(sb, array[j].start) + offset;
348 run->len =
349 fs16_to_cpu(sb, array[j].len) - offset;
350
351 brelse(indirblock);
352 befs_debug(sb,
353 "<--- befs_find_brun_indirect() found "
354 "file block %lu at indirect[%d]",
355 blockno, j + (i * arraylen));
356 return BEFS_OK;
357 }
358 sum += len;
359 }
360
361 brelse(indirblock);
362 }
363
364 /* Only fallthrough is an error */
365 befs_error(sb, "BeFS: befs_find_brun_indirect() failed to find "
366 "file block %lu", blockno);
367
368 befs_debug(sb, "<--- befs_find_brun_indirect() ERROR");
369 return BEFS_ERR;
370}
371
372/*
373 Finds the block run that starts at file block number blockno
374 in the file represented by the datastream data, if that
375 blockno is in the double-indirect region of the datastream.
376
377 sb: the superblock
378 data: the datastream
379 blockno: the blocknumber to find
380 run: The found run is passed back through this pointer
381
382 Return value is BEFS_OK if the blockrun is found, BEFS_ERR
383 otherwise.
384
385 Algorithm:
386 The block runs in the double-indirect region are different.
387 They are always allocated 4 fs blocks at a time, so each
388 block run maps a constant amount of file data. This means
389 that we can directly calculate how many block runs into the
390 double-indirect region we need to go to get to the one that
391 maps a particular filesystem block.
392
393 We do this in two stages. First we calculate which of the
394 inode addresses in the double-indirect block will point us
395 to the indirect block that contains the mapping for the data,
396 then we calculate which of the inode addresses in that
397 indirect block maps the data block we are after.
398
399 Oh, and once we've done that, we actually read in the blocks
400 that contain the inode addresses we calculated above. Even
401 though the double-indirect run may be several blocks long,
402 we can calculate which of those blocks will contain the index
403 we are after and only read that one. We then follow it to
404 the indirect block and perform a similar process to find
405 the actual block run that maps the data block we are interested
406 in.
407
408 Then we offset the run as in befs_find_brun_array() and we are
409 done.
410
411 2001-11-15 Will Dyson
412*/
413static int
414befs_find_brun_dblindirect(struct super_block *sb,
415 befs_data_stream * data, befs_blocknr_t blockno,
416 befs_block_run * run)
417{
418 int dblindir_indx;
419 int indir_indx;
420 int offset;
421 int dbl_which_block;
422 int which_block;
423 int dbl_block_indx;
424 int block_indx;
425 off_t dblindir_leftover;
426 befs_blocknr_t blockno_at_run_start;
427 struct buffer_head *dbl_indir_block;
428 struct buffer_head *indir_block;
429 befs_block_run indir_run;
430 befs_inode_addr *iaddr_array = NULL;
431 befs_sb_info *befs_sb = BEFS_SB(sb);
432
433 befs_blocknr_t indir_start_blk =
434 data->max_indirect_range >> befs_sb->block_shift;
435
436 off_t dbl_indir_off = blockno - indir_start_blk;
437
438 /* number of data blocks mapped by each of the iaddrs in
439 * the indirect block pointed to by the double indirect block
440 */
441 size_t iblklen = BEFS_DBLINDIR_BRUN_LEN;
442
443 /* number of data blocks mapped by each of the iaddrs in
444 * the double indirect block
445 */
446 size_t diblklen = iblklen * befs_iaddrs_per_block(sb)
447 * BEFS_DBLINDIR_BRUN_LEN;
448
449 befs_debug(sb, "---> befs_find_brun_dblindirect() find %lu", blockno);
450
451 /* First, discover which of the double_indir->indir blocks
452 * contains pos. Then figure out how much of pos that
453 * accounted for. Then discover which of the iaddrs in
454 * the indirect block contains pos.
455 */
456
457 dblindir_indx = dbl_indir_off / diblklen;
458 dblindir_leftover = dbl_indir_off % diblklen;
459 indir_indx = dblindir_leftover / diblklen;
460
461 /* Read double indirect block */
462 dbl_which_block = dblindir_indx / befs_iaddrs_per_block(sb);
463 if (dbl_which_block > data->double_indirect.len) {
464 befs_error(sb, "The double-indirect index calculated by "
465 "befs_read_brun_dblindirect(), %d, is outside the range "
466 "of the double-indirect block", dblindir_indx);
467 return BEFS_ERR;
468 }
469
470 dbl_indir_block =
471 befs_bread(sb, iaddr2blockno(sb, &data->double_indirect) +
472 dbl_which_block);
473 if (dbl_indir_block == NULL) {
474 befs_error(sb, "befs_read_brun_dblindirect() couldn't read the "
475 "double-indirect block at blockno %lu",
476 iaddr2blockno(sb,
477 &data->double_indirect) +
478 dbl_which_block);
479 brelse(dbl_indir_block);
480 return BEFS_ERR;
481 }
482
483 dbl_block_indx =
484 dblindir_indx - (dbl_which_block * befs_iaddrs_per_block(sb));
485 iaddr_array = (befs_inode_addr *) dbl_indir_block->b_data;
486 indir_run = fsrun_to_cpu(sb, iaddr_array[dbl_block_indx]);
487 brelse(dbl_indir_block);
488 iaddr_array = NULL;
489
490 /* Read indirect block */
491 which_block = indir_indx / befs_iaddrs_per_block(sb);
492 if (which_block > indir_run.len) {
493 befs_error(sb, "The indirect index calculated by "
494 "befs_read_brun_dblindirect(), %d, is outside the range "
495 "of the indirect block", indir_indx);
496 return BEFS_ERR;
497 }
498
499 indir_block =
500 befs_bread(sb, iaddr2blockno(sb, &indir_run) + which_block);
501 if (indir_block == NULL) {
502 befs_error(sb, "befs_read_brun_dblindirect() couldn't read the "
503 "indirect block at blockno %lu",
504 iaddr2blockno(sb, &indir_run) + which_block);
505 brelse(indir_block);
506 return BEFS_ERR;
507 }
508
509 block_indx = indir_indx - (which_block * befs_iaddrs_per_block(sb));
510 iaddr_array = (befs_inode_addr *) indir_block->b_data;
511 *run = fsrun_to_cpu(sb, iaddr_array[block_indx]);
512 brelse(indir_block);
513 iaddr_array = NULL;
514
515 blockno_at_run_start = indir_start_blk;
516 blockno_at_run_start += diblklen * dblindir_indx;
517 blockno_at_run_start += iblklen * indir_indx;
518 offset = blockno - blockno_at_run_start;
519
520 run->start += offset;
521 run->len -= offset;
522
523 befs_debug(sb, "Found file block %lu in double_indirect[%d][%d],"
524 " double_indirect_leftover = %lu",
525 blockno, dblindir_indx, indir_indx, dblindir_leftover);
526
527 return BEFS_OK;
528}
diff --git a/fs/befs/datastream.h b/fs/befs/datastream.h
new file mode 100644
index 000000000000..45e8a3c98249
--- /dev/null
+++ b/fs/befs/datastream.h
@@ -0,0 +1,19 @@
1/*
2 * datastream.h
3 *
4 */
5
6struct buffer_head *befs_read_datastream(struct super_block *sb,
7 befs_data_stream * ds, befs_off_t pos,
8 uint * off);
9
10int befs_fblock2brun(struct super_block *sb, befs_data_stream * data,
11 befs_blocknr_t fblock, befs_block_run * run);
12
13size_t befs_read_lsymlink(struct super_block *sb, befs_data_stream * data,
14 void *buff, befs_off_t len);
15
16befs_blocknr_t befs_count_blocks(struct super_block *sb, befs_data_stream * ds);
17
18extern const befs_inode_addr BAD_IADDR;
19
diff --git a/fs/befs/debug.c b/fs/befs/debug.c
new file mode 100644
index 000000000000..875cc0aa318c
--- /dev/null
+++ b/fs/befs/debug.c
@@ -0,0 +1,283 @@
1/*
2 * linux/fs/befs/debug.c
3 *
4 * Copyright (C) 2001 Will Dyson (will_dyson at pobox.com)
5 *
6 * With help from the ntfs-tng driver by Anton Altparmakov
7 *
8 * Copyright (C) 1999 Makoto Kato (m_kato@ga2.so-net.ne.jp)
9 *
10 * debug functions
11 */
12
13#ifdef __KERNEL__
14
15#include <stdarg.h>
16#include <linux/string.h>
17#include <linux/spinlock.h>
18#include <linux/kernel.h>
19#include <linux/fs.h>
20
21#endif /* __KERNEL__ */
22
23#include "befs.h"
24#include "endian.h"
25
26#define ERRBUFSIZE 1024
27
28void
29befs_error(const struct super_block *sb, const char *fmt, ...)
30{
31 va_list args;
32 char *err_buf = (char *) kmalloc(ERRBUFSIZE, GFP_KERNEL);
33 if (err_buf == NULL) {
34 printk(KERN_ERR "could not allocate %d bytes\n", ERRBUFSIZE);
35 return;
36 }
37
38 va_start(args, fmt);
39 vsnprintf(err_buf, ERRBUFSIZE, fmt, args);
40 va_end(args);
41
42 printk(KERN_ERR "BeFS(%s): %s\n", sb->s_id, err_buf);
43 kfree(err_buf);
44}
45
46void
47befs_warning(const struct super_block *sb, const char *fmt, ...)
48{
49 va_list args;
50 char *err_buf = (char *) kmalloc(ERRBUFSIZE, GFP_KERNEL);
51 if (err_buf == NULL) {
52 printk(KERN_ERR "could not allocate %d bytes\n", ERRBUFSIZE);
53 return;
54 }
55
56 va_start(args, fmt);
57 vsnprintf(err_buf, ERRBUFSIZE, fmt, args);
58 va_end(args);
59
60 printk(KERN_WARNING "BeFS(%s): %s\n", sb->s_id, err_buf);
61
62 kfree(err_buf);
63}
64
65void
66befs_debug(const struct super_block *sb, const char *fmt, ...)
67{
68#ifdef CONFIG_BEFS_DEBUG
69
70 va_list args;
71 char *err_buf = NULL;
72
73 if (BEFS_SB(sb)->mount_opts.debug) {
74 err_buf = (char *) kmalloc(ERRBUFSIZE, GFP_KERNEL);
75 if (err_buf == NULL) {
76 printk(KERN_ERR "could not allocate %d bytes\n",
77 ERRBUFSIZE);
78 return;
79 }
80
81 va_start(args, fmt);
82 vsnprintf(err_buf, ERRBUFSIZE, fmt, args);
83 va_end(args);
84
85 printk(KERN_DEBUG "BeFS(%s): %s\n", sb->s_id, err_buf);
86
87 kfree(err_buf);
88 }
89
90#endif //CONFIG_BEFS_DEBUG
91}
92
93void
94befs_dump_inode(const struct super_block *sb, befs_inode * inode)
95{
96#ifdef CONFIG_BEFS_DEBUG
97
98 befs_block_run tmp_run;
99
100 befs_debug(sb, "befs_inode information");
101
102 befs_debug(sb, " magic1 %08x", fs32_to_cpu(sb, inode->magic1));
103
104 tmp_run = fsrun_to_cpu(sb, inode->inode_num);
105 befs_debug(sb, " inode_num %u, %hu, %hu",
106 tmp_run.allocation_group, tmp_run.start, tmp_run.len);
107
108 befs_debug(sb, " uid %u", fs32_to_cpu(sb, inode->uid));
109 befs_debug(sb, " gid %u", fs32_to_cpu(sb, inode->gid));
110 befs_debug(sb, " mode %08x", fs32_to_cpu(sb, inode->mode));
111 befs_debug(sb, " flags %08x", fs32_to_cpu(sb, inode->flags));
112 befs_debug(sb, " create_time %Lu",
113 fs64_to_cpu(sb, inode->create_time));
114 befs_debug(sb, " last_modified_time %Lu",
115 fs64_to_cpu(sb, inode->last_modified_time));
116
117 tmp_run = fsrun_to_cpu(sb, inode->parent);
118 befs_debug(sb, " parent [%u, %hu, %hu]",
119 tmp_run.allocation_group, tmp_run.start, tmp_run.len);
120
121 tmp_run = fsrun_to_cpu(sb, inode->attributes);
122 befs_debug(sb, " attributes [%u, %hu, %hu]",
123 tmp_run.allocation_group, tmp_run.start, tmp_run.len);
124
125 befs_debug(sb, " type %08x", fs32_to_cpu(sb, inode->type));
126 befs_debug(sb, " inode_size %u", fs32_to_cpu(sb, inode->inode_size));
127
128 if (S_ISLNK(inode->mode)) {
129 befs_debug(sb, " Symbolic link [%s]", inode->data.symlink);
130 } else {
131 int i;
132
133 for (i = 0; i < BEFS_NUM_DIRECT_BLOCKS; i++) {
134 tmp_run =
135 fsrun_to_cpu(sb, inode->data.datastream.direct[i]);
136 befs_debug(sb, " direct %d [%u, %hu, %hu]", i,
137 tmp_run.allocation_group, tmp_run.start,
138 tmp_run.len);
139 }
140 befs_debug(sb, " max_direct_range %Lu",
141 fs64_to_cpu(sb,
142 inode->data.datastream.
143 max_direct_range));
144
145 tmp_run = fsrun_to_cpu(sb, inode->data.datastream.indirect);
146 befs_debug(sb, " indirect [%u, %hu, %hu]",
147 tmp_run.allocation_group,
148 tmp_run.start, tmp_run.len);
149
150 befs_debug(sb, " max_indirect_range %Lu",
151 fs64_to_cpu(sb,
152 inode->data.datastream.
153 max_indirect_range));
154
155 tmp_run =
156 fsrun_to_cpu(sb, inode->data.datastream.double_indirect);
157 befs_debug(sb, " double indirect [%u, %hu, %hu]",
158 tmp_run.allocation_group, tmp_run.start,
159 tmp_run.len);
160
161 befs_debug(sb, " max_double_indirect_range %Lu",
162 fs64_to_cpu(sb,
163 inode->data.datastream.
164 max_double_indirect_range));
165
166 befs_debug(sb, " size %Lu",
167 fs64_to_cpu(sb, inode->data.datastream.size));
168 }
169
170#endif //CONFIG_BEFS_DEBUG
171}
172
173/*
174 * Display super block structure for debug.
175 */
176
177void
178befs_dump_super_block(const struct super_block *sb, befs_super_block * sup)
179{
180#ifdef CONFIG_BEFS_DEBUG
181
182 befs_block_run tmp_run;
183
184 befs_debug(sb, "befs_super_block information");
185
186 befs_debug(sb, " name %s", sup->name);
187 befs_debug(sb, " magic1 %08x", fs32_to_cpu(sb, sup->magic1));
188 befs_debug(sb, " fs_byte_order %08x",
189 fs32_to_cpu(sb, sup->fs_byte_order));
190
191 befs_debug(sb, " block_size %u", fs32_to_cpu(sb, sup->block_size));
192 befs_debug(sb, " block_shift %u", fs32_to_cpu(sb, sup->block_shift));
193
194 befs_debug(sb, " num_blocks %Lu", fs64_to_cpu(sb, sup->num_blocks));
195 befs_debug(sb, " used_blocks %Lu", fs64_to_cpu(sb, sup->used_blocks));
196
197 befs_debug(sb, " magic2 %08x", fs32_to_cpu(sb, sup->magic2));
198 befs_debug(sb, " blocks_per_ag %u",
199 fs32_to_cpu(sb, sup->blocks_per_ag));
200 befs_debug(sb, " ag_shift %u", fs32_to_cpu(sb, sup->ag_shift));
201 befs_debug(sb, " num_ags %u", fs32_to_cpu(sb, sup->num_ags));
202
203 befs_debug(sb, " flags %08x", fs32_to_cpu(sb, sup->flags));
204
205 tmp_run = fsrun_to_cpu(sb, sup->log_blocks);
206 befs_debug(sb, " log_blocks %u, %hu, %hu",
207 tmp_run.allocation_group, tmp_run.start, tmp_run.len);
208
209 befs_debug(sb, " log_start %Ld", fs64_to_cpu(sb, sup->log_start));
210 befs_debug(sb, " log_end %Ld", fs64_to_cpu(sb, sup->log_end));
211
212 befs_debug(sb, " magic3 %08x", fs32_to_cpu(sb, sup->magic3));
213
214 tmp_run = fsrun_to_cpu(sb, sup->root_dir);
215 befs_debug(sb, " root_dir %u, %hu, %hu",
216 tmp_run.allocation_group, tmp_run.start, tmp_run.len);
217
218 tmp_run = fsrun_to_cpu(sb, sup->indices);
219 befs_debug(sb, " indices %u, %hu, %hu",
220 tmp_run.allocation_group, tmp_run.start, tmp_run.len);
221
222#endif //CONFIG_BEFS_DEBUG
223}
224
225#if 0
226/* unused */
227void
228befs_dump_small_data(const struct super_block *sb, befs_small_data * sd)
229{
230}
231
232/* unused */
233void
234befs_dump_run(const struct super_block *sb, befs_block_run run)
235{
236#ifdef CONFIG_BEFS_DEBUG
237
238 run = fsrun_to_cpu(sb, run);
239
240 befs_debug(sb, "[%u, %hu, %hu]",
241 run.allocation_group, run.start, run.len);
242
243#endif //CONFIG_BEFS_DEBUG
244}
245#endif /* 0 */
246
247void
248befs_dump_index_entry(const struct super_block *sb, befs_btree_super * super)
249{
250#ifdef CONFIG_BEFS_DEBUG
251
252 befs_debug(sb, "Btree super structure");
253 befs_debug(sb, " magic %08x", fs32_to_cpu(sb, super->magic));
254 befs_debug(sb, " node_size %u", fs32_to_cpu(sb, super->node_size));
255 befs_debug(sb, " max_depth %08x", fs32_to_cpu(sb, super->max_depth));
256
257 befs_debug(sb, " data_type %08x", fs32_to_cpu(sb, super->data_type));
258 befs_debug(sb, " root_node_pointer %016LX",
259 fs64_to_cpu(sb, super->root_node_ptr));
260 befs_debug(sb, " free_node_pointer %016LX",
261 fs64_to_cpu(sb, super->free_node_ptr));
262 befs_debug(sb, " maximum size %016LX",
263 fs64_to_cpu(sb, super->max_size));
264
265#endif //CONFIG_BEFS_DEBUG
266}
267
268void
269befs_dump_index_node(const struct super_block *sb, befs_btree_nodehead * node)
270{
271#ifdef CONFIG_BEFS_DEBUG
272
273 befs_debug(sb, "Btree node structure");
274 befs_debug(sb, " left %016LX", fs64_to_cpu(sb, node->left));
275 befs_debug(sb, " right %016LX", fs64_to_cpu(sb, node->right));
276 befs_debug(sb, " overflow %016LX", fs64_to_cpu(sb, node->overflow));
277 befs_debug(sb, " all_key_count %hu",
278 fs16_to_cpu(sb, node->all_key_count));
279 befs_debug(sb, " all_key_length %hu",
280 fs16_to_cpu(sb, node->all_key_length));
281
282#endif //CONFIG_BEFS_DEBUG
283}
diff --git a/fs/befs/endian.h b/fs/befs/endian.h
new file mode 100644
index 000000000000..9ecaea4e3325
--- /dev/null
+++ b/fs/befs/endian.h
@@ -0,0 +1,126 @@
1/*
2 * linux/fs/befs/endian.h
3 *
4 * Copyright (C) 2001 Will Dyson <will_dyson@pobox.com>
5 *
6 * Partially based on similar funtions in the sysv driver.
7 */
8
9#ifndef LINUX_BEFS_ENDIAN
10#define LINUX_BEFS_ENDIAN
11
12#include <linux/byteorder/generic.h>
13#include "befs.h"
14
15static inline u64
16fs64_to_cpu(const struct super_block *sb, u64 n)
17{
18 if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE)
19 return le64_to_cpu(n);
20 else
21 return be64_to_cpu(n);
22}
23
24static inline u64
25cpu_to_fs64(const struct super_block *sb, u64 n)
26{
27 if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE)
28 return cpu_to_le64(n);
29 else
30 return cpu_to_be64(n);
31}
32
33static inline u32
34fs32_to_cpu(const struct super_block *sb, u32 n)
35{
36 if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE)
37 return le32_to_cpu(n);
38 else
39 return be32_to_cpu(n);
40}
41
42static inline u32
43cpu_to_fs32(const struct super_block *sb, u32 n)
44{
45 if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE)
46 return cpu_to_le32(n);
47 else
48 return cpu_to_be32(n);
49}
50
51static inline u16
52fs16_to_cpu(const struct super_block *sb, u16 n)
53{
54 if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE)
55 return le16_to_cpu(n);
56 else
57 return be16_to_cpu(n);
58}
59
60static inline u16
61cpu_to_fs16(const struct super_block *sb, u16 n)
62{
63 if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE)
64 return cpu_to_le16(n);
65 else
66 return cpu_to_be16(n);
67}
68
69/* Composite types below here */
70
71static inline befs_block_run
72fsrun_to_cpu(const struct super_block *sb, befs_block_run n)
73{
74 befs_block_run run;
75
76 if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE) {
77 run.allocation_group = le32_to_cpu(n.allocation_group);
78 run.start = le16_to_cpu(n.start);
79 run.len = le16_to_cpu(n.len);
80 } else {
81 run.allocation_group = be32_to_cpu(n.allocation_group);
82 run.start = be16_to_cpu(n.start);
83 run.len = be16_to_cpu(n.len);
84 }
85 return run;
86}
87
88static inline befs_block_run
89cpu_to_fsrun(const struct super_block *sb, befs_block_run n)
90{
91 befs_block_run run;
92
93 if (BEFS_SB(sb)->byte_order == BEFS_BYTESEX_LE) {
94 run.allocation_group = cpu_to_le32(n.allocation_group);
95 run.start = cpu_to_le16(n.start);
96 run.len = cpu_to_le16(n.len);
97 } else {
98 run.allocation_group = cpu_to_be32(n.allocation_group);
99 run.start = cpu_to_be16(n.start);
100 run.len = cpu_to_be16(n.len);
101 }
102 return run;
103}
104
105static inline befs_data_stream
106fsds_to_cpu(const struct super_block *sb, befs_data_stream n)
107{
108 befs_data_stream data;
109 int i;
110
111 for (i = 0; i < BEFS_NUM_DIRECT_BLOCKS; ++i)
112 data.direct[i] = fsrun_to_cpu(sb, n.direct[i]);
113
114 data.max_direct_range = fs64_to_cpu(sb, n.max_direct_range);
115 data.indirect = fsrun_to_cpu(sb, n.indirect);
116 data.max_indirect_range = fs64_to_cpu(sb, n.max_indirect_range);
117 data.double_indirect = fsrun_to_cpu(sb, n.double_indirect);
118 data.max_double_indirect_range = fs64_to_cpu(sb,
119 n.
120 max_double_indirect_range);
121 data.size = fs64_to_cpu(sb, n.size);
122
123 return data;
124}
125
126#endif //LINUX_BEFS_ENDIAN
diff --git a/fs/befs/inode.c b/fs/befs/inode.c
new file mode 100644
index 000000000000..d41c9247ae8a
--- /dev/null
+++ b/fs/befs/inode.c
@@ -0,0 +1,53 @@
1/*
2 * inode.c
3 *
4 * Copyright (C) 2001 Will Dyson <will_dyson@pobox.com>
5 */
6
7#include <linux/fs.h>
8
9#include "befs.h"
10#include "inode.h"
11#include "endian.h"
12
13/*
14 Validates the correctness of the befs inode
15 Returns BEFS_OK if the inode should be used, otherwise
16 returns BEFS_BAD_INODE
17*/
18int
19befs_check_inode(struct super_block *sb, befs_inode * raw_inode,
20 befs_blocknr_t inode)
21{
22 u32 magic1 = fs32_to_cpu(sb, raw_inode->magic1);
23 befs_inode_addr ino_num = fsrun_to_cpu(sb, raw_inode->inode_num);
24 u32 flags = fs32_to_cpu(sb, raw_inode->flags);
25
26 /* check magic header. */
27 if (magic1 != BEFS_INODE_MAGIC1) {
28 befs_error(sb,
29 "Inode has a bad magic header - inode = %lu", inode);
30 return BEFS_BAD_INODE;
31 }
32
33 /*
34 * Sanity check2: inodes store their own block address. Check it.
35 */
36 if (inode != iaddr2blockno(sb, &ino_num)) {
37 befs_error(sb, "inode blocknr field disagrees with vfs "
38 "VFS: %lu, Inode %lu",
39 inode, iaddr2blockno(sb, &ino_num));
40 return BEFS_BAD_INODE;
41 }
42
43 /*
44 * check flag
45 */
46
47 if (!(flags & BEFS_INODE_IN_USE)) {
48 befs_error(sb, "inode is not used - inode = %lu", inode);
49 return BEFS_BAD_INODE;
50 }
51
52 return BEFS_OK;
53}
diff --git a/fs/befs/inode.h b/fs/befs/inode.h
new file mode 100644
index 000000000000..9dc7fd9b7570
--- /dev/null
+++ b/fs/befs/inode.h
@@ -0,0 +1,8 @@
1/*
2 * inode.h
3 *
4 */
5
6int befs_check_inode(struct super_block *sb, befs_inode * raw_inode,
7 befs_blocknr_t inode);
8
diff --git a/fs/befs/io.c b/fs/befs/io.c
new file mode 100644
index 000000000000..ddef98aa255d
--- /dev/null
+++ b/fs/befs/io.c
@@ -0,0 +1,83 @@
1/*
2 * linux/fs/befs/io.c
3 *
4 * Copyright (C) 2001 Will Dyson <will_dyson@pobox.com
5 *
6 * Based on portions of file.c and inode.c
7 * by Makoto Kato (m_kato@ga2.so-net.ne.jp)
8 *
9 * Many thanks to Dominic Giampaolo, author of Practical File System
10 * Design with the Be File System, for such a helpful book.
11 *
12 */
13
14#include <linux/buffer_head.h>
15
16#include "befs.h"
17#include "io.h"
18
19/*
20 * Converts befs notion of disk addr to a disk offset and uses
21 * linux kernel function sb_bread() to get the buffer containing
22 * the offset. -Will Dyson
23 *
24 */
25
26struct buffer_head *
27befs_bread_iaddr(struct super_block *sb, befs_inode_addr iaddr)
28{
29 struct buffer_head *bh = NULL;
30 befs_blocknr_t block = 0;
31 befs_sb_info *befs_sb = BEFS_SB(sb);
32
33 befs_debug(sb, "---> Enter befs_read_iaddr() "
34 "[%u, %hu, %hu]",
35 iaddr.allocation_group, iaddr.start, iaddr.len);
36
37 if (iaddr.allocation_group > befs_sb->num_ags) {
38 befs_error(sb, "BEFS: Invalid allocation group %u, max is %u",
39 iaddr.allocation_group, befs_sb->num_ags);
40 goto error;
41 }
42
43 block = iaddr2blockno(sb, &iaddr);
44
45 befs_debug(sb, "befs_read_iaddr: offset = %lu", block);
46
47 bh = sb_bread(sb, block);
48
49 if (bh == NULL) {
50 befs_error(sb, "Failed to read block %lu", block);
51 goto error;
52 }
53
54 befs_debug(sb, "<--- befs_read_iaddr()");
55 return bh;
56
57 error:
58 befs_debug(sb, "<--- befs_read_iaddr() ERROR");
59 return NULL;
60}
61
62struct buffer_head *
63befs_bread(struct super_block *sb, befs_blocknr_t block)
64{
65 struct buffer_head *bh = NULL;
66
67 befs_debug(sb, "---> Enter befs_read() %Lu", block);
68
69 bh = sb_bread(sb, block);
70
71 if (bh == NULL) {
72 befs_error(sb, "Failed to read block %lu", block);
73 goto error;
74 }
75
76 befs_debug(sb, "<--- befs_read()");
77
78 return bh;
79
80 error:
81 befs_debug(sb, "<--- befs_read() ERROR");
82 return NULL;
83}
diff --git a/fs/befs/io.h b/fs/befs/io.h
new file mode 100644
index 000000000000..9b78266b6aa5
--- /dev/null
+++ b/fs/befs/io.h
@@ -0,0 +1,9 @@
1/*
2 * io.h
3 */
4
5struct buffer_head *befs_bread_iaddr(struct super_block *sb,
6 befs_inode_addr iaddr);
7
8struct buffer_head *befs_bread(struct super_block *sb, befs_blocknr_t block);
9
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
new file mode 100644
index 000000000000..de5bb280a828
--- /dev/null
+++ b/fs/befs/linuxvfs.c
@@ -0,0 +1,964 @@
1/*
2 * linux/fs/befs/linuxvfs.c
3 *
4 * Copyright (C) 2001 Will Dyson <will_dyson@pobox.com
5 *
6 */
7
8#include <linux/module.h>
9#include <linux/slab.h>
10#include <linux/fs.h>
11#include <linux/errno.h>
12#include <linux/stat.h>
13#include <linux/nls.h>
14#include <linux/buffer_head.h>
15#include <linux/vfs.h>
16#include <linux/parser.h>
17#include <linux/namei.h>
18
19#include "befs.h"
20#include "btree.h"
21#include "inode.h"
22#include "datastream.h"
23#include "super.h"
24#include "io.h"
25#include "endian.h"
26
27MODULE_DESCRIPTION("BeOS File System (BeFS) driver");
28MODULE_AUTHOR("Will Dyson");
29MODULE_LICENSE("GPL");
30
31/* The units the vfs expects inode->i_blocks to be in */
32#define VFS_BLOCK_SIZE 512
33
34static int befs_readdir(struct file *, void *, filldir_t);
35static int befs_get_block(struct inode *, sector_t, struct buffer_head *, int);
36static int befs_readpage(struct file *file, struct page *page);
37static sector_t befs_bmap(struct address_space *mapping, sector_t block);
38static struct dentry *befs_lookup(struct inode *, struct dentry *, struct nameidata *);
39static void befs_read_inode(struct inode *ino);
40static struct inode *befs_alloc_inode(struct super_block *sb);
41static void befs_destroy_inode(struct inode *inode);
42static int befs_init_inodecache(void);
43static void befs_destroy_inodecache(void);
44static int befs_follow_link(struct dentry *, struct nameidata *);
45static void befs_put_link(struct dentry *, struct nameidata *);
46static int befs_utf2nls(struct super_block *sb, const char *in, int in_len,
47 char **out, int *out_len);
48static int befs_nls2utf(struct super_block *sb, const char *in, int in_len,
49 char **out, int *out_len);
50static void befs_put_super(struct super_block *);
51static int befs_remount(struct super_block *, int *, char *);
52static int befs_statfs(struct super_block *, struct kstatfs *);
53static int parse_options(char *, befs_mount_options *);
54
55static const struct super_operations befs_sops = {
56 .read_inode = befs_read_inode, /* initialize & read inode */
57 .alloc_inode = befs_alloc_inode, /* allocate a new inode */
58 .destroy_inode = befs_destroy_inode, /* deallocate an inode */
59 .put_super = befs_put_super, /* uninit super */
60 .statfs = befs_statfs, /* statfs */
61 .remount_fs = befs_remount,
62};
63
64/* slab cache for befs_inode_info objects */
65static kmem_cache_t *befs_inode_cachep;
66
67static struct file_operations befs_dir_operations = {
68 .read = generic_read_dir,
69 .readdir = befs_readdir,
70};
71
72static struct inode_operations befs_dir_inode_operations = {
73 .lookup = befs_lookup,
74};
75
76static struct file_operations befs_file_operations = {
77 .llseek = default_llseek,
78 .read = generic_file_read,
79 .mmap = generic_file_readonly_mmap,
80};
81
82static struct address_space_operations befs_aops = {
83 .readpage = befs_readpage,
84 .sync_page = block_sync_page,
85 .bmap = befs_bmap,
86};
87
88static struct inode_operations befs_symlink_inode_operations = {
89 .readlink = generic_readlink,
90 .follow_link = befs_follow_link,
91 .put_link = befs_put_link,
92};
93
94/*
95 * Called by generic_file_read() to read a page of data
96 *
97 * In turn, simply calls a generic block read function and
98 * passes it the address of befs_get_block, for mapping file
99 * positions to disk blocks.
100 */
101static int
102befs_readpage(struct file *file, struct page *page)
103{
104 return block_read_full_page(page, befs_get_block);
105}
106
107static sector_t
108befs_bmap(struct address_space *mapping, sector_t block)
109{
110 return generic_block_bmap(mapping, block, befs_get_block);
111}
112
113/*
114 * Generic function to map a file position (block) to a
115 * disk offset (passed back in bh_result).
116 *
117 * Used by many higher level functions.
118 *
119 * Calls befs_fblock2brun() in datastream.c to do the real work.
120 *
121 * -WD 10-26-01
122 */
123
124static int
125befs_get_block(struct inode *inode, sector_t block,
126 struct buffer_head *bh_result, int create)
127{
128 struct super_block *sb = inode->i_sb;
129 befs_data_stream *ds = &BEFS_I(inode)->i_data.ds;
130 befs_block_run run = BAD_IADDR;
131 int res = 0;
132 ulong disk_off;
133
134 befs_debug(sb, "---> befs_get_block() for inode %lu, block %ld",
135 inode->i_ino, block);
136
137 if (block < 0) {
138 befs_error(sb, "befs_get_block() was asked for a block "
139 "number less than zero: block %ld in inode %lu",
140 block, inode->i_ino);
141 return -EIO;
142 }
143
144 if (create) {
145 befs_error(sb, "befs_get_block() was asked to write to "
146 "block %ld in inode %lu", block, inode->i_ino);
147 return -EPERM;
148 }
149
150 res = befs_fblock2brun(sb, ds, block, &run);
151 if (res != BEFS_OK) {
152 befs_error(sb,
153 "<--- befs_get_block() for inode %lu, block "
154 "%ld ERROR", inode->i_ino, block);
155 return -EFBIG;
156 }
157
158 disk_off = (ulong) iaddr2blockno(sb, &run);
159
160 map_bh(bh_result, inode->i_sb, disk_off);
161
162 befs_debug(sb, "<--- befs_get_block() for inode %lu, block %ld, "
163 "disk address %lu", inode->i_ino, block, disk_off);
164
165 return 0;
166}
167
168static struct dentry *
169befs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
170{
171 struct inode *inode = NULL;
172 struct super_block *sb = dir->i_sb;
173 befs_data_stream *ds = &BEFS_I(dir)->i_data.ds;
174 befs_off_t offset;
175 int ret;
176 int utfnamelen;
177 char *utfname;
178 const char *name = dentry->d_name.name;
179
180 befs_debug(sb, "---> befs_lookup() "
181 "name %s inode %ld", dentry->d_name.name, dir->i_ino);
182
183 /* Convert to UTF-8 */
184 if (BEFS_SB(sb)->nls) {
185 ret =
186 befs_nls2utf(sb, name, strlen(name), &utfname, &utfnamelen);
187 if (ret < 0) {
188 befs_debug(sb, "<--- befs_lookup() ERROR");
189 return ERR_PTR(ret);
190 }
191 ret = befs_btree_find(sb, ds, utfname, &offset);
192 kfree(utfname);
193
194 } else {
195 ret = befs_btree_find(sb, ds, dentry->d_name.name, &offset);
196 }
197
198 if (ret == BEFS_BT_NOT_FOUND) {
199 befs_debug(sb, "<--- befs_lookup() %s not found",
200 dentry->d_name.name);
201 return ERR_PTR(-ENOENT);
202
203 } else if (ret != BEFS_OK || offset == 0) {
204 befs_warning(sb, "<--- befs_lookup() Error");
205 return ERR_PTR(-ENODATA);
206 }
207
208 inode = iget(dir->i_sb, (ino_t) offset);
209 if (!inode)
210 return ERR_PTR(-EACCES);
211
212 d_add(dentry, inode);
213
214 befs_debug(sb, "<--- befs_lookup()");
215
216 return NULL;
217}
218
219static int
220befs_readdir(struct file *filp, void *dirent, filldir_t filldir)
221{
222 struct inode *inode = filp->f_dentry->d_inode;
223 struct super_block *sb = inode->i_sb;
224 befs_data_stream *ds = &BEFS_I(inode)->i_data.ds;
225 befs_off_t value;
226 int result;
227 size_t keysize;
228 unsigned char d_type;
229 char keybuf[BEFS_NAME_LEN + 1];
230 char *nlsname;
231 int nlsnamelen;
232 const char *dirname = filp->f_dentry->d_name.name;
233
234 befs_debug(sb, "---> befs_readdir() "
235 "name %s, inode %ld, filp->f_pos %Ld",
236 dirname, inode->i_ino, filp->f_pos);
237
238 result = befs_btree_read(sb, ds, filp->f_pos, BEFS_NAME_LEN + 1,
239 keybuf, &keysize, &value);
240
241 if (result == BEFS_ERR) {
242 befs_debug(sb, "<--- befs_readdir() ERROR");
243 befs_error(sb, "IO error reading %s (inode %lu)",
244 dirname, inode->i_ino);
245 return -EIO;
246
247 } else if (result == BEFS_BT_END) {
248 befs_debug(sb, "<--- befs_readdir() END");
249 return 0;
250
251 } else if (result == BEFS_BT_EMPTY) {
252 befs_debug(sb, "<--- befs_readdir() Empty directory");
253 return 0;
254 }
255
256 d_type = DT_UNKNOWN;
257
258 /* Convert to NLS */
259 if (BEFS_SB(sb)->nls) {
260 result =
261 befs_utf2nls(sb, keybuf, keysize, &nlsname, &nlsnamelen);
262 if (result < 0) {
263 befs_debug(sb, "<--- befs_readdir() ERROR");
264 return result;
265 }
266 result = filldir(dirent, nlsname, nlsnamelen, filp->f_pos,
267 (ino_t) value, d_type);
268 kfree(nlsname);
269
270 } else {
271 result = filldir(dirent, keybuf, keysize, filp->f_pos,
272 (ino_t) value, d_type);
273 }
274
275 filp->f_pos++;
276
277 befs_debug(sb, "<--- befs_readdir() filp->f_pos %Ld", filp->f_pos);
278
279 return 0;
280}
281
282static struct inode *
283befs_alloc_inode(struct super_block *sb)
284{
285 struct befs_inode_info *bi;
286 bi = (struct befs_inode_info *)kmem_cache_alloc(befs_inode_cachep,
287 SLAB_KERNEL);
288 if (!bi)
289 return NULL;
290 return &bi->vfs_inode;
291}
292
293static void
294befs_destroy_inode(struct inode *inode)
295{
296 kmem_cache_free(befs_inode_cachep, BEFS_I(inode));
297}
298
299static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
300{
301 struct befs_inode_info *bi = (struct befs_inode_info *) foo;
302
303 if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
304 SLAB_CTOR_CONSTRUCTOR) {
305 inode_init_once(&bi->vfs_inode);
306 }
307}
308
309static void
310befs_read_inode(struct inode *inode)
311{
312 struct buffer_head *bh = NULL;
313 befs_inode *raw_inode = NULL;
314
315 struct super_block *sb = inode->i_sb;
316 befs_sb_info *befs_sb = BEFS_SB(sb);
317 befs_inode_info *befs_ino = NULL;
318
319 befs_debug(sb, "---> befs_read_inode() " "inode = %lu", inode->i_ino);
320
321 befs_ino = BEFS_I(inode);
322
323 /* convert from vfs's inode number to befs's inode number */
324 befs_ino->i_inode_num = blockno2iaddr(sb, inode->i_ino);
325
326 befs_debug(sb, " real inode number [%u, %hu, %hu]",
327 befs_ino->i_inode_num.allocation_group,
328 befs_ino->i_inode_num.start, befs_ino->i_inode_num.len);
329
330 bh = befs_bread(sb, inode->i_ino);
331 if (!bh) {
332 befs_error(sb, "unable to read inode block - "
333 "inode = %lu", inode->i_ino);
334 goto unaquire_none;
335 }
336
337 raw_inode = (befs_inode *) bh->b_data;
338
339 befs_dump_inode(sb, raw_inode);
340
341 if (befs_check_inode(sb, raw_inode, inode->i_ino) != BEFS_OK) {
342 befs_error(sb, "Bad inode: %lu", inode->i_ino);
343 goto unaquire_bh;
344 }
345
346 inode->i_mode = (umode_t) fs32_to_cpu(sb, raw_inode->mode);
347
348 /*
349 * set uid and gid. But since current BeOS is single user OS, so
350 * you can change by "uid" or "gid" options.
351 */
352
353 inode->i_uid = befs_sb->mount_opts.use_uid ?
354 befs_sb->mount_opts.uid : (uid_t) fs32_to_cpu(sb, raw_inode->uid);
355 inode->i_gid = befs_sb->mount_opts.use_gid ?
356 befs_sb->mount_opts.gid : (gid_t) fs32_to_cpu(sb, raw_inode->gid);
357
358 inode->i_nlink = 1;
359
360 /*
361 * BEFS's time is 64 bits, but current VFS is 32 bits...
362 * BEFS don't have access time. Nor inode change time. VFS
363 * doesn't have creation time.
364 * Also, the lower 16 bits of the last_modified_time and
365 * create_time are just a counter to help ensure uniqueness
366 * for indexing purposes. (PFD, page 54)
367 */
368
369 inode->i_mtime.tv_sec =
370 fs64_to_cpu(sb, raw_inode->last_modified_time) >> 16;
371 inode->i_mtime.tv_nsec = 0; /* lower 16 bits are not a time */
372 inode->i_ctime = inode->i_mtime;
373 inode->i_atime = inode->i_mtime;
374 inode->i_blksize = befs_sb->block_size;
375
376 befs_ino->i_inode_num = fsrun_to_cpu(sb, raw_inode->inode_num);
377 befs_ino->i_parent = fsrun_to_cpu(sb, raw_inode->parent);
378 befs_ino->i_attribute = fsrun_to_cpu(sb, raw_inode->attributes);
379 befs_ino->i_flags = fs32_to_cpu(sb, raw_inode->flags);
380
381 if (S_ISLNK(inode->i_mode) && !(befs_ino->i_flags & BEFS_LONG_SYMLINK)){
382 inode->i_size = 0;
383 inode->i_blocks = befs_sb->block_size / VFS_BLOCK_SIZE;
384 strncpy(befs_ino->i_data.symlink, raw_inode->data.symlink,
385 BEFS_SYMLINK_LEN);
386 } else {
387 int num_blks;
388
389 befs_ino->i_data.ds =
390 fsds_to_cpu(sb, raw_inode->data.datastream);
391
392 num_blks = befs_count_blocks(sb, &befs_ino->i_data.ds);
393 inode->i_blocks =
394 num_blks * (befs_sb->block_size / VFS_BLOCK_SIZE);
395 inode->i_size = befs_ino->i_data.ds.size;
396 }
397
398 inode->i_mapping->a_ops = &befs_aops;
399
400 if (S_ISREG(inode->i_mode)) {
401 inode->i_fop = &befs_file_operations;
402 } else if (S_ISDIR(inode->i_mode)) {
403 inode->i_op = &befs_dir_inode_operations;
404 inode->i_fop = &befs_dir_operations;
405 } else if (S_ISLNK(inode->i_mode)) {
406 inode->i_op = &befs_symlink_inode_operations;
407 } else {
408 befs_error(sb, "Inode %lu is not a regular file, "
409 "directory or symlink. THAT IS WRONG! BeFS has no "
410 "on disk special files", inode->i_ino);
411 goto unaquire_bh;
412 }
413
414 brelse(bh);
415 befs_debug(sb, "<--- befs_read_inode()");
416 return;
417
418 unaquire_bh:
419 brelse(bh);
420
421 unaquire_none:
422 make_bad_inode(inode);
423 befs_debug(sb, "<--- befs_read_inode() - Bad inode");
424 return;
425}
426
427/* Initialize the inode cache. Called at fs setup.
428 *
429 * Taken from NFS implementation by Al Viro.
430 */
431static int
432befs_init_inodecache(void)
433{
434 befs_inode_cachep = kmem_cache_create("befs_inode_cache",
435 sizeof (struct befs_inode_info),
436 0, SLAB_RECLAIM_ACCOUNT,
437 init_once, NULL);
438 if (befs_inode_cachep == NULL) {
439 printk(KERN_ERR "befs_init_inodecache: "
440 "Couldn't initalize inode slabcache\n");
441 return -ENOMEM;
442 }
443
444 return 0;
445}
446
447/* Called at fs teardown.
448 *
449 * Taken from NFS implementation by Al Viro.
450 */
451static void
452befs_destroy_inodecache(void)
453{
454 if (kmem_cache_destroy(befs_inode_cachep))
455 printk(KERN_ERR "befs_destroy_inodecache: "
456 "not all structures were freed\n");
457}
458
459/*
460 * The inode of symbolic link is different to data stream.
461 * The data stream become link name. Unless the LONG_SYMLINK
462 * flag is set.
463 */
464static int
465befs_follow_link(struct dentry *dentry, struct nameidata *nd)
466{
467 befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
468 char *link;
469
470 if (befs_ino->i_flags & BEFS_LONG_SYMLINK) {
471 struct super_block *sb = dentry->d_sb;
472 befs_data_stream *data = &befs_ino->i_data.ds;
473 befs_off_t len = data->size;
474
475 befs_debug(sb, "Follow long symlink");
476
477 link = kmalloc(len, GFP_NOFS);
478 if (!link) {
479 link = ERR_PTR(-ENOMEM);
480 } else if (befs_read_lsymlink(sb, data, link, len) != len) {
481 kfree(link);
482 befs_error(sb, "Failed to read entire long symlink");
483 link = ERR_PTR(-EIO);
484 }
485 } else {
486 link = befs_ino->i_data.symlink;
487 }
488
489 nd_set_link(nd, link);
490 return 0;
491}
492
493static void befs_put_link(struct dentry *dentry, struct nameidata *nd)
494{
495 befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
496 if (befs_ino->i_flags & BEFS_LONG_SYMLINK) {
497 char *p = nd_get_link(nd);
498 if (!IS_ERR(p))
499 kfree(p);
500 }
501}
502
503/*
504 * UTF-8 to NLS charset convert routine
505 *
506 *
507 * Changed 8/10/01 by Will Dyson. Now use uni2char() / char2uni() rather than
508 * the nls tables directly
509 */
510
511static int
512befs_utf2nls(struct super_block *sb, const char *in,
513 int in_len, char **out, int *out_len)
514{
515 struct nls_table *nls = BEFS_SB(sb)->nls;
516 int i, o;
517 wchar_t uni;
518 int unilen, utflen;
519 char *result;
520 int maxlen = in_len; /* The utf8->nls conversion can't make more chars */
521
522 befs_debug(sb, "---> utf2nls()");
523
524 if (!nls) {
525 befs_error(sb, "befs_utf2nls called with no NLS table loaded");
526 return -EINVAL;
527 }
528
529 *out = result = kmalloc(maxlen, GFP_NOFS);
530 if (!*out) {
531 befs_error(sb, "befs_utf2nls() cannot allocate memory");
532 *out_len = 0;
533 return -ENOMEM;
534 }
535
536 for (i = o = 0; i < in_len; i += utflen, o += unilen) {
537
538 /* convert from UTF-8 to Unicode */
539 utflen = utf8_mbtowc(&uni, &in[i], in_len - i);
540 if (utflen < 0) {
541 goto conv_err;
542 }
543
544 /* convert from Unicode to nls */
545 unilen = nls->uni2char(uni, &result[o], in_len - o);
546 if (unilen < 0) {
547 goto conv_err;
548 }
549 }
550 result[o] = '\0';
551 *out_len = o;
552
553 befs_debug(sb, "<--- utf2nls()");
554
555 return o;
556
557 conv_err:
558 befs_error(sb, "Name using character set %s contains a character that "
559 "cannot be converted to unicode.", nls->charset);
560 befs_debug(sb, "<--- utf2nls()");
561 kfree(result);
562 return -EILSEQ;
563}
564
565/**
566 * befs_nls2utf - Convert NLS string to utf8 encodeing
567 * @sb: Superblock
568 * @src: Input string buffer in NLS format
569 * @srclen: Length of input string in bytes
570 * @dest: The output string in UTF8 format
571 * @destlen: Length of the output buffer
572 *
573 * Converts input string @src, which is in the format of the loaded NLS map,
574 * into a utf8 string.
575 *
576 * The destination string @dest is allocated by this function and the caller is
577 * responsible for freeing it with kfree()
578 *
579 * On return, *@destlen is the length of @dest in bytes.
580 *
581 * On success, the return value is the number of utf8 characters written to
582 * the output buffer @dest.
583 *
584 * On Failure, a negative number coresponding to the error code is returned.
585 */
586
587static int
588befs_nls2utf(struct super_block *sb, const char *in,
589 int in_len, char **out, int *out_len)
590{
591 struct nls_table *nls = BEFS_SB(sb)->nls;
592 int i, o;
593 wchar_t uni;
594 int unilen, utflen;
595 char *result;
596 int maxlen = 3 * in_len;
597
598 befs_debug(sb, "---> nls2utf()\n");
599
600 if (!nls) {
601 befs_error(sb, "befs_nls2utf called with no NLS table loaded.");
602 return -EINVAL;
603 }
604
605 *out = result = kmalloc(maxlen, GFP_NOFS);
606 if (!*out) {
607 befs_error(sb, "befs_nls2utf() cannot allocate memory");
608 *out_len = 0;
609 return -ENOMEM;
610 }
611
612 for (i = o = 0; i < in_len; i += unilen, o += utflen) {
613
614 /* convert from nls to unicode */
615 unilen = nls->char2uni(&in[i], in_len - i, &uni);
616 if (unilen < 0) {
617 goto conv_err;
618 }
619
620 /* convert from unicode to UTF-8 */
621 utflen = utf8_wctomb(&result[o], uni, 3);
622 if (utflen <= 0) {
623 goto conv_err;
624 }
625 }
626
627 result[o] = '\0';
628 *out_len = o;
629
630 befs_debug(sb, "<--- nls2utf()");
631
632 return i;
633
634 conv_err:
635 befs_error(sb, "Name using charecter set %s contains a charecter that "
636 "cannot be converted to unicode.", nls->charset);
637 befs_debug(sb, "<--- nls2utf()");
638 kfree(result);
639 return -EILSEQ;
640}
641
642/**
643 * Use the
644 *
645 */
646enum {
647 Opt_uid, Opt_gid, Opt_charset, Opt_debug, Opt_err,
648};
649
650static match_table_t befs_tokens = {
651 {Opt_uid, "uid=%d"},
652 {Opt_gid, "gid=%d"},
653 {Opt_charset, "iocharset=%s"},
654 {Opt_debug, "debug"},
655 {Opt_err, NULL}
656};
657
658static int
659parse_options(char *options, befs_mount_options * opts)
660{
661 char *p;
662 substring_t args[MAX_OPT_ARGS];
663 int option;
664
665 /* Initialize options */
666 opts->uid = 0;
667 opts->gid = 0;
668 opts->use_uid = 0;
669 opts->use_gid = 0;
670 opts->iocharset = NULL;
671 opts->debug = 0;
672
673 if (!options)
674 return 1;
675
676 while ((p = strsep(&options, ",")) != NULL) {
677 int token;
678 if (!*p)
679 continue;
680
681 token = match_token(p, befs_tokens, args);
682 switch (token) {
683 case Opt_uid:
684 if (match_int(&args[0], &option))
685 return 0;
686 if (option < 0) {
687 printk(KERN_ERR "BeFS: Invalid uid %d, "
688 "using default\n", option);
689 break;
690 }
691 opts->uid = option;
692 opts->use_uid = 1;
693 break;
694 case Opt_gid:
695 if (match_int(&args[0], &option))
696 return 0;
697 if (option < 0) {
698 printk(KERN_ERR "BeFS: Invalid gid %d, "
699 "using default\n", option);
700 break;
701 }
702 opts->gid = option;
703 opts->use_gid = 1;
704 break;
705 case Opt_charset:
706 kfree(opts->iocharset);
707 opts->iocharset = match_strdup(&args[0]);
708 if (!opts->iocharset) {
709 printk(KERN_ERR "BeFS: allocation failure for "
710 "iocharset string\n");
711 return 0;
712 }
713 break;
714 case Opt_debug:
715 opts->debug = 1;
716 break;
717 default:
718 printk(KERN_ERR "BeFS: Unrecognized mount option \"%s\" "
719 "or missing value\n", p);
720 return 0;
721 }
722 }
723 return 1;
724}
725
726/* This function has the responsibiltiy of getting the
727 * filesystem ready for unmounting.
728 * Basicly, we free everything that we allocated in
729 * befs_read_inode
730 */
731static void
732befs_put_super(struct super_block *sb)
733{
734 if (BEFS_SB(sb)->mount_opts.iocharset) {
735 kfree(BEFS_SB(sb)->mount_opts.iocharset);
736 BEFS_SB(sb)->mount_opts.iocharset = NULL;
737 }
738
739 if (BEFS_SB(sb)->nls) {
740 unload_nls(BEFS_SB(sb)->nls);
741 BEFS_SB(sb)->nls = NULL;
742 }
743
744 if (sb->s_fs_info) {
745 kfree(sb->s_fs_info);
746 sb->s_fs_info = NULL;
747 }
748 return;
749}
750
751/* Allocate private field of the superblock, fill it.
752 *
753 * Finish filling the public superblock fields
754 * Make the root directory
755 * Load a set of NLS translations if needed.
756 */
757static int
758befs_fill_super(struct super_block *sb, void *data, int silent)
759{
760 struct buffer_head *bh;
761 befs_sb_info *befs_sb;
762 befs_super_block *disk_sb;
763 struct inode *root;
764
765 const unsigned long sb_block = 0;
766 const off_t x86_sb_off = 512;
767
768 sb->s_fs_info = kmalloc(sizeof (*befs_sb), GFP_KERNEL);
769 if (sb->s_fs_info == NULL) {
770 printk(KERN_ERR
771 "BeFS(%s): Unable to allocate memory for private "
772 "portion of superblock. Bailing.\n", sb->s_id);
773 goto unaquire_none;
774 }
775 befs_sb = BEFS_SB(sb);
776 memset(befs_sb, 0, sizeof(befs_sb_info));
777
778 if (!parse_options((char *) data, &befs_sb->mount_opts)) {
779 befs_error(sb, "cannot parse mount options");
780 goto unaquire_priv_sbp;
781 }
782
783 befs_debug(sb, "---> befs_fill_super()");
784
785#ifndef CONFIG_BEFS_RW
786 if (!(sb->s_flags & MS_RDONLY)) {
787 befs_warning(sb,
788 "No write support. Marking filesystem read-only");
789 sb->s_flags |= MS_RDONLY;
790 }
791#endif /* CONFIG_BEFS_RW */
792
793 /*
794 * Set dummy blocksize to read super block.
795 * Will be set to real fs blocksize later.
796 *
797 * Linux 2.4.10 and later refuse to read blocks smaller than
798 * the hardsect size for the device. But we also need to read at
799 * least 1k to get the second 512 bytes of the volume.
800 * -WD 10-26-01
801 */
802 sb_min_blocksize(sb, 1024);
803
804 if (!(bh = sb_bread(sb, sb_block))) {
805 befs_error(sb, "unable to read superblock");
806 goto unaquire_priv_sbp;
807 }
808
809 /* account for offset of super block on x86 */
810 disk_sb = (befs_super_block *) bh->b_data;
811 if ((le32_to_cpu(disk_sb->magic1) == BEFS_SUPER_MAGIC1) ||
812 (be32_to_cpu(disk_sb->magic1) == BEFS_SUPER_MAGIC1)) {
813 befs_debug(sb, "Using PPC superblock location");
814 } else {
815 befs_debug(sb, "Using x86 superblock location");
816 disk_sb =
817 (befs_super_block *) ((void *) bh->b_data + x86_sb_off);
818 }
819
820 if (befs_load_sb(sb, disk_sb) != BEFS_OK)
821 goto unaquire_bh;
822
823 befs_dump_super_block(sb, disk_sb);
824
825 brelse(bh);
826
827 if (befs_check_sb(sb) != BEFS_OK)
828 goto unaquire_priv_sbp;
829
830 if( befs_sb->num_blocks > ~((sector_t)0) ) {
831 befs_error(sb, "blocks count: %Lu "
832 "is larger than the host can use",
833 befs_sb->num_blocks);
834 goto unaquire_priv_sbp;
835 }
836
837 /*
838 * set up enough so that it can read an inode
839 * Fill in kernel superblock fields from private sb
840 */
841 sb->s_magic = BEFS_SUPER_MAGIC;
842 /* Set real blocksize of fs */
843 sb_set_blocksize(sb, (ulong) befs_sb->block_size);
844 sb->s_op = (struct super_operations *) &befs_sops;
845 root = iget(sb, iaddr2blockno(sb, &(befs_sb->root_dir)));
846 sb->s_root = d_alloc_root(root);
847 if (!sb->s_root) {
848 iput(root);
849 befs_error(sb, "get root inode failed");
850 goto unaquire_priv_sbp;
851 }
852
853 /* load nls library */
854 if (befs_sb->mount_opts.iocharset) {
855 befs_debug(sb, "Loading nls: %s",
856 befs_sb->mount_opts.iocharset);
857 befs_sb->nls = load_nls(befs_sb->mount_opts.iocharset);
858 if (!befs_sb->nls) {
859 befs_warning(sb, "Cannot load nls %s"
860 " loading default nls",
861 befs_sb->mount_opts.iocharset);
862 befs_sb->nls = load_nls_default();
863 }
864 /* load default nls if none is specified in mount options */
865 } else {
866 befs_debug(sb, "Loading default nls");
867 befs_sb->nls = load_nls_default();
868 }
869
870 return 0;
871/*****************/
872 unaquire_bh:
873 brelse(bh);
874
875 unaquire_priv_sbp:
876 kfree(sb->s_fs_info);
877
878 unaquire_none:
879 sb->s_fs_info = NULL;
880 return -EINVAL;
881}
882
883static int
884befs_remount(struct super_block *sb, int *flags, char *data)
885{
886 if (!(*flags & MS_RDONLY))
887 return -EINVAL;
888 return 0;
889}
890
891static int
892befs_statfs(struct super_block *sb, struct kstatfs *buf)
893{
894
895 befs_debug(sb, "---> befs_statfs()");
896
897 buf->f_type = BEFS_SUPER_MAGIC;
898 buf->f_bsize = sb->s_blocksize;
899 buf->f_blocks = BEFS_SB(sb)->num_blocks;
900 buf->f_bfree = BEFS_SB(sb)->num_blocks - BEFS_SB(sb)->used_blocks;
901 buf->f_bavail = buf->f_bfree;
902 buf->f_files = 0; /* UNKNOWN */
903 buf->f_ffree = 0; /* UNKNOWN */
904 buf->f_namelen = BEFS_NAME_LEN;
905
906 befs_debug(sb, "<--- befs_statfs()");
907
908 return 0;
909}
910
911static struct super_block *
912befs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name,
913 void *data)
914{
915 return get_sb_bdev(fs_type, flags, dev_name, data, befs_fill_super);
916}
917
918static struct file_system_type befs_fs_type = {
919 .owner = THIS_MODULE,
920 .name = "befs",
921 .get_sb = befs_get_sb,
922 .kill_sb = kill_block_super,
923 .fs_flags = FS_REQUIRES_DEV,
924};
925
926static int __init
927init_befs_fs(void)
928{
929 int err;
930
931 printk(KERN_INFO "BeFS version: %s\n", BEFS_VERSION);
932
933 err = befs_init_inodecache();
934 if (err)
935 goto unaquire_none;
936
937 err = register_filesystem(&befs_fs_type);
938 if (err)
939 goto unaquire_inodecache;
940
941 return 0;
942
943unaquire_inodecache:
944 befs_destroy_inodecache();
945
946unaquire_none:
947 return err;
948}
949
950static void __exit
951exit_befs_fs(void)
952{
953 befs_destroy_inodecache();
954
955 unregister_filesystem(&befs_fs_type);
956}
957
958/*
959Macros that typecheck the init and exit functions,
960ensures that they are called at init and cleanup,
961and eliminates warnings about unused functions.
962*/
963module_init(init_befs_fs)
964module_exit(exit_befs_fs)
diff --git a/fs/befs/super.c b/fs/befs/super.c
new file mode 100644
index 000000000000..4557acbac528
--- /dev/null
+++ b/fs/befs/super.c
@@ -0,0 +1,112 @@
1/*
2 * super.c
3 *
4 * Copyright (C) 2001-2002 Will Dyson <will_dyson@pobox.com>
5 *
6 * Licensed under the GNU GPL. See the file COPYING for details.
7 *
8 */
9
10#include <linux/fs.h>
11
12#include "befs.h"
13#include "super.h"
14#include "endian.h"
15
16/**
17 * load_befs_sb -- Read from disk and properly byteswap all the fields
18 * of the befs superblock
19 *
20 *
21 *
22 *
23 */
24int
25befs_load_sb(struct super_block *sb, befs_super_block * disk_sb)
26{
27 befs_sb_info *befs_sb = BEFS_SB(sb);
28
29 /* Check the byte order of the filesystem */
30 if (le32_to_cpu(disk_sb->fs_byte_order) == BEFS_BYTEORDER_NATIVE)
31 befs_sb->byte_order = BEFS_BYTESEX_LE;
32 else if (be32_to_cpu(disk_sb->fs_byte_order) == BEFS_BYTEORDER_NATIVE)
33 befs_sb->byte_order = BEFS_BYTESEX_BE;
34
35 befs_sb->magic1 = fs32_to_cpu(sb, disk_sb->magic1);
36 befs_sb->magic2 = fs32_to_cpu(sb, disk_sb->magic2);
37 befs_sb->magic3 = fs32_to_cpu(sb, disk_sb->magic3);
38 befs_sb->block_size = fs32_to_cpu(sb, disk_sb->block_size);
39 befs_sb->block_shift = fs32_to_cpu(sb, disk_sb->block_shift);
40 befs_sb->num_blocks = fs64_to_cpu(sb, disk_sb->num_blocks);
41 befs_sb->used_blocks = fs64_to_cpu(sb, disk_sb->used_blocks);
42 befs_sb->inode_size = fs32_to_cpu(sb, disk_sb->inode_size);
43
44 befs_sb->blocks_per_ag = fs32_to_cpu(sb, disk_sb->blocks_per_ag);
45 befs_sb->ag_shift = fs32_to_cpu(sb, disk_sb->ag_shift);
46 befs_sb->num_ags = fs32_to_cpu(sb, disk_sb->num_ags);
47
48 befs_sb->log_blocks = fsrun_to_cpu(sb, disk_sb->log_blocks);
49 befs_sb->log_start = fs64_to_cpu(sb, disk_sb->log_start);
50 befs_sb->log_end = fs64_to_cpu(sb, disk_sb->log_end);
51
52 befs_sb->root_dir = fsrun_to_cpu(sb, disk_sb->root_dir);
53 befs_sb->indices = fsrun_to_cpu(sb, disk_sb->indices);
54 befs_sb->nls = NULL;
55
56 return BEFS_OK;
57}
58
59int
60befs_check_sb(struct super_block *sb)
61{
62 befs_sb_info *befs_sb = BEFS_SB(sb);
63
64 /* Check magic headers of super block */
65 if ((befs_sb->magic1 != BEFS_SUPER_MAGIC1)
66 || (befs_sb->magic2 != BEFS_SUPER_MAGIC2)
67 || (befs_sb->magic3 != BEFS_SUPER_MAGIC3)) {
68 befs_error(sb, "invalid magic header");
69 return BEFS_ERR;
70 }
71
72 /*
73 * Check blocksize of BEFS.
74 *
75 * Blocksize of BEFS is 1024, 2048, 4096 or 8192.
76 */
77
78 if ((befs_sb->block_size != 1024)
79 && (befs_sb->block_size != 2048)
80 && (befs_sb->block_size != 4096)
81 && (befs_sb->block_size != 8192)) {
82 befs_error(sb, "invalid blocksize: %u", befs_sb->block_size);
83 return BEFS_ERR;
84 }
85
86 if (befs_sb->block_size > PAGE_SIZE) {
87 befs_error(sb, "blocksize(%u) cannot be larger"
88 "than system pagesize(%lu)", befs_sb->block_size,
89 PAGE_SIZE);
90 return BEFS_ERR;
91 }
92
93 /*
94 * block_shift and block_size encode the same information
95 * in different ways as a consistency check.
96 */
97
98 if ((1 << befs_sb->block_shift) != befs_sb->block_size) {
99 befs_error(sb, "block_shift disagrees with block_size. "
100 "Corruption likely.");
101 return BEFS_ERR;
102 }
103
104 if (befs_sb->log_start != befs_sb->log_end) {
105 befs_error(sb, "Filesystem not clean! There are blocks in the "
106 "journal. You must boot into BeOS and mount this volume "
107 "to make it clean.");
108 return BEFS_ERR;
109 }
110
111 return BEFS_OK;
112}
diff --git a/fs/befs/super.h b/fs/befs/super.h
new file mode 100644
index 000000000000..dc4556376a22
--- /dev/null
+++ b/fs/befs/super.h
@@ -0,0 +1,8 @@
1/*
2 * super.h
3 */
4
5int befs_load_sb(struct super_block *sb, befs_super_block * disk_sb);
6
7int befs_check_sb(struct super_block *sb);
8