summaryrefslogtreecommitdiff
path: root/other/ecfs
diff options
context:
space:
mode:
authorRoot THC2026-02-24 12:42:47 +0000
committerRoot THC2026-02-24 12:42:47 +0000
commitc9cbeced5b3f2bdd7407e29c0811e65954132540 (patch)
treeaefc355416b561111819de159ccbd86c3004cf88 /other/ecfs
parent073fe4bf9fca6bf40cef2886d75df832ef4b6fca (diff)
initial
Diffstat (limited to 'other/ecfs')
-rw-r--r--other/ecfs/CHANGES157
-rw-r--r--other/ecfs/Makefile23
-rw-r--r--other/ecfs/README46
-rw-r--r--other/ecfs/balloc.c805
-rw-r--r--other/ecfs/balloc.obin0 -> 6800 bytes
-rw-r--r--other/ecfs/bitmap.c27
-rw-r--r--other/ecfs/bitmap.obin0 -> 1124 bytes
-rw-r--r--other/ecfs/dir.c182
-rw-r--r--other/ecfs/dir.obin0 -> 3104 bytes
-rw-r--r--other/ecfs/ecfs.obin0 -> 48118 bytes
-rw-r--r--other/ecfs/file.c233
-rw-r--r--other/ecfs/file.obin0 -> 3168 bytes
-rw-r--r--other/ecfs/fsync.c54
-rw-r--r--other/ecfs/fsync.obin0 -> 1308 bytes
-rw-r--r--other/ecfs/ialloc.c550
-rw-r--r--other/ecfs/ialloc.obin0 -> 5356 bytes
-rw-r--r--other/ecfs/inode.c1329
-rw-r--r--other/ecfs/inode.obin0 -> 11924 bytes
-rw-r--r--other/ecfs/ioctl.c91
-rw-r--r--other/ecfs/ioctl.obin0 -> 1972 bytes
-rw-r--r--other/ecfs/namei.c824
-rw-r--r--other/ecfs/namei.obin0 -> 9216 bytes
-rw-r--r--other/ecfs/rc4.c76
-rw-r--r--other/ecfs/rc4.h20
-rw-r--r--other/ecfs/rc4.obin0 -> 1272 bytes
-rw-r--r--other/ecfs/repl.pl26
-rw-r--r--other/ecfs/start-ecfs29
-rw-r--r--other/ecfs/super.c817
-rw-r--r--other/ecfs/super.obin0 -> 12580 bytes
-rw-r--r--other/ecfs/symlink.c38
-rw-r--r--other/ecfs/symlink.obin0 -> 1316 bytes
-rw-r--r--other/ecfs/transform53
32 files changed, 5380 insertions, 0 deletions
diff --git a/other/ecfs/CHANGES b/other/ecfs/CHANGES
new file mode 100644
index 0000000..aa5aaf0
--- /dev/null
+++ b/other/ecfs/CHANGES
@@ -0,0 +1,157 @@
1Changes from version 0.5a to version 0.5b
2=========================================
3 - Now that we have sysctl(), the immutable flag cannot be changed when
4 the system is running at security level > 0.
5 - Some cleanups in the code.
6 - More consistency checks on directories.
7 - The ext2.diff patch from Tom May <ftom@netcom.com> has been
8 integrated. This patch replaces expensive "/" and "%" with
9 cheap ">>" and "&" where possible.
10
11Changes from version 0.5 to version 0.5a
12========================================
13 - Zero the partial block following the end of the file when a file
14 is truncated.
15 - Dates updated in the copyright.
16 - More checks when the filesystem is mounted: the count of blocks,
17 fragments, and inodes per group is checked against the block size.
18 - The buffers used by the error routines are now static variables, to
19 avoid using space on the kernel stack, as requested by Linus.
20 - Some cleanups in the error messages (some versions of syslog contain
21 a bug which truncates an error message if it contains '\n').
22 - Check that no data can be written to a file past the 2GB limit.
23 - The famous readdir() bug has been fixed by Stephen Tweedie.
24 - Added a revision level in the superblock.
25 - Full support for O_SYNC flag of the open system call.
26 - New mount options: `resuid=#uid' and `resgid=#gid'. `resuid' causes
27 ext2fs to consider user #uid like root for the reserved blocks.
28 `resgid' acts the same way with group #gid. New fields in the
29 superblock contain default values for resuid and resgid and can
30 be modified by tune2fs.
31 Idea comes from Rene Cougnenc <cougnenc@renux.frmug.fr.net>.
32 - New mount options: `bsddf' and `minixdf'. `bsddf' causes ext2fs
33 to remove the blocks used for FS structures from the total block
34 count in statfs. With `minixdf', ext2fs mimics Minix behavior
35 in statfs (i.e. it returns the total number of blocks on the
36 partition). This is intended to make bde happy :-)
37 - New file attributes:
38 - Immutable files cannot be modified. Data cannot be written to
39 these files. They cannot be removed, renamed and new links cannot
40 be created. Even root cannot modify the files. He has to remove
41 the immutable attribute first.
42 - Append-only files: can only be written in append-mode when writing.
43 They cannot be removed, renamed and new links cannot be created.
44 Note: files may only be added to an append-only directory.
45 - No-dump files: the attribute is not used by the kernel. My port
46 of dump uses it to avoid backing up files which are not important.
47 - New check in ext2_check_dir_entry: the inode number is checked.
48 - Support for big file systems: the copy of the FS descriptor is now
49 dynamically allocated (previous versions used a fixed size array).
50 This allows to mount 2GB+ FS.
51 - Reorganization of the ext2_inode structure to allow other operating
52 systems to create specific fields if they use ext2fs as their native
53 file system. Currently, ext2fs is only implemented in Linux but
54 will soon be part of Gnu Hurd and of Masix.
55
56Changes from version 0.4b to version 0.5
57========================================
58 - New superblock fields: s_lastcheck and s_checkinterval added
59 by Uwe Ohse <uwe@tirka.gun.de> to implement timedependent checks
60 of the file system
61 - Real random numbers for secure rm added by Pierre del Perugia
62 <delperug@gla.ecoledoc.ibp.fr>
63 - The mount warnings related to the state of a fs are not printed
64 if the fs is mounted read-only, idea by Nick Holloway
65 <alfie@dcs.warwick.ac.uk>
66
67Changes from version 0.4a to version 0.4b
68=========================================
69 - Copyrights changed to include the name of my laboratory.
70 - Clean up of balloc.c and ialloc.c.
71 - More consistency checks.
72 - Block preallocation added by Stephen Tweedie.
73 - Direct reads of directories disallowed.
74 - Readahead implemented in readdir by Stephen Tweedie.
75 - Bugs in block and inodes allocation fixed.
76 - Readahead implemented in ext2_find_entry by Chip Salzenberg.
77 - New mount options:
78 `check=none|normal|strict'
79 `debug'
80 `errors=continue|remount-ro|panic'
81 `grpid', `bsdgroups'
82 `nocheck'
83 `nogrpid', `sysvgroups'
84 - truncate() now tries to deallocate contiguous blocks in a single call
85 to ext2_free_blocks().
86 - lots of cosmetic changes.
87
88Changes from version 0.4 to version 0.4a
89========================================
90 - the `sync' option support is now complete. Version 0.4 was not
91 supporting it when truncating a file. I have tested the synchronous
92 writes and they work but they make the system very slow :-( I have
93 to work again on this to make it faster.
94 - when detecting an error on a mounted filesystem, version 0.4 used
95 to try to write a flag in the super block even if the filesystem had
96 been mounted read-only. This is fixed.
97 - the `sb=#' option now causes the kernel code to use the filesystem
98 descriptors located at block #+1. Version 0.4 used the superblock
99 backup located at block # but used the main copy of the descriptors.
100 - a new file attribute `S' is supported. This attribute causes
101 synchronous writes but is applied to a file not to the entire file
102 system (thanks to Michael Kraehe <kraehe@bakunin.north.de> for
103 suggesting it).
104 - the directory cache is inhibited by default. The cache management
105 code seems to be buggy and I have to look at it carefully before
106 using it again.
107 - deleting a file with the `s' attribute (secure deletion) causes its
108 blocks to be overwritten with random values not with zeros (thanks to
109 Michael A. Griffith <grif@cs.ucr.edu> for suggesting it).
110 - lots of cosmetic changes have been made.
111
112Changes from version 0.3 to version 0.4
113=======================================
114 - Three new mount options are supported: `check', `sync' and `sb=#'.
115 `check' tells the kernel code to make more consistency checks
116 when the file system is mounted. Currently, the kernel code checks
117 that the blocks and inodes bitmaps are consistent with the free
118 blocks and inodes counts. More checks will be added in future
119 releases.
120 `sync' tells the kernel code to use synchronous writes when updating
121 an inode, a bitmap, a directory entry or an indirect block. This
122 can make the file system much slower but can be a big win for files
123 recovery in case of a crash (and we can now say to the BSD folks
124 that Linux also supports synchronous updates :-).
125 `sb=#' tells the kernel code to use an alternate super block instead
126 of its master copy. `#' is the number of the block (counted in
127 1024 bytes blocks) which contains the alternate super block.
128 An ext2 file system typically contains backups of the super block
129 at blocks 8193, 16385, and so on.
130 - I have change the meaning of the valid flag used by e2fsck. it
131 now contains the state of the file system. If the kernel code
132 detects an inconsistency while the file system is mounted, it flags
133 it as erroneous and e2fsck will detect that on next run.
134 - The super block now contains a mount counter. This counter is
135 incremented each time the file system is mounted read/write. When
136 this counter becomes bigger than a maximal mount counts (also stored
137 in the super block), e2fsck checks the file system, even if it had
138 been unmounted cleanly, and resets this counter to 0.
139 - File attributes are now supported. One can associate a set of
140 attributes to a file. Three attributes are defined:
141 `c': the file is marked for automatic compression,
142 `s': the file is marked for secure deletion: when the file is
143 deleted, its blocks are zeroed and written back to the disk,
144 `u': the file is marked for undeletion: when the file is deleted,
145 its contents are saved to allow a future undeletion.
146 Currently, only the `s' attribute is implemented in the kernel
147 code. Support for the other attributes will be added in a future
148 release.
149 - a few bugs related to times updates have been fixed by Bruce
150 Evans and me.
151 - a bug related to the links count of deleted inodes has been fixed.
152 Previous versions used to keep the links count set to 1 when a file
153 was deleted. The new version now sets links_count to 0 when deleting
154 the last link.
155 - a race condition when deallocating an inode has been fixed by
156 Stephen Tweedie.
157
diff --git a/other/ecfs/Makefile b/other/ecfs/Makefile
new file mode 100644
index 0000000..7623ef0
--- /dev/null
+++ b/other/ecfs/Makefile
@@ -0,0 +1,23 @@
1CFLAGS=-m486 -c -O2 -Wall -DMODULE -D__KERNEL__ -I/usr/src/linux/include
2CC=cc
3LD=ld
4
5.SUFFIXES: .o .c
6
7.c.o:
8 $(CC) $(CFLAGS) $<
9
10OBJ = balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
11 ioctl.o namei.o super.o symlink.o rc4.o
12
13all: ecfs.o
14
15ecfs.o: ${OBJ}
16 $(LD) -r ${OBJ} -o $@
17
18clean:
19 rm -rf *.o
20
21
22
23
diff --git a/other/ecfs/README b/other/ecfs/README
new file mode 100644
index 0000000..0936411
--- /dev/null
+++ b/other/ecfs/README
@@ -0,0 +1,46 @@
1for starters
2============
3
4!!!
5
6Do not use ECFS. Use it for testing purposes only!
7
8!!!
9
10
111. Compile ecfs for your current kernel:
12
13 $ cd /path/to/ecfs; make
14
152. Install
16
17 # cp ecfs.o /lib/modules/`uname -r`/fs
18
193. Start ECFS
20
21 # ./start-ecfs
22
23 Enter your key (at least 8 byte) and ECFS is loaded.
24
254. Use ECFS
26
27 # mount -t ecfs /dev/fd0 /mnt
28
29 All read/write to mnt are now crypted. You can use ext2tools
30 to handle ECFS partitions, like fsck.ext2 etc. Its Ext2 after all!
31 ECFS cant handle mmap(), so its not for your root-FS, its even
32 in development, so send feedback to stealth@segfault.net.
33
34
35 !!!
36
37 Since its in development, your data may be unreadable
38 when using ECFS.
39 Don't blame me, use tcfs or so if you want well-tested
40 CFS.
41
42 !!!
43
44
45Stealth
46
diff --git a/other/ecfs/balloc.c b/other/ecfs/balloc.c
new file mode 100644
index 0000000..401b2c5
--- /dev/null
+++ b/other/ecfs/balloc.c
@@ -0,0 +1,805 @@
1/*
2 * linux/fs/ecfs/balloc.c
3 *
4 * Copyright (C) 1992, 1993, 1994, 1995
5 * Remy Card (card@masi.ibp.fr)
6 * Laboratoire MASI - Institut Blaise Pascal
7 * Universite Pierre et Marie Curie (Paris VI)
8 *
9 * Enhanced block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
10 * Big-endian to little-endian byte-swapping/bitmaps by
11 * David S. Miller (davem@caip.rutgers.edu), 1995
12 */
13
14#include <linux/config.h>
15#include <linux/fs_ecfs.h>
16#include <linux/ecfs_fs.h>
17#include <linux/locks.h>
18//#include <linux/quotaops.h>
19
20#define ecfs_find_first_zero_bit find_first_zero_bit
21#define ecfs_clear_bit __test_and_clear_bit
22#define ecfs_set_bit __test_and_set_bit
23#define ecfs_find_next_zero_bit find_next_zero_bit
24#define ecfs_test_bit test_bit
25
26// blubber
27#ifndef KERNEL_VERSION
28#define KERNEL_VERSION(x,y,z) (x,y,z)
29#endif
30
31/*
32 * balloc.c contains the blocks allocation and deallocation routines
33 */
34
35/*
36 * The free blocks are managed by bitmaps. A file system contains several
37 * blocks groups. Each group contains 1 bitmap block for blocks, 1 bitmap
38 * block for inodes, N blocks for the inode table and data blocks.
39 *
40 * The file system contains group descriptors which are located after the
41 * super block. Each descriptor contains the number of the bitmap block and
42 * the free blocks count in the block. The descriptors are loaded in memory
43 * when a file system is mounted (see ecfs_read_super).
44 */
45
46
47#define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1)
48
49struct ecfs_group_desc * ecfs_get_group_desc(struct super_block * sb,
50 unsigned int block_group,
51 struct buffer_head ** bh)
52{
53 unsigned long group_desc;
54 unsigned long desc;
55 struct ecfs_group_desc * gdp;
56
57 if (block_group >= sb->u.ecfs_sb.s_groups_count) {
58 ecfs_error (sb, "ecfs_get_group_desc",
59 "block_group >= groups_count - "
60 "block_group = %d, groups_count = %lu",
61 block_group, sb->u.ecfs_sb.s_groups_count);
62
63 return NULL;
64 }
65
66 group_desc = block_group / ECFS_DESC_PER_BLOCK(sb);
67 desc = block_group % ECFS_DESC_PER_BLOCK(sb);
68 if (!sb->u.ecfs_sb.s_group_desc[group_desc]) {
69 ecfs_error (sb, "ecfs_get_group_desc",
70 "Group descriptor not loaded - "
71 "block_group = %d, group_desc = %lu, desc = %lu",
72 block_group, group_desc, desc);
73 return NULL;
74 }
75
76 gdp = (struct ecfs_group_desc *)
77 sb->u.ecfs_sb.s_group_desc[group_desc]->b_data;
78 if (bh)
79 *bh = sb->u.ecfs_sb.s_group_desc[group_desc];
80 return gdp + desc;
81}
82
83/*
84 * Read the bitmap for a given block_group, reading into the specified
85 * slot in the superblock's bitmap cache.
86 *
87 * Return >=0 on success or a -ve error code.
88 */
89
90static int read_block_bitmap (struct super_block * sb,
91 unsigned int block_group,
92 unsigned long bitmap_nr)
93{
94 struct ecfs_group_desc * gdp;
95 struct buffer_head * bh = NULL;
96 int retval = -EIO;
97
98 gdp = ecfs_get_group_desc (sb, block_group, NULL);
99 if (!gdp)
100 goto error_out;
101 retval = 0;
102 bh = bread (sb->s_dev, le32_to_cpu(gdp->bg_block_bitmap), sb->s_blocksize);
103 if (!bh) {
104 ecfs_error (sb, "read_block_bitmap",
105 "Cannot read block bitmap - "
106 "block_group = %d, block_bitmap = %lu",
107 block_group, (unsigned long) gdp->bg_block_bitmap);
108 retval = -EIO;
109 }
110 /*
111 * On IO error, just leave a zero in the superblock's block pointer for
112 * this group. The IO will be retried next time.
113 */
114error_out:
115 sb->u.ecfs_sb.s_block_bitmap_number[bitmap_nr] = block_group;
116 sb->u.ecfs_sb.s_block_bitmap[bitmap_nr] = bh;
117 return retval;
118}
119
120/*
121 * load_block_bitmap loads the block bitmap for a blocks group
122 *
123 * It maintains a cache for the last bitmaps loaded. This cache is managed
124 * with a LRU algorithm.
125 *
126 * Notes:
127 * 1/ There is one cache per mounted file system.
128 * 2/ If the file system contains less than ECFS_MAX_GROUP_LOADED groups,
129 * this function reads the bitmap without maintaining a LRU cache.
130 *
131 * Return the slot used to store the bitmap, or a -ve error code.
132 */
133static int __load_block_bitmap (struct super_block * sb,
134 unsigned int block_group)
135{
136 int i, j, retval = 0;
137 unsigned long block_bitmap_number;
138 struct buffer_head * block_bitmap;
139
140 if (block_group >= sb->u.ecfs_sb.s_groups_count)
141 ecfs_panic (sb, "load_block_bitmap",
142 "block_group >= groups_count - "
143 "block_group = %d, groups_count = %lu",
144 block_group, sb->u.ecfs_sb.s_groups_count);
145
146 if (sb->u.ecfs_sb.s_groups_count <= ECFS_MAX_GROUP_LOADED) {
147 if (sb->u.ecfs_sb.s_block_bitmap[block_group]) {
148 if (sb->u.ecfs_sb.s_block_bitmap_number[block_group] ==
149 block_group)
150 return block_group;
151 ecfs_error (sb, "__load_block_bitmap",
152 "block_group != block_bitmap_number");
153 }
154 retval = read_block_bitmap (sb, block_group, block_group);
155 if (retval < 0)
156 return retval;
157 return block_group;
158 }
159
160 for (i = 0; i < sb->u.ecfs_sb.s_loaded_block_bitmaps &&
161 sb->u.ecfs_sb.s_block_bitmap_number[i] != block_group; i++)
162 ;
163 if (i < sb->u.ecfs_sb.s_loaded_block_bitmaps &&
164 sb->u.ecfs_sb.s_block_bitmap_number[i] == block_group) {
165 block_bitmap_number = sb->u.ecfs_sb.s_block_bitmap_number[i];
166 block_bitmap = sb->u.ecfs_sb.s_block_bitmap[i];
167 for (j = i; j > 0; j--) {
168 sb->u.ecfs_sb.s_block_bitmap_number[j] =
169 sb->u.ecfs_sb.s_block_bitmap_number[j - 1];
170 sb->u.ecfs_sb.s_block_bitmap[j] =
171 sb->u.ecfs_sb.s_block_bitmap[j - 1];
172 }
173 sb->u.ecfs_sb.s_block_bitmap_number[0] = block_bitmap_number;
174 sb->u.ecfs_sb.s_block_bitmap[0] = block_bitmap;
175
176 /*
177 * There's still one special case here --- if block_bitmap == 0
178 * then our last attempt to read the bitmap failed and we have
179 * just ended up caching that failure. Try again to read it.
180 */
181 if (!block_bitmap)
182 retval = read_block_bitmap (sb, block_group, 0);
183 } else {
184 if (sb->u.ecfs_sb.s_loaded_block_bitmaps < ECFS_MAX_GROUP_LOADED)
185 sb->u.ecfs_sb.s_loaded_block_bitmaps++;
186 else
187 brelse (sb->u.ecfs_sb.s_block_bitmap[ECFS_MAX_GROUP_LOADED - 1]);
188 for (j = sb->u.ecfs_sb.s_loaded_block_bitmaps - 1; j > 0; j--) {
189 sb->u.ecfs_sb.s_block_bitmap_number[j] =
190 sb->u.ecfs_sb.s_block_bitmap_number[j - 1];
191 sb->u.ecfs_sb.s_block_bitmap[j] =
192 sb->u.ecfs_sb.s_block_bitmap[j - 1];
193 }
194 retval = read_block_bitmap (sb, block_group, 0);
195 }
196 return retval;
197}
198
199/*
200 * Load the block bitmap for a given block group. First of all do a couple
201 * of fast lookups for common cases and then pass the request onto the guts
202 * of the bitmap loader.
203 *
204 * Return the slot number of the group in the superblock bitmap cache's on
205 * success, or a -ve error code.
206 *
207 * There is still one inconsistency here --- if the number of groups in this
208 * filesystems is <= ECFS_MAX_GROUP_LOADED, then we have no way of
209 * differentiating between a group for which we have never performed a bitmap
210 * IO request, and a group for which the last bitmap read request failed.
211 */
212static inline int load_block_bitmap (struct super_block * sb,
213 unsigned int block_group)
214{
215 int slot;
216
217 /*
218 * Do the lookup for the slot. First of all, check if we're asking
219 * for the same slot as last time, and did we succeed that last time?
220 */
221 if (sb->u.ecfs_sb.s_loaded_block_bitmaps > 0 &&
222 sb->u.ecfs_sb.s_block_bitmap_number[0] == block_group &&
223 sb->u.ecfs_sb.s_block_bitmap[0]) {
224 return 0;
225 }
226 /*
227 * Or can we do a fast lookup based on a loaded group on a filesystem
228 * small enough to be mapped directly into the superblock?
229 */
230 else if (sb->u.ecfs_sb.s_groups_count <= ECFS_MAX_GROUP_LOADED &&
231 sb->u.ecfs_sb.s_block_bitmap_number[block_group] == block_group &&
232 sb->u.ecfs_sb.s_block_bitmap[block_group]) {
233 slot = block_group;
234 }
235 /*
236 * If not, then do a full lookup for this block group.
237 */
238 else {
239 slot = __load_block_bitmap (sb, block_group);
240 }
241
242 /*
243 * <0 means we just got an error
244 */
245 if (slot < 0)
246 return slot;
247
248 /*
249 * If it's a valid slot, we may still have cached a previous IO error,
250 * in which case the bh in the superblock cache will be zero.
251 */
252 if (!sb->u.ecfs_sb.s_block_bitmap[slot])
253 return -EIO;
254
255 /*
256 * Must have been read in OK to get this far.
257 */
258 return slot;
259}
260
261void ecfs_free_blocks (struct inode * inode, unsigned long block,
262 unsigned long count)
263{
264 struct buffer_head * bh;
265 struct buffer_head * bh2;
266 unsigned long block_group;
267 unsigned long bit;
268 unsigned long i;
269 int bitmap_nr;
270 unsigned long overflow;
271 struct super_block * sb;
272 struct ecfs_group_desc * gdp;
273 struct ecfs_super_block * es;
274
275 sb = inode->i_sb;
276 if (!sb) {
277 printk ("ecfs_free_blocks: nonexistent device");
278 return;
279 }
280 lock_super (sb);
281 es = sb->u.ecfs_sb.s_es;
282 if (block < le32_to_cpu(es->s_first_data_block) ||
283 (block + count) > le32_to_cpu(es->s_blocks_count)) {
284 ecfs_error (sb, "ecfs_free_blocks",
285 "Freeing blocks not in datazone - "
286 "block = %lu, count = %lu", block, count);
287 goto error_return;
288 }
289
290 ecfs_debug ("freeing block %lu\n", block);
291
292do_more:
293 overflow = 0;
294 block_group = (block - le32_to_cpu(es->s_first_data_block)) /
295 ECFS_BLOCKS_PER_GROUP(sb);
296 bit = (block - le32_to_cpu(es->s_first_data_block)) %
297 ECFS_BLOCKS_PER_GROUP(sb);
298 /*
299 * Check to see if we are freeing blocks across a group
300 * boundary.
301 */
302 if (bit + count > ECFS_BLOCKS_PER_GROUP(sb)) {
303 overflow = bit + count - ECFS_BLOCKS_PER_GROUP(sb);
304 count -= overflow;
305 }
306 bitmap_nr = load_block_bitmap (sb, block_group);
307 if (bitmap_nr < 0)
308 goto error_return;
309
310 bh = sb->u.ecfs_sb.s_block_bitmap[bitmap_nr];
311 gdp = ecfs_get_group_desc (sb, block_group, &bh2);
312 if (!gdp)
313 goto error_return;
314
315 if (in_range (le32_to_cpu(gdp->bg_block_bitmap), block, count) ||
316 in_range (le32_to_cpu(gdp->bg_inode_bitmap), block, count) ||
317 in_range (block, le32_to_cpu(gdp->bg_inode_table),
318 sb->u.ecfs_sb.s_itb_per_group) ||
319 in_range (block + count - 1, le32_to_cpu(gdp->bg_inode_table),
320 sb->u.ecfs_sb.s_itb_per_group))
321 ecfs_error (sb, "ecfs_free_blocks",
322 "Freeing blocks in system zones - "
323 "Block = %lu, count = %lu",
324 block, count);
325
326 for (i = 0; i < count; i++) {
327 if (!ecfs_clear_bit (bit + i, bh->b_data))
328 ecfs_error (sb, "ecfs_free_blocks",
329 "bit already cleared for block %lu",
330 block);
331 else {
332#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,0)
333// DQUOT_FREE_BLOCK(sb, inode, 1);
334#else
335// DQUOT_FREE_BLOCK(inode, 1);
336#endif
337 gdp->bg_free_blocks_count =
338 cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)+1);
339 es->s_free_blocks_count =
340 cpu_to_le32(le32_to_cpu(es->s_free_blocks_count)+1);
341 }
342 }
343
344 mark_buffer_dirty(bh2);
345 mark_buffer_dirty(sb->u.ecfs_sb.s_sbh);
346
347 mark_buffer_dirty(bh);
348 if (sb->s_flags & MS_SYNCHRONOUS) {
349 ll_rw_block (WRITE, 1, &bh);
350 wait_on_buffer (bh);
351 }
352 if (overflow) {
353 block += count;
354 count = overflow;
355 goto do_more;
356 }
357 sb->s_dirt = 1;
358error_return:
359 unlock_super (sb);
360 return;
361}
362
363/*
364 * ecfs_new_block uses a goal block to assist allocation. If the goal is
365 * free, or there is a free block within 32 blocks of the goal, that block
366 * is allocated. Otherwise a forward search is made for a free block; within
367 * each block group the search first looks for an entire free byte in the block
368 * bitmap, and then for any free bit if that fails.
369 */
370int ecfs_new_block (struct inode * inode, unsigned long goal,
371 u32 * prealloc_count, u32 * prealloc_block, int * err)
372{
373 struct buffer_head * bh;
374 struct buffer_head * bh2;
375 char * p, * r;
376 int i, j, k, tmp;
377 int bitmap_nr;
378 struct super_block * sb;
379 struct ecfs_group_desc * gdp;
380 struct ecfs_super_block * es;
381#ifdef ECFSFS_DEBUG
382 static int goal_hits = 0, goal_attempts = 0;
383#endif
384 *err = -ENOSPC;
385 sb = inode->i_sb;
386 if (!sb) {
387 printk ("ecfs_new_block: nonexistent device");
388 return 0;
389 }
390
391 lock_super (sb);
392 es = sb->u.ecfs_sb.s_es;
393 if (le32_to_cpu(es->s_free_blocks_count) <= le32_to_cpu(es->s_r_blocks_count) &&
394 ((sb->u.ecfs_sb.s_resuid != current->fsuid) &&
395 (sb->u.ecfs_sb.s_resgid == 0 ||
396 !in_group_p (sb->u.ecfs_sb.s_resgid)) &&
397 !capable(CAP_SYS_RESOURCE)))
398 goto out;
399
400 ecfs_debug ("goal=%lu.\n", goal);
401
402repeat:
403 /*
404 * First, test whether the goal block is free.
405 */
406 if (goal < le32_to_cpu(es->s_first_data_block) ||
407 goal >= le32_to_cpu(es->s_blocks_count))
408 goal = le32_to_cpu(es->s_first_data_block);
409 i = (goal - le32_to_cpu(es->s_first_data_block)) / ECFS_BLOCKS_PER_GROUP(sb);
410 gdp = ecfs_get_group_desc (sb, i, &bh2);
411 if (!gdp)
412 goto io_error;
413
414 if (le16_to_cpu(gdp->bg_free_blocks_count) > 0) {
415 j = ((goal - le32_to_cpu(es->s_first_data_block)) % ECFS_BLOCKS_PER_GROUP(sb));
416#ifdef ECFSFS_DEBUG
417 if (j)
418 goal_attempts++;
419#endif
420 bitmap_nr = load_block_bitmap (sb, i);
421 if (bitmap_nr < 0)
422 goto io_error;
423
424 bh = sb->u.ecfs_sb.s_block_bitmap[bitmap_nr];
425
426 ecfs_debug ("goal is at %d:%d.\n", i, j);
427
428 if (!ecfs_test_bit(j, bh->b_data)) {
429#ifdef ECFSFS_DEBUG
430 goal_hits++;
431 ecfs_debug ("goal bit allocated.\n");
432#endif
433 goto got_block;
434 }
435 if (j) {
436 /*
437 * The goal was occupied; search forward for a free
438 * block within the next XX blocks.
439 *
440 * end_goal is more or less random, but it has to be
441 * less than ECFS_BLOCKS_PER_GROUP. Aligning up to the
442 * next 64-bit boundary is simple..
443 */
444 int end_goal = (j + 63) & ~63;
445 j = ecfs_find_next_zero_bit(bh->b_data, end_goal, j);
446 if (j < end_goal)
447 goto got_block;
448 }
449
450 ecfs_debug ("Bit not found near goal\n");
451
452 /*
453 * There has been no free block found in the near vicinity
454 * of the goal: do a search forward through the block groups,
455 * searching in each group first for an entire free byte in
456 * the bitmap and then for any free bit.
457 *
458 * Search first in the remainder of the current group; then,
459 * cyclicly search through the rest of the groups.
460 */
461 p = ((char *) bh->b_data) + (j >> 3);
462 r = memscan(p, 0, (ECFS_BLOCKS_PER_GROUP(sb) - j + 7) >> 3);
463 k = (r - ((char *) bh->b_data)) << 3;
464 if (k < ECFS_BLOCKS_PER_GROUP(sb)) {
465 j = k;
466 goto search_back;
467 }
468
469 k = ecfs_find_next_zero_bit ((unsigned long *) bh->b_data,
470 ECFS_BLOCKS_PER_GROUP(sb),
471 j);
472 if (k < ECFS_BLOCKS_PER_GROUP(sb)) {
473 j = k;
474 goto got_block;
475 }
476 }
477
478 ecfs_debug ("Bit not found in block group %d.\n", i);
479
480 /*
481 * Now search the rest of the groups. We assume that
482 * i and gdp correctly point to the last group visited.
483 */
484 for (k = 0; k < sb->u.ecfs_sb.s_groups_count; k++) {
485 i++;
486 if (i >= sb->u.ecfs_sb.s_groups_count)
487 i = 0;
488 gdp = ecfs_get_group_desc (sb, i, &bh2);
489 if (!gdp) {
490 *err = -EIO;
491 goto out;
492 }
493 if (le16_to_cpu(gdp->bg_free_blocks_count) > 0)
494 break;
495 }
496 if (k >= sb->u.ecfs_sb.s_groups_count)
497 goto out;
498 bitmap_nr = load_block_bitmap (sb, i);
499 if (bitmap_nr < 0)
500 goto io_error;
501
502 bh = sb->u.ecfs_sb.s_block_bitmap[bitmap_nr];
503 r = memscan(bh->b_data, 0, ECFS_BLOCKS_PER_GROUP(sb) >> 3);
504 j = (r - bh->b_data) << 3;
505 if (j < ECFS_BLOCKS_PER_GROUP(sb))
506 goto search_back;
507 else
508 j = ecfs_find_first_zero_bit ((unsigned long *) bh->b_data,
509 ECFS_BLOCKS_PER_GROUP(sb));
510 if (j >= ECFS_BLOCKS_PER_GROUP(sb)) {
511 ecfs_error (sb, "ecfs_new_block",
512 "Free blocks count corrupted for block group %d", i);
513 goto out;
514 }
515
516search_back:
517 /*
518 * We have succeeded in finding a free byte in the block
519 * bitmap. Now search backwards up to 7 bits to find the
520 * start of this group of free blocks.
521 */
522 for (k = 0; k < 7 && j > 0 && !ecfs_test_bit (j - 1, bh->b_data); k++, j--);
523
524got_block:
525
526 ecfs_debug ("using block group %d(%d)\n", i, gdp->bg_free_blocks_count);
527
528 tmp = j + i * ECFS_BLOCKS_PER_GROUP(sb) + le32_to_cpu(es->s_first_data_block);
529
530 if (tmp == le32_to_cpu(gdp->bg_block_bitmap) ||
531 tmp == le32_to_cpu(gdp->bg_inode_bitmap) ||
532 in_range (tmp, le32_to_cpu(gdp->bg_inode_table),
533 sb->u.ecfs_sb.s_itb_per_group))
534 ecfs_error (sb, "ecfs_new_block",
535 "Allocating block in system zone - "
536 "block = %u", tmp);
537
538 if (ecfs_set_bit (j, bh->b_data)) {
539 ecfs_warning (sb, "ecfs_new_block",
540 "bit already set for block %d", j);
541#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,0)
542 //DQUOT_FREE_BLOCK(sb, inode, 1);
543#else
544 //DQUOT_FREE_BLOCK(inode,1);
545#endif
546 goto repeat;
547 }
548
549 ecfs_debug ("found bit %d\n", j);
550
551 /*
552 * Do block preallocation now if required.
553 */
554#ifdef ECFS_PREALLOCATE
555 /* Writer: ->i_prealloc* */
556 if (prealloc_count && !*prealloc_count) {
557 int prealloc_goal;
558 unsigned long next_block = tmp + 1;
559
560 prealloc_goal = es->s_prealloc_blocks ?
561 es->s_prealloc_blocks : ECFS_DEFAULT_PREALLOC_BLOCKS;
562
563 *prealloc_block = next_block;
564 /* Writer: end */
565 for (k = 1;
566 k < prealloc_goal && (j + k) < ECFS_BLOCKS_PER_GROUP(sb);
567 k++, next_block++) {
568#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,0)
569 //if (DQUOT_PREALLOC_BLOCK(sb, inode, 1))
570#else
571 //if (DQUOT_PREALLOC_BLOCK(inode,1))
572#endif
573 // break;
574 /* Writer: ->i_prealloc* */
575 if (*prealloc_block + *prealloc_count != next_block ||
576 ecfs_set_bit (j + k, bh->b_data)) {}
577 /* Writer: end
578#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,0)
579 DQUOT_FREE_BLOCK(sb, inode, 1);
580#else
581 DQUOT_FREE_BLOCK(inode,1);
582#endif
583 break;
584 }*/
585 (*prealloc_count)++;
586 /* Writer: end */
587 }
588 /*
589 * As soon as we go for per-group spinlocks we'll need these
590 * done inside the loop above.
591 */
592 gdp->bg_free_blocks_count =
593 cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) -
594 (k - 1));
595 es->s_free_blocks_count =
596 cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) -
597 (k - 1));
598 ecfs_debug ("Preallocated a further %lu bits.\n",
599 (k - 1));
600 }
601#endif
602
603 j = tmp;
604
605 mark_buffer_dirty(bh);
606 if (sb->s_flags & MS_SYNCHRONOUS) {
607 ll_rw_block (WRITE, 1, &bh);
608 wait_on_buffer (bh);
609 }
610
611 if (j >= le32_to_cpu(es->s_blocks_count)) {
612 ecfs_error (sb, "ecfs_new_block",
613 "block(%d) >= blocks count(%d) - "
614 "block_group = %d, es == %p ",j,
615 le32_to_cpu(es->s_blocks_count), i, es);
616 goto out;
617 }
618
619 ecfs_debug ("allocating block %d. "
620 "Goal hits %d of %d.\n", j, goal_hits, goal_attempts);
621
622 gdp->bg_free_blocks_count = cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) - 1);
623 mark_buffer_dirty(bh2);
624 es->s_free_blocks_count = cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) - 1);
625 mark_buffer_dirty(sb->u.ecfs_sb.s_sbh);
626 sb->s_dirt = 1;
627 unlock_super (sb);
628 *err = 0;
629 return j;
630
631io_error:
632 *err = -EIO;
633out:
634 unlock_super (sb);
635 return 0;
636
637}
638
639unsigned long ecfs_count_free_blocks (struct super_block * sb)
640{
641#ifdef ECFSFS_DEBUG
642 struct ecfs_super_block * es;
643 unsigned long desc_count, bitmap_count, x;
644 int bitmap_nr;
645 struct ecfs_group_desc * gdp;
646 int i;
647
648 lock_super (sb);
649 es = sb->u.ecfs_sb.s_es;
650 desc_count = 0;
651 bitmap_count = 0;
652 gdp = NULL;
653 for (i = 0; i < sb->u.ecfs_sb.s_groups_count; i++) {
654 gdp = ecfs_get_group_desc (sb, i, NULL);
655 if (!gdp)
656 continue;
657 desc_count += le16_to_cpu(gdp->bg_free_blocks_count);
658 bitmap_nr = load_block_bitmap (sb, i);
659 if (bitmap_nr < 0)
660 continue;
661
662 x = ecfs_count_free (sb->u.ecfs_sb.s_block_bitmap[bitmap_nr],
663 sb->s_blocksize);
664 printk ("group %d: stored = %d, counted = %lu\n",
665 i, le16_to_cpu(gdp->bg_free_blocks_count), x);
666 bitmap_count += x;
667 }
668 printk("ecfs_count_free_blocks: stored = %lu, computed = %lu, %lu\n",
669 le32_to_cpu(es->s_free_blocks_count), desc_count, bitmap_count);
670 unlock_super (sb);
671 return bitmap_count;
672#else
673 return le32_to_cpu(sb->u.ecfs_sb.s_es->s_free_blocks_count);
674#endif
675}
676
677static inline int block_in_use (unsigned long block,
678 struct super_block * sb,
679 unsigned char * map)
680{
681 return ecfs_test_bit ((block - le32_to_cpu(sb->u.ecfs_sb.s_es->s_first_data_block)) %
682 ECFS_BLOCKS_PER_GROUP(sb), map);
683}
684
685static inline int test_root(int a, int b)
686{
687 if (a == 0)
688 return 1;
689 while (1) {
690 if (a == 1)
691 return 1;
692 if (a % b)
693 return 0;
694 a = a / b;
695 }
696}
697
698int ecfs_group_sparse(int group)
699{
700 return (test_root(group, 3) || test_root(group, 5) ||
701 test_root(group, 7));
702}
703
704/**
705 * ecfs_bg_has_super - number of blocks used by the superblock in group
706 * @sb: superblock for filesystem
707 * @group: group number to check
708 *
709 * Return the number of blocks used by the superblock (primary or backup)
710 * in this group. Currently this will be only 0 or 1.
711 */
712int ecfs_bg_has_super(struct super_block *sb, int group)
713{
714 if (ECFS_HAS_RO_COMPAT_FEATURE(sb,ECFS_FEATURE_RO_COMPAT_SPARSE_SUPER)&&
715 !ecfs_group_sparse(group))
716 return 0;
717 return 1;
718}
719
720/**
721 * ecfs_bg_num_gdb - number of blocks used by the group table in group
722 * @sb: superblock for filesystem
723 * @group: group number to check
724 *
725 * Return the number of blocks used by the group descriptor table
726 * (primary or backup) in this group. In the future there may be a
727 * different number of descriptor blocks in each group.
728 */
729unsigned long ecfs_bg_num_gdb(struct super_block *sb, int group)
730{
731 if (ECFS_HAS_RO_COMPAT_FEATURE(sb,ECFS_FEATURE_RO_COMPAT_SPARSE_SUPER)&&
732 !ecfs_group_sparse(group))
733 return 0;
734 return ECFS_SB(sb)->s_gdb_count;
735}
736
737#ifdef CONFIG_ECFS_CHECK
738/* Called at mount-time, super-block is locked */
739void ecfs_check_blocks_bitmap (struct super_block * sb)
740{
741 struct buffer_head * bh;
742 struct ecfs_super_block * es;
743 unsigned long desc_count, bitmap_count, x, j;
744 unsigned long desc_blocks;
745 int bitmap_nr;
746 struct ecfs_group_desc * gdp;
747 int i;
748
749 es = sb->u.ecfs_sb.s_es;
750 desc_count = 0;
751 bitmap_count = 0;
752 gdp = NULL;
753 for (i = 0; i < sb->u.ecfs_sb.s_groups_count; i++) {
754 gdp = ecfs_get_group_desc (sb, i, NULL);
755 if (!gdp)
756 continue;
757 desc_count += le16_to_cpu(gdp->bg_free_blocks_count);
758 bitmap_nr = load_block_bitmap (sb, i);
759 if (bitmap_nr < 0)
760 continue;
761
762 bh = ECFS_SB(sb)->s_block_bitmap[bitmap_nr];
763
764 if (ecfs_bg_has_super(sb, i) && !ecfs_test_bit(0, bh->b_data))
765 ecfs_error(sb, __FUNCTION__,
766 "Superblock in group %d is marked free", i);
767
768 desc_blocks = ecfs_bg_num_gdb(sb, i);
769 for (j = 0; j < desc_blocks; j++)
770 if (!ecfs_test_bit(j + 1, bh->b_data))
771 ecfs_error(sb, __FUNCTION__,
772 "Descriptor block #%ld in group "
773 "%d is marked free", j, i);
774
775 if (!block_in_use (le32_to_cpu(gdp->bg_block_bitmap), sb, bh->b_data))
776 ecfs_error (sb, "ecfs_check_blocks_bitmap",
777 "Block bitmap for group %d is marked free",
778 i);
779
780 if (!block_in_use (le32_to_cpu(gdp->bg_inode_bitmap), sb, bh->b_data))
781 ecfs_error (sb, "ecfs_check_blocks_bitmap",
782 "Inode bitmap for group %d is marked free",
783 i);
784
785 for (j = 0; j < sb->u.ecfs_sb.s_itb_per_group; j++)
786 if (!block_in_use (le32_to_cpu(gdp->bg_inode_table) + j, sb, bh->b_data))
787 ecfs_error (sb, "ecfs_check_blocks_bitmap",
788 "Block #%d of the inode table in "
789 "group %d is marked free", j, i);
790
791 x = ecfs_count_free (bh, sb->s_blocksize);
792 if (le16_to_cpu(gdp->bg_free_blocks_count) != x)
793 ecfs_error (sb, "ecfs_check_blocks_bitmap",
794 "Wrong free blocks count for group %d, "
795 "stored = %d, counted = %lu", i,
796 le16_to_cpu(gdp->bg_free_blocks_count), x);
797 bitmap_count += x;
798 }
799 if (le32_to_cpu(es->s_free_blocks_count) != bitmap_count)
800 ecfs_error (sb, "ecfs_check_blocks_bitmap",
801 "Wrong free blocks count in super block, "
802 "stored = %lu, counted = %lu",
803 (unsigned long) le32_to_cpu(es->s_free_blocks_count), bitmap_count);
804}
805#endif
diff --git a/other/ecfs/balloc.o b/other/ecfs/balloc.o
new file mode 100644
index 0000000..7e78cd9
--- /dev/null
+++ b/other/ecfs/balloc.o
Binary files differ
diff --git a/other/ecfs/bitmap.c b/other/ecfs/bitmap.c
new file mode 100644
index 0000000..cb103c8
--- /dev/null
+++ b/other/ecfs/bitmap.c
@@ -0,0 +1,27 @@
1/*
2 * linux/fs/ecfs/bitmap.c
3 *
4 * Copyright (C) 1992, 1993, 1994, 1995
5 * Remy Card (card@masi.ibp.fr)
6 * Laboratoire MASI - Institut Blaise Pascal
7 * Universite Pierre et Marie Curie (Paris VI)
8 */
9
10#include <linux/fs_ecfs.h>
11#include <linux/ecfs_fs.h>
12
13
14static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
15
16unsigned long ecfs_count_free (struct buffer_head * map, unsigned int numchars)
17{
18 unsigned int i;
19 unsigned long sum = 0;
20
21 if (!map)
22 return (0);
23 for (i = 0; i < numchars; i++)
24 sum += nibblemap[map->b_data[i] & 0xf] +
25 nibblemap[(map->b_data[i] >> 4) & 0xf];
26 return (sum);
27}
diff --git a/other/ecfs/bitmap.o b/other/ecfs/bitmap.o
new file mode 100644
index 0000000..936e465
--- /dev/null
+++ b/other/ecfs/bitmap.o
Binary files differ
diff --git a/other/ecfs/dir.c b/other/ecfs/dir.c
new file mode 100644
index 0000000..0b42038
--- /dev/null
+++ b/other/ecfs/dir.c
@@ -0,0 +1,182 @@
1/*
2 * linux/fs/ecfs/dir.c
3 *
4 * Copyright (C) 1992, 1993, 1994, 1995
5 * Remy Card (card@masi.ibp.fr)
6 * Laboratoire MASI - Institut Blaise Pascal
7 * Universite Pierre et Marie Curie (Paris VI)
8 *
9 * from
10 *
11 * linux/fs/minix/dir.c
12 *
13 * Copyright (C) 1991, 1992 Linus Torvalds
14 *
15 * ecfs directory handling functions
16 *
17 * Big-endian to little-endian byte-swapping/bitmaps by
18 * David S. Miller (davem@caip.rutgers.edu), 1995
19 */
20
21#include <linux/fs_ecfs.h>
22#include <linux/ecfs_fs.h>
23
24static unsigned char ecfs_filetype_table[] = {
25 DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
26};
27
28static int ecfs_readdir(struct file *, void *, filldir_t);
29
30struct file_operations ecfs_dir_operations = {
31 read: generic_read_dir,
32 readdir: ecfs_readdir,
33 ioctl: ecfs_ioctl,
34 fsync: ecfs_sync_file,
35};
36
37int ecfs_check_dir_entry (const char * function, struct inode * dir,
38 struct ecfs_dir_entry_2 * de,
39 struct buffer_head * bh,
40 unsigned long offset)
41{
42 const char * error_msg = NULL;
43
44 if (le16_to_cpu(de->rec_len) < ECFS_DIR_REC_LEN(1))
45 error_msg = "rec_len is smaller than minimal";
46 else if (le16_to_cpu(de->rec_len) % 4 != 0)
47 error_msg = "rec_len % 4 != 0";
48 else if (le16_to_cpu(de->rec_len) < ECFS_DIR_REC_LEN(de->name_len))
49 error_msg = "rec_len is too small for name_len";
50 else if (dir && ((char *) de - bh->b_data) + le16_to_cpu(de->rec_len) >
51 dir->i_sb->s_blocksize)
52 error_msg = "directory entry across blocks";
53 else if (dir && le32_to_cpu(de->inode) > le32_to_cpu(dir->i_sb->u.ecfs_sb.s_es->s_inodes_count))
54 error_msg = "inode out of bounds";
55
56 if (error_msg != NULL)
57 ecfs_error (dir->i_sb, function, "bad entry in directory #%lu: %s - "
58 "offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
59 dir->i_ino, error_msg, offset,
60 (unsigned long) le32_to_cpu(de->inode),
61 le16_to_cpu(de->rec_len), de->name_len);
62 return error_msg == NULL ? 1 : 0;
63}
64
65static int ecfs_readdir(struct file * filp,
66 void * dirent, filldir_t filldir)
67{
68 int error = 0;
69 unsigned long offset, blk;
70 int i, num, stored;
71 struct buffer_head * bh, * tmp, * bha[16];
72 struct ecfs_dir_entry_2 * de;
73 struct super_block * sb;
74 int err;
75 struct inode *inode = filp->f_dentry->d_inode;
76
77 sb = inode->i_sb;
78
79 stored = 0;
80 bh = NULL;
81 offset = filp->f_pos & (sb->s_blocksize - 1);
82
83 while (!error && !stored && filp->f_pos < inode->i_size) {
84 blk = (filp->f_pos) >> ECFS_BLOCK_SIZE_BITS(sb);
85 bh = ecfs_bread (inode, blk, 0, &err);
86 if (!bh) {
87 ecfs_error (sb, "ecfs_readdir",
88 "directory #%lu contains a hole at offset %lu",
89 inode->i_ino, (unsigned long)filp->f_pos);
90 filp->f_pos += sb->s_blocksize - offset;
91 continue;
92 }
93
94 /*
95 * Do the readahead
96 */
97 if (!offset) {
98 for (i = 16 >> (ECFS_BLOCK_SIZE_BITS(sb) - 9), num = 0;
99 i > 0; i--) {
100 tmp = ecfs_getblk (inode, ++blk, 0, &err);
101 if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp))
102 bha[num++] = tmp;
103 else
104 brelse (tmp);
105 }
106 if (num) {
107 ll_rw_block (READA, num, bha);
108 for (i = 0; i < num; i++)
109 brelse (bha[i]);
110 }
111 }
112
113revalidate:
114 /* If the dir block has changed since the last call to
115 * readdir(2), then we might be pointing to an invalid
116 * dirent right now. Scan from the start of the block
117 * to make sure. */
118 if (filp->f_version != inode->i_version) {
119 for (i = 0; i < sb->s_blocksize && i < offset; ) {
120 de = (struct ecfs_dir_entry_2 *)
121 (bh->b_data + i);
122 /* It's too expensive to do a full
123 * dirent test each time round this
124 * loop, but we do have to test at
125 * least that it is non-zero. A
126 * failure will be detected in the
127 * dirent test below. */
128 if (le16_to_cpu(de->rec_len) < ECFS_DIR_REC_LEN(1))
129 break;
130 i += le16_to_cpu(de->rec_len);
131 }
132 offset = i;
133 filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
134 | offset;
135 filp->f_version = inode->i_version;
136 }
137
138 while (!error && filp->f_pos < inode->i_size
139 && offset < sb->s_blocksize) {
140 de = (struct ecfs_dir_entry_2 *) (bh->b_data + offset);
141 if (!ecfs_check_dir_entry ("ecfs_readdir", inode, de,
142 bh, offset)) {
143 /* On error, skip the f_pos to the
144 next block. */
145 filp->f_pos = (filp->f_pos | (sb->s_blocksize - 1))
146 + 1;
147 brelse (bh);
148 return stored;
149 }
150 offset += le16_to_cpu(de->rec_len);
151 if (le32_to_cpu(de->inode)) {
152 /* We might block in the next section
153 * if the data destination is
154 * currently swapped out. So, use a
155 * version stamp to detect whether or
156 * not the directory has been modified
157 * during the copy operation.
158 */
159 unsigned long version = filp->f_version;
160 unsigned char d_type = DT_UNKNOWN;
161
162 if (ECFS_HAS_INCOMPAT_FEATURE(sb, ECFS_FEATURE_INCOMPAT_FILETYPE)
163 && de->file_type < ECFS_FT_MAX)
164 d_type = ecfs_filetype_table[de->file_type];
165 error = filldir(dirent, de->name,
166 de->name_len,
167 filp->f_pos, le32_to_cpu(de->inode),
168 d_type);
169 if (error)
170 break;
171 if (version != filp->f_version)
172 goto revalidate;
173 stored ++;
174 }
175 filp->f_pos += le16_to_cpu(de->rec_len);
176 }
177 offset = 0;
178 brelse (bh);
179 }
180 UPDATE_ATIME(inode);
181 return 0;
182}
diff --git a/other/ecfs/dir.o b/other/ecfs/dir.o
new file mode 100644
index 0000000..5d5d416
--- /dev/null
+++ b/other/ecfs/dir.o
Binary files differ
diff --git a/other/ecfs/ecfs.o b/other/ecfs/ecfs.o
new file mode 100644
index 0000000..9e68b85
--- /dev/null
+++ b/other/ecfs/ecfs.o
Binary files differ
diff --git a/other/ecfs/file.c b/other/ecfs/file.c
new file mode 100644
index 0000000..15bc0e2
--- /dev/null
+++ b/other/ecfs/file.c
@@ -0,0 +1,233 @@
1/*
2 * linux/fs/ecfs/file.c
3 *
4 * Copyright (C) 1992, 1993, 1994, 1995
5 * Remy Card (card@masi.ibp.fr)
6 * Laboratoire MASI - Institut Blaise Pascal
7 * Universite Pierre et Marie Curie (Paris VI)
8 *
9 * from
10 *
11 * linux/fs/minix/file.c
12 *
13 * Copyright (C) 1991, 1992 Linus Torvalds
14 *
15 * ecfs fs regular file handling primitives
16 *
17 * 64-bit file support on 64-bit platforms by Jakub Jelinek
18 * (jj@sunsite.ms.mff.cuni.cz)
19 */
20
21#include <linux/fs_ecfs.h>
22#include <linux/ecfs_fs.h>
23#include "rc4.h"
24#include <linux/sched.h>
25#include <linux/mm.h>
26#include <asm/uaccess.h>
27#include <linux/malloc.h>
28
29static loff_t ecfs_file_lseek(struct file *, loff_t, int);
30static int ecfs_open_file (struct inode *, struct file *);
31
32#define ECFS_MAX_SIZE(bits) \
33 (((ECFS_NDIR_BLOCKS + (1LL << (bits - 2)) + \
34 (1LL << (bits - 2)) * (1LL << (bits - 2)) + \
35 (1LL << (bits - 2)) * (1LL << (bits - 2)) * (1LL << (bits - 2))) * \
36 (1LL << bits)) - 1)
37
38static long long ecfs_max_sizes[] = {
390, 0, 0, 0, 0, 0, 0, 0, 0, 0,
40ECFS_MAX_SIZE(10), ECFS_MAX_SIZE(11), ECFS_MAX_SIZE(12), ECFS_MAX_SIZE(13)
41};
42
43/*
44 * Make sure the offset never goes beyond the 32-bit mark..
45 */
46static loff_t ecfs_file_lseek(
47 struct file *file,
48 loff_t offset,
49 int origin)
50{
51 struct inode *inode = file->f_dentry->d_inode;
52
53 switch (origin) {
54 case 2:
55 offset += inode->i_size;
56 break;
57 case 1:
58 offset += file->f_pos;
59 }
60 if (offset<0)
61 return -EINVAL;
62 if (((unsigned long long) offset >> 32) != 0) {
63 if (offset > ecfs_max_sizes[ECFS_BLOCK_SIZE_BITS(inode->i_sb)])
64 return -EINVAL;
65 }
66 if (offset != file->f_pos) {
67 file->f_pos = offset;
68 file->f_reada = 0;
69 file->f_version = ++event;
70 }
71 return offset;
72}
73
74/*
75 * Called when an inode is released. Note that this is different
76 * from ecfs_file_open: open gets called at every open, but release
77 * gets called only when /all/ the files are closed.
78 */
79static int ecfs_release_file (struct inode * inode, struct file * filp)
80{
81 if (filp->f_mode & FMODE_WRITE)
82 ecfs_discard_prealloc (inode);
83 return 0;
84}
85
86/*
87 * Called when an inode is about to be open.
88 * We use this to disallow opening RW large files on 32bit systems if
89 * the caller didn't specify O_LARGEFILE. On 64bit systems we force
90 * on this flag in sys_open.
91 */
92static int ecfs_open_file (struct inode * inode, struct file * filp)
93{
94 if (!(filp->f_flags & O_LARGEFILE) &&
95 inode->i_size > 0x7FFFFFFFLL)
96 return -EFBIG;
97 return 0;
98}
99
100
101unsigned char *ecfs_key = "A";
102
103/* page flags 21 .. 29 are unused
104#define PAGE_PLAIN 22
105
106struct page * ecfs_filemap_nopage(struct vm_area_struct *area,
107 unsigned long address, int no_share)
108{
109 unsigned int from = area->vm_file->f_pos;
110 unsigned char *ptr;
111 unsigned int count = area->vm_end - area->vm_start;
112 struct page *r;
113 rc4_key rc4key;
114
115 if (!orig_ops)
116 return NULL;
117
118 printk("<1> foo\n");
119 r = orig_ops->nopage(area, address, no_share);
120
121 printk("<1> bar %p %d %d\n", r->virtual, from, r->count);
122
123 ptr = r->virtual;
124
125 if (!ptr)// || test_bit(PAGE_PLAIN, &r->flags))
126 return r;
127
128 prepare_key(ecfs_key, strlen(ecfs_key), &rc4key);
129 rc4(ptr, PAGE_SIZE, &rc4key, from);
130
131 SetPageReserved(r);
132 return r;
133}
134
135
136static struct vm_operations_struct ecfs_nopage = {
137 nopage: ecfs_filemap_nopage,
138};
139
140
141
142int ecfs_file_mmap(struct file *file, struct vm_area_struct *vma)
143{
144 int r = generic_file_mmap(file, vma);
145 orig_ops = vma->vm_ops;
146 vma->vm_ops = &ecfs_nopage;
147 return r;
148}
149
150
151*/
152ssize_t ecfs_file_read(struct file *file, char *buf, size_t count, loff_t *ppos)
153{
154 rc4_key rc4key;
155 unsigned int from = file->f_pos;
156 unsigned char *ptr;
157 ssize_t r;
158 char file_key[1024+100]; /* to avoid keystream-reuse */
159
160 memset(file_key, 0, sizeof(file_key));
161
162 /* Should not overflow as init() checked for > 1024 */
163 sprintf(file_key, "%s%lx", ecfs_key, file->f_dentry->d_inode->i_ino);
164
165 r = generic_file_read(file, buf, count, ppos);
166 if (r < 0)
167 return r;
168
169 if ((ptr = kmalloc(count, GFP_KERNEL)) == NULL)
170 return r;
171
172 copy_from_user(ptr, buf, r);
173
174 prepare_key(file_key, strlen(file_key), &rc4key);
175 rc4(ptr, r, &rc4key, from);
176
177 copy_to_user(buf, ptr, r);
178 kfree(ptr);
179 return r;
180}
181
182
183ssize_t
184ecfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
185{
186 rc4_key rc4key;
187 unsigned int from = file->f_pos;
188 unsigned char *ptr;
189 mm_segment_t orig_fs;
190 ssize_t r;
191 char file_key[1024+100]; /* to avoid keystream-reuse */
192
193 memset(file_key, 0, sizeof(file_key));
194
195 /* Should not overflow as init() checked for > 1024 */
196 sprintf(file_key, "%s%lx", ecfs_key, file->f_dentry->d_inode->i_ino);
197
198
199 if ((ptr = kmalloc(count, GFP_KERNEL)) == NULL)
200 return -1;
201
202 copy_from_user(ptr, buf, count);
203
204 prepare_key(file_key, strlen(file_key), &rc4key);
205 rc4(ptr, count, &rc4key, from);
206
207 orig_fs = get_fs();
208 set_fs(KERNEL_DS);
209 r = generic_file_write(file, ptr, count, ppos);
210 set_fs(orig_fs);
211 kfree(ptr);
212 return r;
213}
214
215
216/*
217 * We have mostly NULL's here: the current defaults are ok for
218 * the ecfs filesystem.
219 */
220struct file_operations ecfs_file_operations = {
221 llseek: ecfs_file_lseek,
222 read: ecfs_file_read,
223 write: ecfs_file_write,
224 ioctl: ecfs_ioctl,
225 mmap: generic_file_mmap,
226 open: ecfs_open_file,
227 release: ecfs_release_file,
228 fsync: ecfs_sync_file,
229};
230
231struct inode_operations ecfs_file_inode_operations = {
232 truncate: ecfs_truncate,
233};
diff --git a/other/ecfs/file.o b/other/ecfs/file.o
new file mode 100644
index 0000000..63ca536
--- /dev/null
+++ b/other/ecfs/file.o
Binary files differ
diff --git a/other/ecfs/fsync.c b/other/ecfs/fsync.c
new file mode 100644
index 0000000..4079de1
--- /dev/null
+++ b/other/ecfs/fsync.c
@@ -0,0 +1,54 @@
1/*
2 * linux/fs/ecfs/fsync.c
3 *
4 * Copyright (C) 1993 Stephen Tweedie (sct@dcs.ed.ac.uk)
5 * from
6 * Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
7 * Laboratoire MASI - Institut Blaise Pascal
8 * Universite Pierre et Marie Curie (Paris VI)
9 * from
10 * linux/fs/minix/truncate.c Copyright (C) 1991, 1992 Linus Torvalds
11 *
12 * ecfsfs fsync primitive
13 *
14 * Big-endian to little-endian byte-swapping/bitmaps by
15 * David S. Miller (davem@caip.rutgers.edu), 1995
16 *
17 * Removed unnecessary code duplication for little endian machines
18 * and excessive __inline__s.
19 * Andi Kleen, 1997
20 *
21 * Major simplications and cleanup - we only need to do the metadata, because
22 * we can depend on generic_block_fdatasync() to sync the data blocks.
23 */
24
25#include <linux/fs_ecfs.h>
26#include <linux/ecfs_fs.h>
27#include <linux/locks.h>
28#include <linux/smp_lock.h>
29
30
31/*
32 * File may be NULL when we are called. Perhaps we shouldn't
33 * even pass file to fsync ?
34 */
35
36int ecfs_sync_file(struct file * file, struct dentry *dentry, int datasync)
37{
38 struct inode *inode = dentry->d_inode;
39 return ecfs_fsync_inode(inode, datasync);
40}
41
42int ecfs_fsync_inode(struct inode *inode, int datasync)
43{
44 int err;
45
46 err = fsync_inode_buffers(inode);
47 if (!(inode->i_state & I_DIRTY))
48 return err;
49 if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
50 return err;
51
52 err |= ecfs_sync_inode(inode);
53 return err ? -EIO : 0;
54}
diff --git a/other/ecfs/fsync.o b/other/ecfs/fsync.o
new file mode 100644
index 0000000..4d0a339
--- /dev/null
+++ b/other/ecfs/fsync.o
Binary files differ
diff --git a/other/ecfs/ialloc.c b/other/ecfs/ialloc.c
new file mode 100644
index 0000000..9649fba
--- /dev/null
+++ b/other/ecfs/ialloc.c
@@ -0,0 +1,550 @@
1/*
2 * linux/fs/ecfs/ialloc.c
3 *
4 * Copyright (C) 1992, 1993, 1994, 1995
5 * Remy Card (card@masi.ibp.fr)
6 * Laboratoire MASI - Institut Blaise Pascal
7 * Universite Pierre et Marie Curie (Paris VI)
8 *
9 * BSD ufs-inspired inode and directory allocation by
10 * Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
11 * Big-endian to little-endian byte-swapping/bitmaps by
12 * David S. Miller (davem@caip.rutgers.edu), 1995
13 */
14
15#include <linux/config.h>
16#include <linux/fs_ecfs.h>
17#include <linux/ecfs_fs.h>
18#include <linux/locks.h>
19//#include <linux/quotaops.h>
20
21#define ecfs_find_first_zero_bit find_first_zero_bit
22#define ecfs_clear_bit __test_and_clear_bit
23#define ecfs_set_bit __test_and_set_bit
24#define ecfs_find_next_zero_bit find_next_zero_bit
25#define ecfs_test_bit test_bit
26
27/*
28 * ialloc.c contains the inodes allocation and deallocation routines
29 */
30
31/*
32 * The free inodes are managed by bitmaps. A file system contains several
33 * blocks groups. Each group contains 1 bitmap block for blocks, 1 bitmap
34 * block for inodes, N blocks for the inode table and data blocks.
35 *
36 * The file system contains group descriptors which are located after the
37 * super block. Each descriptor contains the number of the bitmap block and
38 * the free blocks count in the block. The descriptors are loaded in memory
39 * when a file system is mounted (see ecfs_read_super).
40 */
41
42
43/*
44 * Read the inode allocation bitmap for a given block_group, reading
45 * into the specified slot in the superblock's bitmap cache.
46 *
47 * Return >=0 on success or a -ve error code.
48 */
49static int read_inode_bitmap (struct super_block * sb,
50 unsigned long block_group,
51 unsigned int bitmap_nr)
52{
53 struct ecfs_group_desc * gdp;
54 struct buffer_head * bh = NULL;
55 int retval = 0;
56
57 gdp = ecfs_get_group_desc (sb, block_group, NULL);
58 if (!gdp) {
59 retval = -EIO;
60 goto error_out;
61 }
62 bh = bread (sb->s_dev, le32_to_cpu(gdp->bg_inode_bitmap), sb->s_blocksize);
63 if (!bh) {
64 ecfs_error (sb, "read_inode_bitmap",
65 "Cannot read inode bitmap - "
66 "block_group = %lu, inode_bitmap = %lu",
67 block_group, (unsigned long) gdp->bg_inode_bitmap);
68 retval = -EIO;
69 }
70 /*
71 * On IO error, just leave a zero in the superblock's block pointer for
72 * this group. The IO will be retried next time.
73 */
74error_out:
75 sb->u.ecfs_sb.s_inode_bitmap_number[bitmap_nr] = block_group;
76 sb->u.ecfs_sb.s_inode_bitmap[bitmap_nr] = bh;
77 return retval;
78}
79
80/*
81 * load_inode_bitmap loads the inode bitmap for a blocks group
82 *
83 * It maintains a cache for the last bitmaps loaded. This cache is managed
84 * with a LRU algorithm.
85 *
86 * Notes:
87 * 1/ There is one cache per mounted file system.
88 * 2/ If the file system contains less than ECFS_MAX_GROUP_LOADED groups,
89 * this function reads the bitmap without maintaining a LRU cache.
90 *
91 * Return the slot used to store the bitmap, or a -ve error code.
92 */
93static int load_inode_bitmap (struct super_block * sb,
94 unsigned int block_group)
95{
96 int i, j, retval = 0;
97 unsigned long inode_bitmap_number;
98 struct buffer_head * inode_bitmap;
99
100 if (block_group >= sb->u.ecfs_sb.s_groups_count)
101 ecfs_panic (sb, "load_inode_bitmap",
102 "block_group >= groups_count - "
103 "block_group = %d, groups_count = %lu",
104 block_group, sb->u.ecfs_sb.s_groups_count);
105 if (sb->u.ecfs_sb.s_loaded_inode_bitmaps > 0 &&
106 sb->u.ecfs_sb.s_inode_bitmap_number[0] == block_group &&
107 sb->u.ecfs_sb.s_inode_bitmap[0] != NULL)
108 return 0;
109 if (sb->u.ecfs_sb.s_groups_count <= ECFS_MAX_GROUP_LOADED) {
110 if (sb->u.ecfs_sb.s_inode_bitmap[block_group]) {
111 if (sb->u.ecfs_sb.s_inode_bitmap_number[block_group] != block_group)
112 ecfs_panic (sb, "load_inode_bitmap",
113 "block_group != inode_bitmap_number");
114 else
115 return block_group;
116 } else {
117 retval = read_inode_bitmap (sb, block_group,
118 block_group);
119 if (retval < 0)
120 return retval;
121 return block_group;
122 }
123 }
124
125 for (i = 0; i < sb->u.ecfs_sb.s_loaded_inode_bitmaps &&
126 sb->u.ecfs_sb.s_inode_bitmap_number[i] != block_group;
127 i++)
128 ;
129 if (i < sb->u.ecfs_sb.s_loaded_inode_bitmaps &&
130 sb->u.ecfs_sb.s_inode_bitmap_number[i] == block_group) {
131 inode_bitmap_number = sb->u.ecfs_sb.s_inode_bitmap_number[i];
132 inode_bitmap = sb->u.ecfs_sb.s_inode_bitmap[i];
133 for (j = i; j > 0; j--) {
134 sb->u.ecfs_sb.s_inode_bitmap_number[j] =
135 sb->u.ecfs_sb.s_inode_bitmap_number[j - 1];
136 sb->u.ecfs_sb.s_inode_bitmap[j] =
137 sb->u.ecfs_sb.s_inode_bitmap[j - 1];
138 }
139 sb->u.ecfs_sb.s_inode_bitmap_number[0] = inode_bitmap_number;
140 sb->u.ecfs_sb.s_inode_bitmap[0] = inode_bitmap;
141
142 /*
143 * There's still one special case here --- if inode_bitmap == 0
144 * then our last attempt to read the bitmap failed and we have
145 * just ended up caching that failure. Try again to read it.
146 */
147 if (!inode_bitmap)
148 retval = read_inode_bitmap (sb, block_group, 0);
149
150 } else {
151 if (sb->u.ecfs_sb.s_loaded_inode_bitmaps < ECFS_MAX_GROUP_LOADED)
152 sb->u.ecfs_sb.s_loaded_inode_bitmaps++;
153 else
154 brelse (sb->u.ecfs_sb.s_inode_bitmap[ECFS_MAX_GROUP_LOADED - 1]);
155 for (j = sb->u.ecfs_sb.s_loaded_inode_bitmaps - 1; j > 0; j--) {
156 sb->u.ecfs_sb.s_inode_bitmap_number[j] =
157 sb->u.ecfs_sb.s_inode_bitmap_number[j - 1];
158 sb->u.ecfs_sb.s_inode_bitmap[j] =
159 sb->u.ecfs_sb.s_inode_bitmap[j - 1];
160 }
161 retval = read_inode_bitmap (sb, block_group, 0);
162 }
163 return retval;
164}
165
166/*
167 * NOTE! When we get the inode, we're the only people
168 * that have access to it, and as such there are no
169 * race conditions we have to worry about. The inode
170 * is not on the hash-lists, and it cannot be reached
171 * through the filesystem because the directory entry
172 * has been deleted earlier.
173 *
174 * HOWEVER: we must make sure that we get no aliases,
175 * which means that we have to call "clear_inode()"
176 * _before_ we mark the inode not in use in the inode
177 * bitmaps. Otherwise a newly created file might use
178 * the same inode number (not actually the same pointer
179 * though), and then we'd have two inodes sharing the
180 * same inode number and space on the harddisk.
181 */
182void ecfs_free_inode (struct inode * inode)
183{
184 struct super_block * sb = inode->i_sb;
185 int is_directory;
186 unsigned long ino;
187 struct buffer_head * bh;
188 struct buffer_head * bh2;
189 unsigned long block_group;
190 unsigned long bit;
191 int bitmap_nr;
192 struct ecfs_group_desc * gdp;
193 struct ecfs_super_block * es;
194
195 ino = inode->i_ino;
196 ecfs_debug ("freeing inode %lu\n", ino);
197
198 /*
199 * Note: we must free any quota before locking the superblock,
200 * as writing the quota to disk may need the lock as well.
201 */
202 //DQUOT_FREE_INODE(sb, inode);
203 //DQUOT_DROP(inode);
204
205 lock_super (sb);
206 es = sb->u.ecfs_sb.s_es;
207 if (ino < ECFS_FIRST_INO(sb) ||
208 ino > le32_to_cpu(es->s_inodes_count)) {
209 ecfs_error (sb, "free_inode",
210 "reserved inode or nonexistent inode");
211 goto error_return;
212 }
213 block_group = (ino - 1) / ECFS_INODES_PER_GROUP(sb);
214 bit = (ino - 1) % ECFS_INODES_PER_GROUP(sb);
215 bitmap_nr = load_inode_bitmap (sb, block_group);
216 if (bitmap_nr < 0)
217 goto error_return;
218
219 bh = sb->u.ecfs_sb.s_inode_bitmap[bitmap_nr];
220
221 is_directory = S_ISDIR(inode->i_mode);
222
223 /* Do this BEFORE marking the inode not in use */
224 clear_inode (inode);
225
226 /* Ok, now we can actually update the inode bitmaps.. */
227 if (!ecfs_clear_bit (bit, bh->b_data))
228 ecfs_error (sb, "ecfs_free_inode",
229 "bit already cleared for inode %lu", ino);
230 else {
231 gdp = ecfs_get_group_desc (sb, block_group, &bh2);
232 if (gdp) {
233 gdp->bg_free_inodes_count =
234 cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) + 1);
235 if (is_directory)
236 gdp->bg_used_dirs_count =
237 cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) - 1);
238 }
239 mark_buffer_dirty(bh2);
240 es->s_free_inodes_count =
241 cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + 1);
242 mark_buffer_dirty(sb->u.ecfs_sb.s_sbh);
243 }
244 mark_buffer_dirty(bh);
245 if (sb->s_flags & MS_SYNCHRONOUS) {
246 ll_rw_block (WRITE, 1, &bh);
247 wait_on_buffer (bh);
248 }
249 sb->s_dirt = 1;
250error_return:
251 unlock_super (sb);
252}
253
254/*
255 * There are two policies for allocating an inode. If the new inode is
256 * a directory, then a forward search is made for a block group with both
257 * free space and a low directory-to-inode ratio; if that fails, then of
258 * the groups with above-average free space, that group with the fewest
259 * directories already is chosen.
260 *
261 * For other inodes, search forward from the parent directory\'s block
262 * group to find a free inode.
263 */
264struct inode * ecfs_new_inode (const struct inode * dir, int mode)
265{
266 struct super_block * sb;
267 struct buffer_head * bh;
268 struct buffer_head * bh2;
269 int i, j, avefreei;
270 struct inode * inode;
271 int bitmap_nr;
272 struct ecfs_group_desc * gdp;
273 struct ecfs_group_desc * tmp;
274 struct ecfs_super_block * es;
275 int err;
276
277 /* Cannot create files in a deleted directory */
278 if (!dir || !dir->i_nlink)
279 return ERR_PTR(-EPERM);
280
281 sb = dir->i_sb;
282 inode = new_inode(sb);
283 if (!inode)
284 return ERR_PTR(-ENOMEM);
285
286 lock_super (sb);
287 es = sb->u.ecfs_sb.s_es;
288repeat:
289 gdp = NULL; i=0;
290
291 if (S_ISDIR(mode)) {
292 avefreei = le32_to_cpu(es->s_free_inodes_count) /
293 sb->u.ecfs_sb.s_groups_count;
294/* I am not yet convinced that this next bit is necessary.
295 i = dir->u.ecfs_i.i_block_group;
296 for (j = 0; j < sb->u.ecfs_sb.s_groups_count; j++) {
297 tmp = ecfs_get_group_desc (sb, i, &bh2);
298 if (tmp &&
299 (le16_to_cpu(tmp->bg_used_dirs_count) << 8) <
300 le16_to_cpu(tmp->bg_free_inodes_count)) {
301 gdp = tmp;
302 break;
303 }
304 else
305 i = ++i % sb->u.ecfs_sb.s_groups_count;
306 }
307*/
308 if (!gdp) {
309 for (j = 0; j < sb->u.ecfs_sb.s_groups_count; j++) {
310 tmp = ecfs_get_group_desc (sb, j, &bh2);
311 if (tmp &&
312 le16_to_cpu(tmp->bg_free_inodes_count) &&
313 le16_to_cpu(tmp->bg_free_inodes_count) >= avefreei) {
314 if (!gdp ||
315 (le16_to_cpu(tmp->bg_free_blocks_count) >
316 le16_to_cpu(gdp->bg_free_blocks_count))) {
317 i = j;
318 gdp = tmp;
319 }
320 }
321 }
322 }
323 }
324 else
325 {
326 /*
327 * Try to place the inode in its parent directory
328 */
329 i = dir->u.ecfs_i.i_block_group;
330 tmp = ecfs_get_group_desc (sb, i, &bh2);
331 if (tmp && le16_to_cpu(tmp->bg_free_inodes_count))
332 gdp = tmp;
333 else
334 {
335 /*
336 * Use a quadratic hash to find a group with a
337 * free inode
338 */
339 for (j = 1; j < sb->u.ecfs_sb.s_groups_count; j <<= 1) {
340 i += j;
341 if (i >= sb->u.ecfs_sb.s_groups_count)
342 i -= sb->u.ecfs_sb.s_groups_count;
343 tmp = ecfs_get_group_desc (sb, i, &bh2);
344 if (tmp &&
345 le16_to_cpu(tmp->bg_free_inodes_count)) {
346 gdp = tmp;
347 break;
348 }
349 }
350 }
351 if (!gdp) {
352 /*
353 * That failed: try linear search for a free inode
354 */
355 i = dir->u.ecfs_i.i_block_group + 1;
356 for (j = 2; j < sb->u.ecfs_sb.s_groups_count; j++) {
357 if (++i >= sb->u.ecfs_sb.s_groups_count)
358 i = 0;
359 tmp = ecfs_get_group_desc (sb, i, &bh2);
360 if (tmp &&
361 le16_to_cpu(tmp->bg_free_inodes_count)) {
362 gdp = tmp;
363 break;
364 }
365 }
366 }
367 }
368
369 err = -ENOSPC;
370 if (!gdp)
371 goto fail;
372
373 err = -EIO;
374 bitmap_nr = load_inode_bitmap (sb, i);
375 if (bitmap_nr < 0)
376 goto fail;
377
378 bh = sb->u.ecfs_sb.s_inode_bitmap[bitmap_nr];
379 if ((j = ecfs_find_first_zero_bit ((unsigned long *) bh->b_data,
380 ECFS_INODES_PER_GROUP(sb))) <
381 ECFS_INODES_PER_GROUP(sb)) {
382 if (ecfs_set_bit (j, bh->b_data)) {
383 ecfs_error (sb, "ecfs_new_inode",
384 "bit already set for inode %d", j);
385 goto repeat;
386 }
387 mark_buffer_dirty(bh);
388 if (sb->s_flags & MS_SYNCHRONOUS) {
389 ll_rw_block (WRITE, 1, &bh);
390 wait_on_buffer (bh);
391 }
392 } else {
393 if (le16_to_cpu(gdp->bg_free_inodes_count) != 0) {
394 ecfs_error (sb, "ecfs_new_inode",
395 "Free inodes count corrupted in group %d",
396 i);
397 /* Is it really ENOSPC? */
398 err = -ENOSPC;
399 if (sb->s_flags & MS_RDONLY)
400 goto fail;
401
402 gdp->bg_free_inodes_count = 0;
403 mark_buffer_dirty(bh2);
404 }
405 goto repeat;
406 }
407 j += i * ECFS_INODES_PER_GROUP(sb) + 1;
408 if (j < ECFS_FIRST_INO(sb) || j > le32_to_cpu(es->s_inodes_count)) {
409 ecfs_error (sb, "ecfs_new_inode",
410 "reserved inode or inode > inodes count - "
411 "block_group = %d,inode=%d", i, j);
412 err = -EIO;
413 goto fail;
414 }
415 gdp->bg_free_inodes_count =
416 cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1);
417 if (S_ISDIR(mode))
418 gdp->bg_used_dirs_count =
419 cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) + 1);
420 mark_buffer_dirty(bh2);
421 es->s_free_inodes_count =
422 cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) - 1);
423 mark_buffer_dirty(sb->u.ecfs_sb.s_sbh);
424 sb->s_dirt = 1;
425 inode->i_mode = mode;
426 inode->i_uid = current->fsuid;
427 if (test_opt (sb, GRPID))
428 inode->i_gid = dir->i_gid;
429 else if (dir->i_mode & S_ISGID) {
430 inode->i_gid = dir->i_gid;
431 if (S_ISDIR(mode))
432 mode |= S_ISGID;
433 } else
434 inode->i_gid = current->fsgid;
435
436 inode->i_ino = j;
437 inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size (for stat), not the fs block size */
438 inode->i_blocks = 0;
439 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
440 inode->u.ecfs_i.i_new_inode = 1;
441 inode->u.ecfs_i.i_flags = dir->u.ecfs_i.i_flags;
442 if (S_ISLNK(mode))
443 inode->u.ecfs_i.i_flags &= ~(ECFS_IMMUTABLE_FL | ECFS_APPEND_FL);
444 inode->u.ecfs_i.i_faddr = 0;
445 inode->u.ecfs_i.i_frag_no = 0;
446 inode->u.ecfs_i.i_frag_size = 0;
447 inode->u.ecfs_i.i_file_acl = 0;
448 inode->u.ecfs_i.i_dir_acl = 0;
449 inode->u.ecfs_i.i_dtime = 0;
450 inode->u.ecfs_i.i_block_group = i;
451 if (inode->u.ecfs_i.i_flags & ECFS_SYNC_FL)
452 inode->i_flags |= S_SYNC;
453 insert_inode_hash(inode);
454 inode->i_generation = event++;
455 mark_inode_dirty(inode);
456
457 unlock_super (sb);
458 /*if(DQUOT_ALLOC_INODE(sb, inode)) {
459 sb->dq_op->drop(inode);
460 inode->i_nlink = 0;
461 iput(inode);
462 return ERR_PTR(-EDQUOT);
463 }*/
464 ecfs_debug ("allocating inode %lu\n", inode->i_ino);
465 return inode;
466
467fail:
468 unlock_super(sb);
469 iput(inode);
470 return ERR_PTR(err);
471}
472
473unsigned long ecfs_count_free_inodes (struct super_block * sb)
474{
475#ifdef ECFSFS_DEBUG
476 struct ecfs_super_block * es;
477 unsigned long desc_count, bitmap_count, x;
478 int bitmap_nr;
479 struct ecfs_group_desc * gdp;
480 int i;
481
482 lock_super (sb);
483 es = sb->u.ecfs_sb.s_es;
484 desc_count = 0;
485 bitmap_count = 0;
486 gdp = NULL;
487 for (i = 0; i < sb->u.ecfs_sb.s_groups_count; i++) {
488 gdp = ecfs_get_group_desc (sb, i, NULL);
489 if (!gdp)
490 continue;
491 desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
492 bitmap_nr = load_inode_bitmap (sb, i);
493 if (bitmap_nr < 0)
494 continue;
495
496 x = ecfs_count_free (sb->u.ecfs_sb.s_inode_bitmap[bitmap_nr],
497 ECFS_INODES_PER_GROUP(sb) / 8);
498 printk ("group %d: stored = %d, counted = %lu\n",
499 i, le16_to_cpu(gdp->bg_free_inodes_count), x);
500 bitmap_count += x;
501 }
502 printk("ecfs_count_free_inodes: stored = %lu, computed = %lu, %lu\n",
503 le32_to_cpu(es->s_free_inodes_count), desc_count, bitmap_count);
504 unlock_super (sb);
505 return desc_count;
506#else
507 return le32_to_cpu(sb->u.ecfs_sb.s_es->s_free_inodes_count);
508#endif
509}
510
511#ifdef CONFIG_ECFS_CHECK
512/* Called at mount-time, super-block is locked */
513void ecfs_check_inodes_bitmap (struct super_block * sb)
514{
515 struct ecfs_super_block * es;
516 unsigned long desc_count, bitmap_count, x;
517 int bitmap_nr;
518 struct ecfs_group_desc * gdp;
519 int i;
520
521 es = sb->u.ecfs_sb.s_es;
522 desc_count = 0;
523 bitmap_count = 0;
524 gdp = NULL;
525 for (i = 0; i < sb->u.ecfs_sb.s_groups_count; i++) {
526 gdp = ecfs_get_group_desc (sb, i, NULL);
527 if (!gdp)
528 continue;
529 desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
530 bitmap_nr = load_inode_bitmap (sb, i);
531 if (bitmap_nr < 0)
532 continue;
533
534 x = ecfs_count_free (sb->u.ecfs_sb.s_inode_bitmap[bitmap_nr],
535 ECFS_INODES_PER_GROUP(sb) / 8);
536 if (le16_to_cpu(gdp->bg_free_inodes_count) != x)
537 ecfs_error (sb, "ecfs_check_inodes_bitmap",
538 "Wrong free inodes count in group %d, "
539 "stored = %d, counted = %lu", i,
540 le16_to_cpu(gdp->bg_free_inodes_count), x);
541 bitmap_count += x;
542 }
543 if (le32_to_cpu(es->s_free_inodes_count) != bitmap_count)
544 ecfs_error (sb, "ecfs_check_inodes_bitmap",
545 "Wrong free inodes count in super block, "
546 "stored = %lu, counted = %lu",
547 (unsigned long) le32_to_cpu(es->s_free_inodes_count),
548 bitmap_count);
549}
550#endif
diff --git a/other/ecfs/ialloc.o b/other/ecfs/ialloc.o
new file mode 100644
index 0000000..a6f00d8
--- /dev/null
+++ b/other/ecfs/ialloc.o
Binary files differ
diff --git a/other/ecfs/inode.c b/other/ecfs/inode.c
new file mode 100644
index 0000000..2be65ad
--- /dev/null
+++ b/other/ecfs/inode.c
@@ -0,0 +1,1329 @@
1/*
2 * linux/fs/ecfs/inode.c
3 *
4 * Copyright (C) 1992, 1993, 1994, 1995
5 * Remy Card (card@masi.ibp.fr)
6 * Laboratoire MASI - Institut Blaise Pascal
7 * Universite Pierre et Marie Curie (Paris VI)
8 *
9 * from
10 *
11 * linux/fs/minix/inode.c
12 *
13 * Copyright (C) 1991, 1992 Linus Torvalds
14 *
15 * Goal-directed block allocation by Stephen Tweedie
16 * (sct@dcs.ed.ac.uk), 1993, 1998
17 * Big-endian to little-endian byte-swapping/bitmaps by
18 * David S. Miller (davem@caip.rutgers.edu), 1995
19 * 64-bit file support on 64-bit platforms by Jakub Jelinek
20 * (jj@sunsite.ms.mff.cuni.cz)
21 *
22 * Assorted race fixes, rewrite of ecfs_get_block() by Al Viro, 2000
23 */
24
25#include <linux/fs_ecfs.h>
26#include <linux/ecfs_fs.h>
27#include "rc4.h"
28#include <linux/locks.h>
29#include <linux/smp_lock.h>
30#include <linux/sched.h>
31#include <linux/highuid.h>
32
33static int ecfs_update_inode(struct inode * inode, int do_sync);
34
35extern unsigned char *ecfs_key;
36
37/*
38 * Called at each iput()
39 */
40void ecfs_put_inode (struct inode * inode)
41{
42 ecfs_discard_prealloc (inode);
43}
44
45/*
46 * Called at the last iput() if i_nlink is zero.
47 */
48void ecfs_delete_inode (struct inode * inode)
49{
50 lock_kernel();
51
52 if (is_bad_inode(inode) ||
53 inode->i_ino == ECFS_ACL_IDX_INO ||
54 inode->i_ino == ECFS_ACL_DATA_INO)
55 goto no_delete;
56 inode->u.ecfs_i.i_dtime = CURRENT_TIME;
57 mark_inode_dirty(inode);
58 ecfs_update_inode(inode, IS_SYNC(inode));
59 inode->i_size = 0;
60 if (inode->i_blocks)
61 ecfs_truncate (inode);
62 ecfs_free_inode (inode);
63
64 unlock_kernel();
65 return;
66no_delete:
67 unlock_kernel();
68 clear_inode(inode); /* We must guarantee clearing of inode... */
69}
70
71void ecfs_discard_prealloc (struct inode * inode)
72{
73#ifdef ECFS_PREALLOCATE
74 lock_kernel();
75 /* Writer: ->i_prealloc* */
76 if (inode->u.ecfs_i.i_prealloc_count) {
77 unsigned short total = inode->u.ecfs_i.i_prealloc_count;
78 unsigned long block = inode->u.ecfs_i.i_prealloc_block;
79 inode->u.ecfs_i.i_prealloc_count = 0;
80 inode->u.ecfs_i.i_prealloc_block = 0;
81 /* Writer: end */
82 ecfs_free_blocks (inode, block, total);
83 }
84 unlock_kernel();
85#endif
86}
87
88static int ecfs_alloc_block (struct inode * inode, unsigned long goal, int *err)
89{
90#ifdef ECFSFS_DEBUG
91 static unsigned long alloc_hits = 0, alloc_attempts = 0;
92#endif
93 unsigned long result;
94
95
96#ifdef ECFS_PREALLOCATE
97 /* Writer: ->i_prealloc* */
98 if (inode->u.ecfs_i.i_prealloc_count &&
99 (goal == inode->u.ecfs_i.i_prealloc_block ||
100 goal + 1 == inode->u.ecfs_i.i_prealloc_block))
101 {
102 result = inode->u.ecfs_i.i_prealloc_block++;
103 inode->u.ecfs_i.i_prealloc_count--;
104 /* Writer: end */
105#ifdef ECFSFS_DEBUG
106 ecfs_debug ("preallocation hit (%lu/%lu).\n",
107 ++alloc_hits, ++alloc_attempts);
108#endif
109 } else {
110 ecfs_discard_prealloc (inode);
111#ifdef ECFSFS_DEBUG
112 ecfs_debug ("preallocation miss (%lu/%lu).\n",
113 alloc_hits, ++alloc_attempts);
114#endif
115 if (S_ISREG(inode->i_mode))
116 result = ecfs_new_block (inode, goal,
117 &inode->u.ecfs_i.i_prealloc_count,
118 &inode->u.ecfs_i.i_prealloc_block, err);
119 else
120 result = ecfs_new_block (inode, goal, 0, 0, err);
121 }
122#else
123 result = ecfs_new_block (inode, goal, 0, 0, err);
124#endif
125 return result;
126}
127
128typedef struct {
129 u32 *p;
130 u32 key;
131 struct buffer_head *bh;
132} Indirect;
133
134static inline void add_chain(Indirect *p, struct buffer_head *bh, u32 *v)
135{
136 p->key = *(p->p = v);
137 p->bh = bh;
138}
139
140static inline int verify_chain(Indirect *from, Indirect *to)
141{
142 while (from <= to && from->key == *from->p)
143 from++;
144 return (from > to);
145}
146
147/**
148 * ecfs_block_to_path - parse the block number into array of offsets
149 * @inode: inode in question (we are only interested in its superblock)
150 * @i_block: block number to be parsed
151 * @offsets: array to store the offsets in
152 *
153 * To store the locations of file's data ecfs uses a data structure common
154 * for UNIX filesystems - tree of pointers anchored in the inode, with
155 * data blocks at leaves and indirect blocks in intermediate nodes.
156 * This function translates the block number into path in that tree -
157 * return value is the path length and @offsets[n] is the offset of
158 * pointer to (n+1)th node in the nth one. If @block is out of range
159 * (negative or too large) warning is printed and zero returned.
160 *
161 * Note: function doesn't find node addresses, so no IO is needed. All
162 * we need to know is the capacity of indirect blocks (taken from the
163 * inode->i_sb).
164 */
165
166/*
167 * Portability note: the last comparison (check that we fit into triple
168 * indirect block) is spelled differently, because otherwise on an
169 * architecture with 32-bit longs and 8Kb pages we might get into trouble
170 * if our filesystem had 8Kb blocks. We might use long long, but that would
171 * kill us on x86. Oh, well, at least the sign propagation does not matter -
172 * i_block would have to be negative in the very beginning, so we would not
173 * get there at all.
174 */
175
176static int ecfs_block_to_path(struct inode *inode, long i_block, int offsets[4])
177{
178 int ptrs = ECFS_ADDR_PER_BLOCK(inode->i_sb);
179 int ptrs_bits = ECFS_ADDR_PER_BLOCK_BITS(inode->i_sb);
180 const long direct_blocks = ECFS_NDIR_BLOCKS,
181 indirect_blocks = ptrs,
182 double_blocks = (1 << (ptrs_bits * 2));
183 int n = 0;
184
185 if (i_block < 0) {
186 ecfs_warning (inode->i_sb, "ecfs_block_to_path", "block < 0");
187 } else if (i_block < direct_blocks) {
188 offsets[n++] = i_block;
189 } else if ( (i_block -= direct_blocks) < indirect_blocks) {
190 offsets[n++] = ECFS_IND_BLOCK;
191 offsets[n++] = i_block;
192 } else if ((i_block -= indirect_blocks) < double_blocks) {
193 offsets[n++] = ECFS_DIND_BLOCK;
194 offsets[n++] = i_block >> ptrs_bits;
195 offsets[n++] = i_block & (ptrs - 1);
196 } else if (((i_block -= double_blocks) >> (ptrs_bits * 2)) < ptrs) {
197 offsets[n++] = ECFS_TIND_BLOCK;
198 offsets[n++] = i_block >> (ptrs_bits * 2);
199 offsets[n++] = (i_block >> ptrs_bits) & (ptrs - 1);
200 offsets[n++] = i_block & (ptrs - 1);
201 } else {
202 ecfs_warning (inode->i_sb, "ecfs_block_to_path", "block > big");
203 }
204 return n;
205}
206
207/**
208 * ecfs_get_branch - read the chain of indirect blocks leading to data
209 * @inode: inode in question
210 * @depth: depth of the chain (1 - direct pointer, etc.)
211 * @offsets: offsets of pointers in inode/indirect blocks
212 * @chain: place to store the result
213 * @err: here we store the error value
214 *
215 * Function fills the array of triples <key, p, bh> and returns %NULL
216 * if everything went OK or the pointer to the last filled triple
217 * (incomplete one) otherwise. Upon the return chain[i].key contains
218 * the number of (i+1)-th block in the chain (as it is stored in memory,
219 * i.e. little-endian 32-bit), chain[i].p contains the address of that
220 * number (it points into struct inode for i==0 and into the bh->b_data
221 * for i>0) and chain[i].bh points to the buffer_head of i-th indirect
222 * block for i>0 and NULL for i==0. In other words, it holds the block
223 * numbers of the chain, addresses they were taken from (and where we can
224 * verify that chain did not change) and buffer_heads hosting these
225 * numbers.
226 *
227 * Function stops when it stumbles upon zero pointer (absent block)
228 * (pointer to last triple returned, *@err == 0)
229 * or when it gets an IO error reading an indirect block
230 * (ditto, *@err == -EIO)
231 * or when it notices that chain had been changed while it was reading
232 * (ditto, *@err == -EAGAIN)
233 * or when it reads all @depth-1 indirect blocks successfully and finds
234 * the whole chain, all way to the data (returns %NULL, *err == 0).
235 */
236static inline Indirect *ecfs_get_branch(struct inode *inode,
237 int depth,
238 int *offsets,
239 Indirect chain[4],
240 int *err)
241{
242 kdev_t dev = inode->i_dev;
243 int size = inode->i_sb->s_blocksize;
244 Indirect *p = chain;
245 struct buffer_head *bh;
246
247 *err = 0;
248 /* i_data is not going away, no lock needed */
249 add_chain (chain, NULL, inode->u.ecfs_i.i_data + *offsets);
250 if (!p->key)
251 goto no_block;
252 while (--depth) {
253 bh = bread(dev, le32_to_cpu(p->key), size);
254 if (!bh)
255 goto failure;
256 /* Reader: pointers */
257 if (!verify_chain(chain, p))
258 goto changed;
259 add_chain(++p, bh, (u32*)bh->b_data + *++offsets);
260 /* Reader: end */
261 if (!p->key)
262 goto no_block;
263 }
264 return NULL;
265
266changed:
267 *err = -EAGAIN;
268 goto no_block;
269failure:
270 *err = -EIO;
271no_block:
272 return p;
273}
274
275/**
276 * ecfs_find_near - find a place for allocation with sufficient locality
277 * @inode: owner
278 * @ind: descriptor of indirect block.
279 *
280 * This function returns the prefered place for block allocation.
281 * It is used when heuristic for sequential allocation fails.
282 * Rules are:
283 * + if there is a block to the left of our position - allocate near it.
284 * + if pointer will live in indirect block - allocate near that block.
285 * + if pointer will live in inode - allocate in the same cylinder group.
286 * Caller must make sure that @ind is valid and will stay that way.
287 */
288
289static inline unsigned long ecfs_find_near(struct inode *inode, Indirect *ind)
290{
291 u32 *start = ind->bh ? (u32*) ind->bh->b_data : inode->u.ecfs_i.i_data;
292 u32 *p;
293
294 /* Try to find previous block */
295 for (p = ind->p - 1; p >= start; p--)
296 if (*p)
297 return le32_to_cpu(*p);
298
299 /* No such thing, so let's try location of indirect block */
300 if (ind->bh)
301 return ind->bh->b_blocknr;
302
303 /*
304 * It is going to be refered from inode itself? OK, just put it into
305 * the same cylinder group then.
306 */
307 return (inode->u.ecfs_i.i_block_group *
308 ECFS_BLOCKS_PER_GROUP(inode->i_sb)) +
309 le32_to_cpu(inode->i_sb->u.ecfs_sb.s_es->s_first_data_block);
310}
311
312/**
313 * ecfs_find_goal - find a prefered place for allocation.
314 * @inode: owner
315 * @block: block we want
316 * @chain: chain of indirect blocks
317 * @partial: pointer to the last triple within a chain
318 * @goal: place to store the result.
319 *
320 * Normally this function find the prefered place for block allocation,
321 * stores it in *@goal and returns zero. If the branch had been changed
322 * under us we return -EAGAIN.
323 */
324
325static inline int ecfs_find_goal(struct inode *inode,
326 long block,
327 Indirect chain[4],
328 Indirect *partial,
329 unsigned long *goal)
330{
331 /* Writer: ->i_next_alloc* */
332 if (block == inode->u.ecfs_i.i_next_alloc_block + 1) {
333 inode->u.ecfs_i.i_next_alloc_block++;
334 inode->u.ecfs_i.i_next_alloc_goal++;
335 }
336 /* Writer: end */
337 /* Reader: pointers, ->i_next_alloc* */
338 if (verify_chain(chain, partial)) {
339 /*
340 * try the heuristic for sequential allocation,
341 * failing that at least try to get decent locality.
342 */
343 if (block == inode->u.ecfs_i.i_next_alloc_block)
344 *goal = inode->u.ecfs_i.i_next_alloc_goal;
345 if (!*goal)
346 *goal = ecfs_find_near(inode, partial);
347 return 0;
348 }
349 /* Reader: end */
350 return -EAGAIN;
351}
352
353/**
354 * ecfs_alloc_branch - allocate and set up a chain of blocks.
355 * @inode: owner
356 * @num: depth of the chain (number of blocks to allocate)
357 * @offsets: offsets (in the blocks) to store the pointers to next.
358 * @branch: place to store the chain in.
359 *
360 * This function allocates @num blocks, zeroes out all but the last one,
361 * links them into chain and (if we are synchronous) writes them to disk.
362 * In other words, it prepares a branch that can be spliced onto the
363 * inode. It stores the information about that chain in the branch[], in
364 * the same format as ecfs_get_branch() would do. We are calling it after
365 * we had read the existing part of chain and partial points to the last
366 * triple of that (one with zero ->key). Upon the exit we have the same
367 * picture as after the successful ecfs_get_block(), excpet that in one
368 * place chain is disconnected - *branch->p is still zero (we did not
369 * set the last link), but branch->key contains the number that should
370 * be placed into *branch->p to fill that gap.
371 *
372 * If allocation fails we free all blocks we've allocated (and forget
373 * ther buffer_heads) and return the error value the from failed
374 * ecfs_alloc_block() (normally -ENOSPC). Otherwise we set the chain
375 * as described above and return 0.
376 */
377
378static int ecfs_alloc_branch(struct inode *inode,
379 int num,
380 unsigned long goal,
381 int *offsets,
382 Indirect *branch)
383{
384 int blocksize = inode->i_sb->s_blocksize;
385 int n = 0;
386 int err;
387 int i;
388 int parent = ecfs_alloc_block(inode, goal, &err);
389
390 branch[0].key = cpu_to_le32(parent);
391 if (parent) for (n = 1; n < num; n++) {
392 struct buffer_head *bh;
393 /* Allocate the next block */
394 int nr = ecfs_alloc_block(inode, parent, &err);
395 if (!nr)
396 break;
397 branch[n].key = cpu_to_le32(nr);
398 /*
399 * Get buffer_head for parent block, zero it out and set
400 * the pointer to new one, then send parent to disk.
401 */
402 bh = getblk(inode->i_dev, parent, blocksize);
403 if (!buffer_uptodate(bh))
404 wait_on_buffer(bh);
405 memset(bh->b_data, 0, blocksize);
406 branch[n].bh = bh;
407 branch[n].p = (u32*) bh->b_data + offsets[n];
408 *branch[n].p = branch[n].key;
409 mark_buffer_uptodate(bh, 1);
410 mark_buffer_dirty_inode(bh, inode);
411 if (IS_SYNC(inode) || inode->u.ecfs_i.i_osync) {
412 ll_rw_block (WRITE, 1, &bh);
413 wait_on_buffer (bh);
414 }
415 parent = nr;
416 }
417 if (n == num)
418 return 0;
419
420 /* Allocation failed, free what we already allocated */
421 for (i = 1; i < n; i++)
422 bforget(branch[i].bh);
423 for (i = 0; i < n; i++)
424 ecfs_free_blocks(inode, le32_to_cpu(branch[i].key), 1);
425 return err;
426}
427
428/**
429 * ecfs_splice_branch - splice the allocated branch onto inode.
430 * @inode: owner
431 * @block: (logical) number of block we are adding
432 * @chain: chain of indirect blocks (with a missing link - see
433 * ecfs_alloc_branch)
434 * @where: location of missing link
435 * @num: number of blocks we are adding
436 *
437 * This function verifies that chain (up to the missing link) had not
438 * changed, fills the missing link and does all housekeeping needed in
439 * inode (->i_blocks, etc.). In case of success we end up with the full
440 * chain to new block and return 0. Otherwise (== chain had been changed)
441 * we free the new blocks (forgetting their buffer_heads, indeed) and
442 * return -EAGAIN.
443 */
444
445static inline int ecfs_splice_branch(struct inode *inode,
446 long block,
447 Indirect chain[4],
448 Indirect *where,
449 int num)
450{
451 int i;
452
453 /* Verify that place we are splicing to is still there and vacant */
454
455 /* Writer: pointers, ->i_next_alloc*, ->i_blocks */
456 if (!verify_chain(chain, where-1) || *where->p)
457 /* Writer: end */
458 goto changed;
459
460 /* That's it */
461
462 *where->p = where->key;
463 inode->u.ecfs_i.i_next_alloc_block = block;
464 inode->u.ecfs_i.i_next_alloc_goal = le32_to_cpu(where[num-1].key);
465 inode->i_blocks += num * inode->i_sb->s_blocksize/512;
466
467 /* Writer: end */
468
469 /* We are done with atomic stuff, now do the rest of housekeeping */
470
471 inode->i_ctime = CURRENT_TIME;
472
473 /* had we spliced it onto indirect block? */
474 if (where->bh) {
475 mark_buffer_dirty_inode(where->bh, inode);
476 if (IS_SYNC(inode) || inode->u.ecfs_i.i_osync) {
477 ll_rw_block (WRITE, 1, &where->bh);
478 wait_on_buffer(where->bh);
479 }
480 }
481
482 if (IS_SYNC(inode) || inode->u.ecfs_i.i_osync)
483 ecfs_sync_inode (inode);
484 else
485 mark_inode_dirty(inode);
486 return 0;
487
488changed:
489 for (i = 1; i < num; i++)
490 bforget(where[i].bh);
491 for (i = 0; i < num; i++)
492 ecfs_free_blocks(inode, le32_to_cpu(where[i].key), 1);
493 return -EAGAIN;
494}
495
496/*
497 * Allocation strategy is simple: if we have to allocate something, we will
498 * have to go the whole way to leaf. So let's do it before attaching anything
499 * to tree, set linkage between the newborn blocks, write them if sync is
500 * required, recheck the path, free and repeat if check fails, otherwise
501 * set the last missing link (that will protect us from any truncate-generated
502 * removals - all blocks on the path are immune now) and possibly force the
503 * write on the parent block.
504 * That has a nice additional property: no special recovery from the failed
505 * allocations is needed - we simply release blocks and do not touch anything
506 * reachable from inode.
507 */
508
509static int ecfs_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create)
510{
511 int err = -EIO;
512 int offsets[4];
513 Indirect chain[4];
514 Indirect *partial;
515 unsigned long goal;
516 int left;
517 int depth = ecfs_block_to_path(inode, iblock, offsets);
518
519 if (depth == 0)
520 goto out;
521
522 lock_kernel();
523reread:
524 partial = ecfs_get_branch(inode, depth, offsets, chain, &err);
525
526 /* Simplest case - block found, no allocation needed */
527 if (!partial) {
528got_it:
529 bh_result->b_dev = inode->i_dev;
530 bh_result->b_blocknr = le32_to_cpu(chain[depth-1].key);
531 bh_result->b_state |= (1UL << BH_Mapped);
532 /* Clean up and exit */
533 partial = chain+depth-1; /* the whole chain */
534 goto cleanup;
535 }
536
537 /* Next simple case - plain lookup or failed read of indirect block */
538 if (!create || err == -EIO) {
539cleanup:
540 while (partial > chain) {
541 brelse(partial->bh);
542 partial--;
543 }
544 unlock_kernel();
545out:
546 return err;
547 }
548
549 /*
550 * Indirect block might be removed by truncate while we were
551 * reading it. Handling of that case (forget what we've got and
552 * reread) is taken out of the main path.
553 */
554 if (err == -EAGAIN)
555 goto changed;
556
557 if (ecfs_find_goal(inode, iblock, chain, partial, &goal) < 0)
558 goto changed;
559
560 left = (chain + depth) - partial;
561 err = ecfs_alloc_branch(inode, left, goal,
562 offsets+(partial-chain), partial);
563 if (err)
564 goto cleanup;
565
566 if (ecfs_splice_branch(inode, iblock, chain, partial, left) < 0)
567 goto changed;
568
569 bh_result->b_state |= (1UL << BH_New);
570 goto got_it;
571
572changed:
573 while (partial > chain) {
574 bforget(partial->bh);
575 partial--;
576 }
577 goto reread;
578}
579
580struct buffer_head * ecfs_getblk(struct inode * inode, long block, int create, int * err)
581{
582 struct buffer_head dummy;
583 int error;
584
585 dummy.b_state = 0;
586 dummy.b_blocknr = -1000;
587 error = ecfs_get_block(inode, block, &dummy, create);
588 *err = error;
589 if (!error && buffer_mapped(&dummy)) {
590 struct buffer_head *bh;
591 bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize);
592
593 if (buffer_new(&dummy)) {
594 if (!buffer_uptodate(bh))
595 wait_on_buffer(bh);
596 memset(bh->b_data, 0, inode->i_sb->s_blocksize);
597 mark_buffer_uptodate(bh, 1);
598 mark_buffer_dirty_inode(bh, inode);
599 }
600 return bh;
601 }
602 return NULL;
603}
604
605struct buffer_head * ecfs_bread (struct inode * inode, int block,
606 int create, int *err)
607{
608 struct buffer_head * bh;
609 int prev_blocks;
610
611 prev_blocks = inode->i_blocks;
612
613 bh = ecfs_getblk (inode, block, create, err);
614 if (!bh)
615 return bh;
616
617 /*
618 * If the inode has grown, and this is a directory, then perform
619 * preallocation of a few more blocks to try to keep directory
620 * fragmentation down.
621 */
622 if (create &&
623 S_ISDIR(inode->i_mode) &&
624 inode->i_blocks > prev_blocks &&
625 ECFS_HAS_COMPAT_FEATURE(inode->i_sb,
626 ECFS_FEATURE_COMPAT_DIR_PREALLOC)) {
627 int i;
628 struct buffer_head *tmp_bh;
629
630 for (i = 1;
631 i < ECFS_SB(inode->i_sb)->s_es->s_prealloc_dir_blocks;
632 i++) {
633 /*
634 * ecfs_getblk will zero out the contents of the
635 * directory for us
636 */
637 tmp_bh = ecfs_getblk(inode, block+i, create, err);
638 if (!tmp_bh) {
639 brelse (bh);
640 return 0;
641 }
642 brelse (tmp_bh);
643 }
644 }
645
646 if (buffer_uptodate(bh))
647 return bh;
648 ll_rw_block (READ, 1, &bh);
649 wait_on_buffer (bh);
650 if (buffer_uptodate(bh))
651 return bh;
652 brelse (bh);
653 *err = -EIO;
654 return NULL;
655}
656
657static int ecfs_writepage(struct page *page)
658{
659 return block_write_full_page(page,ecfs_get_block);
660}
661
662
663static int ecfs_readpage(struct file *file, struct page *page)
664{
665 return block_read_full_page(page,ecfs_get_block);
666
667/*
668 ptr = page->virtual;
669
670#define PAGE_PLAIN 22
671
672 printk("<1> ecfs_readpage() %d\n", from);
673 if (!ptr || !test_bit(PAGE_PLAIN, &page->flags))
674 return r;
675
676 prepare_key(ecfs_key, strlen(ecfs_key), &rc4key);
677 rc4(ptr, PAGE_SIZE, &rc4key, from);
678 clear_bit(PAGE_PLAIN, &page->flags);
679
680 printk("<1>HHHH ecfs_readpage() %d\n", from);
681
682 return r;
683*/
684
685}
686
687
688static int ecfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
689{
690 return block_prepare_write(page,from,to,ecfs_get_block);
691}
692
693
694static int ecfs_bmap(struct address_space *mapping, long block)
695{
696 return generic_block_bmap(mapping,block,ecfs_get_block);
697}
698
699
700struct address_space_operations ecfs_aops = {
701 readpage: ecfs_readpage,
702 writepage: ecfs_writepage,
703 sync_page: block_sync_page,
704 prepare_write: ecfs_prepare_write,
705 commit_write: generic_commit_write,
706 bmap: ecfs_bmap
707};
708
709/*
710 * Probably it should be a library function... search for first non-zero word
711 * or memcmp with zero_page, whatever is better for particular architecture.
712 * Linus?
713 */
714static inline int all_zeroes(u32 *p, u32 *q)
715{
716 while (p < q)
717 if (*p++)
718 return 0;
719 return 1;
720}
721
722/**
723 * ecfs_find_shared - find the indirect blocks for partial truncation.
724 * @inode: inode in question
725 * @depth: depth of the affected branch
726 * @offsets: offsets of pointers in that branch (see ecfs_block_to_path)
727 * @chain: place to store the pointers to partial indirect blocks
728 * @top: place to the (detached) top of branch
729 *
730 * This is a helper function used by ecfs_truncate().
731 *
732 * When we do truncate() we may have to clean the ends of several indirect
733 * blocks but leave the blocks themselves alive. Block is partially
734 * truncated if some data below the new i_size is refered from it (and
735 * it is on the path to the first completely truncated data block, indeed).
736 * We have to free the top of that path along with everything to the right
737 * of the path. Since no allocation past the truncation point is possible
738 * until ecfs_truncate() finishes, we may safely do the latter, but top
739 * of branch may require special attention - pageout below the truncation
740 * point might try to populate it.
741 *
742 * We atomically detach the top of branch from the tree, store the block
743 * number of its root in *@top, pointers to buffer_heads of partially
744 * truncated blocks - in @chain[].bh and pointers to their last elements
745 * that should not be removed - in @chain[].p. Return value is the pointer
746 * to last filled element of @chain.
747 *
748 * The work left to caller to do the actual freeing of subtrees:
749 * a) free the subtree starting from *@top
750 * b) free the subtrees whose roots are stored in
751 * (@chain[i].p+1 .. end of @chain[i].bh->b_data)
752 * c) free the subtrees growing from the inode past the @chain[0].p
753 * (no partially truncated stuff there).
754 */
755
756static Indirect *ecfs_find_shared(struct inode *inode,
757 int depth,
758 int offsets[4],
759 Indirect chain[4],
760 u32 *top)
761{
762 Indirect *partial, *p;
763 int k, err;
764
765 *top = 0;
766 for (k = depth; k > 1 && !offsets[k-1]; k--)
767 ;
768 partial = ecfs_get_branch(inode, k, offsets, chain, &err);
769 /* Writer: pointers */
770 if (!partial)
771 partial = chain + k-1;
772 /*
773 * If the branch acquired continuation since we've looked at it -
774 * fine, it should all survive and (new) top doesn't belong to us.
775 */
776 if (!partial->key && *partial->p)
777 /* Writer: end */
778 goto no_top;
779 for (p=partial; p>chain && all_zeroes((u32*)p->bh->b_data,p->p); p--)
780 ;
781 /*
782 * OK, we've found the last block that must survive. The rest of our
783 * branch should be detached before unlocking. However, if that rest
784 * of branch is all ours and does not grow immediately from the inode
785 * it's easier to cheat and just decrement partial->p.
786 */
787 if (p == chain + k - 1 && p > chain) {
788 p->p--;
789 } else {
790 *top = *p->p;
791 *p->p = 0;
792 }
793 /* Writer: end */
794
795 while(partial > p)
796 {
797 brelse(partial->bh);
798 partial--;
799 }
800no_top:
801 return partial;
802}
803
804/**
805 * ecfs_free_data - free a list of data blocks
806 * @inode: inode we are dealing with
807 * @p: array of block numbers
808 * @q: points immediately past the end of array
809 *
810 * We are freeing all blocks refered from that array (numbers are
811 * stored as little-endian 32-bit) and updating @inode->i_blocks
812 * appropriately.
813 */
814static inline void ecfs_free_data(struct inode *inode, u32 *p, u32 *q)
815{
816 int blocks = inode->i_sb->s_blocksize / 512;
817 unsigned long block_to_free = 0, count = 0;
818 unsigned long nr;
819
820 for ( ; p < q ; p++) {
821 nr = le32_to_cpu(*p);
822 if (nr) {
823 *p = 0;
824 /* accumulate blocks to free if they're contiguous */
825 if (count == 0)
826 goto free_this;
827 else if (block_to_free == nr - count)
828 count++;
829 else {
830 /* Writer: ->i_blocks */
831 inode->i_blocks -= blocks * count;
832 /* Writer: end */
833 ecfs_free_blocks (inode, block_to_free, count);
834 mark_inode_dirty(inode);
835 free_this:
836 block_to_free = nr;
837 count = 1;
838 }
839 }
840 }
841 if (count > 0) {
842 /* Writer: ->i_blocks */
843 inode->i_blocks -= blocks * count;
844 /* Writer: end */
845 ecfs_free_blocks (inode, block_to_free, count);
846 mark_inode_dirty(inode);
847 }
848}
849
850/**
851 * ecfs_free_branches - free an array of branches
852 * @inode: inode we are dealing with
853 * @p: array of block numbers
854 * @q: pointer immediately past the end of array
855 * @depth: depth of the branches to free
856 *
857 * We are freeing all blocks refered from these branches (numbers are
858 * stored as little-endian 32-bit) and updating @inode->i_blocks
859 * appropriately.
860 */
861static void ecfs_free_branches(struct inode *inode, u32 *p, u32 *q, int depth)
862{
863 struct buffer_head * bh;
864 unsigned long nr;
865
866 if (depth--) {
867 int addr_per_block = ECFS_ADDR_PER_BLOCK(inode->i_sb);
868 for ( ; p < q ; p++) {
869 nr = le32_to_cpu(*p);
870 if (!nr)
871 continue;
872 *p = 0;
873 bh = bread (inode->i_dev, nr, inode->i_sb->s_blocksize);
874 /*
875 * A read failure? Report error and clear slot
876 * (should be rare).
877 */
878 if (!bh) {
879 ecfs_error(inode->i_sb, "ecfs_free_branches",
880 "Read failure, inode=%ld, block=%ld",
881 inode->i_ino, nr);
882 continue;
883 }
884 ecfs_free_branches(inode,
885 (u32*)bh->b_data,
886 (u32*)bh->b_data + addr_per_block,
887 depth);
888 bforget(bh);
889 /* Writer: ->i_blocks */
890 inode->i_blocks -= inode->i_sb->s_blocksize / 512;
891 /* Writer: end */
892 ecfs_free_blocks(inode, nr, 1);
893 mark_inode_dirty(inode);
894 }
895 } else
896 ecfs_free_data(inode, p, q);
897}
898
899void ecfs_truncate (struct inode * inode)
900{
901 u32 *i_data = inode->u.ecfs_i.i_data;
902 int addr_per_block = ECFS_ADDR_PER_BLOCK(inode->i_sb);
903 int offsets[4];
904 Indirect chain[4];
905 Indirect *partial;
906 int nr = 0;
907 int n;
908 long iblock;
909 unsigned blocksize;
910
911 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
912 S_ISLNK(inode->i_mode)))
913 return;
914 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
915 return;
916
917 ecfs_discard_prealloc(inode);
918
919 blocksize = inode->i_sb->s_blocksize;
920 iblock = (inode->i_size + blocksize-1)
921 >> ECFS_BLOCK_SIZE_BITS(inode->i_sb);
922
923 block_truncate_page(inode->i_mapping, inode->i_size, ecfs_get_block);
924
925 n = ecfs_block_to_path(inode, iblock, offsets);
926 if (n == 0)
927 return;
928
929 if (n == 1) {
930 ecfs_free_data(inode, i_data+offsets[0],
931 i_data + ECFS_NDIR_BLOCKS);
932 goto do_indirects;
933 }
934
935 partial = ecfs_find_shared(inode, n, offsets, chain, &nr);
936 /* Kill the top of shared branch (already detached) */
937 if (nr) {
938 if (partial == chain)
939 mark_inode_dirty(inode);
940 else
941 mark_buffer_dirty_inode(partial->bh, inode);
942 ecfs_free_branches(inode, &nr, &nr+1, (chain+n-1) - partial);
943 }
944 /* Clear the ends of indirect blocks on the shared branch */
945 while (partial > chain) {
946 ecfs_free_branches(inode,
947 partial->p + 1,
948 (u32*)partial->bh->b_data + addr_per_block,
949 (chain+n-1) - partial);
950 mark_buffer_dirty_inode(partial->bh, inode);
951 if (IS_SYNC(inode)) {
952 ll_rw_block (WRITE, 1, &partial->bh);
953 wait_on_buffer (partial->bh);
954 }
955 brelse (partial->bh);
956 partial--;
957 }
958do_indirects:
959 /* Kill the remaining (whole) subtrees */
960 switch (offsets[0]) {
961 default:
962 nr = i_data[ECFS_IND_BLOCK];
963 if (nr) {
964 i_data[ECFS_IND_BLOCK] = 0;
965 mark_inode_dirty(inode);
966 ecfs_free_branches(inode, &nr, &nr+1, 1);
967 }
968 case ECFS_IND_BLOCK:
969 nr = i_data[ECFS_DIND_BLOCK];
970 if (nr) {
971 i_data[ECFS_DIND_BLOCK] = 0;
972 mark_inode_dirty(inode);
973 ecfs_free_branches(inode, &nr, &nr+1, 2);
974 }
975 case ECFS_DIND_BLOCK:
976 nr = i_data[ECFS_TIND_BLOCK];
977 if (nr) {
978 i_data[ECFS_TIND_BLOCK] = 0;
979 mark_inode_dirty(inode);
980 ecfs_free_branches(inode, &nr, &nr+1, 3);
981 }
982 case ECFS_TIND_BLOCK:
983 ;
984 }
985 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
986 if (IS_SYNC(inode))
987 ecfs_sync_inode (inode);
988 else
989 mark_inode_dirty(inode);
990}
991
992void ecfs_read_inode (struct inode * inode)
993{
994 struct buffer_head * bh;
995 struct ecfs_inode * raw_inode;
996 unsigned long block_group;
997 unsigned long group_desc;
998 unsigned long desc;
999 unsigned long block;
1000 unsigned long offset;
1001 struct ecfs_group_desc * gdp;
1002
1003 if ((inode->i_ino != ECFS_ROOT_INO && inode->i_ino != ECFS_ACL_IDX_INO &&
1004 inode->i_ino != ECFS_ACL_DATA_INO &&
1005 inode->i_ino < ECFS_FIRST_INO(inode->i_sb)) ||
1006 inode->i_ino > le32_to_cpu(inode->i_sb->u.ecfs_sb.s_es->s_inodes_count)) {
1007 ecfs_error (inode->i_sb, "ecfs_read_inode",
1008 "bad inode number: %lu", inode->i_ino);
1009 goto bad_inode;
1010 }
1011 block_group = (inode->i_ino - 1) / ECFS_INODES_PER_GROUP(inode->i_sb);
1012 if (block_group >= inode->i_sb->u.ecfs_sb.s_groups_count) {
1013 ecfs_error (inode->i_sb, "ecfs_read_inode",
1014 "group >= groups count");
1015 goto bad_inode;
1016 }
1017 group_desc = block_group >> ECFS_DESC_PER_BLOCK_BITS(inode->i_sb);
1018 desc = block_group & (ECFS_DESC_PER_BLOCK(inode->i_sb) - 1);
1019 bh = inode->i_sb->u.ecfs_sb.s_group_desc[group_desc];
1020 if (!bh) {
1021 ecfs_error (inode->i_sb, "ecfs_read_inode",
1022 "Descriptor not loaded");
1023 goto bad_inode;
1024 }
1025
1026 gdp = (struct ecfs_group_desc *) bh->b_data;
1027 /*
1028 * Figure out the offset within the block group inode table
1029 */
1030 offset = ((inode->i_ino - 1) % ECFS_INODES_PER_GROUP(inode->i_sb)) *
1031 ECFS_INODE_SIZE(inode->i_sb);
1032 block = le32_to_cpu(gdp[desc].bg_inode_table) +
1033 (offset >> ECFS_BLOCK_SIZE_BITS(inode->i_sb));
1034 if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize))) {
1035 ecfs_error (inode->i_sb, "ecfs_read_inode",
1036 "unable to read inode block - "
1037 "inode=%lu, block=%lu", inode->i_ino, block);
1038 goto bad_inode;
1039 }
1040 offset &= (ECFS_BLOCK_SIZE(inode->i_sb) - 1);
1041 raw_inode = (struct ecfs_inode *) (bh->b_data + offset);
1042
1043 inode->i_mode = le16_to_cpu(raw_inode->i_mode);
1044 inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);
1045 inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low);
1046 if(!(test_opt (inode->i_sb, NO_UID32))) {
1047 inode->i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16;
1048 inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16;
1049 }
1050 inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
1051 inode->i_size = le32_to_cpu(raw_inode->i_size);
1052 inode->i_atime = le32_to_cpu(raw_inode->i_atime);
1053 inode->i_ctime = le32_to_cpu(raw_inode->i_ctime);
1054 inode->i_mtime = le32_to_cpu(raw_inode->i_mtime);
1055 inode->u.ecfs_i.i_dtime = le32_to_cpu(raw_inode->i_dtime);
1056 /* We now have enough fields to check if the inode was active or not.
1057 * This is needed because nfsd might try to access dead inodes
1058 * the test is that same one that e2fsck uses
1059 * NeilBrown 1999oct15
1060 */
1061 if (inode->i_nlink == 0 && (inode->i_mode == 0 || inode->u.ecfs_i.i_dtime)) {
1062 /* this inode is deleted */
1063 brelse (bh);
1064 goto bad_inode;
1065 }
1066 inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size (for stat), not the fs block size */
1067 inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
1068 inode->i_version = ++event;
1069 inode->u.ecfs_i.i_flags = le32_to_cpu(raw_inode->i_flags);
1070 inode->u.ecfs_i.i_faddr = le32_to_cpu(raw_inode->i_faddr);
1071 inode->u.ecfs_i.i_frag_no = raw_inode->i_frag;
1072 inode->u.ecfs_i.i_frag_size = raw_inode->i_fsize;
1073 inode->u.ecfs_i.i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
1074 if (S_ISDIR(inode->i_mode))
1075 inode->u.ecfs_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
1076 else {
1077 inode->u.ecfs_i.i_high_size = le32_to_cpu(raw_inode->i_size_high);
1078 inode->i_size |= ((__u64)le32_to_cpu(raw_inode->i_size_high)) << 32;
1079 }
1080 inode->i_generation = le32_to_cpu(raw_inode->i_generation);
1081 inode->u.ecfs_i.i_block_group = block_group;
1082
1083 /*
1084 * NOTE! The in-memory inode i_data array is in little-endian order
1085 * even on big-endian machines: we do NOT byteswap the block numbers!
1086 */
1087 for (block = 0; block < ECFS_N_BLOCKS; block++)
1088 inode->u.ecfs_i.i_data[block] = raw_inode->i_block[block];
1089
1090 if (inode->i_ino == ECFS_ACL_IDX_INO ||
1091 inode->i_ino == ECFS_ACL_DATA_INO)
1092 /* Nothing to do */ ;
1093 else if (S_ISREG(inode->i_mode)) {
1094 inode->i_op = &ecfs_file_inode_operations;
1095 inode->i_fop = &ecfs_file_operations;
1096 inode->i_mapping->a_ops = &ecfs_aops;
1097 } else if (S_ISDIR(inode->i_mode)) {
1098 inode->i_op = &ecfs_dir_inode_operations;
1099 inode->i_fop = &ecfs_dir_operations;
1100 } else if (S_ISLNK(inode->i_mode)) {
1101 if (!inode->i_blocks)
1102 inode->i_op = &ecfs_fast_symlink_inode_operations;
1103 else {
1104 inode->i_op = &page_symlink_inode_operations;
1105 inode->i_mapping->a_ops = &ecfs_aops;
1106 }
1107 } else
1108 init_special_inode(inode, inode->i_mode,
1109 le32_to_cpu(raw_inode->i_block[0]));
1110 brelse (bh);
1111 inode->i_attr_flags = 0;
1112 if (inode->u.ecfs_i.i_flags & ECFS_SYNC_FL) {
1113 inode->i_attr_flags |= ATTR_FLAG_SYNCRONOUS;
1114 inode->i_flags |= S_SYNC;
1115 }
1116 if (inode->u.ecfs_i.i_flags & ECFS_APPEND_FL) {
1117 inode->i_attr_flags |= ATTR_FLAG_APPEND;
1118 inode->i_flags |= S_APPEND;
1119 }
1120 if (inode->u.ecfs_i.i_flags & ECFS_IMMUTABLE_FL) {
1121 inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE;
1122 inode->i_flags |= S_IMMUTABLE;
1123 }
1124 if (inode->u.ecfs_i.i_flags & ECFS_NOATIME_FL) {
1125 inode->i_attr_flags |= ATTR_FLAG_NOATIME;
1126 inode->i_flags |= S_NOATIME;
1127 }
1128 return;
1129
1130bad_inode:
1131 make_bad_inode(inode);
1132 return;
1133}
1134
1135static int ecfs_update_inode(struct inode * inode, int do_sync)
1136{
1137 struct buffer_head * bh;
1138 struct ecfs_inode * raw_inode;
1139 unsigned long block_group;
1140 unsigned long group_desc;
1141 unsigned long desc;
1142 unsigned long block;
1143 unsigned long offset;
1144 int err = 0;
1145 struct ecfs_group_desc * gdp;
1146
1147 if ((inode->i_ino != ECFS_ROOT_INO &&
1148 inode->i_ino < ECFS_FIRST_INO(inode->i_sb)) ||
1149 inode->i_ino > le32_to_cpu(inode->i_sb->u.ecfs_sb.s_es->s_inodes_count)) {
1150 ecfs_error (inode->i_sb, "ecfs_write_inode",
1151 "bad inode number: %lu", inode->i_ino);
1152 return -EIO;
1153 }
1154 block_group = (inode->i_ino - 1) / ECFS_INODES_PER_GROUP(inode->i_sb);
1155 if (block_group >= inode->i_sb->u.ecfs_sb.s_groups_count) {
1156 ecfs_error (inode->i_sb, "ecfs_write_inode",
1157 "group >= groups count");
1158 return -EIO;
1159 }
1160 group_desc = block_group >> ECFS_DESC_PER_BLOCK_BITS(inode->i_sb);
1161 desc = block_group & (ECFS_DESC_PER_BLOCK(inode->i_sb) - 1);
1162 bh = inode->i_sb->u.ecfs_sb.s_group_desc[group_desc];
1163 if (!bh) {
1164 ecfs_error (inode->i_sb, "ecfs_write_inode",
1165 "Descriptor not loaded");
1166 return -EIO;
1167 }
1168 gdp = (struct ecfs_group_desc *) bh->b_data;
1169 /*
1170 * Figure out the offset within the block group inode table
1171 */
1172 offset = ((inode->i_ino - 1) % ECFS_INODES_PER_GROUP(inode->i_sb)) *
1173 ECFS_INODE_SIZE(inode->i_sb);
1174 block = le32_to_cpu(gdp[desc].bg_inode_table) +
1175 (offset >> ECFS_BLOCK_SIZE_BITS(inode->i_sb));
1176 if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize))) {
1177 ecfs_error (inode->i_sb, "ecfs_write_inode",
1178 "unable to read inode block - "
1179 "inode=%lu, block=%lu", inode->i_ino, block);
1180 return -EIO;
1181 }
1182 offset &= ECFS_BLOCK_SIZE(inode->i_sb) - 1;
1183 raw_inode = (struct ecfs_inode *) (bh->b_data + offset);
1184
1185 raw_inode->i_mode = cpu_to_le16(inode->i_mode);
1186 if(!(test_opt(inode->i_sb, NO_UID32))) {
1187 raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid));
1188 raw_inode->i_gid_low = cpu_to_le16(low_16_bits(inode->i_gid));
1189/*
1190 * Fix up interoperability with old kernels. Otherwise, old inodes get
1191 * re-used with the upper 16 bits of the uid/gid intact
1192 */
1193 if(!inode->u.ecfs_i.i_dtime) {
1194 raw_inode->i_uid_high = cpu_to_le16(high_16_bits(inode->i_uid));
1195 raw_inode->i_gid_high = cpu_to_le16(high_16_bits(inode->i_gid));
1196 } else {
1197 raw_inode->i_uid_high = 0;
1198 raw_inode->i_gid_high = 0;
1199 }
1200 } else {
1201 raw_inode->i_uid_low = cpu_to_le16(fs_high2lowuid(inode->i_uid));
1202 raw_inode->i_gid_low = cpu_to_le16(fs_high2lowgid(inode->i_gid));
1203 raw_inode->i_uid_high = 0;
1204 raw_inode->i_gid_high = 0;
1205 }
1206 raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);
1207 raw_inode->i_size = cpu_to_le32(inode->i_size);
1208 raw_inode->i_atime = cpu_to_le32(inode->i_atime);
1209 raw_inode->i_ctime = cpu_to_le32(inode->i_ctime);
1210 raw_inode->i_mtime = cpu_to_le32(inode->i_mtime);
1211 raw_inode->i_blocks = cpu_to_le32(inode->i_blocks);
1212 raw_inode->i_dtime = cpu_to_le32(inode->u.ecfs_i.i_dtime);
1213 raw_inode->i_flags = cpu_to_le32(inode->u.ecfs_i.i_flags);
1214 raw_inode->i_faddr = cpu_to_le32(inode->u.ecfs_i.i_faddr);
1215 raw_inode->i_frag = inode->u.ecfs_i.i_frag_no;
1216 raw_inode->i_fsize = inode->u.ecfs_i.i_frag_size;
1217 raw_inode->i_file_acl = cpu_to_le32(inode->u.ecfs_i.i_file_acl);
1218 if (S_ISDIR(inode->i_mode))
1219 raw_inode->i_dir_acl = cpu_to_le32(inode->u.ecfs_i.i_dir_acl);
1220 else {
1221 raw_inode->i_size_high = cpu_to_le32(inode->i_size >> 32);
1222 if (raw_inode->i_size_high) {
1223 struct super_block *sb = inode->i_sb;
1224 if (!ECFS_HAS_RO_COMPAT_FEATURE(sb,
1225 ECFS_FEATURE_RO_COMPAT_LARGE_FILE) ||
1226 ECFS_SB(sb)->s_es->s_rev_level ==
1227 cpu_to_le32(ECFS_GOOD_OLD_REV)) {
1228 /* If this is the first large file
1229 * created, add a flag to the superblock.
1230 */
1231 lock_kernel();
1232 ecfs_update_dynamic_rev(sb);
1233 ECFS_SET_RO_COMPAT_FEATURE(sb,
1234 ECFS_FEATURE_RO_COMPAT_LARGE_FILE);
1235 unlock_kernel();
1236 ecfs_write_super(sb);
1237 }
1238 }
1239 }
1240
1241 raw_inode->i_generation = cpu_to_le32(inode->i_generation);
1242 if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
1243 raw_inode->i_block[0] = cpu_to_le32(kdev_t_to_nr(inode->i_rdev));
1244 else for (block = 0; block < ECFS_N_BLOCKS; block++)
1245 raw_inode->i_block[block] = inode->u.ecfs_i.i_data[block];
1246 mark_buffer_dirty(bh);
1247 if (do_sync) {
1248 ll_rw_block (WRITE, 1, &bh);
1249 wait_on_buffer (bh);
1250 if (buffer_req(bh) && !buffer_uptodate(bh)) {
1251 printk ("IO error syncing ecfs inode ["
1252 "%s:%08lx]\n",
1253 bdevname(inode->i_dev), inode->i_ino);
1254 err = -EIO;
1255 }
1256 }
1257 brelse (bh);
1258 return err;
1259}
1260
1261void ecfs_write_inode (struct inode * inode, int wait)
1262{
1263 lock_kernel();
1264 ecfs_update_inode (inode, wait);
1265 unlock_kernel();
1266}
1267
1268int ecfs_sync_inode (struct inode *inode)
1269{
1270 return ecfs_update_inode (inode, 1);
1271}
1272
1273int ecfs_notify_change(struct dentry *dentry, struct iattr *iattr)
1274{
1275 struct inode *inode = dentry->d_inode;
1276 int retval;
1277 unsigned int flags;
1278
1279 retval = -EPERM;
1280 if (iattr->ia_valid & ATTR_ATTR_FLAG &&
1281 ((!(iattr->ia_attr_flags & ATTR_FLAG_APPEND) !=
1282 !(inode->u.ecfs_i.i_flags & ECFS_APPEND_FL)) ||
1283 (!(iattr->ia_attr_flags & ATTR_FLAG_IMMUTABLE) !=
1284 !(inode->u.ecfs_i.i_flags & ECFS_IMMUTABLE_FL)))) {
1285 if (!capable(CAP_LINUX_IMMUTABLE))
1286 goto out;
1287 } else if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
1288 goto out;
1289
1290 retval = inode_change_ok(inode, iattr);
1291 if (retval != 0)
1292 goto out;
1293
1294 inode_setattr(inode, iattr);
1295
1296 flags = iattr->ia_attr_flags;
1297 if (flags & ATTR_FLAG_SYNCRONOUS) {
1298 inode->i_flags |= S_SYNC;
1299 inode->u.ecfs_i.i_flags |= ECFS_SYNC_FL;
1300 } else {
1301 inode->i_flags &= ~S_SYNC;
1302 inode->u.ecfs_i.i_flags &= ~ECFS_SYNC_FL;
1303 }
1304 if (flags & ATTR_FLAG_NOATIME) {
1305 inode->i_flags |= S_NOATIME;
1306 inode->u.ecfs_i.i_flags |= ECFS_NOATIME_FL;
1307 } else {
1308 inode->i_flags &= ~S_NOATIME;
1309 inode->u.ecfs_i.i_flags &= ~ECFS_NOATIME_FL;
1310 }
1311 if (flags & ATTR_FLAG_APPEND) {
1312 inode->i_flags |= S_APPEND;
1313 inode->u.ecfs_i.i_flags |= ECFS_APPEND_FL;
1314 } else {
1315 inode->i_flags &= ~S_APPEND;
1316 inode->u.ecfs_i.i_flags &= ~ECFS_APPEND_FL;
1317 }
1318 if (flags & ATTR_FLAG_IMMUTABLE) {
1319 inode->i_flags |= S_IMMUTABLE;
1320 inode->u.ecfs_i.i_flags |= ECFS_IMMUTABLE_FL;
1321 } else {
1322 inode->i_flags &= ~S_IMMUTABLE;
1323 inode->u.ecfs_i.i_flags &= ~ECFS_IMMUTABLE_FL;
1324 }
1325 mark_inode_dirty(inode);
1326out:
1327 return retval;
1328}
1329
diff --git a/other/ecfs/inode.o b/other/ecfs/inode.o
new file mode 100644
index 0000000..8b5b3a8
--- /dev/null
+++ b/other/ecfs/inode.o
Binary files differ
diff --git a/other/ecfs/ioctl.c b/other/ecfs/ioctl.c
new file mode 100644
index 0000000..6fca75d
--- /dev/null
+++ b/other/ecfs/ioctl.c
@@ -0,0 +1,91 @@
1/*
2 * linux/fs/ecfs/ioctl.c
3 *
4 * Copyright (C) 1993, 1994, 1995
5 * Remy Card (card@masi.ibp.fr)
6 * Laboratoire MASI - Institut Blaise Pascal
7 * Universite Pierre et Marie Curie (Paris VI)
8 */
9
10#include <linux/fs_ecfs.h>
11#include <linux/ecfs_fs.h>
12#include <linux/sched.h>
13#include <asm/uaccess.h>
14
15
16int ecfs_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
17 unsigned long arg)
18{
19 unsigned int flags;
20
21 ecfs_debug ("cmd = %u, arg = %lu\n", cmd, arg);
22
23 switch (cmd) {
24 case ECFS_IOC_GETFLAGS:
25 flags = inode->u.ecfs_i.i_flags & ECFS_FL_USER_VISIBLE;
26 return put_user(flags, (int *) arg);
27 case ECFS_IOC_SETFLAGS: {
28 unsigned int oldflags;
29
30 if (IS_RDONLY(inode))
31 return -EROFS;
32
33 if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
34 return -EPERM;
35
36 if (get_user(flags, (int *) arg))
37 return -EFAULT;
38
39 oldflags = inode->u.ecfs_i.i_flags;
40
41 /*
42 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
43 * the relevant capability.
44 *
45 * This test looks nicer. Thanks to Pauline Middelink
46 */
47 if ((flags ^ oldflags) & (ECFS_APPEND_FL | ECFS_IMMUTABLE_FL)) {
48 if (!capable(CAP_LINUX_IMMUTABLE))
49 return -EPERM;
50 }
51
52 flags = flags & ECFS_FL_USER_MODIFIABLE;
53 flags |= oldflags & ~ECFS_FL_USER_MODIFIABLE;
54 inode->u.ecfs_i.i_flags = flags;
55
56 if (flags & ECFS_SYNC_FL)
57 inode->i_flags |= S_SYNC;
58 else
59 inode->i_flags &= ~S_SYNC;
60 if (flags & ECFS_APPEND_FL)
61 inode->i_flags |= S_APPEND;
62 else
63 inode->i_flags &= ~S_APPEND;
64 if (flags & ECFS_IMMUTABLE_FL)
65 inode->i_flags |= S_IMMUTABLE;
66 else
67 inode->i_flags &= ~S_IMMUTABLE;
68 if (flags & ECFS_NOATIME_FL)
69 inode->i_flags |= S_NOATIME;
70 else
71 inode->i_flags &= ~S_NOATIME;
72 inode->i_ctime = CURRENT_TIME;
73 mark_inode_dirty(inode);
74 return 0;
75 }
76 case ECFS_IOC_GETVERSION:
77 return put_user(inode->i_generation, (int *) arg);
78 case ECFS_IOC_SETVERSION:
79 if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
80 return -EPERM;
81 if (IS_RDONLY(inode))
82 return -EROFS;
83 if (get_user(inode->i_generation, (int *) arg))
84 return -EFAULT;
85 inode->i_ctime = CURRENT_TIME;
86 mark_inode_dirty(inode);
87 return 0;
88 default:
89 return -ENOTTY;
90 }
91}
diff --git a/other/ecfs/ioctl.o b/other/ecfs/ioctl.o
new file mode 100644
index 0000000..d55bf55
--- /dev/null
+++ b/other/ecfs/ioctl.o
Binary files differ
diff --git a/other/ecfs/namei.c b/other/ecfs/namei.c
new file mode 100644
index 0000000..c66e6c1
--- /dev/null
+++ b/other/ecfs/namei.c
@@ -0,0 +1,824 @@
1/*
2 * linux/fs/ecfs/namei.c
3 *
4 * Copyright (C) 1992, 1993, 1994, 1995
5 * Remy Card (card@masi.ibp.fr)
6 * Laboratoire MASI - Institut Blaise Pascal
7 * Universite Pierre et Marie Curie (Paris VI)
8 *
9 * from
10 *
11 * linux/fs/minix/namei.c
12 *
13 * Copyright (C) 1991, 1992 Linus Torvalds
14 *
15 * Big-endian to little-endian byte-swapping/bitmaps by
16 * David S. Miller (davem@caip.rutgers.edu), 1995
17 * Directory entry file type support and forward compatibility hooks
18 * for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998
19 */
20
21#include <linux/fs_ecfs.h>
22#include <linux/ecfs_fs.h>
23#include <linux/locks.h>
24#include <linux/quotaops.h>
25
26
27
28/*
29 * define how far ahead to read directories while searching them.
30 */
31#define NAMEI_RA_CHUNKS 2
32#define NAMEI_RA_BLOCKS 4
33#define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
34#define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b))
35
36/*
37 * NOTE! unlike strncmp, ecfs_match returns 1 for success, 0 for failure.
38 *
39 * `len <= ECFS_NAME_LEN' is guaranteed by caller.
40 * `de != NULL' is guaranteed by caller.
41 */
42static inline int ecfs_match (int len, const char * const name,
43 struct ecfs_dir_entry_2 * de)
44{
45 if (len != de->name_len)
46 return 0;
47 if (!de->inode)
48 return 0;
49 return !memcmp(name, de->name, len);
50}
51
52/*
53 * ecfs_find_entry()
54 *
55 * finds an entry in the specified directory with the wanted name. It
56 * returns the cache buffer in which the entry was found, and the entry
57 * itself (as a parameter - res_dir). It does NOT read the inode of the
58 * entry - you'll have to do that yourself if you want to.
59 */
60static struct buffer_head * ecfs_find_entry (struct inode * dir,
61 const char * const name, int namelen,
62 struct ecfs_dir_entry_2 ** res_dir)
63{
64 struct super_block * sb;
65 struct buffer_head * bh_use[NAMEI_RA_SIZE];
66 struct buffer_head * bh_read[NAMEI_RA_SIZE];
67 unsigned long offset;
68 int block, toread, i, err;
69
70 *res_dir = NULL;
71 sb = dir->i_sb;
72
73 if (namelen > ECFS_NAME_LEN)
74 return NULL;
75
76 memset (bh_use, 0, sizeof (bh_use));
77 toread = 0;
78 for (block = 0; block < NAMEI_RA_SIZE; ++block) {
79 struct buffer_head * bh;
80
81 if ((block << ECFS_BLOCK_SIZE_BITS (sb)) >= dir->i_size)
82 break;
83 bh = ecfs_getblk (dir, block, 0, &err);
84 bh_use[block] = bh;
85 if (bh && !buffer_uptodate(bh))
86 bh_read[toread++] = bh;
87 }
88
89 for (block = 0, offset = 0; offset < dir->i_size; block++) {
90 struct buffer_head * bh;
91 struct ecfs_dir_entry_2 * de;
92 char * dlimit;
93
94 if ((block % NAMEI_RA_BLOCKS) == 0 && toread) {
95 ll_rw_block (READ, toread, bh_read);
96 toread = 0;
97 }
98 bh = bh_use[block % NAMEI_RA_SIZE];
99 if (!bh) {
100#if 0
101 ecfs_error (sb, "ecfs_find_entry",
102 "directory #%lu contains a hole at offset %lu",
103 dir->i_ino, offset);
104#endif
105 offset += sb->s_blocksize;
106 continue;
107 }
108 wait_on_buffer (bh);
109 if (!buffer_uptodate(bh)) {
110 /*
111 * read error: all bets are off
112 */
113 break;
114 }
115
116 de = (struct ecfs_dir_entry_2 *) bh->b_data;
117 dlimit = bh->b_data + sb->s_blocksize;
118 while ((char *) de < dlimit) {
119 /* this code is executed quadratically often */
120 /* do minimal checking `by hand' */
121 int de_len;
122
123 if ((char *) de + namelen <= dlimit &&
124 ecfs_match (namelen, name, de)) {
125 /* found a match -
126 just to be sure, do a full check */
127 if (!ecfs_check_dir_entry("ecfs_find_entry",
128 dir, de, bh, offset))
129 goto failure;
130 for (i = 0; i < NAMEI_RA_SIZE; ++i) {
131 if (bh_use[i] != bh)
132 brelse (bh_use[i]);
133 }
134 *res_dir = de;
135 return bh;
136 }
137 /* prevent looping on a bad block */
138 de_len = le16_to_cpu(de->rec_len);
139 if (de_len <= 0)
140 goto failure;
141 offset += de_len;
142 de = (struct ecfs_dir_entry_2 *)
143 ((char *) de + de_len);
144 }
145
146 brelse (bh);
147 if (((block + NAMEI_RA_SIZE) << ECFS_BLOCK_SIZE_BITS (sb)) >=
148 dir->i_size)
149 bh = NULL;
150 else
151 bh = ecfs_getblk (dir, block + NAMEI_RA_SIZE, 0, &err);
152 bh_use[block % NAMEI_RA_SIZE] = bh;
153 if (bh && !buffer_uptodate(bh))
154 bh_read[toread++] = bh;
155 }
156
157failure:
158 for (i = 0; i < NAMEI_RA_SIZE; ++i)
159 brelse (bh_use[i]);
160 return NULL;
161}
162
163static struct dentry *ecfs_lookup(struct inode * dir, struct dentry *dentry)
164{
165 struct inode * inode;
166 struct ecfs_dir_entry_2 * de;
167 struct buffer_head * bh;
168
169 if (dentry->d_name.len > ECFS_NAME_LEN)
170 return ERR_PTR(-ENAMETOOLONG);
171
172 bh = ecfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);
173 inode = NULL;
174 if (bh) {
175 unsigned long ino = le32_to_cpu(de->inode);
176 brelse (bh);
177 inode = iget(dir->i_sb, ino);
178
179 if (!inode)
180 return ERR_PTR(-EACCES);
181 }
182 d_add(dentry, inode);
183 return NULL;
184}
185
186#define S_SHIFT 12
187static unsigned char ecfs_type_by_mode[S_IFMT >> S_SHIFT] = {
188 [S_IFREG >> S_SHIFT] ECFS_FT_REG_FILE,
189 [S_IFDIR >> S_SHIFT] ECFS_FT_DIR,
190 [S_IFCHR >> S_SHIFT] ECFS_FT_CHRDEV,
191 [S_IFBLK >> S_SHIFT] ECFS_FT_BLKDEV,
192 [S_IFIFO >> S_SHIFT] ECFS_FT_FIFO,
193 [S_IFSOCK >> S_SHIFT] ECFS_FT_SOCK,
194 [S_IFLNK >> S_SHIFT] ECFS_FT_SYMLINK,
195};
196
197static inline void ecfs_set_de_type(struct super_block *sb,
198 struct ecfs_dir_entry_2 *de,
199 umode_t mode) {
200 if (ECFS_HAS_INCOMPAT_FEATURE(sb, ECFS_FEATURE_INCOMPAT_FILETYPE))
201 de->file_type = ecfs_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
202}
203
204/*
205 * ecfs_add_entry()
206 *
207 * adds a file entry to the specified directory.
208 */
209int ecfs_add_entry (struct inode * dir, const char * name, int namelen,
210 struct inode *inode)
211{
212 unsigned long offset;
213 unsigned short rec_len;
214 struct buffer_head * bh;
215 struct ecfs_dir_entry_2 * de, * de1;
216 struct super_block * sb;
217 int retval;
218
219 sb = dir->i_sb;
220
221 if (!namelen)
222 return -EINVAL;
223 bh = ecfs_bread (dir, 0, 0, &retval);
224 if (!bh)
225 return retval;
226 rec_len = ECFS_DIR_REC_LEN(namelen);
227 offset = 0;
228 de = (struct ecfs_dir_entry_2 *) bh->b_data;
229 while (1) {
230 if ((char *)de >= sb->s_blocksize + bh->b_data) {
231 brelse (bh);
232 bh = NULL;
233 bh = ecfs_bread (dir, offset >> ECFS_BLOCK_SIZE_BITS(sb), 1, &retval);
234 if (!bh)
235 return retval;
236 if (dir->i_size <= offset) {
237 if (dir->i_size == 0) {
238 return -ENOENT;
239 }
240
241 ecfs_debug ("creating next block\n");
242
243 de = (struct ecfs_dir_entry_2 *) bh->b_data;
244 de->inode = 0;
245 de->rec_len = le16_to_cpu(sb->s_blocksize);
246 dir->i_size = offset + sb->s_blocksize;
247 dir->u.ecfs_i.i_flags &= ~ECFS_BTREE_FL;
248 mark_inode_dirty(dir);
249 } else {
250
251 ecfs_debug ("skipping to next block\n");
252
253 de = (struct ecfs_dir_entry_2 *) bh->b_data;
254 }
255 }
256 if (!ecfs_check_dir_entry ("ecfs_add_entry", dir, de, bh,
257 offset)) {
258 brelse (bh);
259 return -ENOENT;
260 }
261 if (ecfs_match (namelen, name, de)) {
262 brelse (bh);
263 return -EEXIST;
264 }
265 if ((le32_to_cpu(de->inode) == 0 && le16_to_cpu(de->rec_len) >= rec_len) ||
266 (le16_to_cpu(de->rec_len) >= ECFS_DIR_REC_LEN(de->name_len) + rec_len)) {
267 offset += le16_to_cpu(de->rec_len);
268 if (le32_to_cpu(de->inode)) {
269 de1 = (struct ecfs_dir_entry_2 *) ((char *) de +
270 ECFS_DIR_REC_LEN(de->name_len));
271 de1->rec_len = cpu_to_le16(le16_to_cpu(de->rec_len) -
272 ECFS_DIR_REC_LEN(de->name_len));
273 de->rec_len = cpu_to_le16(ECFS_DIR_REC_LEN(de->name_len));
274 de = de1;
275 }
276 de->file_type = ECFS_FT_UNKNOWN;
277 if (inode) {
278 de->inode = cpu_to_le32(inode->i_ino);
279 ecfs_set_de_type(dir->i_sb, de, inode->i_mode);
280 } else
281 de->inode = 0;
282 de->name_len = namelen;
283 memcpy (de->name, name, namelen);
284 /*
285 * XXX shouldn't update any times until successful
286 * completion of syscall, but too many callers depend
287 * on this.
288 *
289 * XXX similarly, too many callers depend on
290 * ecfs_new_inode() setting the times, but error
291 * recovery deletes the inode, so the worst that can
292 * happen is that the times are slightly out of date
293 * and/or different from the directory change time.
294 */
295 dir->i_mtime = dir->i_ctime = CURRENT_TIME;
296 dir->u.ecfs_i.i_flags &= ~ECFS_BTREE_FL;
297 mark_inode_dirty(dir);
298 dir->i_version = ++event;
299 mark_buffer_dirty_inode(bh, dir);
300 if (IS_SYNC(dir)) {
301 ll_rw_block (WRITE, 1, &bh);
302 wait_on_buffer (bh);
303 }
304 brelse(bh);
305 return 0;
306 }
307 offset += le16_to_cpu(de->rec_len);
308 de = (struct ecfs_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
309 }
310 brelse (bh);
311 return -ENOSPC;
312}
313
314/*
315 * ecfs_delete_entry deletes a directory entry by merging it with the
316 * previous entry
317 */
318static int ecfs_delete_entry (struct inode * dir,
319 struct ecfs_dir_entry_2 * de_del,
320 struct buffer_head * bh)
321{
322 struct ecfs_dir_entry_2 * de, * pde;
323 int i;
324
325 i = 0;
326 pde = NULL;
327 de = (struct ecfs_dir_entry_2 *) bh->b_data;
328 while (i < bh->b_size) {
329 if (!ecfs_check_dir_entry ("ecfs_delete_entry", NULL,
330 de, bh, i))
331 return -EIO;
332 if (de == de_del) {
333 if (pde)
334 pde->rec_len =
335 cpu_to_le16(le16_to_cpu(pde->rec_len) +
336 le16_to_cpu(de->rec_len));
337 else
338 de->inode = 0;
339 dir->i_version = ++event;
340 mark_buffer_dirty_inode(bh, dir);
341 if (IS_SYNC(dir)) {
342 ll_rw_block (WRITE, 1, &bh);
343 wait_on_buffer (bh);
344 }
345 return 0;
346 }
347 i += le16_to_cpu(de->rec_len);
348 pde = de;
349 de = (struct ecfs_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
350 }
351 return -ENOENT;
352}
353
354/*
355 * By the time this is called, we already have created
356 * the directory cache entry for the new file, but it
357 * is so far negative - it has no inode.
358 *
359 * If the create succeeds, we fill in the inode information
360 * with d_instantiate().
361 */
362static int ecfs_create (struct inode * dir, struct dentry * dentry, int mode)
363{
364 struct inode * inode = ecfs_new_inode (dir, mode);
365 int err = PTR_ERR(inode);
366 if (IS_ERR(inode))
367 return err;
368
369 inode->i_op = &ecfs_file_inode_operations;
370 inode->i_fop = &ecfs_file_operations;
371 inode->i_mapping->a_ops = &ecfs_aops;
372 inode->i_mode = mode;
373 mark_inode_dirty(inode);
374 err = ecfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len,
375 inode);
376 if (err) {
377 inode->i_nlink--;
378 mark_inode_dirty(inode);
379 iput (inode);
380 return err;
381 }
382 d_instantiate(dentry, inode);
383 return 0;
384}
385
386static int ecfs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
387{
388 struct inode * inode = ecfs_new_inode (dir, mode);
389 int err = PTR_ERR(inode);
390
391 if (IS_ERR(inode))
392 return err;
393
394 inode->i_uid = current->fsuid;
395 init_special_inode(inode, mode, rdev);
396 err = ecfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len,
397 inode);
398 if (err)
399 goto out_no_entry;
400 mark_inode_dirty(inode);
401 d_instantiate(dentry, inode);
402 return 0;
403
404out_no_entry:
405 inode->i_nlink--;
406 mark_inode_dirty(inode);
407 iput(inode);
408 return err;
409}
410
411static int ecfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
412{
413 struct inode * inode;
414 struct buffer_head * dir_block;
415 struct ecfs_dir_entry_2 * de;
416 int err;
417
418 if (dir->i_nlink >= ECFS_LINK_MAX)
419 return -EMLINK;
420
421 inode = ecfs_new_inode (dir, S_IFDIR);
422 err = PTR_ERR(inode);
423 if (IS_ERR(inode))
424 return err;
425
426 inode->i_op = &ecfs_dir_inode_operations;
427 inode->i_fop = &ecfs_dir_operations;
428 inode->i_size = inode->i_sb->s_blocksize;
429 inode->i_blocks = 0;
430 dir_block = ecfs_bread (inode, 0, 1, &err);
431 if (!dir_block) {
432 inode->i_nlink--; /* is this nlink == 0? */
433 mark_inode_dirty(inode);
434 iput (inode);
435 return err;
436 }
437 de = (struct ecfs_dir_entry_2 *) dir_block->b_data;
438 de->inode = cpu_to_le32(inode->i_ino);
439 de->name_len = 1;
440 de->rec_len = cpu_to_le16(ECFS_DIR_REC_LEN(de->name_len));
441 strcpy (de->name, ".");
442 ecfs_set_de_type(dir->i_sb, de, S_IFDIR);
443 de = (struct ecfs_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
444 de->inode = cpu_to_le32(dir->i_ino);
445 de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize - ECFS_DIR_REC_LEN(1));
446 de->name_len = 2;
447 strcpy (de->name, "..");
448 ecfs_set_de_type(dir->i_sb, de, S_IFDIR);
449 inode->i_nlink = 2;
450 mark_buffer_dirty_inode(dir_block, dir);
451 brelse (dir_block);
452 inode->i_mode = S_IFDIR | mode;
453 if (dir->i_mode & S_ISGID)
454 inode->i_mode |= S_ISGID;
455 mark_inode_dirty(inode);
456 err = ecfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len,
457 inode);
458 if (err)
459 goto out_no_entry;
460 dir->i_nlink++;
461 dir->u.ecfs_i.i_flags &= ~ECFS_BTREE_FL;
462 mark_inode_dirty(dir);
463 d_instantiate(dentry, inode);
464 return 0;
465
466out_no_entry:
467 inode->i_nlink = 0;
468 mark_inode_dirty(inode);
469 iput (inode);
470 return err;
471}
472
473/*
474 * routine to check that the specified directory is empty (for rmdir)
475 */
476static int empty_dir (struct inode * inode)
477{
478 unsigned long offset;
479 struct buffer_head * bh;
480 struct ecfs_dir_entry_2 * de, * de1;
481 struct super_block * sb;
482 int err;
483
484 sb = inode->i_sb;
485 if (inode->i_size < ECFS_DIR_REC_LEN(1) + ECFS_DIR_REC_LEN(2) ||
486 !(bh = ecfs_bread (inode, 0, 0, &err))) {
487 ecfs_warning (inode->i_sb, "empty_dir",
488 "bad directory (dir #%lu) - no data block",
489 inode->i_ino);
490 return 1;
491 }
492 de = (struct ecfs_dir_entry_2 *) bh->b_data;
493 de1 = (struct ecfs_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
494 if (le32_to_cpu(de->inode) != inode->i_ino || !le32_to_cpu(de1->inode) ||
495 strcmp (".", de->name) || strcmp ("..", de1->name)) {
496 ecfs_warning (inode->i_sb, "empty_dir",
497 "bad directory (dir #%lu) - no `.' or `..'",
498 inode->i_ino);
499 brelse (bh);
500 return 1;
501 }
502 offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len);
503 de = (struct ecfs_dir_entry_2 *) ((char *) de1 + le16_to_cpu(de1->rec_len));
504 while (offset < inode->i_size ) {
505 if (!bh || (void *) de >= (void *) (bh->b_data + sb->s_blocksize)) {
506 brelse (bh);
507 bh = ecfs_bread (inode, offset >> ECFS_BLOCK_SIZE_BITS(sb), 0, &err);
508 if (!bh) {
509#if 0
510 ecfs_error (sb, "empty_dir",
511 "directory #%lu contains a hole at offset %lu",
512 inode->i_ino, offset);
513#endif
514 offset += sb->s_blocksize;
515 continue;
516 }
517 de = (struct ecfs_dir_entry_2 *) bh->b_data;
518 }
519 if (!ecfs_check_dir_entry ("empty_dir", inode, de, bh,
520 offset)) {
521 brelse (bh);
522 return 1;
523 }
524 if (le32_to_cpu(de->inode)) {
525 brelse (bh);
526 return 0;
527 }
528 offset += le16_to_cpu(de->rec_len);
529 de = (struct ecfs_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
530 }
531 brelse (bh);
532 return 1;
533}
534
535static int ecfs_rmdir (struct inode * dir, struct dentry *dentry)
536{
537 int retval;
538 struct inode * inode;
539 struct buffer_head * bh;
540 struct ecfs_dir_entry_2 * de;
541
542 retval = -ENOENT;
543 bh = ecfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);
544 if (!bh)
545 goto end_rmdir;
546
547 inode = dentry->d_inode;
548 DQUOT_INIT(inode);
549
550 retval = -EIO;
551 if (le32_to_cpu(de->inode) != inode->i_ino)
552 goto end_rmdir;
553
554 retval = -ENOTEMPTY;
555 if (!empty_dir (inode))
556 goto end_rmdir;
557
558 retval = ecfs_delete_entry(dir, de, bh);
559 if (retval)
560 goto end_rmdir;
561 if (inode->i_nlink != 2)
562 ecfs_warning (inode->i_sb, "ecfs_rmdir",
563 "empty directory has nlink!=2 (%d)",
564 inode->i_nlink);
565 inode->i_version = ++event;
566 inode->i_nlink = 0;
567 inode->i_size = 0;
568 mark_inode_dirty(inode);
569 dir->i_nlink--;
570 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
571 dir->u.ecfs_i.i_flags &= ~ECFS_BTREE_FL;
572 mark_inode_dirty(dir);
573
574end_rmdir:
575 brelse (bh);
576 return retval;
577}
578
579static int ecfs_unlink(struct inode * dir, struct dentry *dentry)
580{
581 int retval;
582 struct inode * inode;
583 struct buffer_head * bh;
584 struct ecfs_dir_entry_2 * de;
585
586 retval = -ENOENT;
587 bh = ecfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);
588 if (!bh)
589 goto end_unlink;
590
591 inode = dentry->d_inode;
592 DQUOT_INIT(inode);
593
594 retval = -EIO;
595 if (le32_to_cpu(de->inode) != inode->i_ino)
596 goto end_unlink;
597
598 if (!inode->i_nlink) {
599 ecfs_warning (inode->i_sb, "ecfs_unlink",
600 "Deleting nonexistent file (%lu), %d",
601 inode->i_ino, inode->i_nlink);
602 inode->i_nlink = 1;
603 }
604 retval = ecfs_delete_entry(dir, de, bh);
605 if (retval)
606 goto end_unlink;
607 dir->i_ctime = dir->i_mtime = CURRENT_TIME;
608 dir->u.ecfs_i.i_flags &= ~ECFS_BTREE_FL;
609 mark_inode_dirty(dir);
610 inode->i_nlink--;
611 mark_inode_dirty(inode);
612 inode->i_ctime = dir->i_ctime;
613 retval = 0;
614
615end_unlink:
616 brelse (bh);
617 return retval;
618}
619
620static int ecfs_symlink (struct inode * dir, struct dentry *dentry, const char * symname)
621{
622 struct inode * inode;
623 int l, err;
624
625 l = strlen(symname)+1;
626 if (l > dir->i_sb->s_blocksize)
627 return -ENAMETOOLONG;
628
629 inode = ecfs_new_inode (dir, S_IFLNK);
630 err = PTR_ERR(inode);
631 if (IS_ERR(inode))
632 return err;
633
634 inode->i_mode = S_IFLNK | S_IRWXUGO;
635
636 if (l > sizeof (inode->u.ecfs_i.i_data)) {
637 inode->i_op = &page_symlink_inode_operations;
638 inode->i_mapping->a_ops = &ecfs_aops;
639 err = block_symlink(inode, symname, l);
640 if (err)
641 goto out_no_entry;
642 } else {
643 inode->i_op = &ecfs_fast_symlink_inode_operations;
644 memcpy((char*)&inode->u.ecfs_i.i_data,symname,l);
645 inode->i_size = l-1;
646 }
647 mark_inode_dirty(inode);
648
649 err = ecfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len,
650 inode);
651 if (err)
652 goto out_no_entry;
653 d_instantiate(dentry, inode);
654 return 0;
655
656out_no_entry:
657 inode->i_nlink--;
658 mark_inode_dirty(inode);
659 iput (inode);
660 return err;
661}
662
663static int ecfs_link (struct dentry * old_dentry,
664 struct inode * dir, struct dentry *dentry)
665{
666 struct inode *inode = old_dentry->d_inode;
667 int err;
668
669 if (S_ISDIR(inode->i_mode))
670 return -EPERM;
671
672 if (inode->i_nlink >= ECFS_LINK_MAX)
673 return -EMLINK;
674
675 err = ecfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len,
676 inode);
677 if (err)
678 return err;
679
680 inode->i_nlink++;
681 inode->i_ctime = CURRENT_TIME;
682 mark_inode_dirty(inode);
683 atomic_inc(&inode->i_count);
684 d_instantiate(dentry, inode);
685 return 0;
686}
687
688#define PARENT_INO(buffer) \
689 ((struct ecfs_dir_entry_2 *) ((char *) buffer + \
690 le16_to_cpu(((struct ecfs_dir_entry_2 *) buffer)->rec_len)))->inode
691
692/*
693 * Anybody can rename anything with this: the permission checks are left to the
694 * higher-level routines.
695 */
696static int ecfs_rename (struct inode * old_dir, struct dentry *old_dentry,
697 struct inode * new_dir,struct dentry *new_dentry)
698{
699 struct inode * old_inode, * new_inode;
700 struct buffer_head * old_bh, * new_bh, * dir_bh;
701 struct ecfs_dir_entry_2 * old_de, * new_de;
702 int retval;
703
704 old_bh = new_bh = dir_bh = NULL;
705
706 old_bh = ecfs_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de);
707 /*
708 * Check for inode number is _not_ due to possible IO errors.
709 * We might rmdir the source, keep it as pwd of some process
710 * and merrily kill the link to whatever was created under the
711 * same name. Goodbye sticky bit ;-<
712 */
713 old_inode = old_dentry->d_inode;
714 retval = -ENOENT;
715 if (!old_bh || le32_to_cpu(old_de->inode) != old_inode->i_ino)
716 goto end_rename;
717
718 new_inode = new_dentry->d_inode;
719 new_bh = ecfs_find_entry (new_dir, new_dentry->d_name.name,
720 new_dentry->d_name.len, &new_de);
721 if (new_bh) {
722 if (!new_inode) {
723 brelse (new_bh);
724 new_bh = NULL;
725 } else {
726 DQUOT_INIT(new_inode);
727 }
728 }
729 if (S_ISDIR(old_inode->i_mode)) {
730 if (new_inode) {
731 retval = -ENOTEMPTY;
732 if (!empty_dir (new_inode))
733 goto end_rename;
734 }
735 retval = -EIO;
736 dir_bh = ecfs_bread (old_inode, 0, 0, &retval);
737 if (!dir_bh)
738 goto end_rename;
739 if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino)
740 goto end_rename;
741 retval = -EMLINK;
742 if (!new_inode && new_dir!=old_dir &&
743 new_dir->i_nlink >= ECFS_LINK_MAX)
744 goto end_rename;
745 }
746 if (!new_bh) {
747 retval = ecfs_add_entry (new_dir, new_dentry->d_name.name,
748 new_dentry->d_name.len,
749 old_inode);
750 if (retval)
751 goto end_rename;
752 } else {
753 new_de->inode = le32_to_cpu(old_inode->i_ino);
754 if (ECFS_HAS_INCOMPAT_FEATURE(new_dir->i_sb,
755 ECFS_FEATURE_INCOMPAT_FILETYPE))
756 new_de->file_type = old_de->file_type;
757 new_dir->i_version = ++event;
758 mark_buffer_dirty_inode(new_bh, new_dir);
759 if (IS_SYNC(new_dir)) {
760 ll_rw_block (WRITE, 1, &new_bh);
761 wait_on_buffer (new_bh);
762 }
763 brelse(new_bh);
764 new_bh = NULL;
765 }
766
767 /*
768 * Like most other Unix systems, set the ctime for inodes on a
769 * rename.
770 */
771 old_inode->i_ctime = CURRENT_TIME;
772 mark_inode_dirty(old_inode);
773
774 /*
775 * ok, that's it
776 */
777 ecfs_delete_entry(old_dir, old_de, old_bh);
778
779 if (new_inode) {
780 new_inode->i_nlink--;
781 new_inode->i_ctime = CURRENT_TIME;
782 mark_inode_dirty(new_inode);
783 }
784 old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
785 old_dir->u.ecfs_i.i_flags &= ~ECFS_BTREE_FL;
786 mark_inode_dirty(old_dir);
787 if (dir_bh) {
788 PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino);
789 mark_buffer_dirty_inode(dir_bh, old_inode);
790 old_dir->i_nlink--;
791 mark_inode_dirty(old_dir);
792 if (new_inode) {
793 new_inode->i_nlink--;
794 mark_inode_dirty(new_inode);
795 } else {
796 new_dir->i_nlink++;
797 new_dir->u.ecfs_i.i_flags &= ~ECFS_BTREE_FL;
798 mark_inode_dirty(new_dir);
799 }
800 }
801
802 retval = 0;
803
804end_rename:
805 brelse (dir_bh);
806 brelse (old_bh);
807 brelse (new_bh);
808 return retval;
809}
810
811/*
812 * directories can handle most operations...
813 */
814struct inode_operations ecfs_dir_inode_operations = {
815 create: ecfs_create,
816 lookup: ecfs_lookup,
817 link: ecfs_link,
818 unlink: ecfs_unlink,
819 symlink: ecfs_symlink,
820 mkdir: ecfs_mkdir,
821 rmdir: ecfs_rmdir,
822 mknod: ecfs_mknod,
823 rename: ecfs_rename,
824};
diff --git a/other/ecfs/namei.o b/other/ecfs/namei.o
new file mode 100644
index 0000000..c567acd
--- /dev/null
+++ b/other/ecfs/namei.o
Binary files differ
diff --git a/other/ecfs/rc4.c b/other/ecfs/rc4.c
new file mode 100644
index 0000000..a922b75
--- /dev/null
+++ b/other/ecfs/rc4.c
@@ -0,0 +1,76 @@
1#include <linux/types.h>
2#include "rc4.h"
3
4
5/* originally implemented by <unknown> */
6void
7prepare_key(unsigned char *key_data_ptr, size_t key_data_len, rc4_key *key)
8{
9 unsigned char index1;
10 unsigned char index2;
11 unsigned char* state;
12 short counter;
13
14 state = &key->state[0];
15 for(counter = 0; counter < 256; counter++)
16 state[counter] = counter;
17 key->x = 0;
18 key->y = 0;
19 index1 = 0;
20 index2 = 0;
21 for (counter = 0; counter < 256; counter++) {
22 index2 = (key_data_ptr[index1] + state[counter] +
23 index2) % 256;
24 my_swap_byte(&state[counter], &state[index2]);
25
26 index1 = (index1 + 1) % key_data_len;
27 }
28}
29
30
31void
32rc4(unsigned char *buffer_ptr, size_t buffer_len, rc4_key *key, unsigned int from)
33{
34 unsigned char x;
35 unsigned char y;
36 unsigned char *state;
37 unsigned char xorIndex;
38 unsigned int counter;
39 unsigned int j;
40
41 x = key->x;
42 y = key->y;
43
44 state = &key->state[0];
45
46 for (counter = 0; counter < from; ++counter) {
47 x = (x + 1) % 256;
48 y = (state[x] + y) % 256;
49 my_swap_byte(&state[x], &state[y]);
50 }
51
52
53 for (j = 0; j < buffer_len; ++j) {
54 x = (x + 1) % 256;
55 y = (state[x] + y) % 256;
56 my_swap_byte(&state[x], &state[y]);
57
58 xorIndex = (state[x] + state[y]) % 256;
59 buffer_ptr[j] ^= state[xorIndex];
60 }
61
62 key->x = x;
63 key->y = y;
64}
65
66
67void my_swap_byte(unsigned char *a, unsigned char *b)
68{
69 unsigned char swapByte;
70
71 swapByte = *a;
72 *a = *b;
73 *b = swapByte;
74}
75
76
diff --git a/other/ecfs/rc4.h b/other/ecfs/rc4.h
new file mode 100644
index 0000000..7915285
--- /dev/null
+++ b/other/ecfs/rc4.h
@@ -0,0 +1,20 @@
1#ifndef __rc4_h__
2#define __rc4_h__
3
4typedef struct {
5 unsigned char state[256];
6 unsigned char x;
7 unsigned char y;
8} rc4_key;
9
10typedef struct {
11 unsigned char *ptr;
12 int stream_len;
13} rc4_stream;
14
15void prepare_key(unsigned char *, unsigned int, rc4_key *);
16void rc4(unsigned char *, unsigned int, rc4_key *, unsigned int);
17void my_swap_byte(unsigned char *,unsigned char *);
18
19#endif
20
diff --git a/other/ecfs/rc4.o b/other/ecfs/rc4.o
new file mode 100644
index 0000000..9144b8c
--- /dev/null
+++ b/other/ecfs/rc4.o
Binary files differ
diff --git a/other/ecfs/repl.pl b/other/ecfs/repl.pl
new file mode 100644
index 0000000..46e5b5b
--- /dev/null
+++ b/other/ecfs/repl.pl
@@ -0,0 +1,26 @@
1#!/usr/bin/perl
2
3# Written to transform ext2 functions and structs
4# to ecfs.
5#
6
7my $f= shift;
8open I, "<$f" or die "$!";
9open O, ">$f.new" or die "$!";
10
11while (<I>) {
12 s/ext2/ecfs/g;
13 s/EXT2/ECFS/g;
14
15 s/const// if (/ecfs_free_blocks/);
16 s/const// if (/ecfs_new_block/);
17
18 print O;
19}
20
21close O;
22close I;
23
24
25unlink $f;
26rename "$f.new", $f;
diff --git a/other/ecfs/start-ecfs b/other/ecfs/start-ecfs
new file mode 100644
index 0000000..1fc39ab
--- /dev/null
+++ b/other/ecfs/start-ecfs
@@ -0,0 +1,29 @@
1#!/usr/bin/perl
2
3use Term::ReadKey;
4
5print "This program is used to read in the key for ECFS\n".
6 "This avoids that your key shows up in .history-file\n".
7 "since ECFS is started like 'insmod ecfs_key=blah'\n\n".
8 "You are now prompted for the key. Mount ECFS partitions like\n".
9 "'mount -t ecfs /dev/fd0 /mnt' afterwards. Remember that mmap()\n".
10 "is not supported by ECFS.\n\n".
11 "Also make sure ecfs.o is in apropriate /lib/modules/... location.\n\n";
12
13$p1 = "X";
14$p2 = "Y";
15
16ReadMode('noecho');
17while ($p1 ne $p2) {
18 print "Key: ";
19 $p1 = ReadLine(0);
20 print "\n(again): ";
21 $p2 = ReadLine(0);
22 print "\n";
23 chop($p1); chop($p2);
24}
25
26ReadMode('normal');
27
28exec "insmod", "ecfs", "ecfs_key=$p1";
29
diff --git a/other/ecfs/super.c b/other/ecfs/super.c
new file mode 100644
index 0000000..abd8fb5
--- /dev/null
+++ b/other/ecfs/super.c
@@ -0,0 +1,817 @@
1/*
2 * linux/fs/ecfs/super.c
3 *
4 * Copyright (C) 1992, 1993, 1994, 1995
5 * Remy Card (card@masi.ibp.fr)
6 * Laboratoire MASI - Institut Blaise Pascal
7 * Universite Pierre et Marie Curie (Paris VI)
8 *
9 * from
10 *
11 * linux/fs/minix/inode.c
12 *
13 * Copyright (C) 1991, 1992 Linus Torvalds
14 *
15 * Big-endian to little-endian byte-swapping/bitmaps by
16 * David S. Miller (davem@caip.rutgers.edu), 1995
17 */
18
19#include <linux/config.h>
20#include <linux/module.h>
21#include <linux/string.h>
22#include <linux/fs_ecfs.h>
23#include <linux/ecfs_fs.h>
24#include <linux/slab.h>
25#include <linux/init.h>
26#include <linux/locks.h>
27#include <asm/uaccess.h>
28
29#include <linux/blkdev.h>
30
31extern unsigned char *ecfs_key;
32
33static char error_buf[1024];
34
35void ecfs_error (struct super_block * sb, const char * function,
36 const char * fmt, ...)
37{
38 va_list args;
39
40 if (!(sb->s_flags & MS_RDONLY)) {
41 sb->u.ecfs_sb.s_mount_state |= ECFS_ERROR_FS;
42 sb->u.ecfs_sb.s_es->s_state =
43 cpu_to_le16(le16_to_cpu(sb->u.ecfs_sb.s_es->s_state) | ECFS_ERROR_FS);
44 mark_buffer_dirty(sb->u.ecfs_sb.s_sbh);
45 sb->s_dirt = 1;
46 }
47 va_start (args, fmt);
48 vsprintf (error_buf, fmt, args);
49 va_end (args);
50 if (test_opt (sb, ERRORS_PANIC) ||
51 (le16_to_cpu(sb->u.ecfs_sb.s_es->s_errors) == ECFS_ERRORS_PANIC &&
52 !test_opt (sb, ERRORS_CONT) && !test_opt (sb, ERRORS_RO)))
53 panic ("ECFS-fs panic (device %s): %s: %s\n",
54 bdevname(sb->s_dev), function, error_buf);
55 printk (KERN_CRIT "ECFS-fs error (device %s): %s: %s\n",
56 bdevname(sb->s_dev), function, error_buf);
57 if (test_opt (sb, ERRORS_RO) ||
58 (le16_to_cpu(sb->u.ecfs_sb.s_es->s_errors) == ECFS_ERRORS_RO &&
59 !test_opt (sb, ERRORS_CONT) && !test_opt (sb, ERRORS_PANIC))) {
60 printk ("Remounting filesystem read-only\n");
61 sb->s_flags |= MS_RDONLY;
62 }
63}
64
65NORET_TYPE void ecfs_panic (struct super_block * sb, const char * function,
66 const char * fmt, ...)
67{
68 va_list args;
69
70 if (!(sb->s_flags & MS_RDONLY)) {
71 sb->u.ecfs_sb.s_mount_state |= ECFS_ERROR_FS;
72 sb->u.ecfs_sb.s_es->s_state =
73 cpu_to_le16(le16_to_cpu(sb->u.ecfs_sb.s_es->s_state) | ECFS_ERROR_FS);
74 mark_buffer_dirty(sb->u.ecfs_sb.s_sbh);
75 sb->s_dirt = 1;
76 }
77 va_start (args, fmt);
78 vsprintf (error_buf, fmt, args);
79 va_end (args);
80 /* this is to prevent panic from syncing this filesystem */
81#if 0
82 if (sb->s_lock)
83 sb->s_lock=0;
84#endif
85 sb->s_flags |= MS_RDONLY;
86 panic ("ECFS-fs panic (device %s): %s: %s\n",
87 bdevname(sb->s_dev), function, error_buf);
88}
89
90void ecfs_warning (struct super_block * sb, const char * function,
91 const char * fmt, ...)
92{
93 va_list args;
94
95 va_start (args, fmt);
96 vsprintf (error_buf, fmt, args);
97 va_end (args);
98 printk (KERN_WARNING "ECFS-fs warning (device %s): %s: %s\n",
99 bdevname(sb->s_dev), function, error_buf);
100}
101
102void ecfs_update_dynamic_rev(struct super_block *sb)
103{
104 struct ecfs_super_block *es = ECFS_SB(sb)->s_es;
105
106 if (le32_to_cpu(es->s_rev_level) > ECFS_GOOD_OLD_REV)
107 return;
108
109 ecfs_warning(sb, __FUNCTION__,
110 "updating to rev %d because of new feature flag, "
111 "running e2fsck is recommended",
112 ECFS_DYNAMIC_REV);
113
114 es->s_first_ino = cpu_to_le32(ECFS_GOOD_OLD_FIRST_INO);
115 es->s_inode_size = cpu_to_le16(ECFS_GOOD_OLD_INODE_SIZE);
116 es->s_rev_level = cpu_to_le32(ECFS_DYNAMIC_REV);
117 /* leave es->s_feature_*compat flags alone */
118 /* es->s_uuid will be set by e2fsck if empty */
119
120 /*
121 * The rest of the superblock fields should be zero, and if not it
122 * means they are likely already in use, so leave them alone. We
123 * can leave it up to e2fsck to clean up any inconsistencies there.
124 */
125}
126
127void ecfs_put_super (struct super_block * sb)
128{
129 int db_count;
130 int i;
131
132 if (!(sb->s_flags & MS_RDONLY)) {
133 sb->u.ecfs_sb.s_es->s_state = le16_to_cpu(sb->u.ecfs_sb.s_mount_state);
134 mark_buffer_dirty(sb->u.ecfs_sb.s_sbh);
135 }
136 db_count = ECFS_SB(sb)->s_gdb_count;
137 for (i = 0; i < db_count; i++)
138 if (sb->u.ecfs_sb.s_group_desc[i])
139 brelse (sb->u.ecfs_sb.s_group_desc[i]);
140 kfree(sb->u.ecfs_sb.s_group_desc);
141 for (i = 0; i < ECFS_MAX_GROUP_LOADED; i++)
142 if (sb->u.ecfs_sb.s_inode_bitmap[i])
143 brelse (sb->u.ecfs_sb.s_inode_bitmap[i]);
144 for (i = 0; i < ECFS_MAX_GROUP_LOADED; i++)
145 if (sb->u.ecfs_sb.s_block_bitmap[i])
146 brelse (sb->u.ecfs_sb.s_block_bitmap[i]);
147 brelse (sb->u.ecfs_sb.s_sbh);
148
149 return;
150}
151
152static struct super_operations ecfs_sops = {
153 read_inode: ecfs_read_inode,
154 write_inode: ecfs_write_inode,
155 put_inode: ecfs_put_inode,
156 delete_inode: ecfs_delete_inode,
157 put_super: ecfs_put_super,
158 write_super: ecfs_write_super,
159 statfs: ecfs_statfs,
160 remount_fs: ecfs_remount,
161};
162
163/*
164 * This function has been shamelessly adapted from the msdos fs
165 */
166static int parse_options (char * options, unsigned long * sb_block,
167 unsigned short *resuid, unsigned short * resgid,
168 unsigned long * mount_options)
169{
170 char * this_char;
171 char * value;
172
173 if (!options)
174 return 1;
175 for (this_char = strtok (options, ",");
176 this_char != NULL;
177 this_char = strtok (NULL, ",")) {
178 if ((value = strchr (this_char, '=')) != NULL)
179 *value++ = 0;
180 if (!strcmp (this_char, "bsddf"))
181 clear_opt (*mount_options, MINIX_DF);
182 else if (!strcmp (this_char, "nouid32")) {
183 set_opt (*mount_options, NO_UID32);
184 }
185 else if (!strcmp (this_char, "check")) {
186 if (!value || !*value || !strcmp (value, "none"))
187 clear_opt (*mount_options, CHECK);
188 else
189#ifdef CONFIG_ECFS_CHECK
190 set_opt (*mount_options, CHECK);
191#else
192 printk("ECFS Check option not supported\n");
193#endif
194 }
195 else if (!strcmp (this_char, "debug"))
196 set_opt (*mount_options, DEBUG);
197 else if (!strcmp (this_char, "errors")) {
198 if (!value || !*value) {
199 printk ("ECFS-fs: the errors option requires "
200 "an argument\n");
201 return 0;
202 }
203 if (!strcmp (value, "continue")) {
204 clear_opt (*mount_options, ERRORS_RO);
205 clear_opt (*mount_options, ERRORS_PANIC);
206 set_opt (*mount_options, ERRORS_CONT);
207 }
208 else if (!strcmp (value, "remount-ro")) {
209 clear_opt (*mount_options, ERRORS_CONT);
210 clear_opt (*mount_options, ERRORS_PANIC);
211 set_opt (*mount_options, ERRORS_RO);
212 }
213 else if (!strcmp (value, "panic")) {
214 clear_opt (*mount_options, ERRORS_CONT);
215 clear_opt (*mount_options, ERRORS_RO);
216 set_opt (*mount_options, ERRORS_PANIC);
217 }
218 else {
219 printk ("ECFS-fs: Invalid errors option: %s\n",
220 value);
221 return 0;
222 }
223 }
224 else if (!strcmp (this_char, "grpid") ||
225 !strcmp (this_char, "bsdgroups"))
226 set_opt (*mount_options, GRPID);
227 else if (!strcmp (this_char, "minixdf"))
228 set_opt (*mount_options, MINIX_DF);
229 else if (!strcmp (this_char, "nocheck"))
230 clear_opt (*mount_options, CHECK);
231 else if (!strcmp (this_char, "nogrpid") ||
232 !strcmp (this_char, "sysvgroups"))
233 clear_opt (*mount_options, GRPID);
234 else if (!strcmp (this_char, "resgid")) {
235 if (!value || !*value) {
236 printk ("ECFS-fs: the resgid option requires "
237 "an argument\n");
238 return 0;
239 }
240 *resgid = simple_strtoul (value, &value, 0);
241 if (*value) {
242 printk ("ECFS-fs: Invalid resgid option: %s\n",
243 value);
244 return 0;
245 }
246 }
247 else if (!strcmp (this_char, "resuid")) {
248 if (!value || !*value) {
249 printk ("ECFS-fs: the resuid option requires "
250 "an argument");
251 return 0;
252 }
253 *resuid = simple_strtoul (value, &value, 0);
254 if (*value) {
255 printk ("ECFS-fs: Invalid resuid option: %s\n",
256 value);
257 return 0;
258 }
259 }
260 else if (!strcmp (this_char, "sb")) {
261 if (!value || !*value) {
262 printk ("ECFS-fs: the sb option requires "
263 "an argument");
264 return 0;
265 }
266 *sb_block = simple_strtoul (value, &value, 0);
267 if (*value) {
268 printk ("ECFS-fs: Invalid sb option: %s\n",
269 value);
270 return 0;
271 }
272 }
273 /* Silently ignore the quota options */
274 else if (!strcmp (this_char, "grpquota")
275 || !strcmp (this_char, "noquota")
276 || !strcmp (this_char, "quota")
277 || !strcmp (this_char, "usrquota"))
278 /* Don't do anything ;-) */ ;
279 else {
280 printk ("ECFS-fs: Unrecognized mount option %s\n", this_char);
281 return 0;
282 }
283 }
284 return 1;
285}
286
287static int ecfs_setup_super (struct super_block * sb,
288 struct ecfs_super_block * es,
289 int read_only)
290{
291 int res = 0;
292 if (le32_to_cpu(es->s_rev_level) > ECFS_MAX_SUPP_REV) {
293 printk ("ECFS-fs warning: revision level too high, "
294 "forcing read-only mode\n");
295 res = MS_RDONLY;
296 }
297 if (read_only)
298 return res;
299 if (!(sb->u.ecfs_sb.s_mount_state & ECFS_VALID_FS))
300 printk ("ECFS-fs warning: mounting unchecked fs, "
301 "running e2fsck is recommended\n");
302 else if ((sb->u.ecfs_sb.s_mount_state & ECFS_ERROR_FS))
303 printk ("ECFS-fs warning: mounting fs with errors, "
304 "running e2fsck is recommended\n");
305 else if ((__s16) le16_to_cpu(es->s_max_mnt_count) >= 0 &&
306 le16_to_cpu(es->s_mnt_count) >=
307 (unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count))
308 printk ("ECFS-fs warning: maximal mount count reached, "
309 "running e2fsck is recommended\n");
310 else if (le32_to_cpu(es->s_checkinterval) &&
311 (le32_to_cpu(es->s_lastcheck) + le32_to_cpu(es->s_checkinterval) <= CURRENT_TIME))
312 printk ("ECFS-fs warning: checktime reached, "
313 "running e2fsck is recommended\n");
314 es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & ~ECFS_VALID_FS);
315 if (!(__s16) le16_to_cpu(es->s_max_mnt_count))
316 es->s_max_mnt_count = (__s16) cpu_to_le16(ECFS_DFL_MAX_MNT_COUNT);
317 es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1);
318 es->s_mtime = cpu_to_le32(CURRENT_TIME);
319 mark_buffer_dirty(sb->u.ecfs_sb.s_sbh);
320 sb->s_dirt = 1;
321 if (test_opt (sb, DEBUG))
322 printk ("[EXT II FS %s, %s, bs=%lu, fs=%lu, gc=%lu, "
323 "bpg=%lu, ipg=%lu, mo=%04lx]\n",
324 ECFSFS_VERSION, ECFSFS_DATE, sb->s_blocksize,
325 sb->u.ecfs_sb.s_frag_size,
326 sb->u.ecfs_sb.s_groups_count,
327 ECFS_BLOCKS_PER_GROUP(sb),
328 ECFS_INODES_PER_GROUP(sb),
329 sb->u.ecfs_sb.s_mount_opt);
330#ifdef CONFIG_ECFS_CHECK
331 if (test_opt (sb, CHECK)) {
332 ecfs_check_blocks_bitmap (sb);
333 ecfs_check_inodes_bitmap (sb);
334 }
335#endif
336 return res;
337}
338
339static int ecfs_check_descriptors (struct super_block * sb)
340{
341 int i;
342 int desc_block = 0;
343 unsigned long block = le32_to_cpu(sb->u.ecfs_sb.s_es->s_first_data_block);
344 struct ecfs_group_desc * gdp = NULL;
345
346 ecfs_debug ("Checking group descriptors");
347
348 for (i = 0; i < sb->u.ecfs_sb.s_groups_count; i++)
349 {
350 if ((i % ECFS_DESC_PER_BLOCK(sb)) == 0)
351 gdp = (struct ecfs_group_desc *) sb->u.ecfs_sb.s_group_desc[desc_block++]->b_data;
352 if (le32_to_cpu(gdp->bg_block_bitmap) < block ||
353 le32_to_cpu(gdp->bg_block_bitmap) >= block + ECFS_BLOCKS_PER_GROUP(sb))
354 {
355 ecfs_error (sb, "ecfs_check_descriptors",
356 "Block bitmap for group %d"
357 " not in group (block %lu)!",
358 i, (unsigned long) le32_to_cpu(gdp->bg_block_bitmap));
359 return 0;
360 }
361 if (le32_to_cpu(gdp->bg_inode_bitmap) < block ||
362 le32_to_cpu(gdp->bg_inode_bitmap) >= block + ECFS_BLOCKS_PER_GROUP(sb))
363 {
364 ecfs_error (sb, "ecfs_check_descriptors",
365 "Inode bitmap for group %d"
366 " not in group (block %lu)!",
367 i, (unsigned long) le32_to_cpu(gdp->bg_inode_bitmap));
368 return 0;
369 }
370 if (le32_to_cpu(gdp->bg_inode_table) < block ||
371 le32_to_cpu(gdp->bg_inode_table) + sb->u.ecfs_sb.s_itb_per_group >=
372 block + ECFS_BLOCKS_PER_GROUP(sb))
373 {
374 ecfs_error (sb, "ecfs_check_descriptors",
375 "Inode table for group %d"
376 " not in group (block %lu)!",
377 i, (unsigned long) le32_to_cpu(gdp->bg_inode_table));
378 return 0;
379 }
380 block += ECFS_BLOCKS_PER_GROUP(sb);
381 gdp++;
382 }
383 return 1;
384}
385
386#define log2(n) ffz(~(n))
387
388struct super_block * ecfs_read_super (struct super_block * sb, void * data,
389 int silent)
390{
391 struct buffer_head * bh;
392 struct ecfs_super_block * es;
393 unsigned long sb_block = 1;
394 unsigned short resuid = ECFS_DEF_RESUID;
395 unsigned short resgid = ECFS_DEF_RESGID;
396 unsigned long logic_sb_block = 1;
397 unsigned long offset = 0;
398 kdev_t dev = sb->s_dev;
399 int blocksize = BLOCK_SIZE;
400 int hblock;
401 int db_count;
402 int i, j;
403
404
405
406
407 /*
408 * See what the current blocksize for the device is, and
409 * use that as the blocksize. Otherwise (or if the blocksize
410 * is smaller than the default) use the default.
411 * This is important for devices that have a hardware
412 * sectorsize that is larger than the default.
413 */
414// blocksize = get_hardblocksize(dev);
415 blocksize = get_hardsect_size(dev);
416 if( blocksize == 0 || blocksize < BLOCK_SIZE )
417 {
418 blocksize = BLOCK_SIZE;
419 }
420
421 sb->u.ecfs_sb.s_mount_opt = 0;
422 if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
423 &sb->u.ecfs_sb.s_mount_opt)) {
424 return NULL;
425 }
426
427 set_blocksize (dev, blocksize);
428
429 /*
430 * If the superblock doesn't start on a sector boundary,
431 * calculate the offset. FIXME(eric) this doesn't make sense
432 * that we would have to do this.
433 */
434 if (blocksize != BLOCK_SIZE) {
435 logic_sb_block = (sb_block*BLOCK_SIZE) / blocksize;
436 offset = (sb_block*BLOCK_SIZE) % blocksize;
437 }
438
439 if (!(bh = bread (dev, logic_sb_block, blocksize))) {
440 printk ("ECFS-fs: unable to read superblock\n");
441 return NULL;
442 }
443 /*
444 * Note: s_es must be initialized s_es as soon as possible because
445 * some ecfs macro-instructions depend on its value
446 */
447 es = (struct ecfs_super_block *) (((char *)bh->b_data) + offset);
448 sb->u.ecfs_sb.s_es = es;
449 sb->s_magic = le16_to_cpu(es->s_magic);
450 if (sb->s_magic != ECFS_SUPER_MAGIC) {
451 if (!silent)
452 printk ("VFS: Can't find an ecfs filesystem on dev "
453 "%s.\n", bdevname(dev));
454 failed_mount:
455 if (bh)
456 brelse(bh);
457 return NULL;
458 }
459 if (le32_to_cpu(es->s_rev_level) == ECFS_GOOD_OLD_REV &&
460 (ECFS_HAS_COMPAT_FEATURE(sb, ~0U) ||
461 ECFS_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||
462 ECFS_HAS_INCOMPAT_FEATURE(sb, ~0U)))
463 printk("ECFS-fs warning: feature flags set on rev 0 fs, "
464 "running e2fsck is recommended\n");
465 /*
466 * Check feature flags regardless of the revision level, since we
467 * previously didn't change the revision level when setting the flags,
468 * so there is a chance incompat flags are set on a rev 0 filesystem.
469 */
470 if ((i = ECFS_HAS_INCOMPAT_FEATURE(sb, ~ECFS_FEATURE_INCOMPAT_SUPP))) {
471 printk("ECFS-fs: %s: couldn't mount because of "
472 "unsupported optional features (%x).\n",
473 bdevname(dev), i);
474 goto failed_mount;
475 }
476 if (!(sb->s_flags & MS_RDONLY) &&
477 (i = ECFS_HAS_RO_COMPAT_FEATURE(sb, ~ECFS_FEATURE_RO_COMPAT_SUPP))){
478 printk("ECFS-fs: %s: couldn't mount RDWR because of "
479 "unsupported optional features (%x).\n",
480 bdevname(dev), i);
481 goto failed_mount;
482 }
483 sb->s_blocksize_bits =
484 le32_to_cpu(ECFS_SB(sb)->s_es->s_log_block_size) + 10;
485 sb->s_blocksize = 1 << sb->s_blocksize_bits;
486 if (sb->s_blocksize != BLOCK_SIZE &&
487 (sb->s_blocksize == 1024 || sb->s_blocksize == 2048 ||
488 sb->s_blocksize == 4096)) {
489 /*
490 * Make sure the blocksize for the filesystem is larger
491 * than the hardware sectorsize for the machine.
492 */
493// hblock = get_hardblocksize(dev);
494 hblock = get_hardsect_size(dev);
495 if( (hblock != 0)
496 && (sb->s_blocksize < hblock) )
497 {
498 printk("ECFS-fs: blocksize too small for device.\n");
499 goto failed_mount;
500 }
501
502 brelse (bh);
503 set_blocksize (dev, sb->s_blocksize);
504 logic_sb_block = (sb_block*BLOCK_SIZE) / sb->s_blocksize;
505 offset = (sb_block*BLOCK_SIZE) % sb->s_blocksize;
506 bh = bread (dev, logic_sb_block, sb->s_blocksize);
507 if(!bh) {
508 printk("ECFS-fs: Couldn't read superblock on "
509 "2nd try.\n");
510 goto failed_mount;
511 }
512 es = (struct ecfs_super_block *) (((char *)bh->b_data) + offset);
513 sb->u.ecfs_sb.s_es = es;
514 if (es->s_magic != le16_to_cpu(ECFS_SUPER_MAGIC)) {
515 printk ("ECFS-fs: Magic mismatch, very weird !\n");
516 goto failed_mount;
517 }
518 }
519 if (le32_to_cpu(es->s_rev_level) == ECFS_GOOD_OLD_REV) {
520 sb->u.ecfs_sb.s_inode_size = ECFS_GOOD_OLD_INODE_SIZE;
521 sb->u.ecfs_sb.s_first_ino = ECFS_GOOD_OLD_FIRST_INO;
522 } else {
523 sb->u.ecfs_sb.s_inode_size = le16_to_cpu(es->s_inode_size);
524 sb->u.ecfs_sb.s_first_ino = le32_to_cpu(es->s_first_ino);
525 if (sb->u.ecfs_sb.s_inode_size != ECFS_GOOD_OLD_INODE_SIZE) {
526 printk ("ECFS-fs: unsupported inode size: %d\n",
527 sb->u.ecfs_sb.s_inode_size);
528 goto failed_mount;
529 }
530 }
531 sb->u.ecfs_sb.s_frag_size = ECFS_MIN_FRAG_SIZE <<
532 le32_to_cpu(es->s_log_frag_size);
533 if (sb->u.ecfs_sb.s_frag_size)
534 sb->u.ecfs_sb.s_frags_per_block = sb->s_blocksize /
535 sb->u.ecfs_sb.s_frag_size;
536 else
537 sb->s_magic = 0;
538 sb->u.ecfs_sb.s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
539 sb->u.ecfs_sb.s_frags_per_group = le32_to_cpu(es->s_frags_per_group);
540 sb->u.ecfs_sb.s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
541 sb->u.ecfs_sb.s_inodes_per_block = sb->s_blocksize /
542 ECFS_INODE_SIZE(sb);
543 sb->u.ecfs_sb.s_itb_per_group = sb->u.ecfs_sb.s_inodes_per_group /
544 sb->u.ecfs_sb.s_inodes_per_block;
545 sb->u.ecfs_sb.s_desc_per_block = sb->s_blocksize /
546 sizeof (struct ecfs_group_desc);
547 sb->u.ecfs_sb.s_sbh = bh;
548 if (resuid != ECFS_DEF_RESUID)
549 sb->u.ecfs_sb.s_resuid = resuid;
550 else
551 sb->u.ecfs_sb.s_resuid = le16_to_cpu(es->s_def_resuid);
552 if (resgid != ECFS_DEF_RESGID)
553 sb->u.ecfs_sb.s_resgid = resgid;
554 else
555 sb->u.ecfs_sb.s_resgid = le16_to_cpu(es->s_def_resgid);
556 sb->u.ecfs_sb.s_mount_state = le16_to_cpu(es->s_state);
557 sb->u.ecfs_sb.s_addr_per_block_bits =
558 log2 (ECFS_ADDR_PER_BLOCK(sb));
559 sb->u.ecfs_sb.s_desc_per_block_bits =
560 log2 (ECFS_DESC_PER_BLOCK(sb));
561 if (sb->s_magic != ECFS_SUPER_MAGIC) {
562 if (!silent)
563 printk ("VFS: Can't find an ecfs filesystem on dev "
564 "%s.\n",
565 bdevname(dev));
566 goto failed_mount;
567 }
568 if (sb->s_blocksize != bh->b_size) {
569 if (!silent)
570 printk ("VFS: Unsupported blocksize on dev "
571 "%s.\n", bdevname(dev));
572 goto failed_mount;
573 }
574
575 if (sb->s_blocksize != sb->u.ecfs_sb.s_frag_size) {
576 printk ("ECFS-fs: fragsize %lu != blocksize %lu (not supported yet)\n",
577 sb->u.ecfs_sb.s_frag_size, sb->s_blocksize);
578 goto failed_mount;
579 }
580
581 if (sb->u.ecfs_sb.s_blocks_per_group > sb->s_blocksize * 8) {
582 printk ("ECFS-fs: #blocks per group too big: %lu\n",
583 sb->u.ecfs_sb.s_blocks_per_group);
584 goto failed_mount;
585 }
586 if (sb->u.ecfs_sb.s_frags_per_group > sb->s_blocksize * 8) {
587 printk ("ECFS-fs: #fragments per group too big: %lu\n",
588 sb->u.ecfs_sb.s_frags_per_group);
589 goto failed_mount;
590 }
591 if (sb->u.ecfs_sb.s_inodes_per_group > sb->s_blocksize * 8) {
592 printk ("ECFS-fs: #inodes per group too big: %lu\n",
593 sb->u.ecfs_sb.s_inodes_per_group);
594 goto failed_mount;
595 }
596
597 sb->u.ecfs_sb.s_groups_count = (le32_to_cpu(es->s_blocks_count) -
598 le32_to_cpu(es->s_first_data_block) +
599 ECFS_BLOCKS_PER_GROUP(sb) - 1) /
600 ECFS_BLOCKS_PER_GROUP(sb);
601 db_count = (sb->u.ecfs_sb.s_groups_count + ECFS_DESC_PER_BLOCK(sb) - 1) /
602 ECFS_DESC_PER_BLOCK(sb);
603 sb->u.ecfs_sb.s_group_desc = kmalloc (db_count * sizeof (struct buffer_head *), GFP_KERNEL);
604 if (sb->u.ecfs_sb.s_group_desc == NULL) {
605 printk ("ECFS-fs: not enough memory\n");
606 goto failed_mount;
607 }
608 for (i = 0; i < db_count; i++) {
609 sb->u.ecfs_sb.s_group_desc[i] = bread (dev, logic_sb_block + i + 1,
610 sb->s_blocksize);
611 if (!sb->u.ecfs_sb.s_group_desc[i]) {
612 for (j = 0; j < i; j++)
613 brelse (sb->u.ecfs_sb.s_group_desc[j]);
614 kfree(sb->u.ecfs_sb.s_group_desc);
615 printk ("ECFS-fs: unable to read group descriptors\n");
616 goto failed_mount;
617 }
618 }
619 if (!ecfs_check_descriptors (sb)) {
620 for (j = 0; j < db_count; j++)
621 brelse (sb->u.ecfs_sb.s_group_desc[j]);
622 kfree(sb->u.ecfs_sb.s_group_desc);
623 printk ("ECFS-fs: group descriptors corrupted !\n");
624 goto failed_mount;
625 }
626 for (i = 0; i < ECFS_MAX_GROUP_LOADED; i++) {
627 sb->u.ecfs_sb.s_inode_bitmap_number[i] = 0;
628 sb->u.ecfs_sb.s_inode_bitmap[i] = NULL;
629 sb->u.ecfs_sb.s_block_bitmap_number[i] = 0;
630 sb->u.ecfs_sb.s_block_bitmap[i] = NULL;
631 }
632 sb->u.ecfs_sb.s_loaded_inode_bitmaps = 0;
633 sb->u.ecfs_sb.s_loaded_block_bitmaps = 0;
634 sb->u.ecfs_sb.s_gdb_count = db_count;
635 /*
636 * set up enough so that it can read an inode
637 */
638 sb->s_op = &ecfs_sops;
639 sb->s_root = d_alloc_root(iget(sb, ECFS_ROOT_INO));
640 if (!sb->s_root) {
641 for (i = 0; i < db_count; i++)
642 if (sb->u.ecfs_sb.s_group_desc[i])
643 brelse (sb->u.ecfs_sb.s_group_desc[i]);
644 kfree(sb->u.ecfs_sb.s_group_desc);
645 brelse (bh);
646 printk ("ECFS-fs: get root inode failed\n");
647 return NULL;
648 }
649 ecfs_setup_super (sb, es, sb->s_flags & MS_RDONLY);
650 return sb;
651}
652
653static void ecfs_commit_super (struct super_block * sb,
654 struct ecfs_super_block * es)
655{
656 es->s_wtime = cpu_to_le32(CURRENT_TIME);
657 mark_buffer_dirty(sb->u.ecfs_sb.s_sbh);
658 sb->s_dirt = 0;
659}
660
661/*
662 * In the second extended file system, it is not necessary to
663 * write the super block since we use a mapping of the
664 * disk super block in a buffer.
665 *
666 * However, this function is still used to set the fs valid
667 * flags to 0. We need to set this flag to 0 since the fs
668 * may have been checked while mounted and e2fsck may have
669 * set s_state to ECFS_VALID_FS after some corrections.
670 */
671
672void ecfs_write_super (struct super_block * sb)
673{
674 struct ecfs_super_block * es;
675
676 if (!(sb->s_flags & MS_RDONLY)) {
677 es = sb->u.ecfs_sb.s_es;
678
679 ecfs_debug ("setting valid to 0\n");
680
681 if (le16_to_cpu(es->s_state) & ECFS_VALID_FS) {
682 es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & ~ECFS_VALID_FS);
683 es->s_mtime = cpu_to_le32(CURRENT_TIME);
684 }
685 ecfs_commit_super (sb, es);
686 }
687 sb->s_dirt = 0;
688}
689
690int ecfs_remount (struct super_block * sb, int * flags, char * data)
691{
692 struct ecfs_super_block * es;
693 unsigned short resuid = sb->u.ecfs_sb.s_resuid;
694 unsigned short resgid = sb->u.ecfs_sb.s_resgid;
695 unsigned long new_mount_opt;
696 unsigned long tmp;
697
698 /*
699 * Allow the "check" option to be passed as a remount option.
700 */
701 new_mount_opt = sb->u.ecfs_sb.s_mount_opt;
702 if (!parse_options (data, &tmp, &resuid, &resgid,
703 &new_mount_opt))
704 return -EINVAL;
705
706 sb->u.ecfs_sb.s_mount_opt = new_mount_opt;
707 sb->u.ecfs_sb.s_resuid = resuid;
708 sb->u.ecfs_sb.s_resgid = resgid;
709 es = sb->u.ecfs_sb.s_es;
710 if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
711 return 0;
712 if (*flags & MS_RDONLY) {
713 if (le16_to_cpu(es->s_state) & ECFS_VALID_FS ||
714 !(sb->u.ecfs_sb.s_mount_state & ECFS_VALID_FS))
715 return 0;
716 /*
717 * OK, we are remounting a valid rw partition rdonly, so set
718 * the rdonly flag and then mark the partition as valid again.
719 */
720 es->s_state = cpu_to_le16(sb->u.ecfs_sb.s_mount_state);
721 es->s_mtime = cpu_to_le32(CURRENT_TIME);
722 mark_buffer_dirty(sb->u.ecfs_sb.s_sbh);
723 sb->s_dirt = 1;
724 ecfs_commit_super (sb, es);
725 }
726 else {
727 int ret;
728 if ((ret = ECFS_HAS_RO_COMPAT_FEATURE(sb,
729 ~ECFS_FEATURE_RO_COMPAT_SUPP))) {
730 printk("ECFS-fs: %s: couldn't remount RDWR because of "
731 "unsupported optional features (%x).\n",
732 bdevname(sb->s_dev), ret);
733 return -EROFS;
734 }
735 /*
736 * Mounting a RDONLY partition read-write, so reread and
737 * store the current valid flag. (It may have been changed
738 * by e2fsck since we originally mounted the partition.)
739 */
740 sb->u.ecfs_sb.s_mount_state = le16_to_cpu(es->s_state);
741 if (!ecfs_setup_super (sb, es, 0))
742 sb->s_flags &= ~MS_RDONLY;
743 }
744 return 0;
745}
746
747int ecfs_statfs (struct super_block * sb, struct statfs * buf)
748{
749 unsigned long overhead;
750 int i;
751
752 if (test_opt (sb, MINIX_DF))
753 overhead = 0;
754 else {
755 /*
756 * Compute the overhead (FS structures)
757 */
758
759 /*
760 * All of the blocks before first_data_block are
761 * overhead
762 */
763 overhead = le32_to_cpu(sb->u.ecfs_sb.s_es->s_first_data_block);
764
765 /*
766 * Add the overhead attributed to the superblock and
767 * block group descriptors. If the sparse superblocks
768 * feature is turned on, then not all groups have this.
769 */
770 for (i = 0; i < ECFS_SB(sb)->s_groups_count; i++)
771 overhead += ecfs_bg_has_super(sb, i) +
772 ecfs_bg_num_gdb(sb, i);
773
774 /*
775 * Every block group has an inode bitmap, a block
776 * bitmap, and an inode table.
777 */
778 overhead += (sb->u.ecfs_sb.s_groups_count *
779 (2 + sb->u.ecfs_sb.s_itb_per_group));
780 }
781
782 buf->f_type = ECFS_SUPER_MAGIC;
783 buf->f_bsize = sb->s_blocksize;
784 buf->f_blocks = le32_to_cpu(sb->u.ecfs_sb.s_es->s_blocks_count) - overhead;
785 buf->f_bfree = ecfs_count_free_blocks (sb);
786 buf->f_bavail = buf->f_bfree - le32_to_cpu(sb->u.ecfs_sb.s_es->s_r_blocks_count);
787 if (buf->f_bfree < le32_to_cpu(sb->u.ecfs_sb.s_es->s_r_blocks_count))
788 buf->f_bavail = 0;
789 buf->f_files = le32_to_cpu(sb->u.ecfs_sb.s_es->s_inodes_count);
790 buf->f_ffree = ecfs_count_free_inodes (sb);
791 buf->f_namelen = ECFS_NAME_LEN;
792 return 0;
793}
794
795static DECLARE_FSTYPE_DEV(ecfs_fs_type, "ecfs", ecfs_read_super);
796
797MODULE_PARM(ecfs_key, "s");
798
799static int __init init_ecfs_fs(void)
800{
801 if (strlen(ecfs_key) < 8 || strlen(ecfs_key) > 1024) {
802 printk("<1> You need a key of 8 <= len <= 1024. Please rmmod and\n"
803 "'insmod ecfs_key=<key>' again.\n\n");
804 return -1;
805 }
806 return register_filesystem(&ecfs_fs_type);
807}
808
809static void __exit exit_ecfs_fs(void)
810{
811 unregister_filesystem(&ecfs_fs_type);
812}
813
814EXPORT_NO_SYMBOLS;
815
816module_init(init_ecfs_fs)
817module_exit(exit_ecfs_fs)
diff --git a/other/ecfs/super.o b/other/ecfs/super.o
new file mode 100644
index 0000000..a2367ef
--- /dev/null
+++ b/other/ecfs/super.o
Binary files differ
diff --git a/other/ecfs/symlink.c b/other/ecfs/symlink.c
new file mode 100644
index 0000000..1108793
--- /dev/null
+++ b/other/ecfs/symlink.c
@@ -0,0 +1,38 @@
1/*
2 * linux/fs/ecfs/symlink.c
3 *
4 * Only fast symlinks left here - the rest is done by generic code. AV, 1999
5 *
6 * Copyright (C) 1992, 1993, 1994, 1995
7 * Remy Card (card@masi.ibp.fr)
8 * Laboratoire MASI - Institut Blaise Pascal
9 * Universite Pierre et Marie Curie (Paris VI)
10 *
11 * from
12 *
13 * linux/fs/minix/symlink.c
14 *
15 * Copyright (C) 1991, 1992 Linus Torvalds
16 *
17 * ecfs symlink handling code
18 */
19
20#include <linux/fs_ecfs.h>
21#include <linux/ecfs_fs.h>
22
23static int ecfs_readlink(struct dentry *dentry, char *buffer, int buflen)
24{
25 char *s = (char *)dentry->d_inode->u.ecfs_i.i_data;
26 return vfs_readlink(dentry, buffer, buflen, s);
27}
28
29static int ecfs_follow_link(struct dentry *dentry, struct nameidata *nd)
30{
31 char *s = (char *)dentry->d_inode->u.ecfs_i.i_data;
32 return vfs_follow_link(nd, s);
33}
34
35struct inode_operations ecfs_fast_symlink_inode_operations = {
36 readlink: ecfs_readlink,
37 follow_link: ecfs_follow_link,
38};
diff --git a/other/ecfs/symlink.o b/other/ecfs/symlink.o
new file mode 100644
index 0000000..9bca096
--- /dev/null
+++ b/other/ecfs/symlink.o
Binary files differ
diff --git a/other/ecfs/transform b/other/ecfs/transform
new file mode 100644
index 0000000..9071929
--- /dev/null
+++ b/other/ecfs/transform
@@ -0,0 +1,53 @@
1#!/usr/bin/perl
2
3# Takes kernel Ext2 headers and rewrites
4# them to Ecfs headers in separate files.
5# No kernel-headers are touched.
6
7@cp = (
8 "cp ".
9 "/usr/src/linux/include/linux/ext2_fs.h ".
10 "/usr/src/linux/include/linux/ecfs_fs.h",
11
12 "cp ".
13 "/usr/src/linux/include/linux/ext2_fs_sb.h ".
14 "/usr/src/linux/include/linux/ecfs_fs_sb.h",
15
16 "cp ".
17 "/usr/src/linux/include/linux/ext2_fs_i.h ".
18 "/usr/src/linux/include/linux/ecfs_fs_i.h",
19
20 "cp ".
21 "/usr/src/linux/include/linux/fs.h ".
22 "/usr/src/linux/include/linux/fs_ecfs.h "
23);
24
25
26@sed = (
27 "./repl.pl ".
28 "/usr/src/linux/include/linux/ecfs_fs.h",
29
30 "./repl.pl ".
31 "/usr/src/linux/include/linux/ecfs_fs_sb.h",
32
33 "./repl.pl ".
34 "/usr/src/linux/include/linux/ecfs_fs_i.h",
35
36 "./repl.pl ".
37 "/usr/src/linux/include/linux/fs_ecfs.h "
38);
39
40
41foreach (@cp) {
42 print "$_\n";
43 system($_);
44}
45
46foreach (@sed) {
47 print "$_\n";
48 system($_);
49}
50
51
52
53