Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 54684 | Differences between
and this patch

Collapse All | Expand All

(-)kernel-source-2.6.5/Documentation/filesystems/00-INDEX (+2 lines)
Lines 6-11 Link Here
6
	- info and mount options for the Acorn Advanced Disc Filing System.
6
	- info and mount options for the Acorn Advanced Disc Filing System.
7
affs.txt
7
affs.txt
8
	- info and mount options for the Amiga Fast File System.
8
	- info and mount options for the Amiga Fast File System.
9
asfs.txt
10
	- info and mount options for the Amiga Smart File System.
9
bfs.txt
11
bfs.txt
10
	- info for the SCO UnixWare Boot Filesystem (BFS).
12
	- info for the SCO UnixWare Boot Filesystem (BFS).
11
cifs.txt
13
cifs.txt
(-)kernel-source-2.6.5/Documentation/filesystems/asfs.txt (+150 lines)
Line 0 Link Here
1
2
Amiga SmartFileSystem, Linux implementation
3
===========================================
4
5
ASFS is a Amiga Smart FileSystem driver for Linux. It supports reading
6
files and directories. From version 1.0 there is also an experimental 
7
(almost full) write support. Experimental means that it hasn't been 
8
tested enough yet, so use it with care. Symbolic links (in AmigaOS
9
called soft links) are also supported read/write. Read notes below 
10
about symlinks support.
11
12
13
Unsupported features of Amiga SFS
14
================================
15
16
ASFS currently does not support safe-delete feature of Amiga SFS 
17
filesystem. It simply deletes files instead of moving them to 
18
".recycled" directory. It also doesn't remove files from ".recycled" 
19
directory, when there is no space left on drive. 
20
21
If there is no space left, you need to manually remove files from 
22
".recycled" directory. Also if you want to delete a file in a safe 
23
way, you need to move it to ".recycled" directory by hand.
24
25
Because of all of above, the amount of free space on disk does not 
26
include space used by all files from ".recycled" directory.
27
28
29
Limitations
30
===========
31
32
There is no Amiga protection bits into Linux permission bits tranlation
33
and vice versa. If you need this feature, mail me.
34
35
ASFS will always keep some amount of blocks free. This means that you 
36
cannot fill the drive completely. It is because Amiga SFS uses some 
37
special methods of writing data (called safe write), which needs some
38
additional free space.
39
40
File systems with unfinished transactions (this happens when system crashed
41
during writing data to disk on AmigaOS/MorphOS) will be mounted read-only
42
to protect data. The only way to fix such filesystem is to mount it under
43
AmigaOS or MorphOS.
44
45
Do not try to mount and write to filesystem with errors. Bad things will
46
happen.
47
48
49
Mount options for the ASFS
50
==========================
51
52
setuid[=uid]	
53
		This sets the owner of all files and directories in the file
54
		system to uid or the uid of the current user, respectively.
55
56
setgid[=gid]	
57
		Same as above, but for gid.
58
59
mode=mode	
60
		Sets the mode flags to the given (octal) value. Directories 
61
		will get an x permission if the corresponding r bit is set.
62
		The default mode is 0666, which means all r and w bits are set
63
		(for directories this means also that all x bits are set).
64
65
prefix=path	
66
		Path will be prefixed to every absolute path name of symbolic 
67
		links on an ASFS/AFFS partition. Default = "/". (See below.)
68
69
volume=name
70
		When symbolic links with an absolute path are created
71
      on an ASFS/AFFS partition, name will be prepended as the
72
      volume name. Default = "" (empty string). (See below.)
73
74
lowercasevol
75
		Translate all volume names in symlinks to lower case.
76
		Disabled by default. (See below.)
77
78
Symbolic links
79
==============
80
81
Although the Amiga and Linux file systems resemble each other, there
82
are some, not always subtle, differences. One of them becomes apparent
83
with symbolic links. While Linux has a file system with exactly one
84
root directory, the Amiga has a separate root directory for each
85
file system (for example, partition, floppy disk, ...). With the Amiga,
86
these entities are called "volumes". They have symbolic names which
87
can be used to access them. Thus, symbolic links can point to a
88
different volume. ASFS turns the volume name into a directory name
89
and prepends the prefix path (see prefix option) to it. When option
90
"lowercasevol" is set, it also translates volume names to lower case.
91
If the volume name is the same as a name given in "volume" option,
92
it will be ignored and an absolute path will be created.
93
94
Example:
95
You mount all your Amiga partitions under /amiga/<volume> (where
96
<volume> is the name of the volume), and you give options
97
`prefix="/amiga/",volume="Linux",lowercasevol' when mounting all your 
98
ASFS partitions. (They might be "User", "WB" and "Graphics", the mount 
99
points /amiga/user, /amiga/wb and /amiga/graphics). 
100
101
A symbolic link referring to "USER:sc/include/dos/dos.h" will be 
102
translated to "/amiga/user/sc/include/dos/dos.h".
103
A symbolic link referring to "Linux:etc/fstab" will be translated to
104
"/etc/fstab".
105
If you create a symlink referring to "/amiga/graphics/data/pict.jpg",
106
it will be saved as "graphics:data/pict.jpg".
107
If you create a symlink referring to "/boot/System.map", it will be 
108
saved as "Linux:boot/System.map".
109
110
111
Other information
112
=================
113
114
Supported block sizes are: 512, 1024, 2048 and 4096 bytes. Larger blocks
115
speed up almost everything at the expense of wasted disk space. The speed
116
gain above 4K seems not really worth the price, so you don't lose too
117
much here, either.
118
119
This file system has been tested on Motorola PPC and 68k, as well as 
120
Intel x86 systems. I don't know, if it works on other Linux systems.
121
122
This filesystem is in BETA STAGE. This means that driver could crash in
123
some circumstances and it also MIGHT corrupt/damage data on your disk.
124
Remember! YOU USE IT ON YOUR OWN RISK! 
125
126
I made almost all I could to minimalize this risk. On my systems several 
127
gigabytes has been succesfully copied from and to SFS disks. I would also 
128
appreciate any infomation if this filesystem works on your system or not. 
129
See  next paragraph for my email.
130
131
Some parts of this documentation has been adapted from AFFS driver docs.
132
133
134
Author, contact and copyright infos
135
===================================
136
137
ASFS has been written by Marek 'March' Szyprowski <marek@amiga.pl>.
138
Mail me if you have any suggestions or found a bug.
139
140
Copyright (C) 2003,2004  Marek 'March' Szyprowski <marek@amiga.pl>
141
142
Thanks to Marcin Kurek (Morgoth/Dreamolers-CAPS) for help and parts 
143
of original amiga version of SmartFilesystem source code. 
144
145
SmartFilesystem is copyrighted (C) 2003,2004 by: John Hendrikx, 
146
Ralph Schmidt, Emmanuel Lesueur, David Gerber and Marcin Kurek
147
148
The ASFS driver is realased under the terms of of the GNU General 
149
Public License. See source code for more details.
150
(-)kernel-source-2.6.5/fs/asfs/adminspace.c (+445 lines)
Line 0 Link Here
1
/*
2
 *
3
 * Amiga Smart File System, Linux implementation
4
 * version: 1.0beta3
5
 *
6
 * This file contains some parts of the original amiga version of 
7
 * SmartFilesystem source code.
8
 *
9
 * SmartFilesystem is copyrighted (C) 2003 by: John Hendrikx, 
10
 * Ralph Schmidt, Emmanuel Lesueur, David Gerber, and Marcin Kurek
11
 * 
12
 * Adapted and modified by Marek 'March' Szyprowski <marek@amiga.pl>
13
 *
14
 */
15
16
#include <linux/types.h>
17
#include <linux/errno.h>
18
#include <linux/slab.h>
19
#include <linux/fs.h>
20
#include <linux/buffer_head.h>
21
#include <linux/vfs.h>
22
#include <linux/asfs_fs.h>
23
24
#include <asm/byteorder.h>
25
26
#ifdef CONFIG_ASFS_RW
27
28
static int setfreeblocks(struct super_block *sb, u32 freeblocks)
29
{
30
	struct buffer_head *bh;
31
	if ((bh = asfs_breadcheck(sb, ASFS_SB(sb)->rootobjectcontainer, ASFS_OBJECTCONTAINER_ID))) {
32
		struct fsRootInfo *ri = (struct fsRootInfo *) ((u8 *) bh->b_data + sb->s_blocksize - sizeof(struct fsRootInfo));
33
		ASFS_SB(sb)->freeblocks = freeblocks;
34
		ri->freeblocks = cpu_to_be32(freeblocks);
35
		asfs_bstore(sb, bh);
36
		asfs_brelse(bh);
37
		return 0;
38
	}
39
	return -EIO;
40
}
41
42
int enoughspace(struct super_block *sb, u32 blocks)
43
{
44
	if (ASFS_SB(sb)->freeblocks - ASFS_ALWAYSFREE < blocks)
45
		return FALSE;
46
47
	return TRUE;
48
}
49
50
	/* Determines the amount of free blocks starting from block /block/.
51
	   If there are no blocks found or if there was an error -1 is returned,
52
	   otherwise this function will count the number of free blocks until
53
	   an allocated block is encountered or until maxneeded has been
54
	   exceeded. */
55
56
int availablespace(struct super_block *sb, u32 block, u32 maxneeded)
57
{
58
	struct buffer_head *bh = NULL;
59
	struct fsBitmap *b;
60
	u32 longs = ASFS_SB(sb)->blocks_inbitmap >> 5;
61
	u32 maxbitmapblock = ASFS_SB(sb)->bitmapbase + ASFS_SB(sb)->blocks_bitmap;
62
	int blocksfound = 0;
63
	u32 bitstart;
64
	int bitend;
65
	u32 nextblock = ASFS_SB(sb)->bitmapbase + block / ASFS_SB(sb)->blocks_inbitmap;
66
67
	bitstart = block % ASFS_SB(sb)->blocks_inbitmap;
68
69
	while (nextblock < maxbitmapblock && (bh = asfs_breadcheck(sb, nextblock++, ASFS_BITMAP_ID))) {
70
		b = (void *) bh->b_data;
71
72
		if ((bitend = bmffz(b->bitmap, longs, bitstart)) >= 0) {
73
			blocksfound += bitend - bitstart;
74
			asfs_brelse(bh);
75
			return blocksfound;
76
		}
77
		blocksfound += ASFS_SB(sb)->blocks_inbitmap - bitstart;
78
		if (blocksfound >= maxneeded) {
79
			asfs_brelse(bh);
80
			return blocksfound;
81
		}
82
		bitstart = 0;
83
		asfs_brelse(bh);
84
	}
85
86
	if (bh == NULL)
87
		return (-1);
88
89
	return (blocksfound);
90
}
91
92
int findspace(struct super_block *sb, u32 maxneeded, u32 start, u32 end, u32 * returned_block, u32 * returned_blocks)
93
{
94
	struct buffer_head *bh;
95
	u32 longs = ASFS_SB(sb)->blocks_inbitmap >> 5;
96
	u32 space = 0;
97
	u32 block;
98
	u32 bitmapblock = ASFS_SB(sb)->bitmapbase + start / ASFS_SB(sb)->blocks_inbitmap;
99
	u32 breakpoint;
100
	int bitstart, bitend;
101
	int reads;
102
103
	if (enoughspace(sb, maxneeded) == FALSE) {
104
		*returned_block = 0;
105
		*returned_blocks = 0;
106
		return -ENOSPC;
107
	}
108
109
	if (start >= ASFS_SB(sb)->totalblocks)
110
		start -= ASFS_SB(sb)->totalblocks;
111
112
	if (end == 0)
113
		end = ASFS_SB(sb)->totalblocks;
114
115
	reads = ((end - 1) / ASFS_SB(sb)->blocks_inbitmap) + 1 - start / ASFS_SB(sb)->blocks_inbitmap;
116
117
	if (start >= end)
118
		reads += (ASFS_SB(sb)->totalblocks - 1) / ASFS_SB(sb)->blocks_inbitmap + 1;
119
120
	breakpoint = (start < end ? end : ASFS_SB(sb)->totalblocks);
121
122
	*returned_block = 0;
123
	*returned_blocks = 0;
124
125
	bitend = start % ASFS_SB(sb)->blocks_inbitmap;
126
	block = start - bitend;
127
128
	while ((bh = asfs_breadcheck(sb, bitmapblock++, ASFS_BITMAP_ID))) {
129
		struct fsBitmap *b = (void *) bh->b_data;
130
		u32 localbreakpoint = breakpoint - block;
131
132
		if (localbreakpoint > ASFS_SB(sb)->blocks_inbitmap)
133
			localbreakpoint = ASFS_SB(sb)->blocks_inbitmap;
134
135
		/* At this point space contains the amount of free blocks at
136
		   the end of the previous bitmap block.  If there are no
137
		   free blocks at the start of this bitmap block, space will
138
		   be set to zero, since in that case the space isn't adjacent. */
139
140
		while ((bitstart = bmffo(b->bitmap, longs, bitend)) < ASFS_SB(sb)->blocks_inbitmap) {
141
			/* found the start of an empty space, now find out how large it is */
142
143
			if (bitstart >= localbreakpoint)
144
				break;
145
146
			if (bitstart != 0)
147
				space = 0;
148
149
			bitend = bmffz(b->bitmap, longs, bitstart);
150
151
			if (bitend > localbreakpoint)
152
				bitend = localbreakpoint;
153
154
			space += bitend - bitstart;
155
156
			if (*returned_blocks < space) {
157
				*returned_block = block + bitend - space;
158
				if (space >= maxneeded) {
159
					*returned_blocks = maxneeded;
160
					asfs_brelse(bh);
161
					return 0;
162
				}
163
				*returned_blocks = space;
164
			}
165
166
			if (bitend >= localbreakpoint)
167
				break;
168
		}
169
170
		if (--reads == 0)
171
			break;
172
173
		/* no (more) empty spaces found in this block */
174
175
		if (bitend != ASFS_SB(sb)->blocks_inbitmap)
176
			space = 0;
177
178
		bitend = 0;
179
		block += ASFS_SB(sb)->blocks_inbitmap;
180
181
		if (block >= ASFS_SB(sb)->totalblocks) {
182
			block = 0;
183
			space = 0;
184
			breakpoint = end;
185
			bitmapblock = ASFS_SB(sb)->bitmapbase;
186
		}
187
		asfs_brelse(bh);
188
	}
189
190
	if (bh == NULL)
191
		return -EIO;
192
193
	asfs_brelse(bh);
194
195
	if (*returned_blocks == 0)
196
		return -ENOSPC;
197
	else
198
		return 0;
199
}
200
201
int markspace(struct super_block *sb, u32 block, u32 blocks)
202
{
203
	int errorcode;
204
205
	asfs_debug("markspace: Marking %d blocks from block %d\n", blocks, block);
206
207
	if ((availablespace(sb, block, blocks)) < blocks) {
208
		printk("ASFS: Attempted to mark %d blocks from block %d, but some of them were already full!\n", blocks, block);
209
		return -EIO;
210
	}
211
212
	if ((errorcode = setfreeblocks(sb, ASFS_SB(sb)->freeblocks - blocks)) == 0) {
213
		struct buffer_head *bh;
214
		u32 skipblocks = block / ASFS_SB(sb)->blocks_inbitmap;
215
		u32 longs = (sb->s_blocksize - sizeof(struct fsBitmap)) >> 2;
216
		u32 bitmapblock;
217
218
		block -= skipblocks * ASFS_SB(sb)->blocks_inbitmap;
219
		bitmapblock = ASFS_SB(sb)->bitmapbase + skipblocks;
220
221
		while (blocks > 0) {
222
			if ((bh = asfs_breadcheck(sb, bitmapblock++, ASFS_BITMAP_ID))) {
223
				struct fsBitmap *b = (void *) bh->b_data;
224
225
				blocks -= bmclr(b->bitmap, longs, block, blocks);
226
				block = 0;
227
228
				asfs_bstore(sb, bh);
229
				asfs_brelse(bh);
230
			} else
231
				return -EIO;
232
		}
233
	}
234
235
	return (errorcode);
236
}
237
238
	/* This function checks the bitmap and tries to locate at least /blocksneeded/
239
	   adjacent unused blocks.  If found it sets returned_block to the start block
240
	   and returns no error.  If not found, ERROR_DISK_IS_FULL is returned and
241
	   returned_block is set to zero.  Any other errors are returned as well. */
242
243
static inline int internalfindspace(struct super_block *sb, u32 blocksneeded, u32 startblock, u32 endblock, u32 * returned_block)
244
{
245
	u32 blocks;
246
	int errorcode;
247
248
	if ((errorcode = findspace(sb, blocksneeded, startblock, endblock, returned_block, &blocks)) == 0)
249
		if (blocks != blocksneeded)
250
			return -ENOSPC;
251
252
	return errorcode;
253
}
254
255
static int findandmarkspace(struct super_block *sb, u32 blocksneeded, u32 * returned_block)
256
{
257
	int errorcode;
258
259
	if (enoughspace(sb, blocksneeded) != FALSE) {
260
		if ((errorcode = internalfindspace(sb, blocksneeded, 0, ASFS_SB(sb)->totalblocks, returned_block)) == 0)
261
			errorcode = markspace(sb, *returned_block, blocksneeded);
262
	} else
263
		errorcode = -ENOSPC;
264
265
	return (errorcode);
266
}
267
268
/* ************************** */
269
270
int freespace(struct super_block *sb, u32 block, u32 blocks)
271
{
272
	int errorcode;
273
274
	asfs_debug("freespace: Freeing %d blocks from block %d\n", blocks, block);
275
276
	if ((errorcode = setfreeblocks(sb, ASFS_SB(sb)->freeblocks + blocks)) == 0) {
277
		struct buffer_head *bh;
278
		u32 skipblocks = block / ASFS_SB(sb)->blocks_inbitmap;
279
		u32 longs = (sb->s_blocksize - sizeof(struct fsBitmap)) >> 2;
280
		u32 bitmapblock;
281
282
		block -= skipblocks * ASFS_SB(sb)->blocks_inbitmap;
283
		bitmapblock = ASFS_SB(sb)->bitmapbase + skipblocks;
284
285
		while (blocks > 0) {
286
			if ((bh = asfs_breadcheck(sb, bitmapblock++, ASFS_BITMAP_ID))) {
287
				struct fsBitmap *b = (void *) bh->b_data;
288
289
				blocks -= bmset(b->bitmap, longs, block, blocks);
290
				block = 0;
291
292
				asfs_bstore(sb, bh);
293
				asfs_brelse(bh);
294
			} else
295
				return -EIO;
296
		}
297
	}
298
299
	return (errorcode);
300
}
301
302
/*************** admin space containers ****************/
303
304
int allocadminspace(struct super_block *sb, u32 *returned_block)
305
{
306
	struct buffer_head *bh;
307
	u32 adminspaceblock = ASFS_SB(sb)->adminspacecontainer;
308
	int errorcode = -EIO;
309
310
	asfs_debug("allocadminspace: allocating new block\n");
311
312
	while ((bh = asfs_breadcheck(sb, adminspaceblock, ASFS_ADMINSPACECONTAINER_ID))) {
313
		struct fsAdminSpaceContainer *asc1 = (void *) bh->b_data;
314
		struct fsAdminSpace *as1 = asc1->adminspace;
315
		int adminspaces1 = (sb->s_blocksize - sizeof(struct fsAdminSpaceContainer)) / sizeof(struct fsAdminSpace);
316
317
		while (adminspaces1-- > 0) {
318
			s16 bitoffset;
319
320
			if (as1->space != 0 && (bitoffset = bfffz(be32_to_cpu(as1->bits), 0)) >= 0) {
321
				u32 emptyadminblock = be32_to_cpu(as1->space) + bitoffset;
322
				as1->bits |= cpu_to_be32(1 << (31 - bitoffset));
323
				asfs_bstore(sb, bh);
324
				*returned_block = emptyadminblock;
325
				asfs_brelse(bh);
326
				asfs_debug("allocadminspace: found block %d\n", *returned_block);
327
				return 0;
328
			}
329
			as1++;
330
		}
331
332
		adminspaceblock = be32_to_cpu(asc1->next);
333
		asfs_brelse(bh);
334
335
		if (adminspaceblock == 0) {
336
			u32 startblock;
337
338
			asfs_debug("allocadminspace: allocating new adminspace area\n");
339
340
			/* If we get here it means current adminspace areas are all filled.
341
			   We would now need to find a new area and create a fsAdminSpace
342
			   structure in one of the AdminSpaceContainer blocks.  If these
343
			   don't have any room left for new adminspace areas a new
344
			   AdminSpaceContainer would have to be created first which is
345
			   placed as the first block in the newly found admin area. */
346
347
			adminspaceblock = ASFS_SB(sb)->adminspacecontainer;
348
349
			if ((errorcode = findandmarkspace(sb, 32, &startblock)))
350
				return errorcode;
351
352
			while ((bh = asfs_breadcheck(sb, adminspaceblock, ASFS_ADMINSPACECONTAINER_ID))) {
353
				struct fsAdminSpaceContainer *asc2 = (void *) bh->b_data;
354
				struct fsAdminSpace *as2 = asc2->adminspace;
355
				int adminspaces2 = (sb->s_blocksize - sizeof(struct fsAdminSpaceContainer)) / sizeof(struct fsAdminSpace);
356
357
				while (adminspaces2-- > 0 && as2->space != 0)
358
					as2++;
359
360
				if (adminspaces2 >= 0) {	/* Found a unused AdminSpace in this AdminSpaceContainer! */
361
					as2->space = cpu_to_be32(startblock);
362
					as2->bits = 0;
363
					asfs_bstore(sb, bh);
364
					asfs_brelse(bh);
365
					break;
366
				}
367
368
				if (asc2->next == 0) {
369
					/* Oh-oh... we marked our new adminspace area in use, but we couldn't
370
					   find space to store a fsAdminSpace structure in the existing
371
					   fsAdminSpaceContainer blocks.  This means we need to create and
372
					   link a new fsAdminSpaceContainer as the first block in our newly
373
					   marked adminspace. */
374
375
					asc2->next = cpu_to_be32(startblock);
376
					asfs_bstore(sb, bh);
377
					asfs_brelse(bh);
378
379
					/* Now preparing new AdminSpaceContainer */
380
381
					if ((bh = asfs_getzeroblk(sb, startblock)) == NULL)
382
						return -EIO;
383
384
					asc2 = (void *) bh->b_data;
385
					asc2->bheader.id = cpu_to_be32(ASFS_ADMINSPACECONTAINER_ID);
386
					asc2->bheader.ownblock = cpu_to_be32(startblock);
387
					asc2->previous = cpu_to_be32(adminspaceblock);
388
					asc2->adminspace[0].space = cpu_to_be32(startblock);
389
					asc2->adminspace[0].bits = cpu_to_be32(0x80000000);
390
					asc2->bits = 32;
391
392
					asfs_bstore(sb, bh);
393
					asfs_brelse(bh);
394
395
					adminspaceblock = startblock;
396
					break;	/* Breaks through to outer loop! */
397
				}
398
				adminspaceblock = be32_to_cpu(asc2->next);
399
				asfs_brelse(bh);
400
			}
401
		}
402
	}
403
	return errorcode;
404
}
405
406
int freeadminspace(struct super_block *sb, u32 block)
407
{
408
	struct buffer_head *bh;
409
	u32 adminspaceblock = ASFS_SB(sb)->adminspacecontainer;
410
411
	asfs_debug("freeadminspace: Entry -- freeing block %d\n", block);
412
413
	while ((bh = asfs_breadcheck(sb, adminspaceblock, ASFS_ADMINSPACECONTAINER_ID))) {
414
		struct fsAdminSpaceContainer *asc = (void *) bh->b_data;
415
		struct fsAdminSpace *as = asc->adminspace;
416
		int adminspaces = (sb->s_blocksize - sizeof(struct fsAdminSpaceContainer)) / sizeof(struct fsAdminSpace);
417
418
		while (adminspaces-- > 0) {
419
			if (block >= be32_to_cpu(as->space) && block < be32_to_cpu(as->space) + 32) {
420
				s16 bitoffset = block - be32_to_cpu(as->space);
421
				asfs_debug("freeadminspace: Block to be freed is located in AdminSpaceContainer block at %d\n", adminspaceblock);
422
				as->bits &= cpu_to_be32(~(1 << (31 - bitoffset)));
423
				asfs_bstore(sb, bh);
424
				asfs_brelse(bh);
425
				return 0;
426
			}
427
			as++;
428
		}
429
430
		if ((adminspaceblock = be32_to_cpu(asc->next)) == 0)
431
			break;
432
433
		asfs_brelse(bh);
434
	}
435
436
	if (bh != NULL) {
437
		asfs_brelse(bh);
438
		printk("ASFS: Unable to free an administration block. The block cannot be found.");
439
		return -ENOENT;
440
	}
441
442
	return -EIO;
443
}
444
445
#endif
(-)kernel-source-2.6.5/fs/asfs/bitfuncs.c (+249 lines)
Line 0 Link Here
1
/*
2
 *
3
 * This program is free software; you can redistribute it and/or
4
 * modify it under the terms of the GNU General Public License
5
 * as published by the Free Software Foundation; either version
6
 * 2 of the License, or (at your option) any later version.
7
 *
8
 */
9
10
#include <linux/types.h>
11
#include <asm/byteorder.h>
12
13
#ifdef CONFIG_ASFS_RW
14
15
static s16 bfffo(u32 data, s16 bitoffset)
16
{
17
	u32 bitmask = 1 << (31 - bitoffset);
18
19
  /** Finds first set bit in /data/ starting at /bitoffset/.  This function
20
      considers the MSB to be the first bit. */
21
22
	do {
23
		if ((data & bitmask) != 0) {
24
			return bitoffset;
25
		}
26
		bitoffset++;
27
		bitmask >>= 1;
28
	} while (bitmask != 0);
29
30
	return -1;
31
}
32
33
34
s16 bfffz(u32 data, s16 bitoffset)
35
{
36
	u32 bitmask = 1 << (31 - bitoffset);
37
38
  /** Finds first zero bit in /data/ starting at /bitoffset/.  This function
39
      considers the MSB to be the first bit. */
40
41
	do {
42
		if ((data & bitmask) == 0) {
43
			return (bitoffset);
44
		}
45
		bitoffset++;
46
		bitmask >>= 1;
47
	} while (bitmask != 0);
48
49
	return (-1);
50
}
51
52
53
54
static u32 bfset(u32 data, s16 bitoffset, s16 bits)
55
{
56
	u32 mask;
57
58
  /** Sets /bits/ bits starting from /bitoffset/ in /data/.
59
      /bits/ must be between 1 and 32. */
60
61
	/* we want a mask which sets /bits/ bits starting from bit 31 */
62
63
	mask = ~((1 << (32 - bits)) - 1);
64
	mask >>= bitoffset;
65
66
	return data | mask;
67
}
68
69
70
static u32 bfclr(u32 data, s16 bitoffset, s16 bits)
71
{
72
	u32 mask;
73
74
	/* we want a mask which sets /bits/ bits starting from bit 31 */
75
76
	mask = ~((1 << (32 - bits)) - 1);
77
	mask >>= bitoffset;
78
79
	return data & ~mask;
80
}
81
82
83
/* bitmap (bm) functions:
84
85
   These functions perform bit-operations on regions of memory which
86
   are a multiple of 4 bytes in length. Bitmap is in bigendian byte order.
87
*/
88
89
s32 bmffo(u32 * bitmap, s32 longs, s32 bitoffset)
90
{
91
	u32 *scan = bitmap;
92
	u32 longoffset;
93
	s16 bit;
94
95
	/* This function finds the first set bit in a region of memory starting
96
	   with /bitoffset/.  The region of memory is /longs/ longs long.  It
97
	   returns the bitoffset of the first set bit it finds. */
98
99
	longoffset = bitoffset >> 5;
100
	longs -= longoffset;
101
	scan += longoffset;
102
103
	bitoffset = bitoffset & 0x1F;
104
105
	if (bitoffset != 0) {
106
		if ((bit = bfffo(be32_to_cpu(*scan), bitoffset)) >= 0) {
107
			return (bit + ((scan - bitmap) << 5));
108
		}
109
110
		scan++;
111
		longs--;
112
	}
113
114
	while (longs-- > 0) {
115
		if (*scan++ != 0) {
116
			return (bfffo(be32_to_cpu(*--scan), 0) + ((scan - bitmap) << 5));
117
		}
118
	}
119
120
	return (-1);
121
}
122
123
s32 bmffz(u32 * bitmap, s32 longs, s32 bitoffset)
124
{
125
	u32 *scan = bitmap;
126
	u32 longoffset;
127
	s16 bit;
128
129
	/* This function finds the first unset bit in a region of memory starting
130
	   with /bitoffset/.  The region of memory is /longs/ longs long.  It
131
	   returns the bitoffset of the first unset bit it finds. */
132
133
	longoffset = bitoffset >> 5;
134
	longs -= longoffset;
135
	scan += longoffset;
136
137
	bitoffset = bitoffset & 0x1F;
138
139
	if (bitoffset != 0) {
140
		if ((bit = bfffz(be32_to_cpu(*scan), bitoffset)) >= 0) {
141
			return (bit + ((scan - bitmap) << 5));
142
		}
143
144
		scan++;
145
		longs--;
146
	}
147
148
	while (longs-- > 0) {
149
		if (*scan++ != 0xFFFFFFFF) {
150
			return (bfffz(be32_to_cpu(*--scan), 0) + ((scan - bitmap) << 5));
151
		}
152
	}
153
154
	return (-1);
155
}
156
157
s32 bmclr(u32 * bitmap, s32 longs, s32 bitoffset, s32 bits)
158
{
159
	u32 *scan = bitmap;
160
	u32 longoffset;
161
	s32 orgbits = bits;
162
163
	/* This function clears /bits/ bits in a region of memory starting
164
	   with /bitoffset/.  The region of memory is /longs/ longs long.  If
165
	   the region of memory is too small to clear /bits/ bits then this
166
	   function exits after having cleared all bits till the end of the
167
	   memory region.  In any case it returns the number of bits which
168
	   were actually cleared. */
169
170
	longoffset = bitoffset >> 5;
171
	longs -= longoffset;
172
	scan += longoffset;
173
174
	bitoffset = bitoffset & 0x1F;
175
176
	if (bitoffset != 0) {
177
		if (bits < 32) {
178
			*scan = cpu_to_be32(bfclr(be32_to_cpu(*scan), bitoffset, bits));
179
		} else {
180
			*scan = cpu_to_be32(bfclr(be32_to_cpu(*scan), bitoffset, 32));
181
		}
182
183
		scan++;
184
		longs--;
185
		bits -= 32 - bitoffset;
186
	}
187
188
	while (bits > 0 && longs-- > 0) {
189
		if (bits > 31) {
190
			*scan++ = 0;
191
		} else {
192
			*scan = cpu_to_be32(bfclr(be32_to_cpu(*scan), 0, bits));
193
		}
194
		bits -= 32;
195
	}
196
197
	if (bits <= 0) {
198
		return (orgbits);
199
	}
200
	return (orgbits - bits);
201
}
202
203
s32 bmset(u32 * bitmap, s32 longs, s32 bitoffset, s32 bits)
204
{
205
	u32 *scan = bitmap;
206
	u32 longoffset;
207
	s32 orgbits = bits;
208
209
	/* This function sets /bits/ bits in a region of memory starting
210
	   with /bitoffset/.  The region of memory is /longs/ longs long.  If
211
	   the region of memory is too small to set /bits/ bits then this
212
	   function exits after having set all bits till the end of the
213
	   memory region.  In any case it returns the number of bits which
214
	   were actually set. */
215
216
	longoffset = bitoffset >> 5;
217
	longs -= longoffset;
218
	scan += longoffset;
219
220
	bitoffset = bitoffset & 0x1F;
221
222
	if (bitoffset != 0) {
223
		if (bits < 32) {
224
			*scan = cpu_to_be32(bfset(be32_to_cpu(*scan), bitoffset, bits));
225
		} else {
226
			*scan = cpu_to_be32(bfset(be32_to_cpu(*scan), bitoffset, 32));
227
		}
228
229
		scan++;
230
		longs--;
231
		bits -= 32 - bitoffset;
232
	}
233
234
	while (bits > 0 && longs-- > 0) {
235
		if (bits > 31) {
236
			*scan++ = 0xFFFFFFFF;
237
		} else {
238
			*scan = cpu_to_be32(bfset(be32_to_cpu(*scan), 0, bits));
239
		}
240
		bits -= 32;
241
	}
242
243
	if (bits <= 0) {
244
		return (orgbits);
245
	}
246
	return (orgbits - bits);
247
}
248
249
#endif
(-)kernel-source-2.6.5/fs/asfs/dir.c (+221 lines)
Line 0 Link Here
1
/*
2
 *
3
 * Amiga Smart File System, Linux implementation
4
 * version: 1.0beta3
5
 *  
6
 * Copyright (C) 2003,2004  Marek 'March' Szyprowski <marek@amiga.pl>
7
 *
8
 *
9
 * This program is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU General Public License
11
 * as published by the Free Software Foundation; either version
12
 * 2 of the License, or (at your option) any later version.
13
 *
14
 */
15
16
#include <linux/types.h>
17
#include <linux/errno.h>
18
#include <linux/slab.h>
19
#include <linux/asfs_fs.h>
20
#include <linux/fs.h>
21
#include <linux/buffer_head.h>
22
#include <linux/vfs.h>
23
24
#include <asm/byteorder.h>
25
26
extern struct dentry_operations asfs_dentry_operations;
27
28
int asfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
29
{
30
	struct inode *dir = filp->f_dentry->d_inode;
31
	struct super_block *sb = dir->i_sb;
32
	unsigned long f_pos;
33
	int stored = 0;
34
35
	struct buffer_head *bh;
36
	struct fsObjectContainer *objcont;
37
	struct fsObject *obj;
38
	u32 block;
39
	int startnode;
40
	int add;
41
42
	asfs_debug("asfs_readdir:\n");
43
44
	if (filp->f_pos == ASFS_SB(sb)->totalblocks)
45
		return stored;
46
47
	f_pos = filp->f_pos;
48
49
	if (f_pos == 0) {
50
		filp->private_data = (void *)0;
51
		if (filldir(dirent, ".", 1, f_pos, dir->i_ino, DT_DIR) < 0)
52
			return 0;
53
		filp->f_pos = f_pos = 1;
54
		stored++;
55
	}
56
	if (f_pos == 1) {
57
		if (filldir(dirent, "..", 2, f_pos, parent_ino(filp->f_dentry), DT_DIR) < 0)
58
			return stored;
59
		filp->f_pos = f_pos = 2;
60
		stored++;
61
	}
62
63
	if (ASFS_I(dir)->firstblock == 0) {	/* empty directory */
64
		filp->f_pos = ASFS_SB(sb)->totalblocks;
65
		ASFS_I(dir)->modified = 0;
66
		return stored;
67
	}
68
69
	if (f_pos == 2) {	/* reading directory from its beginning */
70
		block = ASFS_I(dir)->firstblock;
71
		add = 1;
72
		startnode = 0;
73
	} else {
74
		startnode = (int)filp->private_data;
75
		add = 0;
76
		if (ASFS_I(dir)->modified == 0)
77
			block = f_pos;
78
		else
79
			block = ASFS_I(dir)->firstblock;
80
	}
81
82
	do {
83
		if (!(bh = asfs_breadcheck(sb, block, ASFS_OBJECTCONTAINER_ID)))
84
			return stored;
85
		objcont = (struct fsObjectContainer *) bh->b_data;
86
		obj = &(objcont->object[0]);
87
88
		while (be32_to_cpu(obj->objectnode) > 0 && 
89
		      ((char *)obj - (char *)objcont) + sizeof(struct fsObject) + 2 < sb->s_blocksize) {
90
91
			if (!add && be32_to_cpu(obj->objectnode) == startnode)
92
				add++;
93
94
			if (add && !(obj->bits & OTYPE_HIDDEN)) {
95
				unsigned int type;
96
				asfs_debug("ASFS: DirFilling: entry #%d \"%s\" (node %u offset %u), type %x\n", \
97
				           stored, obj->name, be32_to_cpu(obj->objectnode), block, obj->bits);
98
				filp->f_pos = block;
99
100
				if (obj->bits & OTYPE_DIR)
101
					type = DT_DIR;
102
				else if (obj->bits & OTYPE_LINK && !(obj->bits & OTYPE_HARDLINK))
103
					type = DT_LNK;
104
				else
105
					type = DT_REG;
106
107
				if (filldir(dirent, obj->name, strlen(obj->name), block, be32_to_cpu(obj->objectnode), type) < 0) {
108
					filp->private_data = (void *)be32_to_cpu(obj->objectnode);
109
					ASFS_I(dir)->modified = 0;
110
					asfs_debug("ASFS: DirFilling: to be continued...\n");
111
					asfs_brelse(bh);
112
					return stored;
113
				}
114
				stored++;
115
			}
116
			obj = asfs_nextobject(obj);
117
		}
118
		block = be32_to_cpu(objcont->next);
119
		asfs_brelse(bh);
120
121
	} while (block != 0);
122
123
	filp->f_pos = ASFS_SB(sb)->totalblocks;
124
	ASFS_I(dir)->modified = 0;
125
126
	return stored;
127
}
128
129
struct dentry *asfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
130
{
131
	int res = -EACCES;       /* placeholder for "no data here" */
132
	struct inode *inode;
133
	struct super_block *sb = dir->i_sb;
134
	u8 *name = (u8 *) dentry->d_name.name;
135
	struct buffer_head *bh;
136
	struct fsObject *obj;
137
138
	asfs_debug("asfs_lookup: (searching \"%s\"...) ", name);
139
140
	lock_super(sb);
141
142
	if (ASFS_I(dir)->hashtable != 0) {	/* hashtable block is available, quick search */
143
		struct fsObjectNode *node_p;
144
		struct buffer_head *node_bh;
145
		u32 node;
146
		u16 hash16;
147
148
		asfs_debug("(quick search) ");
149
150
		if (!(bh = asfs_breadcheck(sb, ASFS_I(dir)->hashtable, ASFS_HASHTABLE_ID))) {
151
			unlock_super(sb);
152
			return ERR_PTR(res);
153
		}
154
		hash16 = asfs_hash(name, ASFS_SB(sb)->flags & ASFS_ROOTBITS_CASESENSITIVE); 
155
		node = be32_to_cpu(((struct fsHashTable *) bh->b_data)->hashentry[HASHCHAIN(hash16)]);
156
		asfs_brelse(bh);
157
158
		while (node != 0) {
159
			if (getnode(sb, node, &node_bh, &node_p) != 0)
160
				goto not_found;
161
			if (be16_to_cpu(node_p->hash16) == hash16) {
162
				if (!(bh = asfs_breadcheck(sb, be32_to_cpu(node_p->node.data), ASFS_OBJECTCONTAINER_ID))) {
163
					asfs_brelse(node_bh);
164
					unlock_super(sb);
165
					return ERR_PTR(res);
166
				}
167
				if ((obj = find_obj_by_name(sb, (struct fsObjectContainer *) bh->b_data, name)) != NULL) {
168
					asfs_brelse(node_bh);
169
					goto found_inode;
170
				}
171
				asfs_brelse(bh);
172
			}
173
			node = be32_to_cpu(node_p->next);
174
			asfs_brelse(node_bh);
175
		}
176
	} else { /* hashtable not available, long search */
177
		struct fsObjectContainer *objcont;
178
		u32 block;
179
180
		asfs_debug("(long search) ");
181
182
		block = ASFS_I(dir)->firstblock;
183
184
		if (block == 0)
185
			goto not_found;
186
		do {
187
			if (!(bh = asfs_breadcheck(sb, block, ASFS_OBJECTCONTAINER_ID))) {
188
				unlock_super(sb);
189
				return ERR_PTR(res);
190
			}
191
			objcont = (struct fsObjectContainer *) bh->b_data;
192
			if ((obj = find_obj_by_name(sb, objcont, name)) != NULL)
193
				goto found_inode;
194
			block = be32_to_cpu(objcont->next);
195
			asfs_brelse(bh);
196
		} while (block != 0);
197
	}
198
199
not_found:
200
	unlock_super(sb);
201
	inode = NULL;
202
	asfs_debug("object not found.\n");
203
	if (0) {
204
found_inode:
205
		unlock_super(sb);
206
		if (!(inode = iget_locked(sb, be32_to_cpu(obj->objectnode)))) {
207
			asfs_debug("ASFS: Strange - no inode allocated.\n");
208
			return ERR_PTR(res);
209
		}
210
		if (inode->i_state & I_NEW) {
211
			asfs_read_locked_inode(inode, obj);
212
			unlock_new_inode(inode);
213
		}
214
215
		asfs_brelse(bh);
216
	}
217
	res = 0;
218
	dentry->d_op = &asfs_dentry_operations;
219
	d_add(dentry, inode);
220
	return ERR_PTR(res);
221
}
(-)kernel-source-2.6.5/fs/asfs/extents.c (+585 lines)
Line 0 Link Here
1
/*
2
 *
3
 * Amiga Smart File System, Linux implementation
4
 * version: 1.0beta3
5
 *
6
 * This file contains some parts of the original amiga version of 
7
 * SmartFilesystem source code.
8
 *
9
 * SmartFilesystem is copyrighted (C) 2003 by: John Hendrikx, 
10
 * Ralph Schmidt, Emmanuel Lesueur, David Gerber and Marcin Kurek
11
 * 
12
 * Adapted and modified by Marek 'March' Szyprowski <marek@amiga.pl>
13
 *
14
 */
15
16
#include <linux/types.h>
17
#include <linux/errno.h>
18
#include <linux/slab.h>
19
#include <linux/asfs_fs.h>
20
#include <linux/fs.h>
21
#include <linux/buffer_head.h>
22
#include <linux/vfs.h>
23
24
#include <asm/byteorder.h>
25
26
	/* This function looks for the BNode equal to the key.  If no
27
	   exact match is available then the BNode which is slightly
28
	   lower than key will be returned.  If no such BNode exists
29
	   either, then the first BNode in this block is returned.
30
31
	   This function will return the first BNode even if there
32
	   are no BNode's at all in this block (this can only happen
33
	   for the Root of the tree).  Be sure to check if the Root
34
	   is not empty before calling this function. */
35
36
static struct BNode *searchforbnode(u32 key, struct BTreeContainer *tc)
37
{
38
	struct BNode *tn;
39
	s16 n = be16_to_cpu(tc->nodecount) - 1;
40
41
	tn = (struct BNode *) ((u8 *) tc->bnode + n * tc->nodesize);
42
	for (;;) {
43
		if (n <= 0 || key >= be32_to_cpu(tn->key))
44
			return tn;
45
46
		tn = (struct BNode *) ((u8 *) tn - tc->nodesize);
47
		n--;
48
	}
49
}
50
51
/* This function finds the BNode with the given key.  If no exact match can be
52
   found then this function will return either the next or previous closest
53
   match (don't rely on this).
54
55
   If there were no BNode's at all, then *returned_bh will be NULL. */
56
57
static int findbnode(struct super_block *sb, u32 key, struct buffer_head **returned_bh, struct BNode **returned_bnode)
58
{
59
	u32 rootblock = ASFS_SB(sb)->extentbnoderoot;
60
61
	asfs_debug("findbnode: Looking for BNode with key %d\n", key);
62
63
	while ((*returned_bh = asfs_breadcheck(sb, rootblock, ASFS_BNODECONTAINER_ID))) {
64
		struct fsBNodeContainer *bnc = (void *) (*returned_bh)->b_data;
65
		struct BTreeContainer *btc = &bnc->btc;
66
67
		if (btc->nodecount == 0) {
68
			*returned_bnode = NULL;
69
			break;
70
		}
71
72
		*returned_bnode = searchforbnode(key, btc);
73
		if (btc->isleaf == TRUE)
74
			break;
75
76
		rootblock = be32_to_cpu((*returned_bnode)->data);
77
		asfs_brelse(*returned_bh);
78
	}
79
80
	if (*returned_bh == NULL)
81
		return -EIO;
82
83
	return 0;
84
}
85
86
int getextent(struct super_block *sb, u32 key, struct buffer_head **ret_bh, struct fsExtentBNode **ret_ebn)
87
{
88
	int result;
89
	if ((result = findbnode(sb, key, ret_bh, (struct BNode **)ret_ebn)) == 0) 
90
		if (be32_to_cpu((*ret_ebn)->key) != key) {
91
			brelse(*ret_bh);
92
			*ret_bh = NULL;
93
			return -ENOENT;
94
		}
95
96
	return result;
97
}
98
99
#ifdef CONFIG_ASFS_RW
100
101
	/* This routine inserts a node sorted into a BTreeContainer.  It does
102
	   this by starting at the end, and moving the nodes one by one to
103
	   a higher slot until the empty slot has the correct position for
104
	   this key.  Donot use this function on completely filled
105
	   BTreeContainers! */
106
107
static struct BNode *insertbnode(u32 key, struct BTreeContainer *btc)
108
{
109
	struct BNode *bn;
110
	bn = (struct BNode *) ((u8 *) btc->bnode + btc->nodesize * (be16_to_cpu(btc->nodecount) - 1));
111
112
	for (;;) {
113
		if (bn < btc->bnode || key > be32_to_cpu(bn->key)) {
114
			bn = (struct BNode *) ((u8 *) bn + btc->nodesize);
115
			bn->key = cpu_to_be32(key);
116
			btc->nodecount = cpu_to_be16(be16_to_cpu(btc->nodecount) + 1);
117
			break;
118
		} else 
119
			memmove((u8 *)bn + btc->nodesize, bn, btc->nodesize);
120
121
		bn = (struct BNode *) ((u8 *) bn - btc->nodesize);
122
	}
123
124
	return bn;
125
}
126
127
static int getparentbtreecontainer(struct super_block *sb, struct buffer_head *bh, struct buffer_head **parent_bh)
128
{
129
	u32 rootblock = ASFS_SB(sb)->extentbnoderoot;
130
	u32 childkey = be32_to_cpu(((struct fsBNodeContainer *) bh->b_data)->btc.bnode[0].key);
131
	u32 childblock = be32_to_cpu(((struct fsBNodeContainer *) bh->b_data)->bheader.ownblock);
132
133
	asfs_debug("getparentbtreecontainer: Getting parent of block %d\n", childblock);
134
135
	/* This function gets the BTreeContainer parent of the passed in buffer_head. If
136
	   there is no parent this function sets dest_cont io_bh to NULL */
137
138
	if (rootblock != childblock) {
139
		while ((*parent_bh = asfs_breadcheck(sb, rootblock, ASFS_BNODECONTAINER_ID))) {
140
			struct fsBNodeContainer *bnc = (void *) (*parent_bh)->b_data;
141
			struct BTreeContainer *btc = &bnc->btc;
142
			struct BNode *bn;
143
			s16 n = be16_to_cpu(btc->nodecount);
144
145
			if (btc->isleaf == TRUE) {
146
				asfs_brelse(*parent_bh);
147
				break;
148
			}
149
150
			while (n-- > 0)
151
				if (be32_to_cpu(btc->bnode[n].data) == childblock)
152
					return 0;	/* Found parent!! */
153
154
			bn = searchforbnode(childkey, btc);	/* This searchforbnode() doesn't have to get EXACT key matches. */
155
			rootblock = be32_to_cpu(bn->data);
156
			asfs_brelse(*parent_bh);
157
		}
158
		if (*parent_bh == NULL)
159
			return -EIO;
160
	}
161
162
	*parent_bh = NULL;
163
	return 0;
164
}
165
166
/* Spits a btreecontainer. It realses passed in bh! */
167
168
static int splitbtreecontainer(struct super_block *sb, struct buffer_head *bh)
169
{
170
	struct buffer_head *bhparent;
171
	struct BNode *bn;
172
	int errorcode;
173
174
	asfs_debug("splitbtreecontainer: splitting block %u\n", be32_to_cpu(((struct fsBlockHeader *) bh->b_data)->ownblock));
175
176
	if ((errorcode = getparentbtreecontainer(sb, bh, &bhparent)) == 0) {
177
		if (bhparent == NULL) {
178
			u32 newbcontblock;
179
			u32 bcontblock;
180
			/* We need to create Root tree-container - adding new level to extent tree */
181
182
			asfs_debug("splitbtreecontainer: creating root tree-container.\n");
183
184
			bhparent = bh;
185
			if ((errorcode = allocadminspace(sb, &newbcontblock)) == 0 && (bh = asfs_getzeroblk(sb, newbcontblock))) {
186
				struct fsBNodeContainer *bnc = (void *) bh->b_data;
187
				struct fsBNodeContainer *bncparent = (void *) bhparent->b_data;
188
				struct BTreeContainer *btcparent = &bncparent->btc;
189
190
				bcontblock = be32_to_cpu(bncparent->bheader.ownblock);
191
				memcpy(bh->b_data, bhparent->b_data, sb->s_blocksize);
192
				bnc->bheader.ownblock = cpu_to_be32(newbcontblock);
193
				asfs_bstore(sb, bh);
194
195
				memset(bhparent->b_data, '\0', sb->s_blocksize);	/* Not strictly needed, but makes things more clear. */
196
				bncparent->bheader.id = cpu_to_be32(ASFS_BNODECONTAINER_ID);
197
				bncparent->bheader.ownblock = cpu_to_be32(bcontblock);
198
				btcparent->isleaf = FALSE;
199
				btcparent->nodesize = sizeof(struct BNode);
200
				btcparent->nodecount = 0;
201
202
				bn = insertbnode(0, btcparent);
203
				bn->data = cpu_to_be32(newbcontblock);
204
205
				asfs_bstore(sb, bhparent);
206
			}
207
			if (bh == NULL)
208
				errorcode = -EIO;
209
		}
210
211
		if (errorcode == 0) {
212
			struct fsBNodeContainer *bncparent = (void *) bhparent->b_data;
213
			struct BTreeContainer *btcparent = &bncparent->btc;
214
			int branches1 = (sb->s_blocksize - sizeof(struct fsBNodeContainer)) / btcparent->nodesize;
215
216
			if (be16_to_cpu(btcparent->nodecount) == branches1) {
217
				/* We need to split the parent tree-container first! */
218
				if ((errorcode = splitbtreecontainer(sb, bhparent)) == 0) {
219
					/* bhparent might have changed after the split and has been released */
220
					if ((errorcode = getparentbtreecontainer(sb, bh, &bhparent)) == 0) {	
221
						bncparent = (void *) bhparent->b_data;
222
						btcparent = &bncparent->btc;
223
					}
224
				}
225
			}
226
227
			if (errorcode == 0) {
228
				u32 newbcontblock;
229
				struct buffer_head *bhnew;
230
231
				/* We can split this container and add it to the parent
232
				   because the parent has enough room. */
233
234
				if ((errorcode = allocadminspace(sb, &newbcontblock)) == 0 && (bhnew = asfs_getzeroblk(sb, newbcontblock))) {
235
					struct fsBNodeContainer *bncnew = (void *) bhnew->b_data;
236
					struct BTreeContainer *btcnew = &bncnew->btc;
237
					struct fsBNodeContainer *bnc = (void *) bh->b_data;
238
					struct BTreeContainer *btc = &bnc->btc;
239
					int branches2 = (sb->s_blocksize - sizeof(struct fsBNodeContainer)) / btc->nodesize;
240
					u32 newkey;
241
242
					bncnew->bheader.id = cpu_to_be32(ASFS_BNODECONTAINER_ID);
243
					bncnew->bheader.ownblock = cpu_to_be32(newbcontblock);
244
245
					btcnew->isleaf = btc->isleaf;
246
					btcnew->nodesize = btc->nodesize;
247
248
					btcnew->nodecount = cpu_to_be16(branches2 - branches2 / 2);
249
250
					memcpy(btcnew->bnode, (u8 *) btc->bnode + branches2 / 2 * btc->nodesize, (branches2 - branches2 / 2) * btc->nodesize);
251
					newkey = be32_to_cpu(btcnew->bnode[0].key);
252
253
					asfs_bstore(sb, bhnew);
254
					asfs_brelse(bhnew);
255
256
					btc->nodecount = cpu_to_be16(branches2 / 2);
257
					asfs_bstore(sb, bh);
258
259
					bn = insertbnode(newkey, btcparent);
260
					bn->data = cpu_to_be32(newbcontblock);
261
					asfs_bstore(sb, bhparent);
262
				}
263
			}
264
		}
265
		asfs_brelse(bhparent);
266
	}
267
	asfs_brelse(bh);
268
269
	return errorcode;
270
}
271
272
/* zwraca wstawiony node w bloku, zapisaæ trzeba samemu! */
273
int createextentbnode(struct super_block *sb, u32 key, struct buffer_head **returned_bh, struct BNode **returned_bnode)
274
{
275
	int errorcode;
276
277
	asfs_debug("createbnode: Creating BNode with key %d\n", key);
278
279
	while ((errorcode = findbnode(sb, key, returned_bh, returned_bnode)) == 0) {
280
		struct fsBNodeContainer *bnc = (void *) (*returned_bh)->b_data;
281
		struct BTreeContainer *btc = &bnc->btc;
282
		int extbranches = (sb->s_blocksize - sizeof(struct fsBNodeContainer)) / btc->nodesize;
283
284
		asfs_debug("createbnode: findbnode found block %d\n", be32_to_cpu(((struct fsBlockHeader *) (*returned_bh)->b_data)->ownblock));
285
286
		if (be16_to_cpu(btc->nodecount) < extbranches) {
287
			/* Simply insert new node in this BTreeContainer */
288
			asfs_debug("createbnode: Simple insert\n");
289
			*returned_bnode = insertbnode(key, btc);
290
			break;
291
		} else if ((errorcode = splitbtreecontainer(sb, *returned_bh)) != 0)
292
			break;
293
294
		/* Loop and try insert it the normal way again :-) */
295
	}
296
297
	return (errorcode);
298
}
299
300
301
/* This routine removes a node from a BTreeContainer indentified
302
   by its key.  If no such key exists this routine does nothing.
303
   It correctly handles empty BTreeContainers. */
304
305
static void removebnode(u32 key, struct BTreeContainer *btc)
306
{
307
	struct BNode *bn = btc->bnode;
308
	int n = 0;
309
310
	asfs_debug("removebnode: key %d\n", key);
311
312
	while (n < be16_to_cpu(btc->nodecount)) {
313
		if (be32_to_cpu(bn->key) == key) {
314
			btc->nodecount = cpu_to_be16(be16_to_cpu(btc->nodecount) - 1);
315
			memmove(bn, (u8 *) bn + btc->nodesize, (be16_to_cpu(btc->nodecount) - n) * btc->nodesize);
316
			break;
317
		}
318
		bn = (struct BNode *) ((u8 *) bn + btc->nodesize);
319
		n++;
320
	}
321
}
322
323
int deletebnode(struct super_block *sb, struct buffer_head *bh, u32 key)
324
{
325
	struct fsBNodeContainer *bnc1 = (void *) bh->b_data;
326
	struct BTreeContainer *btc = &bnc1->btc;
327
	u16 branches = (sb->s_blocksize - sizeof(struct fsBNodeContainer)) / btc->nodesize;
328
	int errorcode = 0;
329
330
	/* Deletes specified internal node. */
331
332
	removebnode(key, btc);
333
	asfs_bstore(sb, bh);
334
335
	/* Now checks if the container still contains enough nodes,
336
	   and takes action accordingly. */
337
338
	asfs_debug("deletebnode: branches = %d, btc->nodecount = %d\n", branches, be16_to_cpu(btc->nodecount));
339
340
	if (be16_to_cpu(btc->nodecount) < (branches + 1) / 2) {
341
		struct buffer_head *bhparent;
342
		struct buffer_head *bhsec;
343
344
		/* nodecount has become to low.  We need to merge this Container
345
		   with a neighbouring Container, or we need to steal a few nodes
346
		   from a neighbouring Container. */
347
348
		/* We get the parent of the container here, so we can find out what
349
		   containers neighbour the container which currently hasn't got enough nodes. */
350
351
		if ((errorcode = getparentbtreecontainer(sb, bh, &bhparent)) == 0) {
352
			if (bhparent != NULL) {
353
				struct fsBNodeContainer *bncparent = (void *) bhparent->b_data;
354
				struct BTreeContainer *btcparent = &bncparent->btc;
355
				s16 n;
356
357
				asfs_debug("deletebnode: get parent returned block %d.\n", be32_to_cpu(((struct fsBlockHeader *) bhparent->b_data)->ownblock));
358
359
				for (n = 0; n < be16_to_cpu(btcparent->nodecount); n++)
360
					if (btcparent->bnode[n].data == bnc1->bheader.ownblock)
361
						break;
362
				/* n is now the offset of our own bnode. */
363
364
				if (n < be16_to_cpu(btcparent->nodecount) - 1) {	/* Check if we have a next neighbour. */
365
					asfs_debug("deletebnode: using next container - merging blocks %d and %d\n", be32_to_cpu(bnc1->bheader.ownblock), be32_to_cpu(btcparent->bnode[n+1].data));
366
367
					if ((bhsec = asfs_breadcheck(sb, be32_to_cpu(btcparent->bnode[n + 1].data), ASFS_BNODECONTAINER_ID))) {
368
						struct fsBNodeContainer *bnc_next = (void *) bhsec->b_data;
369
						struct BTreeContainer *btc_next = &bnc_next->btc;
370
371
						if (be16_to_cpu(btc_next->nodecount) + be16_to_cpu(btc->nodecount) > branches) {	/* Check if we need to steal nodes. */
372
							s16 nodestosteal = (be16_to_cpu(btc_next->nodecount) + be16_to_cpu(btc->nodecount)) / 2 - be16_to_cpu(btc->nodecount);
373
374
							/* Merging them is not possible.  Steal a few nodes then. */
375
							memcpy((u8 *) btc->bnode + be16_to_cpu(btc->nodecount) * btc->nodesize, btc_next->bnode, nodestosteal * btc->nodesize);
376
							btc->nodecount = cpu_to_be16(be16_to_cpu(btc->nodecount) + nodestosteal);
377
							asfs_bstore(sb, bh);
378
379
							memcpy(btc_next->bnode, (u8 *) btc_next->bnode + btc_next->nodesize * nodestosteal,
380
							       btc->nodesize * (be16_to_cpu(btc_next->nodecount) - nodestosteal));
381
							btc_next->nodecount = cpu_to_be16(be16_to_cpu(btc_next->nodecount) - nodestosteal);
382
							asfs_bstore(sb, bhsec);
383
384
							btcparent->bnode[n + 1].key = btc_next->bnode[0].key;
385
							asfs_bstore(sb, bhparent);
386
						} else {	/* Merging is possible. */
387
							memcpy((u8 *) btc->bnode + btc->nodesize * be16_to_cpu(btc->nodecount), btc_next->bnode, btc->nodesize * be16_to_cpu(btc_next->nodecount));
388
							btc->nodecount = cpu_to_be16(be16_to_cpu(btc->nodecount) + be16_to_cpu(btc_next->nodecount));
389
							asfs_bstore(sb, bh);
390
391
							if ((errorcode = freeadminspace(sb, be32_to_cpu(((struct fsBlockHeader *) bhsec->b_data)->ownblock))) == 0)
392
								errorcode = deletebnode(sb, bhparent, be32_to_cpu(btcparent->bnode[n + 1].key));
393
						}
394
						asfs_brelse(bhsec);
395
					}
396
				} else if (n > 0) {	/* Check if we have a previous neighbour. */
397
					asfs_debug("deletebnode: using prev container.\n");
398
399
					if ((bhsec = asfs_breadcheck(sb, be32_to_cpu(btcparent->bnode[n - 1].data), ASFS_BNODECONTAINER_ID)) == 0) {
400
						struct fsBNodeContainer *bnc2 = (void *) bhsec->b_data;
401
						struct BTreeContainer *btc2 = &bnc2->btc;
402
403
						if (be16_to_cpu(btc2->nodecount) + be16_to_cpu(btc->nodecount) > branches) {
404
							/* Merging them is not possible.  Steal a few nodes then. */
405
							s16 nodestosteal = (be16_to_cpu(btc2->nodecount) + be16_to_cpu(btc->nodecount)) / 2 - be16_to_cpu(btc->nodecount);
406
407
							memmove((u8 *) btc->bnode + nodestosteal * btc->nodesize, btc->bnode, be16_to_cpu(btc->nodecount) * btc->nodesize);
408
							btc->nodecount = cpu_to_be16(be16_to_cpu(btc->nodecount) + nodestosteal);
409
							memcpy(btc->bnode, (u8 *) btc2->bnode + (be16_to_cpu(btc2->nodecount) - nodestosteal) * btc2->nodesize, nodestosteal * btc->nodesize);
410
411
							asfs_bstore(sb, bh);
412
413
							btc2->nodecount = cpu_to_be16(be16_to_cpu(btc2->nodecount) - nodestosteal);
414
							asfs_bstore(sb, bhsec);
415
416
							btcparent->bnode[n].key = btc->bnode[0].key;
417
							asfs_bstore(sb, bhparent);
418
						} else {	/* Merging is possible. */
419
							memcpy((u8 *) btc2->bnode + be16_to_cpu(btc2->nodecount) * btc2->nodesize, btc->bnode, be16_to_cpu(btc->nodecount) * btc->nodesize);
420
							btc2->nodecount = cpu_to_be16(be16_to_cpu(btc2->nodecount) + be16_to_cpu(btc->nodecount));
421
							asfs_bstore(sb, bhsec);
422
423
							if ((errorcode = freeadminspace(sb, be32_to_cpu(((struct fsBlockHeader *) bhsec->b_data)->ownblock))) == 0)
424
								errorcode = deletebnode(sb, bhparent, be32_to_cpu(btcparent->bnode[n].key));
425
						}
426
						asfs_brelse(bhsec);
427
					}
428
				}
429
				/*      else    
430
				   {
431
				   // Never happens, except for root and then we don't care.
432
				   } */
433
			} else if (btc->nodecount == 1) {
434
				/* No parent, so must be root. */
435
436
				asfs_debug("deletebnode: no parent so must be root\n");
437
438
				if (btc->isleaf == FALSE) {
439
					struct fsBNodeContainer *bnc3 = (void *) bh->b_data;
440
441
					/* The current root has only 1 node.  We now copy the data of this node into the
442
					   root and promote that data to be the new root.  The rootblock number stays the
443
					   same that way. */
444
445
					if ((bhsec = asfs_breadcheck(sb, be32_to_cpu(btc->bnode[0].data), ASFS_BNODECONTAINER_ID))) {
446
						u32 blockno = be32_to_cpu(((struct fsBlockHeader *) bh->b_data)->ownblock);
447
						memcpy(bh->b_data, bhsec->b_data, sb->s_blocksize);
448
						bnc3->bheader.ownblock = cpu_to_be32(blockno);
449
450
						asfs_bstore(sb, bh);
451
						errorcode = freeadminspace(sb, be32_to_cpu(((struct fsBlockHeader *) bhsec->b_data)->ownblock));
452
						asfs_brelse(bhsec);
453
					} else
454
						errorcode = -EIO;
455
				}
456
				/* If not, then root contains leafs. */
457
			}
458
459
			asfs_debug("deletebnode: almost done\n");
460
			/* otherwise, it must be the root, and the root is allowed
461
			   to contain less than the minimum amount of nodes. */
462
463
		}
464
		if (bhparent != NULL)
465
			asfs_brelse(bhparent);
466
	}
467
468
	return errorcode;
469
}
470
471
   /* Deletes an fsExtentBNode structure by key and any fsExtentBNodes linked to it.
472
      This function DOES NOT fix the next pointer in a possible fsExtentBNode which
473
      might have been pointing to the first BNode we are deleting.  Make sure you check
474
      this yourself, if needed.
475
476
      If key is zero, than this function does nothing. */
477
478
int deleteextents(struct super_block *sb, u32 key)
479
{
480
	struct buffer_head *bh;
481
	struct fsExtentBNode *ebn;
482
	int errorcode = 0;
483
484
	asfs_debug("deleteextents: Entry -- deleting extents from key %d\n", key);
485
486
	while (key != 0 && (errorcode = findbnode(sb, key, &bh, (struct BNode **) &ebn)) == 0) {
487
		/* node to be deleted located. */
488
		key = be32_to_cpu(ebn->next);
489
		if ((errorcode = freespace(sb, be32_to_cpu(ebn->key), be16_to_cpu(ebn->blocks))) != 0)
490
			break;
491
492
		if ((errorcode = deletebnode(sb, bh, be32_to_cpu(ebn->key))) != 0)
493
			break;
494
495
		asfs_brelse(bh);
496
	}
497
498
	return (errorcode);
499
}
500
501
   /* This function adds /blocks/ blocks starting at block /newspace/ to a file
502
      identified by /objectnode/ and /lastextentbnode/.  /io_lastextentbnode/ can
503
      be zero if there is no ExtentBNode chain attached to this file yet.
504
      /blocks/ ranges from 1 to 8192.  To be able to extend Extents which are
505
      almost full, it is wise to make this value no higher than 8192 blocks.
506
      /io_lastextentbnode/ will contain the new lastextentbnode value when this
507
      function completes.
508
      If there was no chain yet, then this function will create a new one.  */
509
510
int addblocks(struct super_block *sb, u16 blocks, u32 newspace, u32 objectnode, u32 *io_lastextentbnode)
511
{
512
	struct buffer_head *bh;
513
	struct fsExtentBNode *ebn;
514
	int errorcode = 0;
515
516
	if (*io_lastextentbnode != 0) {
517
		/* There was already a ExtentBNode chain for this file.  Extending it. */
518
519
		asfs_debug("  addblocks: Extending existing ExtentBNode chain.\n");
520
521
		if ((errorcode = getextent(sb, *io_lastextentbnode, &bh, &ebn)) == 0) {
522
			if (be32_to_cpu(ebn->key) + be16_to_cpu(ebn->blocks) == newspace && be16_to_cpu(ebn->blocks) + blocks < 65536) {
523
				/* It is possible to extent the last ExtentBNode! */
524
				asfs_debug("  addblocks: Extending last ExtentBNode.\n");
525
526
				ebn->blocks = cpu_to_be16(be16_to_cpu(ebn->blocks) + blocks);
527
528
				asfs_bstore(sb, bh);
529
				asfs_brelse(bh);
530
			} else {
531
				/* It isn't possible to extent the last ExtentBNode so we create
532
				   a new one and link it to the last ExtentBNode. */
533
534
				ebn->next = cpu_to_be32(newspace);
535
				asfs_bstore(sb, bh);
536
				asfs_brelse(bh);
537
538
				if ((errorcode = createextentbnode(sb, newspace, &bh, (struct BNode **) &ebn)) == 0) {
539
					asfs_debug("  addblocks: Created new ExtentBNode.\n");
540
541
					ebn->key = cpu_to_be32(newspace);
542
					ebn->prev = cpu_to_be32(*io_lastextentbnode);
543
					ebn->next = 0;
544
					ebn->blocks = cpu_to_be16(blocks);
545
546
					*io_lastextentbnode = newspace;
547
548
					asfs_bstore(sb, bh);
549
					asfs_brelse(bh);
550
551
					ASFS_SB(sb)->block_rovingblockptr = newspace + blocks;
552
553
	/* to be changed in the future */
554
/*					if (ASFS_SB(sb)->block_rovingblockptr >= ASFS_SB(sb)->totalblocks)
555
						ASFS_SB(sb)->block_rovingblockptr = 0;*/
556
				}
557
			}
558
		}
559
	} else {
560
		/* There is no ExtentBNode chain yet for this file.  Attaching one! */
561
		if ((errorcode = createextentbnode(sb, newspace, &bh, (struct BNode **) &ebn)) == 0) {
562
			asfs_debug("  addblocks: Created new ExtentBNode chain.\n");
563
564
			ebn->key = cpu_to_be32(newspace);
565
			ebn->prev = cpu_to_be32(objectnode + 0x80000000);
566
			ebn->next = 0;
567
			ebn->blocks = cpu_to_be16(blocks);
568
569
			*io_lastextentbnode = newspace;
570
571
			asfs_bstore(sb, bh);
572
			asfs_brelse(bh);
573
574
			ASFS_SB(sb)->block_rovingblockptr = newspace + blocks;
575
576
/*			if (ASFS_SB(sb)->block_rovingblockptr >= ASFS_SB(sb)->totalblocks)
577
				ASFS_SB(sb)->block_rovingblockptr = 0;*/
578
		}
579
	}
580
581
	asfs_debug("  addblocks: done.\n");
582
583
	return errorcode;
584
}
585
#endif
(-)kernel-source-2.6.5/fs/asfs/file.c (+256 lines)
Line 0 Link Here
1
/*
2
 *
3
 * Amiga Smart File System, Linux implementation
4
 * version: 1.0beta3
5
 *  
6
 * Copyright (C) 2003,2004  Marek 'March' Szyprowski <marek@amiga.pl>
7
 *
8
 *
9
 * This program is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU General Public License
11
 * as published by the Free Software Foundation; either version
12
 * 2 of the License, or (at your option) any later version.
13
 *
14
 */
15
16
#include <linux/types.h>
17
#include <linux/errno.h>
18
#include <linux/slab.h>
19
#include <linux/asfs_fs.h>
20
#include <linux/fs.h>
21
#include <linux/pagemap.h>
22
#include <linux/buffer_head.h>
23
#include <linux/vfs.h>
24
25
#include <asm/byteorder.h>
26
27
static int
28
asfs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_result, int create)
29
{
30
	struct buffer_head *ebn_bh;
31
	struct fsExtentBNode extent, *ebn_p;
32
	u32 filedata;
33
	unsigned long pos;
34
	struct super_block *sb = inode->i_sb;
35
#ifdef CONFIG_ASFS_RW
36
	int error;
37
	struct buffer_head *bh;
38
	struct fsObject *obj;
39
#endif
40
41
	asfs_debug("ASFS: get_block(%lu, %ld, %d)\n", inode->i_ino, block, create);
42
43
	if (block < 0) {
44
		printk(KERN_ERR "ASFS: asfsget_block: requested block (%ld) < 0!\n", block);
45
		return -EIO;
46
	} else if (block >= inode->i_blocks && !create) {
47
		printk(KERN_ERR "ASFS: asfsget_block: strange block request %ld!\n", block);
48
		return -EIO;
49
	} 
50
51
	if (create)
52
#ifdef CONFIG_ASFS_RW
53
		ASFS_I(inode)->modified = TRUE;
54
#else
55
		return -EROFS;
56
#endif
57
58
	if (block < inode->i_blocks)
59
		create = 0;
60
61
	lock_super(sb);
62
63
#ifdef CONFIG_ASFS_RW
64
	if (create) {
65
		int blockstoadd;
66
		u32 newspace, addedblocks;
67
68
		blockstoadd = block - inode->i_blocks + 1;
69
70
		if (blockstoadd < ASFS_BLOCKCHUNKS)
71
			blockstoadd = ASFS_BLOCKCHUNKS;
72
 
73
		asfs_debug("ASFS get_block: Trying to add %d blocks to file\n", blockstoadd);
74
		
75
		if ((error = readobject(sb, inode->i_ino, &bh, &obj)) != 0) {
76
			unlock_super(sb);
77
			return error;
78
		}
79
80
		if ((error = addblockstofile(sb, bh, obj, blockstoadd, &newspace, &addedblocks)) != 0) {
81
			asfs_brelse(bh);
82
			unlock_super(sb);
83
			return error;
84
		}
85
		ASFS_I(inode)->mmu_private += addedblocks * sb->s_blocksize;
86
		inode->i_blocks += addedblocks;
87
		ASFS_I(inode)->ext_cache.key = 0;
88
		ASFS_I(inode)->firstblock = be32_to_cpu(obj->object.file.data);
89
		asfs_brelse(bh);
90
	}
91
#endif
92
93
	if (ASFS_I(inode)->ext_cache.key > 0 && ASFS_I(inode)->ext_cache.startblock <= block) {
94
		extent.key = ASFS_I(inode)->ext_cache.key;
95
		extent.next = ASFS_I(inode)->ext_cache.next;
96
		extent.blocks = ASFS_I(inode)->ext_cache.blocks;
97
		pos = ASFS_I(inode)->ext_cache.startblock;
98
	} else {
99
		if (getextent(inode->i_sb, ASFS_I(inode)->firstblock, &ebn_bh, &ebn_p) != 0) {
100
			unlock_super(sb);
101
			return -EIO;
102
		}
103
		extent.key = be32_to_cpu(ebn_p->key);
104
		extent.next = be32_to_cpu(ebn_p->next);
105
		extent.blocks = be16_to_cpu(ebn_p->blocks);
106
		pos = 0;
107
		asfs_brelse(ebn_bh);
108
	}
109
	ebn_p = &extent;
110
	filedata = ebn_p->next;
111
112
	while (pos + ebn_p->blocks <= block && ebn_p->next != 0 && pos < inode->i_blocks) {
113
		pos += ebn_p->blocks;
114
		if (getextent(inode->i_sb, filedata, &ebn_bh, &ebn_p) != 0) {
115
			unlock_super(sb);
116
			return -EIO;
117
		}
118
		extent.key = be32_to_cpu(ebn_p->key);
119
		extent.next = be32_to_cpu(ebn_p->next);
120
		extent.blocks = be16_to_cpu(ebn_p->blocks);
121
		ebn_p = &extent;	
122
		filedata = ebn_p->next;
123
		asfs_brelse(ebn_bh);
124
	}
125
126
	unlock_super(sb);
127
128
	map_bh(bh_result, inode->i_sb, (sector_t) (ebn_p->key + block - pos));
129
130
	if (create)
131
		set_buffer_new(bh_result);
132
133
	asfs_debug("ASFS: get_block - mapped block %lu\n", ebn_p->key + block - pos);
134
135
	ASFS_I(inode)->ext_cache.startblock = pos;
136
	ASFS_I(inode)->ext_cache.key = ebn_p->key;
137
	ASFS_I(inode)->ext_cache.next = ebn_p->next;
138
	ASFS_I(inode)->ext_cache.blocks = ebn_p->blocks;
139
140
	return 0;
141
}
142
143
int asfs_readpage(struct file *file, struct page *page)
144
{
145
	asfs_debug(__FUNCTION__ "\n");
146
	return block_read_full_page(page, asfs_get_block);
147
}
148
149
sector_t asfs_bmap(struct address_space *mapping, sector_t block)
150
{
151
	asfs_debug(__FUNCTION__ "\n");
152
	return generic_block_bmap(mapping,block,asfs_get_block);
153
}
154
155
#ifdef CONFIG_ASFS_RW
156
157
int asfs_writepage(struct page *page, struct writeback_control *wbc)
158
{
159
	asfs_debug(__FUNCTION__ "\n");
160
	return block_write_full_page(page, asfs_get_block, wbc);
161
}
162
163
int asfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
164
{
165
	asfs_debug(__FUNCTION__ "\n");
166
	return cont_prepare_write(page, from, to, asfs_get_block, &ASFS_I(page->mapping->host)->mmu_private);
167
}
168
169
void asfs_truncate(struct inode *inode)
170
{
171
	struct super_block *sb = inode->i_sb;
172
	struct buffer_head *bh;
173
	struct fsObject *obj;
174
175
	asfs_debug("AFFS: truncate(inode=%d, oldsize=%u, newsize=%u)\n",
176
		 (u32)inode->i_ino, (u32)ASFS_I(inode)->mmu_private, (u32)inode->i_size);
177
178
	if (inode->i_size > ASFS_I(inode)->mmu_private) {
179
		printk("ASFS: enlarging file is not supported yet\n");
180
		return;
181
	}
182
183
	lock_super(sb);
184
185
	if ((readobject(sb, inode->i_ino, &bh, &obj)) != 0) {
186
		unlock_super(sb);
187
		return;
188
	}
189
190
	if (truncateblocksinfile(sb, bh, obj, inode->i_size) != 0) {
191
		asfs_brelse(bh);
192
		unlock_super(sb);
193
		return;
194
	}
195
		
196
	obj->object.file.size = cpu_to_be32(inode->i_size);
197
	ASFS_I(inode)->mmu_private = inode->i_size;
198
	ASFS_I(inode)->modified = TRUE;
199
	inode->i_blocks = (be32_to_cpu(obj->object.file.size) + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
200
	asfs_bstore(sb, bh);
201
	asfs_brelse(bh);
202
203
	unlock_super(sb);
204
}
205
206
int asfs_file_open(struct inode *inode, struct file *filp)
207
{
208
	if (atomic_read(&filp->f_count) != 1)
209
		return 0;
210
	asfs_debug("ASFS: file open (node %d)\n", (int)inode->i_ino);
211
	ASFS_I(inode)->i_opencnt++;
212
	return 0;
213
}
214
215
int asfs_file_release(struct inode *inode, struct file *filp)
216
{
217
	int error = 0;
218
219
	if (atomic_read(&filp->f_count) != 0)
220
		return 0;
221
222
	ASFS_I(inode)->i_opencnt--;
223
	if (ASFS_I(inode)->i_opencnt)
224
		return 0;
225
226
	asfs_debug("ASFS: file release (node %d)\n", (int)inode->i_ino);
227
228
	if (ASFS_I(inode)->modified == TRUE) {
229
		struct buffer_head *bh;
230
		struct fsObject *obj;
231
		lock_super(inode->i_sb);
232
233
		if ((error = readobject(inode->i_sb, inode->i_ino, &bh, &obj)) != 0) {
234
			unlock_super(inode->i_sb);
235
			return error;
236
		}
237
238
		obj->datemodified = cpu_to_be32(inode->i_mtime.tv_sec - (365*8+2)*24*60*60);
239
		if (inode->i_mode & S_IFREG) {
240
			error = truncateblocksinfile(inode->i_sb, bh, obj, (u32)inode->i_size);
241
			obj->object.file.size = cpu_to_be32(inode->i_size);
242
			ASFS_I(inode)->mmu_private = inode->i_size;
243
			inode->i_blocks = (be32_to_cpu(obj->object.file.size) + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
244
		}
245
		asfs_bstore(inode->i_sb, bh);
246
247
		unlock_super(inode->i_sb);
248
249
		asfs_brelse(bh);
250
	}
251
	ASFS_I(inode)->modified = FALSE;
252
253
	return error;
254
}
255
256
#endif
(-)kernel-source-2.6.5/fs/asfs/inode.c (+487 lines)
Line 0 Link Here
1
/*
2
 *
3
 * Amiga Smart File System, Linux implementation
4
 * version: 1.0beta4
5
 *  
6
 * Copyright (C) 2003,2004  Marek 'March' Szyprowski <marek@amiga.pl>
7
 *
8
 *
9
 * This program is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU General Public License
11
 * as published by the Free Software Foundation; either version
12
 * 2 of the License, or (at your option) any later version.
13
 *
14
 */
15
16
#include <linux/types.h>
17
#include <linux/errno.h>
18
#include <linux/slab.h>
19
#include <linux/asfs_fs.h>
20
#include <linux/fs.h>
21
#include <linux/smp_lock.h>
22
#include <linux/time.h>
23
#include <linux/buffer_head.h>
24
#include <linux/vfs.h>
25
#include <linux/dirent.h>
26
27
#include <asm/byteorder.h>
28
29
/* Mapping from our types to the kernel */
30
31
static struct address_space_operations asfs_aops = {
32
	.readpage	= asfs_readpage,
33
	.sync_page	= block_sync_page,
34
	.bmap		= asfs_bmap,
35
#ifdef CONFIG_ASFS_RW
36
	.writepage	= asfs_writepage,
37
	.prepare_write = asfs_prepare_write,
38
	.commit_write = generic_commit_write,
39
#endif
40
};
41
42
struct file_operations asfs_file_operations = {
43
	.llseek		= generic_file_llseek,
44
	.read		= generic_file_read,
45
	.mmap		= generic_file_mmap,
46
#ifdef CONFIG_ASFS_RW
47
	.write		= generic_file_write,
48
	.open		= asfs_file_open,
49
	.release	= asfs_file_release,
50
	.fsync		= file_fsync,
51
#endif
52
};
53
54
static struct file_operations asfs_dir_operations = {
55
	.read		= generic_read_dir,
56
	.readdir	= asfs_readdir,
57
};
58
59
static struct inode_operations asfs_dir_inode_operations = {
60
	.lookup		= asfs_lookup,
61
#ifdef CONFIG_ASFS_RW
62
	.create		= asfs_create,
63
	.unlink		= asfs_delete,
64
	.symlink	= asfs_symlink,
65
	.mkdir		= asfs_mkdir,
66
	.rmdir		= asfs_rmdir,
67
	.rename		= asfs_rename,
68
/*	.setattr	= asfs_notify_change,*/
69
#endif
70
};
71
72
static struct inode_operations asfs_file_inode_operations = {
73
#ifdef CONFIG_ASFS_RW
74
	.truncate	= asfs_truncate,
75
/*	.setattr		= asfs_notify_change,*/
76
#endif
77
};
78
79
struct address_space_operations asfs_symlink_aops = {
80
	.readpage	= asfs_symlink_readpage,
81
};
82
83
static struct inode_operations asfs_symlink_inode_operations = {
84
	.readlink	= page_readlink,
85
	.follow_link	= page_follow_link,
86
#ifdef CONFIG_ASFS_RW
87
/*	.setattr	= asfs_notify_change,*/
88
#endif
89
};
90
91
void asfs_read_locked_inode(struct inode *inode, void *arg)
92
{
93
	struct super_block *sb = inode->i_sb;
94
	struct fsObject *obj = arg;
95
96
	inode->i_mode = ASFS_SB(sb)->mode;
97
	inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = be32_to_cpu(obj->datemodified) + (365*8+2)*24*60*60;  
98
	/* Linux: seconds since 01-01-1970, AmigaSFS: seconds since 01-01-1978 */
99
	inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_atime.tv_nsec = 0;
100
	inode->i_uid = ASFS_SB(sb)->uid;
101
	inode->i_gid = ASFS_SB(sb)->gid;
102
103
	ASFS_I(inode)->i_opencnt = 0;
104
105
	asfs_debug("asfs_read_inode2: Setting-up node %lu... ", inode->i_ino);
106
107
	if (obj->bits & OTYPE_DIR) {
108
		asfs_debug("dir (FirstdirBlock: %u, HashTable %u)\n", \
109
		           be32_to_cpu(obj->object.dir.firstdirblock), be32_to_cpu(obj->object.dir.hashtable));
110
111
		inode->i_size = 0;
112
		inode->i_op = &asfs_dir_inode_operations;
113
		inode->i_fop = &asfs_dir_operations;
114
		inode->i_mode |= S_IFDIR | ((inode->i_mode & 0400) ? 0100 : 0) | 
115
		              ((inode->i_mode & 0040) ? 0010 : 0) | ((inode->i_mode & 0004) ? 0001 : 0);
116
		ASFS_I(inode)->firstblock = be32_to_cpu(obj->object.dir.firstdirblock);
117
		ASFS_I(inode)->hashtable = be32_to_cpu(obj->object.dir.hashtable);
118
		ASFS_I(inode)->modified = 0;
119
	} else if (obj->bits & OTYPE_LINK && !(obj->bits & OTYPE_HARDLINK)) {
120
		asfs_debug("symlink\n");
121
		inode->i_size = 0;
122
		inode->i_op = &asfs_symlink_inode_operations;
123
		inode->i_mapping->a_ops = &asfs_symlink_aops;
124
		inode->i_mode |= S_IFLNK | S_IRWXUGO;
125
		ASFS_I(inode)->firstblock = be32_to_cpu(obj->object.file.data);
126
	} else {
127
		asfs_debug("file (Size: %u, FirstBlock: %u)\n", be32_to_cpu(obj->object.file.size), be32_to_cpu(obj->object.file.data));
128
		inode->i_size = be32_to_cpu(obj->object.file.size);
129
		inode->i_blocks = (be32_to_cpu(obj->object.file.size) + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
130
		inode->i_op = &asfs_file_inode_operations;
131
		inode->i_fop = &asfs_file_operations;
132
		inode->i_mapping->a_ops = &asfs_aops;
133
		inode->i_mode |= S_IFREG;
134
		ASFS_I(inode)->firstblock = be32_to_cpu(obj->object.file.data);
135
		ASFS_I(inode)->ext_cache.startblock = 0;
136
		ASFS_I(inode)->ext_cache.key = 0;
137
		ASFS_I(inode)->mmu_private = inode->i_size;
138
	}
139
	return;	
140
}
141
142
struct inode *asfs_get_root_inode(struct super_block *sb)
143
{
144
	struct inode *result = NULL;
145
	struct fsObject *obj;
146
	struct buffer_head *bh;
147
148
	asfs_debug("asfs_get_root_inode\n");
149
150
	if ((bh = asfs_breadcheck(sb, ASFS_SB(sb)->rootobjectcontainer, ASFS_OBJECTCONTAINER_ID))) {
151
		obj = &(((struct fsObjectContainer *)bh->b_data)->object[0]);
152
		if (be32_to_cpu(obj->objectnode) > 0)
153
			result = iget_locked(sb, be32_to_cpu(obj->objectnode));
154
155
		if (result != NULL && result->i_state & I_NEW) {
156
			asfs_read_locked_inode(result, obj);
157
			unlock_new_inode(result);
158
		}
159
160
		asfs_brelse(bh);
161
	}
162
	return result;
163
}
164
165
#ifdef CONFIG_ASFS_RW
166
167
int asfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
168
{
169
	int error;
170
	struct super_block *sb = dir->i_sb;
171
	struct inode *inode;
172
	struct buffer_head *bh, *dir_bh;
173
	struct fsObject obj_data, *dir_obj, *obj;
174
	u8 *name = (u8 *) dentry->d_name.name;
175
176
	asfs_debug("asfs_create %s in dir node %d\n", name, (int)dir->i_ino);
177
178
	sb = dir->i_sb;
179
	inode = new_inode(sb);
180
	if (!inode)
181
		return -ENOMEM;
182
183
	inode->i_mode = mode;
184
	inode->i_uid = current->fsuid;
185
	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
186
	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
187
	inode->i_blocks = inode->i_blksize = 0;
188
189
	inode->i_fop = &asfs_file_operations;
190
	inode->i_mapping->a_ops = &asfs_aops;
191
192
	memset(&obj_data, 0, sizeof(struct fsObject));
193
194
	obj_data.protection = cpu_to_be32(FIBF_READ|FIBF_WRITE|FIBF_EXECUTE|FIBF_DELETE);
195
	obj_data.datemodified = cpu_to_be32(inode->i_mtime.tv_sec - (365*8+2)*24*60*60);
196
197
	lock_super(sb);
198
199
	if ((error = readobject(sb, dir->i_ino, &dir_bh, &dir_obj)) != 0) {
200
		dec_count(inode);
201
		unlock_super(sb);
202
		return error;
203
	}
204
205
	bh = dir_bh;
206
	obj = dir_obj;
207
208
	if ((error = createobject(sb, &bh, &obj, &obj_data, name, FALSE)) != 0) {
209
		asfs_brelse(dir_bh);
210
		dec_count(inode);
211
		unlock_super(sb);
212
		return error;
213
	}
214
215
	inode->i_ino = be32_to_cpu(obj->objectnode);
216
217
	ASFS_I(inode)->firstblock = be32_to_cpu(obj->object.file.data);
218
	ASFS_I(inode)->ext_cache.startblock = 0;
219
	ASFS_I(inode)->ext_cache.key = 0;
220
221
	asfs_bstore(sb, bh);
222
223
	insert_inode_hash(inode);
224
	mark_inode_dirty(inode);
225
226
	d_instantiate(dentry, inode);
227
	ASFS_I(dir)->firstblock = be32_to_cpu(dir_obj->object.dir.firstdirblock);
228
	ASFS_I(dir)->modified = 1;
229
	dir->i_mtime = dir->i_ctime = inode->i_mtime;
230
	dir_obj->datemodified = cpu_to_be32(inode->i_mtime.tv_sec - (365*8+2)*24*60*60);
231
	asfs_bstore(sb, dir_bh); 
232
233
	unlock_super(sb);
234
235
	asfs_brelse(bh);
236
	asfs_brelse(dir_bh);
237
	
238
	return 0;
239
}
240
241
int asfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
242
{
243
	int error;
244
	struct super_block *sb = dir->i_sb;
245
	struct inode *inode;
246
	struct buffer_head *bh, *dir_bh;
247
	struct fsObject obj_data, *dir_obj, *obj;
248
	u8 *name = (u8 *) dentry->d_name.name;
249
250
	asfs_debug("asfs_create %s in dir node %d\n", name, (int)dir->i_ino);
251
252
	sb = dir->i_sb;
253
	inode = new_inode(sb);
254
	if (!inode)
255
		return -ENOMEM;
256
257
	inode->i_mode = S_IFDIR | mode;
258
	inode->i_uid = current->fsuid;
259
	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
260
	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
261
	inode->i_blocks = inode->i_blksize = 0;
262
263
	inode->i_op = &asfs_dir_inode_operations;
264
	inode->i_fop = &asfs_dir_operations;
265
266
	memset(&obj_data, 0, sizeof(struct fsObject));
267
268
	obj_data.protection = cpu_to_be32(FIBF_READ|FIBF_WRITE|FIBF_EXECUTE|FIBF_DELETE);
269
	obj_data.datemodified = cpu_to_be32(inode->i_mtime.tv_sec - (365*8+2)*24*60*60);
270
	obj_data.bits = OTYPE_DIR;
271
272
	lock_super(sb);
273
274
	if ((error = readobject(sb, dir->i_ino, &dir_bh, &dir_obj)) != 0) {
275
		dec_count(inode);
276
		unlock_super(sb);
277
		return error;
278
	}
279
280
	bh = dir_bh;
281
	obj = dir_obj;
282
283
	if ((error = createobject(sb, &bh, &obj, &obj_data, name, FALSE)) != 0) {
284
		asfs_brelse(dir_bh);
285
		dec_count(inode);
286
		unlock_super(sb);
287
		return error;
288
	}
289
290
	inode->i_ino = be32_to_cpu(obj->objectnode);
291
	ASFS_I(inode)->firstblock = be32_to_cpu(obj->object.dir.firstdirblock);
292
	ASFS_I(inode)->hashtable = be32_to_cpu(obj->object.dir.hashtable);
293
294
	asfs_bstore(sb, bh);
295
296
	insert_inode_hash(inode);
297
	mark_inode_dirty(inode);
298
299
	d_instantiate(dentry, inode);
300
	ASFS_I(dir)->firstblock = be32_to_cpu(dir_obj->object.dir.firstdirblock);
301
	ASFS_I(dir)->modified = 1;
302
	dir->i_mtime = dir->i_ctime = inode->i_mtime;
303
	dir_obj->datemodified = cpu_to_be32(inode->i_mtime.tv_sec - (365*8+2)*24*60*60);
304
	asfs_bstore(sb, dir_bh); 
305
306
	unlock_super(sb);
307
308
	asfs_brelse(bh);
309
	asfs_brelse(dir_bh);
310
	
311
	return 0;
312
}
313
314
int asfs_rmdir(struct inode *dir, struct dentry *dentry)
315
{
316
	struct inode *inode = dentry->d_inode;
317
	int error;
318
	struct super_block *sb = dir->i_sb;
319
	struct buffer_head *bh, *dir_bh;
320
	struct fsObject *dir_obj, *obj;
321
322
	asfs_debug("ASFS: " __FUNCTION__ "\n");
323
324
	if (ASFS_I(inode)->firstblock != 0)
325
		return -ENOTEMPTY;
326
327
	lock_super(sb);
328
329
	if ((error = readobject(sb, inode->i_ino, &bh, &obj)) != 0) {
330
		unlock_super(sb);
331
		return error;
332
	}
333
334
	if ((error = deleteobject(sb, bh, obj)) != 0)
335
	{
336
		unlock_super(sb);
337
		asfs_brelse(bh);
338
		return error;
339
	}
340
341
	asfs_brelse(bh);
342
343
	/* directory data could change after removing the object... */
344
345
	if ((error = readobject(sb, dir->i_ino, &dir_bh, &dir_obj)) != 0) {
346
		unlock_super(sb);
347
		return error;
348
	}
349
350
	ASFS_I(dir)->firstblock = be32_to_cpu(dir_obj->object.dir.firstdirblock);
351
	ASFS_I(dir)->modified = 1;
352
	dir->i_mtime = dir->i_ctime = inode->i_mtime;
353
	dir_obj->datemodified = cpu_to_be32(inode->i_mtime.tv_sec - (365*8+2)*24*60*60);
354
	asfs_bstore(sb, dir_bh); 
355
356
	dec_count(inode);
357
358
	unlock_super(sb);
359
360
	asfs_brelse(dir_bh);
361
362
	return 0;
363
}
364
365
int asfs_delete(struct inode *dir, struct dentry *dentry)
366
{
367
	struct inode *inode = dentry->d_inode;
368
	int error;
369
	struct super_block *sb = dir->i_sb;
370
	struct buffer_head *bh, *dir_bh;
371
	struct fsObject *dir_obj, *obj;
372
373
	asfs_debug("ASFS: " __FUNCTION__ "\n");
374
375
	lock_super(sb);
376
377
	if ((error = readobject(sb, inode->i_ino, &bh, &obj)) != 0) {
378
		unlock_super(sb);
379
		return error;
380
	}
381
382
	if ((error = deleteobject(sb, bh, obj)) != 0) {
383
		asfs_brelse(bh);
384
		unlock_super(sb);
385
		return error;
386
	}
387
388
	asfs_brelse(bh);
389
390
	if ((error = readobject(sb, dir->i_ino, &dir_bh, &dir_obj)) != 0) {
391
		unlock_super(sb);
392
		return error;
393
	}
394
395
	ASFS_I(dir)->firstblock = be32_to_cpu(dir_obj->object.dir.firstdirblock);
396
	ASFS_I(dir)->modified = 1;
397
	dir->i_mtime = dir->i_ctime = inode->i_mtime;
398
	dir_obj->datemodified = cpu_to_be32(inode->i_mtime.tv_sec - (365*8+2)*24*60*60);
399
	asfs_bstore(sb, dir_bh); 
400
401
	dec_count(inode);
402
403
	unlock_super(sb);
404
405
	asfs_brelse(dir_bh);
406
407
	return 0;
408
}
409
410
int asfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry)
411
{
412
	struct super_block *sb = old_dir->i_sb;
413
	struct buffer_head *src_bh, *old_bh, *new_bh;
414
	int error;
415
	struct fsObject *src_obj, *old_obj, *new_obj;
416
417
	asfs_debug("ASFS: rename (old=%u,\"%*s\" to new=%u,\"%*s\")\n",
418
		 (u32)old_dir->i_ino, (int)old_dentry->d_name.len, old_dentry->d_name.name,
419
		 (u32)new_dir->i_ino, (int)new_dentry->d_name.len, new_dentry->d_name.name);
420
421
	/* Unlink destination if it already exists */
422
	if (new_dentry->d_inode) 
423
		if ((error = asfs_delete(new_dir, new_dentry)) != 0)
424
			return error;
425
426
	lock_super(sb);
427
428
	if ((error = readobject(sb, old_dentry->d_inode->i_ino, &src_bh, &src_obj)) != 0) {
429
		unlock_super(sb);
430
		return error;
431
	}
432
433
	if ((error = readobject(sb, new_dir->i_ino, &new_bh, &new_obj)) != 0) {
434
		asfs_brelse(src_bh);
435
		unlock_super(sb);
436
		return error;
437
	}
438
439
	if ((error = renameobject(sb, src_bh, src_obj, new_bh, new_obj, (u8 *) new_dentry->d_name.name)) != 0) {
440
		asfs_brelse(src_bh);
441
		asfs_brelse(new_bh);
442
		unlock_super(sb);
443
		return error;
444
	}
445
446
	asfs_brelse(src_bh);
447
448
	if ((error = readobject(sb, old_dir->i_ino, &old_bh, &old_obj)) != 0) {
449
		asfs_brelse(new_bh);
450
		unlock_super(sb);
451
		return error;
452
	}
453
454
	old_dir->i_mtime = old_dir->i_ctime = new_dir->i_mtime = new_dir->i_ctime = CURRENT_TIME;
455
456
	ASFS_I(old_dir)->firstblock = be32_to_cpu(old_obj->object.dir.firstdirblock);
457
	ASFS_I(old_dir)->modified = 1;
458
	old_obj->datemodified = cpu_to_be32(old_dir->i_mtime.tv_sec - (365*8+2)*24*60*60);
459
460
	ASFS_I(new_dir)->firstblock = be32_to_cpu(new_obj->object.dir.firstdirblock);
461
	ASFS_I(new_dir)->modified = 1;
462
	new_obj->datemodified = cpu_to_be32(old_dir->i_mtime.tv_sec - (365*8+2)*24*60*60);
463
464
	asfs_bstore(sb, new_bh);	
465
	asfs_bstore(sb, old_bh);
466
467
	unlock_super(sb);
468
469
	asfs_brelse(new_bh);
470
	asfs_brelse(old_bh);
471
472
	mark_inode_dirty(old_dir);
473
	mark_inode_dirty(new_dir);
474
475
	return 0;
476
}
477
/*
478
int asfs_notify_change(struct dentry *dentry, struct iattr *attr)
479
{
480
	int error = 0;
481
482
	asfs_debug("ASFS: notify_change(%lu,0x%x)\n",dentry->d_inode->i_ino,attr->ia_valid);
483
484
	return error;
485
}
486
*/
487
#endif
(-)kernel-source-2.6.5/fs/asfs/Makefile (+7 lines)
Line 0 Link Here
1
#
2
# Makefile for the linux asfs filesystem routines.
3
#
4
5
obj-$(CONFIG_ASFS_FS) += asfs.o
6
7
asfs-objs := adminspace.o bitfuncs.o dir.o extents.o file.o inode.o namei.o nodes.o objects.o super.o symlink.o
(-)kernel-source-2.6.5/fs/asfs/namei.c (+155 lines)
Line 0 Link Here
1
/*
2
 *
3
 * Amiga Smart File System, Linux implementation
4
 * version: 1.0beta3
5
 *
6
 * Copyright (C) 2003,2004  Marek 'March' Szyprowski <marek@amiga.pl>
7
 *
8
 *
9
 * This program is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU General Public License
11
 * as published by the Free Software Foundation; either version
12
 * 2 of the License, or (at your option) any later version.
13
 *
14
 */
15
16
#include <linux/types.h>
17
#include <linux/errno.h>
18
#include <linux/slab.h>
19
#include <linux/string.h>
20
#include <linux/asfs_fs.h>
21
#include <linux/fs.h>
22
#include <linux/buffer_head.h>
23
#include <linux/vfs.h>
24
#include <linux/string.h>
25
26
static inline u8 asfs_upperchar(u8 c)
27
{
28
	if ((c >= 224 && c <= 254 && c != 247) || (c >= 'a' && c <= 'z'))
29
		c -= 32;
30
	return (c);
31
}
32
33
u8 asfs_lowerchar(u8 c)
34
{
35
	if ((c >= 192 && c <= 222 && c != 215) || (c >= 'A' && c <= 'Z'))
36
		c += 32;
37
	return (c);
38
}
39
40
/* Check if the name is valid for a asfs object. */
41
42
static inline int asfs_check_name(const u8 *name, int len)
43
{
44
	int i;
45
46
	if (len > ASFS_MAXFN)
47
		return -ENAMETOOLONG;
48
49
	for (i = 0; i < len; i++)
50
		if (name[i] < ' ' || name[i] == ':' || (name[i] > 0x7e && name[i] < 0xa0))
51
			return -EINVAL;
52
53
	return 0;
54
}
55
56
/* Note: the dentry argument is the parent dentry. */
57
58
static int asfs_hash_dentry(struct dentry *dentry, struct qstr *qstr)
59
{
60
	struct super_block *sb = dentry->d_inode->i_sb;
61
	const u8 *name = qstr->name;
62
	unsigned long hash;
63
	int i;
64
65
	i = asfs_check_name(qstr->name,qstr->len);
66
	if (i)
67
		return i;
68
69
	hash = init_name_hash();
70
71
	if (ASFS_SB(sb)->flags & ASFS_ROOTBITS_CASESENSITIVE)
72
		for (i=qstr->len; i > 0; name++, i--)
73
			hash = partial_name_hash(*name, hash);
74
	else
75
		for (i=qstr->len; i > 0; name++, i--)
76
			hash = partial_name_hash(asfs_upperchar(*name), hash);
77
78
	qstr->hash = end_name_hash(hash);
79
80
	return 0;
81
}
82
83
static int asfs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
84
{
85
	struct super_block *sb = dentry->d_inode->i_sb;
86
	const u8 *aname = a->name;
87
	const u8 *bname = b->name;
88
	int len;
89
90
	/* 'a' is the qstr of an already existing dentry, so the name
91
	 * must be valid. 'b' must be validated first.
92
	 */
93
94
	if (asfs_check_name(b->name,b->len))
95
		return 1;
96
97
	if (a->len != b->len)
98
		return 1;
99
100
	if (ASFS_SB(sb)->flags & ASFS_ROOTBITS_CASESENSITIVE) {
101
		for (len=a->len; len > 0; len--)
102
			if (*aname++ != *bname++)
103
				return 1;
104
	} else {
105
		for (len=a->len; len > 0; len--)
106
			if (asfs_upperchar(*aname++) != asfs_upperchar(*bname++))
107
				return 1;
108
	}
109
110
	return 0;
111
}
112
113
struct dentry_operations asfs_dentry_operations = {
114
	d_hash:		asfs_hash_dentry,
115
	d_compare:	asfs_compare_dentry,
116
};
117
118
int asfs_namecmp(u8 *s, u8 *ct, int casesensitive)
119
{
120
	if (casesensitive) {
121
		while (*s == *ct && *ct != '\0' && *ct != '/') {
122
			s++;
123
			ct++;
124
		}
125
	} else {
126
		while (asfs_upperchar(*s) == asfs_upperchar(*ct) && *ct != '\0'
127
		       && *ct != '/') {
128
			s++;
129
			ct++;
130
		}
131
	}
132
	return (*s == '\0' && (*ct == '\0' || *ct == '/')) ? 0 : *ct - *s;
133
}
134
135
u16 asfs_hash(u8 *name, int casesensitive)
136
{
137
	u16 hashval = 0;
138
	while (name[hashval] != 0 && name[hashval] != '/')
139
		hashval++;
140
	if (casesensitive) {
141
		u8 c = *name;
142
		while (c != 0 && c != '/') {
143
			hashval = hashval * 13 + c;
144
			c = *++name;
145
		}
146
	} else {
147
		u8 c = *name;
148
		while (c != 0 && c != '/') {
149
			hashval = hashval * 13 + asfs_upperchar(c);
150
			c = *++name;
151
		}
152
	}
153
	return hashval;
154
}
155
(-)kernel-source-2.6.5/fs/asfs/nodes.c (+455 lines)
Line 0 Link Here
1
/*
2
 *
3
 * Amiga Smart File System, Linux implementation
4
 * version: 1.0beta3
5
 *
6
 * This file contains some parts of the original amiga version of 
7
 * SmartFilesystem source code.
8
 *
9
 * SmartFilesystem is copyrighted (C) 2003 by: John Hendrikx, 
10
 * Ralph Schmidt, Emmanuel Lesueur, David Gerber and Marcin Kurek
11
 * 
12
 * Adapted and modified by Marek 'March' Szyprowski <marek@amiga.pl>
13
 *
14
 */
15
16
#include <linux/types.h>
17
#include <linux/errno.h>
18
#include <linux/slab.h>
19
#include <linux/asfs_fs.h>
20
#include <linux/fs.h>
21
#include <linux/buffer_head.h>
22
#include <linux/vfs.h>
23
24
#include <asm/byteorder.h>
25
26
/* Finds a specific node by number. */
27
int getnode(struct super_block *sb, u32 nodeno, struct buffer_head **ret_bh, struct fsObjectNode **ret_node)
28
{
29
	struct buffer_head *bh;
30
	struct fsNodeContainer *nodecont;
31
	u32 nodeindex = ASFS_SB(sb)->objectnoderoot;
32
33
	while ((bh = asfs_breadcheck(sb, nodeindex, ASFS_NODECONTAINER_ID))) {
34
		nodecont = (struct fsNodeContainer *) bh->b_data;
35
36
		if (be32_to_cpu(nodecont->nodes) == 1) {
37
			*ret_node = (struct fsObjectNode *) ((u8 *) nodecont->node + NODE_STRUCT_SIZE * (nodeno - be32_to_cpu(nodecont->nodenumber)));
38
			*ret_bh = bh;
39
			return 0;
40
		} else {
41
			u16 containerentry = (nodeno - be32_to_cpu(nodecont->nodenumber)) / be32_to_cpu(nodecont->nodes);
42
			nodeindex = be32_to_cpu(nodecont->node[containerentry]) >> (sb->s_blocksize_bits - ASFS_BLCKFACCURACY);
43
		}
44
		asfs_brelse(bh);
45
	}
46
	if (bh == NULL)
47
		return -EIO;
48
	return -ENOENT;
49
}
50
51
#ifdef CONFIG_ASFS_RW
52
53
	/* Looks for the parent of the passed-in buffer_head (fsNodeContainer)
54
	   starting from the root.  It returns an error if any error occured.
55
	   If error is 0 and io_bh is NULL as well, then there was no parent (ie,
56
	   you asked parent of the root).  Otherwise io_bh should contain the
57
	   parent of the passed-in NodeContainer. */
58
59
static int parentnodecontainer(struct super_block *sb, struct buffer_head **io_bh)
60
{
61
	u32 noderoot = ASFS_SB(sb)->objectnoderoot;
62
	u32 childblock = be32_to_cpu(((struct fsBlockHeader *) (*io_bh)->b_data)->ownblock);
63
	u32 nodenumber = be32_to_cpu(((struct fsNodeContainer *) (*io_bh)->b_data)->nodenumber);
64
	int errorcode = 0;
65
66
	if (noderoot == childblock) {
67
		*io_bh = NULL;
68
		return 0;
69
	}
70
71
	while ((*io_bh = asfs_breadcheck(sb, noderoot, ASFS_NODECONTAINER_ID))) {
72
		struct fsNodeContainer *nc = (void *) (*io_bh)->b_data;
73
74
		if (be32_to_cpu(nc->nodes) == 1) {
75
			/* We've descended the tree to a leaf NodeContainer, something
76
			   which should never happen if the passed-in io_bh had
77
			   contained a valid fsNodeContainer. */
78
			printk("ASFS: Failed to locate the parent NodeContainer - node tree is corrupted!\n");
79
			*io_bh = NULL;
80
			return -EIO;
81
		} else {
82
			u16 containerentry = (nodenumber - be32_to_cpu(nc->nodenumber)) / be32_to_cpu(nc->nodes);
83
			noderoot = be32_to_cpu(nc->node[containerentry]) >> (sb->s_blocksize_bits - ASFS_BLCKFACCURACY);
84
		}
85
86
		if (noderoot == childblock)
87
			break;
88
89
		asfs_brelse(*io_bh);
90
	}
91
92
	if (*io_bh == NULL)
93
		return -EIO;
94
95
	return errorcode;
96
}
97
98
99
static int isfull(struct super_block *sb, struct fsNodeContainer *nc)
100
{
101
	u32 *p = nc->node;
102
	s16 n = NODECONT_BLOCK_COUNT;
103
104
	while (--n >= 0) {
105
		if (*p == 0 || (be32_to_cpu(*p) & 0x00000001) == 0) {
106
			break;
107
		}
108
		p++;
109
	}
110
111
	return n < 0;
112
}
113
114
static int markparentfull(struct super_block *sb, struct buffer_head *bh)
115
{
116
	u32 nodenumber = be32_to_cpu(((struct fsNodeContainer *) (bh->b_data))->nodenumber);
117
	int errorcode;
118
119
	if ((errorcode = parentnodecontainer(sb, &bh)) == 0 && bh != 0) {
120
		struct fsNodeContainer *nc = (void *) bh->b_data;
121
		u16 containerentry = (nodenumber - be32_to_cpu(nc->nodenumber)) / be32_to_cpu(nc->nodes);
122
123
		nc->node[containerentry] = cpu_to_be32(be32_to_cpu(nc->node[containerentry]) | 0x00000001);
124
125
		asfs_bstore(sb, bh);
126
127
		if (isfull(sb, nc)) {	/* This container now is full as well!  Mark the next higher up container too then! */
128
			return markparentfull(sb, bh);
129
		}
130
		asfs_brelse(bh);
131
	}
132
133
	return errorcode;
134
}
135
136
static int addnewnodelevel(struct super_block *sb, u16 nodesize)
137
{
138
	struct buffer_head *bh;
139
	u32 noderoot = ASFS_SB(sb)->objectnoderoot;
140
	int errorcode;
141
142
	/* Adds a new level to the Node tree. */
143
144
	asfs_debug("addnewnodelevel: Entry\n");
145
146
	if ((bh = asfs_breadcheck(sb, noderoot, ASFS_NODECONTAINER_ID))) {
147
		struct buffer_head *newbh;
148
		u32 newblock;
149
150
		if ((errorcode = allocadminspace(sb, &newblock)) == 0 && (newbh = asfs_getzeroblk(sb, newblock))) {
151
			struct fsNodeContainer *nc = (void *) bh->b_data;
152
			struct fsNodeContainer *newnc = (void *) newbh->b_data;
153
154
			/* The newly allocated block will become a copy of the current root. */
155
156
			newnc->bheader.id = cpu_to_be32(ASFS_NODECONTAINER_ID);
157
			newnc->bheader.ownblock = cpu_to_be32(newblock);
158
			newnc->nodenumber = nc->nodenumber;
159
			newnc->nodes = nc->nodes;
160
			memcpy(newnc->node, nc->node, sb->s_blocksize - sizeof(struct fsNodeContainer));
161
162
			asfs_bstore(sb, newbh);
163
			asfs_brelse(newbh);
164
165
			/* The current root will now be transformed into a new root. */
166
167
			if (be32_to_cpu(nc->nodes) == 1)
168
				nc->nodes = cpu_to_be32((sb->s_blocksize - sizeof(struct fsNodeContainer)) / nodesize);
169
			else
170
				nc->nodes = cpu_to_be32(be32_to_cpu(nc->nodes) * NODECONT_BLOCK_COUNT);
171
172
			nc->node[0] = cpu_to_be32((newblock << (sb->s_blocksize_bits - ASFS_BLCKFACCURACY)) + 1);	/* Tree is full from that point! */
173
			memset(&nc->node[1], 0, sb->s_blocksize - sizeof(struct fsNodeContainer) - 4);
174
175
			asfs_bstore(sb, bh);
176
		}
177
		asfs_brelse(bh);
178
	} else
179
		errorcode = -EIO;
180
181
	return errorcode;
182
}
183
184
static int createnodecontainer(struct super_block *sb, u32 nodenumber, u32 nodes, u32 * returned_block)
185
{
186
	struct buffer_head *bh;
187
	int errorcode;
188
	u32 newblock;
189
190
	asfs_debug("createnodecontainer: nodenumber = %u, nodes = %u\n", nodenumber, nodes);
191
192
	if ((errorcode = allocadminspace(sb, &newblock)) == 0 && (bh = asfs_getzeroblk(sb, newblock))) {
193
		struct fsNodeContainer *nc = (void *) bh->b_data;
194
195
		nc->bheader.id = cpu_to_be32(ASFS_NODECONTAINER_ID);
196
		nc->bheader.ownblock = cpu_to_be32(newblock);
197
198
		nc->nodenumber = cpu_to_be32(nodenumber);
199
		nc->nodes = cpu_to_be32(nodes);
200
201
		asfs_bstore(sb, bh);
202
		asfs_brelse(bh);
203
		*returned_block = newblock;
204
	}
205
206
	return errorcode;
207
}
208
209
	/* This function creates a new fsNode structure in a fsNodeContainer.  If needed
210
	   it will create a new fsNodeContainers and a new fsNodeIndexContainer. */
211
212
int createnode(struct super_block *sb, struct buffer_head **returned_bh, struct fsNode **returned_node, u32 * returned_nodeno)
213
{
214
	u16 nodecount = (sb->s_blocksize - sizeof(struct fsNodeContainer)) / NODE_STRUCT_SIZE;
215
	u32 noderoot = ASFS_SB(sb)->objectnoderoot;
216
	u32 nodeindex = noderoot;
217
	int errorcode = 0;
218
219
	while ((*returned_bh = asfs_breadcheck(sb, nodeindex, ASFS_NODECONTAINER_ID))) {
220
		struct fsNodeContainer *nc = (void *) (*returned_bh)->b_data;
221
222
		if (be32_to_cpu(nc->nodes) == 1) {	/* Is it a leaf-container? */
223
			struct fsNode *n;
224
			s16 i = nodecount;
225
226
			n = (struct fsNode *) nc->node;
227
228
			while (i-- > 0) {
229
				if (n->data == 0)
230
					break;
231
232
				n = (struct fsNode *) ((u8 *) n + NODE_STRUCT_SIZE);
233
			}
234
235
			if (i >= 0) {
236
				/* Found an empty fsNode structure! */
237
				*returned_node = n;
238
				*returned_nodeno = be32_to_cpu(nc->nodenumber) + ((u8 *) n - (u8 *) nc->node) / NODE_STRUCT_SIZE;
239
240
				asfs_debug("createnode: Created Node %d\n", *returned_nodeno);
241
242
				/* Below we continue to look through the NodeContainer block.  We skip the entry
243
				   we found to be unused, and see if there are any more unused entries.  If we
244
				   do not find any more unused entries then this container is now full. */
245
246
				n = (struct fsNode *) ((u8 *) n + NODE_STRUCT_SIZE);
247
248
				while (i-- > 0) {
249
					if (n->data == 0)
250
						break;
251
252
					n = (struct fsNode *) ((u8 *) n + NODE_STRUCT_SIZE);
253
				}
254
255
				if (i < 0) {
256
					/* No more empty fsNode structures in this block.  Mark parent full. */
257
					errorcode = markparentfull(sb, *returned_bh);
258
				}
259
260
				return errorcode;
261
			} else {
262
				/* What happened now is that we found a leaf-container which was
263
				   completely filled.  In practice this should only happen when there
264
				   is only a single NodeContainer (only this container), or when there
265
				   was an error in one of the full-bits in a higher level container. */
266
267
				if (noderoot != nodeindex) {
268
					/*** Hmmm... it looks like there was a damaged full-bit or something.
269
					     In this case we'd probably better call markcontainerfull. */
270
271
					printk("ASFS: Couldn't find empty Node in NodeContainer while NodeIndexContainer indicated there should be one!\n");
272
273
					errorcode = -ENOSPC;
274
					break;
275
				} else {
276
					/* Container is completely filled. */
277
278
					if ((errorcode = addnewnodelevel(sb, NODE_STRUCT_SIZE)) != 0)
279
						return errorcode;
280
281
					nodeindex = noderoot;
282
				}
283
			}
284
		} else {	/* This isn't a leaf container */
285
			u32 *p = nc->node;
286
			s16 i = NODECONT_BLOCK_COUNT;
287
288
			/* We've read a normal container */
289
290
			while (i-- > 0) {
291
				if (*p != 0 && (be32_to_cpu(*p) & 0x00000001) == 0)
292
					break;
293
294
				p++;
295
			}
296
297
			if (i >= 0) {
298
				/* Found a not completely filled Container */
299
300
				nodeindex = be32_to_cpu(*p) >> (sb->s_blocksize_bits - ASFS_BLCKFACCURACY);
301
			} else {
302
				/* Everything in the NodeIndexContainer was completely filled.  There possibly
303
				   are some unused pointers in this block however.  */
304
305
				asfs_debug("createnode: NodeContainer at block has no empty Nodes.\n");
306
307
				p = nc->node;
308
				i = NODECONT_BLOCK_COUNT;
309
310
				while (i-- > 0) {
311
					if (*p == 0)
312
						break;
313
314
					p++;
315
				}
316
317
				if (i >= 0) {
318
					u32 newblock;
319
					u32 nodes;
320
321
					/* Found an unused Container pointer */
322
323
					if (be32_to_cpu(nc->nodes) == (sb->s_blocksize - sizeof(struct fsNodeContainer)) / NODE_STRUCT_SIZE) {
324
						nodes = 1;
325
					} else {
326
						nodes = be32_to_cpu(nc->nodes) / NODECONT_BLOCK_COUNT;
327
					}
328
329
					if ((errorcode = createnodecontainer(sb, be32_to_cpu(nc->nodenumber) + (p - nc->node) * be32_to_cpu(nc->nodes), nodes, &newblock)) != 0) {
330
						break;
331
					}
332
333
					*p = cpu_to_be32(newblock << (sb->s_blocksize_bits - ASFS_BLCKFACCURACY));
334
335
					asfs_bstore(sb, *returned_bh);
336
				} else {
337
					/* Container is completely filled.  This must be the top-level NodeIndex container
338
					   as otherwise the full-bit would have been wrong! */
339
340
					if ((errorcode = addnewnodelevel(sb, NODE_STRUCT_SIZE)) != 0)
341
						break;
342
343
					nodeindex = noderoot;
344
				}
345
			}
346
		}
347
		asfs_brelse(*returned_bh);
348
	}
349
350
	if (*returned_bh == NULL)
351
		return -EIO;
352
353
	return (errorcode);
354
}
355
356
static int markparentempty(struct super_block *sb, struct buffer_head *bh)
357
{
358
	u32 nodenumber = be32_to_cpu(((struct fsNodeContainer *) bh->b_data)->nodenumber);
359
	int errorcode;
360
361
	if ((errorcode = parentnodecontainer(sb, &bh)) == 0 && bh != 0) {
362
		struct fsNodeContainer *nc = (void *) bh->b_data;
363
		int wasfull;
364
		u16 containerentry = (nodenumber - be32_to_cpu(nc->nodenumber)) / be32_to_cpu(nc->nodes);
365
366
		wasfull = isfull(sb, nc);
367
368
		nc->node[containerentry] = cpu_to_be32(be32_to_cpu(nc->node[containerentry]) & ~0x00000001);
369
370
		asfs_bstore(sb, bh);
371
372
		if (wasfull) {
373
			/* This container was completely full before!  Mark the next higher up container too then! */
374
			return markparentempty(sb, bh);
375
		}
376
		asfs_brelse(bh);
377
	}
378
379
	return errorcode;
380
}
381
382
static int freecontainer(struct super_block *sb, struct buffer_head *bh)
383
{
384
	u32 nodenumber = be32_to_cpu(((struct fsNodeContainer *) bh->b_data)->nodenumber);
385
	int errorcode;
386
387
	if ((errorcode = parentnodecontainer(sb, &bh)) == 0 && bh != NULL) {	/* This line also prevents the freeing of the noderoot. */
388
		struct fsNodeContainer *nc = (void *) bh->b_data;
389
		u16 containerindex = (nodenumber - be32_to_cpu(nc->nodenumber)) / be32_to_cpu(nc->nodes);
390
391
		if ((errorcode = freeadminspace(sb, be32_to_cpu(nc->node[containerindex]) >> (sb->s_blocksize_bits - ASFS_BLCKFACCURACY))) == 0) {
392
			u32 *p = nc->node;
393
			s16 n = NODECONT_BLOCK_COUNT;
394
395
			nc->node[containerindex] = 0;
396
			asfs_bstore(sb, bh);
397
398
			while (n-- > 0)
399
				if (*p++ != 0)
400
					break;
401
402
			if (n < 0) {	/* This container is now completely empty!  Free this NodeIndexContainer too then! */
403
				return freecontainer(sb, bh);
404
			}
405
		}
406
		asfs_brelse(bh);
407
	}
408
409
	return errorcode;
410
}
411
412
static int internaldeletenode(struct super_block *sb, struct buffer_head *bh, struct fsNode *n)
413
{
414
	struct fsNodeContainer *nc = (void *) bh->b_data;
415
	u16 nodecount = (sb->s_blocksize - sizeof(struct fsNodeContainer)) / NODE_STRUCT_SIZE;
416
	s16 i = nodecount;
417
	s16 empty = 0;
418
	int errorcode = 0;
419
420
	n->data = 0;
421
	n = (struct fsNode *) nc->node;
422
423
	while (i-- > 0) {
424
		if (n->data == 0)
425
			empty++;
426
427
		n = (struct fsNode *) ((u8 *) n + NODE_STRUCT_SIZE);
428
	}
429
430
	asfs_bstore(sb, bh);
431
432
	if (empty == 1)		/* NodeContainer was completely full before, so we need to mark it empty now. */
433
		errorcode = markparentempty(sb, bh);
434
	else if (empty == nodecount)	/* NodeContainer is now completely empty!  Free it! */
435
		errorcode = freecontainer(sb, bh);
436
437
	return (errorcode);
438
}
439
440
int deletenode(struct super_block *sb, u32 objectnode)
441
{
442
	struct buffer_head *bh;
443
	struct fsObjectNode *on;
444
	int errorcode;
445
446
	asfs_debug("deletenode: Deleting Node %d\n", objectnode);
447
448
	if ((errorcode = getnode(sb, objectnode, &bh, &on)) == 0)
449
		errorcode = internaldeletenode(sb, bh, (struct fsNode *) on);
450
451
	asfs_brelse(bh);
452
	return (errorcode);
453
}
454
455
#endif
(-)kernel-source-2.6.5/fs/asfs/objects.c (+765 lines)
Line 0 Link Here
1
/*
2
 *
3
 * Amiga Smart File System, Linux implementation
4
 * version: 1.0beta3
5
 *
6
 * This file contains some parts of the original amiga version of 
7
 * SmartFilesystem source code.
8
 *
9
 * SmartFilesystem is copyrighted (C) 2003 by: John Hendrikx, 
10
 * Ralph Schmidt, Emmanuel Lesueur, David Gerber, and Marcin Kurek
11
 * 
12
 * Adapted and modified by Marek 'March' Szyprowski <marek@amiga.pl>
13
 *
14
 */
15
16
#include <linux/types.h>
17
#include <linux/errno.h>
18
#include <linux/slab.h>
19
#include <linux/asfs_fs.h>
20
#include <linux/fs.h>
21
#include <linux/buffer_head.h>
22
#include <linux/vfs.h>
23
24
#include <asm/byteorder.h>
25
26
struct fsObject *asfs_nextobject(struct fsObject *obj)
27
{
28
	int i;
29
	u8 *p = obj->name;
30
31
	for (i = 2; i > 0; p++)
32
		if (*p == '\0')
33
			i--;
34
	if ((p - (u8 *) obj) & 0x01)
35
		p++;
36
37
	return ((struct fsObject *) p);
38
}
39
40
struct fsObject *find_obj_by_name(struct super_block *sb, struct fsObjectContainer *objcont, u8 * name)
41
{
42
	struct fsObject *obj;
43
44
	obj = &(objcont->object[0]);
45
	while (be32_to_cpu(obj->objectnode) > 0 && ((char *) obj - (char *) objcont) + sizeof(struct fsObject) + 2 < sb->s_blocksize) {
46
		if (asfs_namecmp(obj->name, name, ASFS_SB(sb)->flags & ASFS_ROOTBITS_CASESENSITIVE) == 0) {
47
			asfs_debug("Object found! Node %u, Name %s, Type %x, inCont %u\n", be32_to_cpu(obj->objectnode), obj->name, obj->bits, be32_to_cpu(objcont->bheader.ownblock));
48
			return obj;
49
		}
50
		obj = asfs_nextobject(obj);
51
	}
52
	return NULL;
53
}
54
55
#ifdef CONFIG_ASFS_RW
56
57
struct fsObject *find_obj_by_node(struct super_block *sb, struct fsObjectContainer *objcont, u32 objnode)
58
{
59
	struct fsObject *obj;
60
61
	obj = &(objcont->object[0]);
62
	while (be32_to_cpu(obj->objectnode) > 0 && ((char *) obj - (char *) objcont) + sizeof(struct fsObject) + 2 < sb->s_blocksize) {
63
		if (be32_to_cpu(obj->objectnode) == objnode) {
64
			return obj;
65
		}
66
		obj = asfs_nextobject(obj);
67
	}
68
	return NULL;
69
}
70
71
int readobject(struct super_block *sb, u32 objectnode, struct buffer_head **bh, struct fsObject **returned_object)
72
{
73
	struct fsObjectNode *on;
74
	int errorcode;
75
	u32 contblock;
76
77
	asfs_debug("Seaching object - node %d\n", objectnode);
78
79
	if ((errorcode = getnode(sb, objectnode, bh, &on)) != 0)
80
		return errorcode;
81
	contblock = be32_to_cpu(on->node.data);
82
	asfs_brelse(*bh);
83
84
	if (contblock > 0 && (*bh = asfs_breadcheck(sb, contblock, ASFS_OBJECTCONTAINER_ID))) {
85
		*returned_object = find_obj_by_node(sb, (void *) (*bh)->b_data, objectnode);
86
		if (*returned_object == NULL) {
87
			brelse(*bh);
88
			*bh = NULL;
89
			return -ENOENT;
90
		}
91
		return 0;
92
	} else
93
		return -EIO;
94
}
95
96
static int removeobjectcontainer(struct super_block *sb, struct buffer_head *bh)
97
{
98
	struct fsObjectContainer *oc = (void *) bh->b_data;
99
	int errorcode;
100
	struct buffer_head *block;
101
102
	asfs_debug("removeobjectcontainer: block %u\n", be32_to_cpu(oc->bheader.ownblock));
103
104
	if (oc->next != 0 && oc->next != oc->bheader.ownblock) {
105
		struct fsObjectContainer *next_oc;
106
107
		if ((block = asfs_breadcheck(sb, be32_to_cpu(oc->next), ASFS_OBJECTCONTAINER_ID)) == NULL)
108
			return -EIO;
109
110
		next_oc = (void *) block->b_data;
111
		next_oc->previous = oc->previous;
112
113
		asfs_bstore(sb, block);
114
		asfs_brelse(block);
115
	}
116
117
	if (oc->previous != 0 && oc->previous != oc->bheader.ownblock) {
118
		struct fsObjectContainer *previous_oc;
119
120
		if ((block = asfs_breadcheck(sb, be32_to_cpu(oc->previous), ASFS_OBJECTCONTAINER_ID)) == NULL)
121
			return -EIO;
122
123
		previous_oc = (void *) block->b_data;
124
		previous_oc->next = oc->next;
125
126
		asfs_bstore(sb, block);
127
		asfs_brelse(block);
128
	} else {
129
		struct fsObject *parent_o;
130
131
		if ((errorcode = readobject(sb, be32_to_cpu(oc->parent), &block, &parent_o)) != 0)
132
			return (errorcode);
133
134
		parent_o->object.dir.firstdirblock = oc->next;
135
136
		asfs_bstore(sb, block);
137
		asfs_brelse(block);
138
	}
139
140
	if ((errorcode = freeadminspace(sb, be32_to_cpu(oc->bheader.ownblock))) != 0)
141
		return (errorcode);
142
143
	return (0);
144
}
145
146
int setrecycledinfodiff(struct super_block *sb, s32 deletedfiles, s32 deletedblocks)
147
{
148
	struct buffer_head *bh;
149
150
	if ((bh = asfs_breadcheck(sb, ASFS_SB(sb)->rootobjectcontainer, ASFS_OBJECTCONTAINER_ID))) {
151
		struct fsRootInfo *ri = (struct fsRootInfo *) ((u8 *) bh->b_data + sb->s_blocksize - sizeof(struct fsRootInfo));
152
153
		ri->deletedfiles = cpu_to_be32(be32_to_cpu(ri->deletedfiles) + deletedfiles);
154
		ri->deletedblocks = cpu_to_be32(be32_to_cpu(ri->deletedblocks) + deletedblocks);
155
156
		asfs_bstore(sb, bh);
157
		asfs_brelse(bh);
158
	} else
159
		return -EIO;
160
	return 0;
161
}
162
163
	/* This function removes the fsObject structure passed in from the passed
164
	   buffer_head.  If the ObjectContainer becomes completely empty it will be 
165
	   delinked from the ObjectContainer chain and marked free for reuse.
166
	   This function doesn't delink the object from the hashchain! */
167
168
static int simpleremoveobject(struct super_block *sb, struct buffer_head *bh, struct fsObject *o)
169
{
170
	struct fsObjectContainer *oc = (void *) bh->b_data;
171
	int errorcode = 0;
172
173
	asfs_debug("simpleremoveobject:\n");
174
175
	if (be32_to_cpu(oc->parent) == ASFS_RECYCLEDNODE) {
176
		/* This object is removed from the Recycled directory. */
177
		if ((errorcode = setrecycledinfodiff(sb, -1, -((be32_to_cpu(o->object.file.size) + sb->s_blocksize - 1) >> sb->s_blocksize_bits))) != 0)
178
			return errorcode;
179
	}
180
181
	if ((asfs_nextobject(oc->object))->name[0] == '\0')
182
		errorcode = removeobjectcontainer(sb, bh);
183
	else {
184
		struct fsObject *nexto;
185
		int objlen;
186
187
		nexto = asfs_nextobject(o);
188
		objlen = (u8 *) nexto - (u8 *) o;
189
190
		memmove(o, nexto, sb->s_blocksize - ((u8 *) nexto - (u8 *) oc));
191
		memset((u8 *) oc + sb->s_blocksize - objlen, 0, objlen);
192
193
		asfs_bstore(sb, bh);
194
	}
195
	return errorcode;
196
}
197
198
/* This function delinks the passed in ObjectNode from its hash-chain.  Handy when deleting
199
   the object, or when renaming/moving it. */
200
201
static int dehashobjectquick(struct super_block *sb, u32 objectnode, u8 *name, u32 parentobjectnode)
202
{
203
	struct fsObject *o;
204
	int errorcode;
205
	struct buffer_head *block;
206
207
	asfs_debug("dehashobject: Delinking object %d (=ObjectNode) from hashchain. Parentnode = %d\n", objectnode, parentobjectnode);
208
209
	if ((errorcode = readobject(sb, parentobjectnode, &block, &o)) == 0 && o->object.dir.hashtable != 0) {
210
		u32 hashtable = be32_to_cpu(o->object.dir.hashtable);
211
		asfs_brelse(block);
212
213
		if ((block = asfs_breadcheck(sb, hashtable, ASFS_HASHTABLE_ID))) {
214
			struct buffer_head *node_bh;
215
			struct fsObjectNode *onptr, on;
216
			struct fsHashTable *ht = (void *) block->b_data;
217
			u32 nexthash;
218
219
			if ((errorcode = getnode(sb, objectnode, &node_bh, &onptr)) == 0) {
220
				u16 hashchain;
221
222
				asfs_debug("dehashobject: Read HashTable block of parent object of object to be delinked\n");
223
224
				hashchain = HASHCHAIN(asfs_hash(name, ASFS_SB(sb)->flags & ASFS_ROOTBITS_CASESENSITIVE));
225
				nexthash = be32_to_cpu(ht->hashentry[hashchain]);
226
227
				if (nexthash == objectnode) {
228
					/* The hashtable directly points to the fsObject to be delinked.  We simply
229
					   modify the Hashtable to point to the new nexthash entry. */
230
231
					asfs_debug("dehashobject: The hashtable points directly to the to be delinked object\n");
232
233
					ht->hashentry[hashchain] = onptr->next;
234
					asfs_bstore(sb, block);
235
				} else {
236
					struct fsObjectNode *onsearch = 0;
237
238
					on = *onptr;
239
240
					asfs_debug("dehashobject: Walking through hashchain\n");
241
242
					while (nexthash != 0 && nexthash != objectnode) {
243
						asfs_brelse(node_bh);
244
						if ((errorcode = getnode(sb, nexthash, &node_bh, &onsearch)) != 0)
245
							break;
246
						nexthash = be32_to_cpu(onsearch->next);
247
					}
248
249
					if (errorcode == 0) {
250
						if (nexthash != 0) {
251
							/* Previous fsObjectNode found in hash chain.  Modify the fsObjectNode to 'skip' the
252
							   ObjectNode which is being delinked from the hash chain. */
253
254
							onsearch->next = on.next;
255
							asfs_bstore(sb, node_bh);
256
						} else {
257
							printk("ASFS: Hashchain of object %d is corrupt or incorrectly linked.", objectnode);
258
259
							/*** This is strange.  We have been looking for the fsObjectNode which is located before the
260
							     passed in fsObjectNode in the hash-chain.  However, we never found the
261
							     fsObjectNode reffered to in the hash-chain!  Has to be somekind
262
							     of internal error... */
263
264
							errorcode = -ENOENT;
265
						}
266
					}
267
				}
268
				asfs_brelse(node_bh);
269
			}
270
			asfs_brelse(block);
271
		}
272
	}
273
	return errorcode;
274
}
275
276
277
	/* This function removes an object from any directory.  It takes care
278
	   of delinking the object from the hashchain and also frees the
279
	   objectnode number. */
280
281
int removeobject(struct super_block *sb, struct buffer_head *bh, struct fsObject *o)
282
{
283
	struct fsObjectContainer *oc = (void *) bh->b_data;
284
	int errorcode;
285
286
	asfs_debug("removeobject\n");
287
288
	if ((errorcode = dehashobjectquick(sb, be32_to_cpu(o->objectnode), o->name, be32_to_cpu(oc->parent))) == 0) {
289
		u32 objectnode = be32_to_cpu(o->objectnode);
290
291
		if ((errorcode = simpleremoveobject(sb, bh, o)) == 0)
292
			errorcode = deletenode(sb, objectnode);
293
	}
294
295
	return (errorcode);
296
}
297
298
	/* This function deletes the specified object. */
299
int deleteobject(struct super_block *sb, struct buffer_head *bh, struct fsObject *o)
300
{
301
	int errorcode = 0;
302
303
	asfs_debug("deleteobject: Entry -- deleting object %d (%s)\n", be32_to_cpu(o->objectnode), o->name);
304
305
	if ((o->bits & OTYPE_DIR) == 0 || o->object.dir.firstdirblock == 0) {
306
		u8 bits = o->bits;
307
		u32 hashblckno = be32_to_cpu(o->object.dir.hashtable);
308
		u32 extentbnode = be32_to_cpu(o->object.file.data);
309
310
		if ((errorcode = removeobject(sb, bh, o)) == 0) {
311
			if ((bits & OTYPE_LINK) != 0) {
312
				asfs_debug("deleteobject: Object is soft link!\n");
313
				errorcode = freeadminspace(sb, extentbnode);
314
			} else if ((bits & OTYPE_DIR) != 0) {
315
				asfs_debug("deleteobject: Object is a directory!\n");
316
				errorcode = freeadminspace(sb, hashblckno);
317
			} else {
318
				asfs_debug("deleteobject: Object is a file\n");
319
				if (extentbnode != 0)
320
					errorcode = deleteextents(sb, extentbnode);
321
			}
322
		}
323
	}
324
325
	return (errorcode);
326
}
327
328
	/* This function takes a HashBlock pointer, an ObjectNode and an ObjectName.
329
	   If there is a hashblock, then this function will correctly link the object
330
	   into the hashchain.  If there isn't a hashblock (=0) then this function
331
	   does nothing.  */
332
333
static int hashobject(struct super_block *sb, u32 hashblock, struct fsObjectNode *on, u32 nodeno, u8 *objectname)
334
{
335
	struct buffer_head *hash_bh;
336
337
	asfs_debug("hashobject, using hashblock %d\n", hashblock);
338
	if (hashblock == 0)
339
		return 0;
340
341
	if ((hash_bh = asfs_breadcheck(sb, hashblock, ASFS_HASHTABLE_ID))) {
342
		struct fsHashTable *ht = (void *) hash_bh->b_data;
343
		u32 nexthash;
344
		u16 hashvalue, hashchain;
345
346
		hashvalue = asfs_hash(objectname, ASFS_SB(sb)->flags & ASFS_ROOTBITS_CASESENSITIVE);
347
		hashchain = HASHCHAIN(hashvalue);
348
		nexthash = be32_to_cpu(ht->hashentry[hashchain]);
349
350
		ht->hashentry[hashchain] = cpu_to_be32(nodeno);
351
352
		asfs_bstore(sb, hash_bh);
353
		asfs_brelse(hash_bh);
354
355
		on->next = cpu_to_be32(nexthash);
356
		on->hash16 = cpu_to_be16(hashvalue);
357
	} else
358
		return -EIO;
359
360
	return 0;
361
}
362
363
	/* This function returns a pointer to the first unused byte in
364
	   an ObjectContainer. */
365
366
static u8 *emptyspaceinobjectcontainer(struct super_block *sb, struct fsObjectContainer *oc)
367
{
368
	struct fsObject *o = oc->object;
369
	u8 *endadr;
370
371
	endadr = (u8 *) oc + sb->s_blocksize - sizeof(struct fsObject) - 2;
372
373
	while ((u8 *) o < endadr && o->name[0] != 0)
374
		o = asfs_nextobject(o);
375
376
	return (u8 *) o;
377
}
378
379
	/* This function will look in the directory indicated by io_o
380
	   for an ObjectContainer block which contains bytesneeded free
381
	   bytes.  If none is found then this function simply creates a
382
	   new ObjectContainer and adds that to the indicated directory. */
383
384
static int findobjectspace(struct super_block *sb, struct buffer_head **io_bh, struct fsObject **io_o, u32 bytesneeded)
385
{
386
	struct buffer_head *bhparent = *io_bh;
387
	struct fsObject *oparent = *io_o;
388
	struct buffer_head *bh;
389
	u32 nextblock = be32_to_cpu(oparent->object.dir.firstdirblock);
390
	int errorcode = 0;
391
392
	asfs_debug("findobjectspace: Looking for %u bytes in directory with ObjectNode number %d (in block %d)\n", bytesneeded, be32_to_cpu((*io_o)->objectnode),
393
		   be32_to_cpu(((struct fsBlockHeader *) (*io_bh)->b_data)->ownblock));
394
395
	while (nextblock != 0 && (bh = asfs_breadcheck(sb, nextblock, ASFS_OBJECTCONTAINER_ID))) {
396
		struct fsObjectContainer *oc = (void *) bh->b_data;
397
		u8 *emptyspace;
398
399
		/* We need to find out how much free space this ObjectContainer has */
400
401
		emptyspace = emptyspaceinobjectcontainer(sb, oc);
402
403
		if ((u8 *) oc + sb->s_blocksize - emptyspace >= bytesneeded) {
404
			/* We found enough space in one of the ObjectContainer blocks!!
405
			   We return a struct fsObject *. */
406
			*io_bh = bh;
407
			*io_o = (struct fsObject *) emptyspace;
408
			break;
409
		}
410
		nextblock = be32_to_cpu(oc->next);
411
		asfs_brelse(bh);
412
	}
413
414
	if (nextblock == 0) {
415
		u32 newcontblock;
416
		/* If we get here, we traversed the *entire* directory (ough!) and found no empty
417
		   space large enough for our entry.  We allocate new space and add it to this
418
		   directory. */
419
420
		if ((errorcode = allocadminspace(sb, &newcontblock)) == 0 && (bh = asfs_getzeroblk(sb, newcontblock))) {
421
			struct fsObjectContainer *oc = (void *) bh->b_data;
422
			struct buffer_head *bhnext;
423
424
			asfs_debug("findobjectspace: No room was found, allocated new block at %u\n", newcontblock);
425
426
			/* Allocated new block.  We will now link it to the START of the directory chain
427
			   so the new free space can be found quickly when more entries need to be added. */
428
429
			oc->bheader.id = cpu_to_be32(ASFS_OBJECTCONTAINER_ID);
430
			oc->bheader.ownblock = cpu_to_be32(newcontblock);
431
			oc->parent = oparent->objectnode;
432
			oc->next = oparent->object.dir.firstdirblock;
433
			oc->previous = 0;
434
435
			oparent->object.dir.firstdirblock = cpu_to_be32(newcontblock);
436
437
			asfs_bstore(sb, bhparent);
438
439
			if (oc->next != 0 && (bhnext = asfs_breadcheck(sb, be32_to_cpu(oc->next), ASFS_OBJECTCONTAINER_ID))) {
440
				struct fsObjectContainer *ocnext = (void *) bhnext->b_data;
441
				ocnext->previous = cpu_to_be32(newcontblock);
442
				asfs_bstore(sb, bhnext);
443
				asfs_brelse(bhnext);
444
			}
445
446
			*io_bh = bh;
447
			*io_o = oc->object;
448
		}
449
	}
450
451
	asfs_debug("findobjectspace: new object will be in container block %u\n", be32_to_cpu(((struct fsBlockHeader *) (*io_bh)->b_data)->ownblock));
452
453
	return (errorcode);
454
}
455
456
/* io_bh & io_o refer to the direct parent of the new object.  Objectname is the
457
	name of the new object (name only). Does not realese io_bh !!! */
458
459
int createobject(struct super_block *sb, struct buffer_head **io_bh, struct fsObject **io_o, struct fsObject *src_o, u8 *objectname, int force)
460
{
461
	int errorcode;
462
	u32 object_size;
463
	u32 hashblock = be32_to_cpu((*io_o)->object.dir.hashtable);
464
465
	asfs_debug("createobject: Creating object '%s' in dir '%s'.\n", objectname, (*io_o)->name);
466
467
	if (!force && ASFS_SB(sb)->freeblocks < ASFS_ALWAYSFREE)
468
		return -ENOSPC;
469
470
	if (!force && be32_to_cpu((*io_o)->objectnode) == ASFS_RECYCLEDNODE)
471
		return -EINVAL;
472
473
	object_size = sizeof(struct fsObject) + strlen(objectname) + 2;
474
475
	if ((errorcode = findobjectspace(sb, io_bh, io_o, object_size)) == 0) {
476
		struct fsObject *o2 = *io_o;
477
		u8 *name = o2->name;
478
		u8 *objname = objectname;
479
		struct buffer_head *node_bh;
480
		struct fsObjectNode *on;
481
		u32 nodeno;
482
483
		**io_o = *src_o;	/* Copying whole object data... */
484
485
		while (*objname != 0)	/* Copying name */
486
			*name++ = *objname++;
487
488
		*name++ = 0;
489
		*name = 0;	/* zero byte for comment */
490
491
		if (o2->objectnode != 0)	/* ObjectNode reuse or creation */
492
			errorcode = getnode(sb, o2->objectnode, &node_bh, &on);
493
		else {
494
			if ((errorcode = createnode(sb, &node_bh, (struct fsNode **) &on, &nodeno)) == 0) {
495
				on->hash16 = cpu_to_be16(asfs_hash(o2->name, ASFS_SB(sb)->flags & ASFS_ROOTBITS_CASESENSITIVE));
496
				o2->objectnode = cpu_to_be32(nodeno);
497
			}
498
			asfs_debug("createnode returned with errorcode: %d\n", errorcode);
499
		}
500
501
		if (errorcode == 0) {	/* in io_bh there is a container with created object */
502
			on->node.data = ((struct fsBlockHeader *) (*io_bh)->b_data)->ownblock;
503
			if ((errorcode = hashobject(sb, hashblock, on, be32_to_cpu(o2->objectnode), objectname)) == 0) {
504
				asfs_bstore(sb, node_bh);
505
				asfs_brelse(node_bh);
506
			} else
507
				errorcode = -EIO;
508
		}
509
510
		if (errorcode == 0) {	/* HashBlock reuse or creation:*/
511
512
			if ((o2->bits & OTYPE_DIR) != 0 && o2->object.dir.hashtable == 0) {
513
				struct buffer_head *hashbh;
514
				u32 hashblock;
515
516
				asfs_debug("creating Hashblock\n");
517
518
				if ((errorcode = allocadminspace(sb, &hashblock)) == 0 && (hashbh = asfs_getzeroblk(sb, hashblock))) {	    
519
					struct fsHashTable *ht = (void *) hashbh->b_data;
520
521
					o2->object.dir.hashtable = cpu_to_be32(hashblock);
522
523
					ht->bheader.id = cpu_to_be32(ASFS_HASHTABLE_ID);
524
					ht->bheader.ownblock = cpu_to_be32(hashblock);
525
					ht->parent = o2->objectnode;
526
527
					asfs_bstore(sb, hashbh);
528
					asfs_brelse(hashbh);
529
				}
530
			}
531
		}
532
533
		if (errorcode == 0) {	/* SoftLink creation: */
534
			if ((o2->bits & (OTYPE_LINK | OTYPE_HARDLINK)) == OTYPE_LINK && o2->object.file.data == 0) {
535
				struct buffer_head *bh2;
536
				u32 slinkblock;
537
538
				if ((errorcode = allocadminspace(sb, &slinkblock)) == 0 && (bh2 = asfs_getzeroblk(sb, slinkblock))) {
539
					struct fsSoftLink *sl = (void *) bh2->b_data;
540
					o2->object.file.data = cpu_to_be32(slinkblock);
541
					sl->bheader.id = cpu_to_be32(ASFS_SOFTLINK_ID);
542
					sl->bheader.ownblock = cpu_to_be32(slinkblock);
543
					sl->parent = o2->objectnode;
544
					sl->next = 0;
545
					sl->previous = 0;
546
					asfs_bstore(sb, bh2);
547
					asfs_brelse(bh2);
548
				}
549
			}
550
		}
551
	}
552
	asfs_debug("createobject: done.\n");
553
554
	return (errorcode);
555
}
556
557
	/* This function extends the file object 'o' with a number  of blocks 
558
		(hopefully, if any blocks has been found!). Only new Extents will 
559
      be created -- the size of the file will not be altered, and changing 
560
		it is left up to the caller.  If the file did not have any blocks 
561
		yet, then the o->object.file.data will be set to the first (new) 
562
		ExtentBNode. It returns the number of added blocks through 
563
		addedblocks pointer */
564
565
int addblockstofile(struct super_block *sb, struct buffer_head *objbh, struct fsObject *o, u32 blocks, u32 * newspace, u32 * addedblocks)
566
{
567
	u32 lastextentbnode;
568
	int errorcode = 0;
569
	struct fsExtentBNode *ebnp;
570
	struct buffer_head *block = NULL;
571
572
573
	asfs_debug("extendblocksinfile: Trying to increasing number of blocks by %d.\n", blocks);
574
575
	lastextentbnode = be32_to_cpu(o->object.file.data);
576
577
	if (lastextentbnode != 0) {
578
		while (lastextentbnode != 0 && errorcode == 0) {
579
			if (block != NULL)
580
				asfs_brelse(block);
581
			errorcode = getextent(sb, lastextentbnode, &block, &ebnp);
582
			lastextentbnode = be32_to_cpu(ebnp->next);
583
		}
584
		lastextentbnode = be32_to_cpu(ebnp->key);
585
	}
586
587
	if (errorcode == 0) {
588
		u32 searchstart;
589
590
		u32 found_block;
591
		u32 found_blocks;
592
593
		*addedblocks = 0;
594
		*newspace = 0;
595
596
		if (lastextentbnode != 0)
597
			searchstart = be32_to_cpu(ebnp->key) + be16_to_cpu(ebnp->blocks);
598
		else
599
			searchstart = 0; //ASFS_SB(sb)->block_rovingblockptr;
600
601
		if ((errorcode = findspace(sb, blocks, searchstart, searchstart, &found_block, &found_blocks)) != 0) {
602
			asfs_brelse(block);
603
			asfs_debug("extendblocksinfile: findspace returned %s\n", errorcode == -ENOSPC ? "ENOSPC" : "error");
604
			return errorcode;
605
		}
606
607
		blocks = found_blocks;
608
		errorcode = markspace(sb, found_block, found_blocks);
609
		*addedblocks = found_blocks;
610
		*newspace = found_block;
611
612
		asfs_debug("extendblocksinfile: block = %u, lastextentbnode = %u, extentblocks = %d\n", found_block, lastextentbnode, blocks);
613
614
		if ((errorcode = addblocks(sb, blocks, found_block, be32_to_cpu(o->objectnode), &lastextentbnode)) != 0) {
615
			asfs_debug("extendblocksinfile: addblocks returned errorcode %d\n", errorcode);
616
			return errorcode;
617
		}
618
619
		if (o->object.file.data == 0)
620
			o->object.file.data = cpu_to_be32(lastextentbnode);
621
	}
622
623
	if (block)
624
		asfs_brelse(block);
625
	asfs_bstore(sb, objbh);
626
627
	asfs_debug("addblockstofile: done. added %d blocks\n", *addedblocks);
628
629
	return errorcode;
630
}
631
632
	/* The Object indicated by bh1 & o1, gets renamed to newname and placed
633
	   in the directory indicated by bhparent & oparent. */
634
635
int renameobject(struct super_block *sb, struct buffer_head *bh1, struct fsObject *o1, struct buffer_head *bhparent, struct fsObject *oparent, u8 * newname)
636
{
637
	struct fsObject object;
638
	u32 oldparentnode = be32_to_cpu(((struct fsObjectContainer *) bh1->b_data)->parent);
639
	u8 oldname[107];
640
	int errorcode;
641
642
	asfs_debug("renameobject: Renaming '%s' to '%s' in dir '%s'\n", o1->name, newname, oparent->name);
643
644
	object = *o1;
645
	strcpy(oldname, o1->name);
646
647
	if ((errorcode = dehashobjectquick(sb, be32_to_cpu(o1->objectnode), o1->name, oldparentnode)) == 0) {
648
		u32 parentobjectnode = be32_to_cpu(oparent->objectnode);
649
650
		if ((errorcode = simpleremoveobject(sb, bh1, o1)) == 0) {
651
			struct buffer_head *bh2 = bhparent;
652
			struct fsObject *o2;
653
654
			/* oparent might changed after simpleremoveobject */
655
			oparent = o2 = find_obj_by_node(sb, (struct fsObjectContainer *) bhparent->b_data, parentobjectnode);
656
657
			/* In goes the Parent bh & o, out comes the New object's bh & o :-) */
658
			if ((errorcode = createobject(sb, &bh2, &o2, &object, newname, TRUE)) == 0) {
659
				asfs_bstore(sb, bh2);
660
				if (be32_to_cpu(oparent->objectnode) == ASFS_RECYCLEDNODE) {
661
					asfs_debug("renameobject: Updating recycled dir info\n");
662
					if ((errorcode = setrecycledinfodiff(sb, 1, (be32_to_cpu(o2->object.file.size) + sb->s_blocksize - 1) >> sb->s_blocksize_bits)) != 0) {
663
						brelse(bh2);
664
						return errorcode;
665
					}
666
				}
667
				brelse(bh2);
668
				asfs_debug("renameobject: Succesfully created & stored new object.\n");
669
			} else { /* recreate object in old place, maybe this will not fail, but who knows... */
670
				asfs_debug("renameobject: Creating new object failed. Trying to recreate it in source directory.\n");
671
				if (readobject(sb, oldparentnode, &bh1, &o1) == 0) {
672
					struct buffer_head *bh2 = bh1;
673
					if (createobject(sb, &bh2, &o1, &object, oldname, TRUE) == 0) {
674
						asfs_bstore(sb, bh2);
675
						if (oldparentnode == ASFS_RECYCLEDNODE) {
676
							asfs_debug("renameobject: Updating recycled dir info\n");
677
							setrecycledinfodiff(sb, 1, (be32_to_cpu(o1->object.file.size) + sb->s_blocksize - 1) >> sb->s_blocksize_bits);
678
						}
679
						brelse(bh2);
680
					}
681
					brelse(bh1);
682
				}
683
			}
684
		}
685
	}
686
	return errorcode;
687
}
688
689
		/* Truncates the specified file to /newsize/ bytes */
690
691
int truncateblocksinfile(struct super_block *sb, struct buffer_head *bh, struct fsObject *o, u32 newsize)
692
{
693
	struct buffer_head *ebh;
694
	struct fsExtentBNode *ebn;
695
	int errorcode;
696
	u32 pos = 0;
697
	u32 newblocks = (newsize + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
698
	u32 filedata = be32_to_cpu(o->object.file.data);
699
	u32 eprev, ekey;
700
	u16 eblocks;
701
702
	asfs_debug("trucateblocksinfile: newsize %u\n", newsize);
703
704
	if (filedata == 0)
705
		return 0;
706
707
	for (;;) {
708
		if ((errorcode = getextent(sb, filedata, &ebh, &ebn)) != 0)
709
			return errorcode;
710
		if (pos + be16_to_cpu(ebn->blocks) >= newblocks)
711
			break;
712
		pos += be16_to_cpu(ebn->blocks);
713
		if ((filedata = be32_to_cpu(ebn->next)) == 0)
714
			break;
715
		asfs_brelse(ebh);
716
	};
717
718
	eblocks = newblocks - pos;
719
	ekey = be32_to_cpu(ebn->key);
720
	eprev = be32_to_cpu(ebn->prev);
721
722
	if (be16_to_cpu(ebn->blocks) < eblocks) {
723
		printk("ASFS: Extent chain is too short or damaged!\n");
724
		asfs_brelse(ebh);
725
		return -ENOENT;
726
	}
727
	if (be16_to_cpu(ebn->blocks) - eblocks > 0 && (errorcode = freespace(sb, be32_to_cpu(ebn->key) + eblocks, be16_to_cpu(ebn->blocks) - eblocks)) != 0) {
728
		asfs_brelse(ebh);
729
		return errorcode;
730
	}
731
	if (be32_to_cpu(ebn->next) > 0 && (errorcode = deleteextents(sb, be32_to_cpu(ebn->next))) != 0) {
732
		asfs_brelse(ebh);
733
		return errorcode;
734
	}
735
	ebn->blocks = cpu_to_be16(eblocks);
736
	ebn->next = 0;
737
	asfs_bstore(sb, ebh);
738
739
	if (eblocks == 0) {
740
		if (eprev & MSB_MASK) {
741
			o->object.file.data = 0;
742
			asfs_bstore(sb, bh);
743
		} else {
744
			struct buffer_head *ebhp;
745
			struct fsExtentBNode *ebnp;
746
747
			if ((errorcode = getextent(sb, eprev & !MSB_MASK, &ebhp, &ebnp)) != 0) {
748
				asfs_brelse(ebh);
749
				return errorcode;
750
			}
751
752
			ebnp->next = 0;
753
			asfs_bstore(sb, ebhp);
754
			asfs_brelse(ebhp);
755
		}
756
		if ((errorcode = deletebnode(sb, ebh, ekey)) != 0) {
757
			asfs_brelse(ebh);
758
			return errorcode;
759
		}
760
	}
761
	asfs_brelse(ebh);
762
763
	return 0;
764
}
765
#endif
(-)kernel-source-2.6.5/fs/asfs/super.c (+502 lines)
Line 0 Link Here
1
/*
2
 *
3
 * Amiga Smart File System, Linux implementation
4
 *
5
 * version: 1.0beta4 (12.04.2004) for 2.6.x kernel
6
 *  
7
 * Copyright (C) 2003,2004  Marek 'March' Szyprowski <marek@amiga.pl>
8
 *
9
 *
10
 * Thanks to Marcin Kurek (Morgoth/Dreamolers-CAPS) for help and parts 
11
 * of original amiga version of SmartFilesystem source code. 
12
 *
13
 * SmartFilesystem is copyrighted (C) 2003 by: John Hendrikx, 
14
 * Ralph Schmidt, Emmanuel Lesueur, David Gerber and Marcin Kurek
15
 * 
16
 *
17
 * ASFS is based on the Amiga FFS filesystem for Linux
18
 * Copyright (C) 1993  Ray Burr
19
 * Copyright (C) 1996  Hans-Joachim Widmaier
20
 *
21
 * Earlier versions were based on the Linux implementation of 
22
 * the ROMFS file system
23
 * Copyright (C) 1997-1999  Janos Farkas <chexum@shadow.banki.hu>
24
 *
25
 * ASFS used some parts of the smbfs filesystem:
26
 * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
27
 * Copyright (C) 1997 by Volker Lendecke
28
 *
29
 * and parts of the Minix filesystem additionally
30
 * Copyright (C) 1991, 1992  Linus Torvalds
31
 * Copyright (C) 1996  Gertjan van Wingerde 
32
 *
33
 *
34
 * This program is free software; you can redistribute it and/or
35
 * modify it under the terms of the GNU General Public License
36
 * as published by the Free Software Foundation; either version
37
 * 2 of the License, or (at your option) any later version.
38
 *
39
 *
40
 * History:
41
 *
42
 * v1.0beta4 (12.04.2004)
43
 * - removed dummy asfs_notify_change (this fixes major bug introduced
44
 *   in 1.0beta3 - file size wasn't written to disk) until it will 
45
 *   be implemented completely
46
 *
47
 * v1.0beta3 (22.03.2004) - still beta
48
 * - updated for 2.6.x kernels VFS changes
49
 * - code clean-up 
50
 * - added dummy asfs_notify_change (chmod now returns no errors)
51
 * - added symlinks write support
52
 * - fixed: ASFS_SB(sb)->flags was always zero
53
 *
54
 * v1.0beta2 (11.01.2004) - special version for Pegasos][ kernel
55
 * - separated read and write functions, can be compiled also
56
 *   as read-only fs
57
 * v1.0beta1 (02.12.2003) - first public beta with write support
58
 * - added dentry hashing/comparing routines
59
 * - code clean-up
60
 *
61
 * v1.0aplha4 (30.11.2003) - preparing for first public beta
62
 * - fixed some problems with renaming/moving files
63
 * - fixed two major bugs, which didn't occur when fs was mounted
64
 *   on loopback device (newly allocated blocks were not written to
65
 *   disk and state bits were not set correctly on newly mapped file
66
 *   blocks)
67
 * - fixed many small bugs in io code (some buffers were not freed)
68
 * - added/modified sb locks in asfs_lookup and asfs_getblock
69
 * - fixed serious bug in file block allocation routines
70
 * v1.0aplha3 (23.11.2003)
71
 * - added (hopefully) all byteswap code, should now work again on 
72
 *   little-endian systems (also with write support!)
73
 * - updated documentation
74
 * v1.0alpha2 (13.11.2003) 
75
 * - now alocates file blocks in chunks during one request
76
 * - fixed some dead-locks, other fixes
77
 * v1.0alpha (02.11.2003) - first working version with full write support
78
 * - too much to list it here ;)
79
 *
80
 * ... (working on write support)
81
 *
82
 * v0.7 (12.10.2003) - internal realase
83
 * - added asfs_breadcheck, modified asfs_get_node, asfs_search_BTree, 
84
 *   no more from_be32/16 macros, other...
85
 * - code splitted into several files
86
 *
87
 * v0.6 (04.09.2003) - final read-only version
88
 * - added support for HashTables, directory scaning should be
89
 *   MUCH faster now
90
 * - added checking of block IDs before reading any data from block
91
 *
92
 * v0.5 (19.07.2003)
93
 * - added simple but effective extent cache - real speed-up 
94
 *   in reading large files
95
 * - added read support for symlinks - based on AFFS symlinks
96
 *
97
 * v0.4 (10.07.2003)
98
 * - third code clean-up (thanks to Roman Zippel for advice)
99
 * - now uses generic readpage and readinode routines
100
 *
101
 * v0.3beta (17.06.2003)
102
 * - second code clean-up
103
 *
104
 * v0.2beta2 (15.06.2003)
105
 * - fixed yet another stupid bug - driver can't read root block on little-endian systems
106
 * v0.2beta (15.06.2003)
107
 * - fixed stupid bug - now files have 'file' flag (S_IFREG) set...
108
 * - added mount options to set uid, gid and mode of files and dirs
109
 * - made hidden files & dirs really hidden (= not listed in directories)
110
 * - code clean-up
111
 *
112
 * v0.1beta (11.06.2003) 
113
 * - after many kernel crashes, finally got it! 
114
 * - first working read-only filesystem driver
115
 *
116
 */
117
118
/* todo:
119
 * - clean-up the code
120
 *	- remove bugs
121
 * - add missing features (maybe safe-delete, other...)
122
 * - create other fs tools like mkfs.asfs and fsck.asfs, some data-recovery tools
123
 */
124
125
#include <linux/module.h>
126
#include <linux/types.h>
127
#include <linux/errno.h>
128
#include <linux/slab.h>
129
#include <linux/asfs_fs.h>
130
#include <linux/fs.h>
131
#include <linux/init.h>
132
#include <linux/smp_lock.h>
133
#include <linux/buffer_head.h>
134
#include <linux/vfs.h>
135
#include <linux/string.h>
136
137
#include <asm/byteorder.h>
138
#include <asm/uaccess.h>
139
140
u32 asfs_calcchecksum(void *block, u32 blocksize)
141
{
142
	u32 *data = block, checksum = 1;
143
	while (blocksize > 0) {
144
		checksum += be32_to_cpu(*data++);
145
		blocksize -= 4;
146
	}
147
	checksum -= be32_to_cpu(((struct fsBlockHeader *)block)->checksum);
148
	return -checksum;
149
}
150
151
static struct super_operations asfs_ops = {
152
	.alloc_inode	= asfs_alloc_inode,
153
	.destroy_inode	= asfs_destroy_inode,
154
	.put_super		= asfs_put_super,
155
	.statfs			= asfs_statfs,
156
#ifdef CONFIG_ASFS_RW
157
	.remount_fs		= asfs_remount,
158
#endif
159
};
160
161
extern struct dentry_operations asfs_dentry_operations;
162
163
static int asfs_parse_options(char *options, struct super_block *sb)
164
{
165
	char *this_char, *value, *optn;
166
	int f;
167
168
	if (!options)
169
		return 1;
170
	while ((this_char = strsep(&options, ",")) != NULL) {
171
		if (!*this_char)
172
			continue;
173
 		f = 0;
174
		if ((value = strchr(this_char,'=')) != NULL)
175
			*value++ = 0;
176
		if ((optn = "lowercasevol") && !strcmp(this_char, optn)) {
177
			if (value)
178
				goto out_inv_arg;
179
			ASFS_SB(sb)->flags |= ASFS_VOL_LOWERCASE;
180
		} else if ((f = !strcmp(this_char,"setuid")) || !strcmp(this_char,"setgid")) {
181
			if (value) {
182
				if (!*value) {
183
					printk("ASFS: Argument for set[ug]id option missing\n");
184
					return 0;
185
				} else {
186
					(f ? ASFS_SB(sb)->uid : ASFS_SB(sb)->gid) = simple_strtoul(value,&value,0);
187
					if (*value) {
188
						printk("ASFS: Bad set[ug]id argument\n");
189
						return 0;
190
					}
191
				}
192
			}
193
		} else if (!strcmp(this_char,"mode")) {
194
			optn = "mode";
195
			if (!value || !*value)
196
				goto out_no_arg;
197
			ASFS_SB(sb)->mode = simple_strtoul(value,&value,8) & 0777;
198
			if (*value)
199
				return 0;
200
		} else if (!strcmp(this_char,"prefix")) {
201
			optn = "prefix";
202
			if (!value || !*value)
203
				goto out_no_arg;
204
			if (ASFS_SB(sb)->prefix)
205
				kfree(ASFS_SB(sb)->prefix);
206
			ASFS_SB(sb)->prefix = kmalloc(strlen(value) + 1,GFP_KERNEL);
207
			if (!ASFS_SB(sb)->prefix)
208
				return 0;
209
			strcpy(ASFS_SB(sb)->prefix,value);
210
		} else if (!strcmp(this_char,"volume")) {
211
			optn = "volume";
212
			if (!value || !*value)
213
				goto out_no_arg;
214
			if (ASFS_SB(sb)->root_volume)
215
				kfree(ASFS_SB(sb)->root_volume);
216
			ASFS_SB(sb)->root_volume = kmalloc(strlen(value) + 1,GFP_KERNEL);
217
			if (!ASFS_SB(sb)->root_volume)
218
				return 0;
219
			strcpy(ASFS_SB(sb)->root_volume,value);
220
		} else {
221
			printk("ASFS: Unrecognized mount option %s\n", this_char);
222
			return 0;
223
		}
224
	}
225
	return 1;
226
227
out_no_arg:
228
	printk("ASFS: The %s option requires an argument\n", optn);
229
	return 0;
230
out_inv_arg:
231
	printk("ASFS: Option %s does not take an argument\n", optn);
232
	return 0;
233
}
234
235
static int asfs_fill_super(struct super_block *sb, void *data, int silent)
236
{
237
	struct asfs_sb_info *sbi;
238
	struct buffer_head *bh;
239
	struct fsRootBlock *rootblock;
240
241
	sbi = kmalloc(sizeof(struct asfs_sb_info), GFP_KERNEL);
242
	if (!sbi)
243
		return -ENOMEM;
244
	sb->s_fs_info = sbi;
245
246
	/* Fill in defaults */
247
	ASFS_SB(sb)->uid = ASFS_DEFAULT_UID;
248
	ASFS_SB(sb)->gid = ASFS_DEFAULT_GID;
249
	ASFS_SB(sb)->mode = ASFS_DEFAULT_MODE;
250
	ASFS_SB(sb)->prefix = NULL;
251
	ASFS_SB(sb)->root_volume = NULL;
252
	ASFS_SB(sb)->flags = 0;
253
254
	if (!asfs_parse_options(data, sb)) {
255
		printk(KERN_ERR "ASFS: Error parsing options\n");
256
		return -EINVAL;
257
	}
258
259
	if (!sb_set_blocksize(sb, 512))
260
		return -EINVAL;
261
	sb->s_maxbytes = 0x8FFFFFFE;
262
263
	bh = sb_bread(sb, 0);
264
	if (!bh) {
265
		printk(KERN_ERR "ASFS: unable to read superblock\n");
266
		goto outnobh;
267
	}
268
269
	rootblock = (struct fsRootBlock *)bh->b_data;
270
271
	if (be32_to_cpu(rootblock->bheader.id) == ASFS_ROOTID && 
272
		be16_to_cpu(rootblock->version) == ASFS_STRUCTURE_VERISON) {
273
274
		sb->s_blocksize = be32_to_cpu(rootblock->blocksize);
275
		ASFS_SB(sb)->totalblocks = be32_to_cpu(rootblock->totalblocks);
276
		ASFS_SB(sb)->rootobjectcontainer = be32_to_cpu(rootblock->rootobjectcontainer);
277
		ASFS_SB(sb)->extentbnoderoot = be32_to_cpu(rootblock->extentbnoderoot);
278
		ASFS_SB(sb)->objectnoderoot = be32_to_cpu(rootblock->objectnoderoot);
279
		ASFS_SB(sb)->flags |= 0xff & rootblock->bits;
280
#ifdef CONFIG_ASFS_RW
281
		ASFS_SB(sb)->adminspacecontainer = be32_to_cpu(rootblock->adminspacecontainer);
282
		ASFS_SB(sb)->bitmapbase = be32_to_cpu(rootblock->bitmapbase);
283
		ASFS_SB(sb)->blocks_inbitmap = (sb->s_blocksize - sizeof(struct fsBitmap))<<3;  /* must be a multiple of 32 !! */
284
		ASFS_SB(sb)->blocks_bitmap = (ASFS_SB(sb)->totalblocks + ASFS_SB(sb)->blocks_inbitmap - 1) / ASFS_SB(sb)->blocks_inbitmap;
285
		ASFS_SB(sb)->block_rovingblockptr = 0;
286
#endif
287
		asfs_brelse(bh);
288
289
		if (!sb_set_blocksize(sb, sb->s_blocksize)) {
290
			printk(KERN_ERR "ASFS: Found Amiga SFS RootBlock on dev %s, but blocksize %ld is not supported!\n", \
291
			       sb->s_id, sb->s_blocksize);
292
			return -EINVAL;
293
		}
294
295
		bh = sb_bread(sb, 0);
296
		if (!bh) {
297
			printk(KERN_ERR "ASFS: unable to read superblock\n");
298
			goto out;
299
		}
300
		rootblock = (struct fsRootBlock *)bh->b_data;
301
302
		if (asfs_check_block((void *)rootblock, sb->s_blocksize, 0, ASFS_ROOTID)) {
303
#ifdef CONFIG_ASFS_RW
304
			struct buffer_head *tmpbh;
305
			if ((tmpbh = asfs_breadcheck(sb, ASFS_SB(sb)->rootobjectcontainer, ASFS_OBJECTCONTAINER_ID))) {
306
				struct fsRootInfo *ri = (struct fsRootInfo *)((u8 *)tmpbh->b_data + sb->s_blocksize - sizeof(struct fsRootInfo));
307
				ASFS_SB(sb)->freeblocks = be32_to_cpu(ri->freeblocks);
308
				asfs_brelse(tmpbh);
309
			} else
310
				ASFS_SB(sb)->freeblocks = 0;
311
312
			if ((tmpbh = asfs_breadcheck(sb, ASFS_SB(sb)->rootobjectcontainer+2, ASFS_TRANSACTIONFAILURE_ID))) {
313
				printk(KERN_NOTICE "VFS: Found Amiga SFS RootBlock on dev %s, but it has unfinished transaction. Mounting read-only.\n", sb->s_id);
314
				ASFS_SB(sb)->flags |= ASFS_READONLY;
315
				asfs_brelse(tmpbh);
316
			}
317
318
			if ((tmpbh = asfs_breadcheck(sb, ASFS_SB(sb)->totalblocks-1, ASFS_ROOTID)) == NULL) {
319
				printk(KERN_NOTICE "VFS: Found Amiga SFS RootBlock on dev %s, but there is no second RootBlock! Mounting read-only.\n", sb->s_id);
320
				ASFS_SB(sb)->flags |= ASFS_READONLY;
321
				asfs_brelse(tmpbh);
322
			}
323
			if (!(ASFS_SB(sb)->flags &= ASFS_READONLY))
324
				printk(KERN_NOTICE "VFS: Found Amiga SFS RootBlock on dev %s.\n", sb->s_id);
325
#else
326
			ASFS_SB(sb)->freeblocks = 0;
327
			ASFS_SB(sb)->flags |= ASFS_READONLY;
328
			printk(KERN_NOTICE "VFS: Found Amiga SFS RootBlock on dev %s.\n", sb->s_id);
329
#endif
330
		} else {
331
			if (!silent)
332
				printk(KERN_ERR "VFS: Found Amiga SFS RootBlock on dev %s, but it has checksum error!\n", \
333
				       sb->s_id);
334
			goto out;
335
		}
336
	} else {
337
		if (!silent)
338
			printk(KERN_ERR "VFS: Can't find a valid Amiga SFS filesystem on dev %s.\n", \
339
			       sb->s_id);
340
		goto out;
341
	}
342
343
	asfs_brelse(bh);
344
345
	sb->s_magic = ASFS_MAGIC;
346
	sb->s_flags |= MS_NODEV | MS_NOSUID;
347
	if (ASFS_SB(sb)->flags & ASFS_READONLY) 
348
		sb->s_flags |= MS_RDONLY;
349
	sb->s_op = &asfs_ops;
350
	sb->s_root = d_alloc_root(asfs_get_root_inode(sb));
351
	if (!sb->s_root)
352
		goto outnobh;
353
	sb->s_root->d_op = &asfs_dentry_operations;
354
355
	/* Ehrhm; sorry.. :) */
356
	if (0) {
357
out:
358
		asfs_brelse(bh);
359
outnobh:
360
		return -EINVAL;
361
	}
362
	return 0;
363
}
364
365
#ifdef CONFIG_ASFS_RW
366
int asfs_remount(struct super_block *sb, int *flags, char *data)
367
{
368
	asfs_debug("ASFS: remount (flags=0x%x, opts=\"%s\")\n",*flags,data);
369
370
	if (!asfs_parse_options(data,sb))
371
		return -EINVAL;
372
373
	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
374
		return 0;
375
376
	if (*flags & MS_RDONLY) {
377
		sb->s_flags |= MS_RDONLY;
378
	} else if (!(ASFS_SB(sb)->flags & ASFS_READONLY)) {
379
		sb->s_flags &= ~MS_RDONLY;
380
	} else {
381
		printk("VFS: Can't remount Amiga SFS on dev %s read/write because of errors.", sb->s_id);
382
		return -EINVAL;
383
	}
384
	return 0;
385
}
386
#endif
387
388
void asfs_put_super(struct super_block *sb)
389
{
390
	struct asfs_sb_info *sbi = ASFS_SB(sb);
391
392
	if (ASFS_SB(sb)->prefix)
393
		kfree(ASFS_SB(sb)->prefix);
394
395
	kfree(sbi);
396
	sb->s_fs_info = NULL;
397
	return;
398
}
399
400
/* That's simple too. */
401
402
int asfs_statfs(struct super_block *sb, struct kstatfs *buf)
403
{
404
	buf->f_type = ASFS_MAGIC;
405
	buf->f_bsize = sb->s_blocksize;
406
	buf->f_bfree = buf->f_bavail = ASFS_SB(sb)->freeblocks;
407
	buf->f_blocks = ASFS_SB(sb)->totalblocks;
408
	buf->f_namelen = ASFS_MAXFN;
409
	return 0;
410
}
411
412
/* --- new in 2.6.x --- */
413
static kmem_cache_t * asfs_inode_cachep;
414
415
struct inode *asfs_alloc_inode(struct super_block *sb)
416
{
417
	struct asfs_inode_info *ei;
418
	ei = (struct asfs_inode_info *)kmem_cache_alloc(asfs_inode_cachep, SLAB_KERNEL);
419
	if (!ei)
420
		return NULL;
421
	return &ei->vfs_inode;
422
}
423
424
void asfs_destroy_inode(struct inode *inode)
425
{
426
	kmem_cache_free(asfs_inode_cachep, ASFS_I(inode));
427
}
428
429
static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
430
{
431
	struct asfs_inode_info *ei = (struct asfs_inode_info *) foo;
432
433
	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
434
	    SLAB_CTOR_CONSTRUCTOR) {
435
		inode_init_once(&ei->vfs_inode);
436
	}
437
}
438
439
static int init_inodecache(void)
440
{
441
	asfs_inode_cachep = kmem_cache_create("asfs_inode_cache",
442
					     sizeof(struct asfs_inode_info),
443
					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
444
					     init_once, NULL);
445
	if (asfs_inode_cachep == NULL)
446
		return -ENOMEM;
447
	return 0;
448
}
449
450
static void destroy_inodecache(void)
451
{
452
	if (kmem_cache_destroy(asfs_inode_cachep))
453
		printk(KERN_INFO "asfs_inode_cache: not all structures were freed\n");
454
}
455
456
static struct super_block *asfs_get_sb(struct file_system_type *fs_type,
457
	int flags, const char *dev_name, void *data)
458
{
459
	return get_sb_bdev(fs_type, flags, dev_name, data, asfs_fill_super);
460
}
461
462
static struct file_system_type asfs_fs_type = {
463
	.owner		= THIS_MODULE,
464
	.name		= "asfs",
465
	.get_sb		= asfs_get_sb,
466
	.kill_sb	= kill_block_super,
467
	.fs_flags	= FS_REQUIRES_DEV,
468
};
469
470
static int __init init_asfs_fs(void)
471
{
472
	int err = init_inodecache();
473
	if (err)
474
		goto out1;
475
	err = register_filesystem(&asfs_fs_type);
476
	if (err)
477
		goto out;
478
	return 0;
479
out:
480
	destroy_inodecache();
481
out1:
482
	return err;
483
}
484
485
static void __exit exit_asfs_fs(void)
486
{
487
	unregister_filesystem(&asfs_fs_type);
488
	destroy_inodecache();
489
}
490
491
/* Yes, works even as a module... :) */
492
493
#ifdef CONFIG_ASFS_RW
494
MODULE_DESCRIPTION("Amiga Smart File System (read/write) support for Linux kernel 2.6.x v1.0beta4 (12.04.2004)");
495
#else
496
MODULE_DESCRIPTION("Amiga Smart File System (read-only) support for Linux kernel 2.6.x v1.0beta4 (12.04.2004)");
497
#endif
498
MODULE_LICENSE("GPL");
499
MODULE_AUTHOR("Marek Szyprowski <marek@amiga.pl>");
500
501
module_init(init_asfs_fs)
502
module_exit(exit_asfs_fs)
(-)kernel-source-2.6.5/fs/asfs/symlink.c (+227 lines)
Line 0 Link Here
1
/*
2
 *
3
 * Amiga Smart File System, Linux implementation
4
 * version: 1.0beta3
5
 *  
6
 * Copyright (C) 2003,2004  Marek 'March' Szyprowski <marek@amiga.pl>
7
 *
8
 *
9
 * This program is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU General Public License
11
 * as published by the Free Software Foundation; either version
12
 * 2 of the License, or (at your option) any later version.
13
 *
14
 */
15
16
#include <linux/types.h>
17
#include <linux/errno.h>
18
#include <linux/slab.h>
19
#include <linux/asfs_fs.h>
20
#include <linux/fs.h>
21
#include <linux/buffer_head.h>
22
#include <linux/vfs.h>
23
#include <linux/pagemap.h>
24
25
#include <asm/byteorder.h>
26
#include <asm/uaccess.h>
27
28
extern struct address_space_operations asfs_symlink_aops;
29
30
int asfs_symlink_readpage(struct file *file, struct page *page)
31
{
32
	struct buffer_head *bh;
33
	struct fsSoftLink *slinkcont;
34
	struct inode *inode = page->mapping->host;
35
	struct super_block *sb = inode->i_sb;
36
	char *link = kmap(page);
37
	int i = 0, j = 0;
38
	char c, lc = 0, *prefix, *lf, *p;
39
40
	if (!(bh = asfs_breadcheck(sb, ASFS_I(inode)->firstblock, ASFS_SOFTLINK_ID))) {
41
		SetPageError(page);
42
		kunmap(page);
43
		unlock_page(page);
44
		return -EIO;
45
	}
46
	slinkcont = (struct fsSoftLink *) bh->b_data;
47
48
	lf = slinkcont->string;
49
	prefix = ASFS_SB(sb)->prefix ? ASFS_SB(sb)->prefix : "/";
50
51
	if ((p = strchr(lf,':'))) {	/* Handle assign or volume name */
52
		if (ASFS_SB(sb)->root_volume &&
53
		    strncmp(lf, ASFS_SB(sb)->root_volume, strlen(ASFS_SB(sb)->root_volume)) == 0) {
54
			/* global root volume name found */
55
			link[i++] = '/';
56
			lf = p+1;
57
		} else {
58
			/* adding volume prefix */ 
59
			while (i < 1023 && (c = prefix[i]))
60
				link[i++] = c;
61
			if (ASFS_SB(sb)->flags & ASFS_VOL_LOWERCASE) {
62
				while (i < 1023 && lf[j] != ':')
63
					link[i++] = asfs_lowerchar(lf[j++]);
64
			} else {
65
				while (i < 1023 && lf[j] != ':')
66
					link[i++] = lf[j++];
67
			}
68
			if (i < 1023)
69
				link[i++] = '/';
70
			j++;
71
		}
72
		lc = '/';
73
	}
74
75
	while (i < 1023 && (c = lf[j])) {
76
		if (c == '/' && lc == '/' && i < 1020) {	/* parent dir */
77
			link[i++] = '.';
78
			link[i++] = '.';
79
		}
80
		link[i++] = c;
81
		lc = c;
82
		j++;
83
	}
84
	link[i] = '\0';
85
	SetPageUptodate(page);
86
	kunmap(page);
87
	unlock_page(page);
88
	asfs_brelse(bh);
89
	return 0;
90
}
91
92
#ifdef CONFIG_ASFS_RW
93
94
int asfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
95
{
96
	int error;
97
	struct super_block *sb = dir->i_sb;
98
	struct inode *inode;
99
	struct buffer_head *bh, *dir_bh;
100
	struct fsObject obj_data, *dir_obj, *obj;
101
	u8 *name = (u8 *) dentry->d_name.name;
102
	struct fsSoftLink *slinkcont;
103
	char			*p;
104
	int			 i, maxlen, pflen;
105
	char			 c, lc;
106
107
	asfs_debug("asfs_symlink %s in dir node %d\n", name, (int)dir->i_ino);
108
109
	sb = dir->i_sb;
110
	inode = new_inode(sb);
111
	if (!inode)
112
		return -ENOMEM;
113
114
	inode->i_mode = S_IFLNK | S_IRWXUGO;
115
	inode->i_uid = current->fsuid;
116
	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
117
	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
118
	inode->i_blocks = inode->i_blksize = inode->i_size = 0;
119
120
	inode->i_op = &page_symlink_inode_operations;
121
	inode->i_mapping->a_ops = &asfs_symlink_aops;
122
123
	memset(&obj_data, 0, sizeof(struct fsObject));
124
125
	obj_data.protection = cpu_to_be32(FIBF_READ|FIBF_WRITE|FIBF_EXECUTE|FIBF_DELETE);
126
	obj_data.datemodified = cpu_to_be32(inode->i_mtime.tv_sec - (365*8+2)*24*60*60);
127
	obj_data.bits = OTYPE_LINK;
128
129
	lock_super(sb);
130
131
	if ((error = readobject(sb, dir->i_ino, &dir_bh, &dir_obj)) != 0) {
132
		dec_count(inode);
133
		unlock_super(sb);
134
		return error;
135
	}
136
137
	bh = dir_bh;
138
	obj = dir_obj;
139
140
	if ((error = createobject(sb, &bh, &obj, &obj_data, name, FALSE)) != 0) {
141
		asfs_brelse(dir_bh);
142
		dec_count(inode);
143
		unlock_super(sb);
144
		return error;
145
	}
146
147
	inode->i_ino = be32_to_cpu(obj->objectnode);
148
	ASFS_I(inode)->firstblock = be32_to_cpu(obj->object.file.data);
149
	asfs_bstore(sb, bh);
150
151
	insert_inode_hash(inode);
152
	mark_inode_dirty(inode);
153
154
	d_instantiate(dentry, inode);
155
	ASFS_I(dir)->firstblock = be32_to_cpu(dir_obj->object.dir.firstdirblock);
156
	ASFS_I(dir)->modified = 1;
157
	dir->i_mtime = dir->i_ctime = inode->i_mtime;
158
	dir_obj->datemodified = cpu_to_be32(inode->i_mtime.tv_sec - (365*8+2)*24*60*60);
159
	asfs_bstore(sb, dir_bh); 
160
161
	asfs_brelse(dir_bh);
162
	asfs_brelse(bh);
163
164
	if (!(bh = asfs_breadcheck(sb, ASFS_I(inode)->firstblock, ASFS_SOFTLINK_ID))) {
165
		unlock_super(sb);
166
		return -EIO;
167
	}
168
	slinkcont = (struct fsSoftLink *) bh->b_data;
169
170
	/* translating symlink target path */
171
172
	maxlen = sb->s_blocksize - sizeof(struct fsSoftLink) - 2;
173
	i  = 0;
174
	p  = slinkcont->string;
175
	lc = '/';
176
177
	if (*symname == '/') {
178
		while (*symname == '/')
179
			symname++;
180
		if (ASFS_SB(sb)->prefix &&
181
		    strncmp(symname-1, ASFS_SB(sb)->prefix, (pflen = strlen(ASFS_SB(sb)->prefix))) == 0) {
182
			/* found volume prefix, ommiting it */
183
			symname += pflen;
184
			while ((c = *symname++) != '/' && c != '\0') {
185
				*p++ = c;
186
				i++;
187
			}
188
			*p++ = ':';
189
		} else if (ASFS_SB(sb)->root_volume) {	/* adding root volume name */
190
			while (ASFS_SB(sb)->root_volume[i])
191
				*p++ = ASFS_SB(sb)->root_volume[i++];
192
			*p++ = ':';
193
		} else {	/* do nothing */
194
			*p++ = '/';
195
		}
196
		i++;
197
	}
198
199
	while (i < maxlen && (c = *symname++)) {
200
		if (c == '.' && lc == '/' && *symname == '.' && symname[1] == '/') {
201
			*p++ = '/';
202
			i++;
203
			symname += 2;
204
			lc = '/';
205
		} else if (c == '.' && lc == '/' && *symname == '/') {
206
			symname++;
207
			lc = '/';
208
		} else {
209
			*p++ = c;
210
			lc   = c;
211
			i++;
212
		}
213
		if (lc == '/')
214
			while (*symname == '/')
215
				symname++;
216
	}
217
	*p = 0;
218
219
	asfs_bstore(sb, bh);
220
	asfs_brelse(bh);
221
222
	unlock_super(sb);
223
	
224
	return 0;
225
}
226
227
#endif
(-)kernel-source-2.6.5/fs/Kconfig (+34 lines)
Lines 966-971 Link Here
966
	  To compile this file system support as a module, choose M here: the
966
	  To compile this file system support as a module, choose M here: the
967
	  module will be called affs.  If unsure, say N.
967
	  module will be called affs.  If unsure, say N.
968
968
969
config ASFS_FS
970
	tristate "Amiga SFS file system support (EXPERIMENTAL)"
971
	depends on EXPERIMENTAL
972
	help
973
974
	  The Amiga Smart FileSystem (SFS) is the file system used on hard 
975
	  disks by Amiga(tm) and MorphOS(tm) systems.  Say Y if you want 
976
	  to be able to read files from an Amiga SFS partition on your hard 
977
	  drive.
978
979
	  This file system driver is in EXPERIMENTAL state. Use it with care.
980
	  It MIGHT cause a crash in some circumstances.
981
982
	  For more information read <file:Documentation/filesystems/asfs.txt>
983
984
	  This file system is also available as a module ( = code which can be
985
	  inserted in and removed from the running kernel whenever you want).
986
	  The module is called asfs.o.  If you want to compile it as a module,
987
	  say M here and read <file:Documentation/modules.txt>.
988
989
	  If unsure, say N.
990
991
config ASFS_RW
992
	bool "Amiga SFS write support (DANGEROUS)"
993
	depends on ASFS_FS
994
	help
995
996
	  If you say Y here, you will be able to write to ASFS file
997
	  systems as well as read from them. The read-write support in ASFS
998
	  is in early beta stage. This means that useing it to write files 
999
	  to SFS partitions is DANGEROUS and COULD corrupt the filesystem. 
1000
1001
	  If unsure, say N.
1002
969
config HFS_FS
1003
config HFS_FS
970
	tristate "Apple Macintosh file system support (EXPERIMENTAL)"
1004
	tristate "Apple Macintosh file system support (EXPERIMENTAL)"
971
	depends on EXPERIMENTAL
1005
	depends on EXPERIMENTAL
(-)kernel-source-2.6.5/fs/Makefile (+1 lines)
Lines 81-86 Link Here
81
obj-$(CONFIG_JFFS_FS)		+= jffs/
81
obj-$(CONFIG_JFFS_FS)		+= jffs/
82
obj-$(CONFIG_JFFS2_FS)		+= jffs2/
82
obj-$(CONFIG_JFFS2_FS)		+= jffs2/
83
obj-$(CONFIG_AFFS_FS)		+= affs/
83
obj-$(CONFIG_AFFS_FS)		+= affs/
84
obj-$(CONFIG_ASFS_FS)		+= asfs/
84
obj-$(CONFIG_ROMFS_FS)		+= romfs/
85
obj-$(CONFIG_ROMFS_FS)		+= romfs/
85
obj-$(CONFIG_QNX4FS_FS)		+= qnx4/
86
obj-$(CONFIG_QNX4FS_FS)		+= qnx4/
86
obj-$(CONFIG_AUTOFS_FS)		+= autofs/
87
obj-$(CONFIG_AUTOFS_FS)		+= autofs/
(-)kernel-source-2.6.5/include/linux/asfs_fs.h (+455 lines)
Line 0 Link Here
1
#ifndef __LINUX_ASFS_FS_H
2
#define __LINUX_ASFS_FS_H
3
4
#include <linux/types.h>
5
#include <asm/byteorder.h>
6
7
#define asfs_debug(fmt,arg...) /* no debug at all */
8
//#define asfs_debug(fmt,arg...) printk(fmt,##arg)  /* general debug infos */
9
10
#if !defined (__BIG_ENDIAN) && !defined (__LITTLE_ENDIAN)
11
#error Endianes must be known for ASFS to work. Sorry.
12
#endif
13
14
/* some helper macros... */
15
#define ASFS_MAKE_ID(a,b,c,d) (((a)&0xff)<<24|((b)&0xff)<<16|((c)&0xff)<<8|((d)&0xff))
16
17
/* Amiga SFS block IDs */
18
#define ASFS_ROOTID                 ASFS_MAKE_ID('S','F','S','\0')
19
#define ASFS_OBJECTCONTAINER_ID     ASFS_MAKE_ID('O','B','J','C')
20
#define ASFS_BNODECONTAINER_ID      ASFS_MAKE_ID('B','N','D','C')
21
#define ASFS_NODECONTAINER_ID       ASFS_MAKE_ID('N','D','C',' ')
22
#define ASFS_HASHTABLE_ID           ASFS_MAKE_ID('H','T','A','B')
23
#define ASFS_SOFTLINK_ID            ASFS_MAKE_ID('S','L','N','K')
24
#define ASFS_ADMINSPACECONTAINER_ID ASFS_MAKE_ID('A','D','M','C')
25
#define ASFS_BITMAP_ID              ASFS_MAKE_ID('B','T','M','P')
26
#define ASFS_TRANSACTIONFAILURE_ID  ASFS_MAKE_ID('T','R','F','A')
27
28
/* Amiga SFS defines and magic values */
29
30
#define ASFS_MAGIC 0xa0ff
31
#define ASFS_MAXFN (105u)
32
33
#define ASFS_DEFAULT_UID 0
34
#define ASFS_DEFAULT_GID 0
35
#define ASFS_DEFAULT_MODE 0644	/* default permission bits for files, dirs have same permission, but with "x" set */
36
37
#define ASFS_STRUCTURE_VERISON (3)
38
#define ASFS_BLCKFACCURACY	(5)
39
40
#define ASFS_ROOTBITS_CASESENSITIVE (128)
41
#define ASFS_READONLY (512)
42
#define ASFS_VOL_LOWERCASE (1024)
43
44
#define ASFS_ROOTNODE   (1)
45
#define ASFS_RECYCLEDNODE (2)
46
47
#define OTYPE_HIDDEN      (1)
48
#define OTYPE_HARDLINK    (32)
49
#define OTYPE_LINK        (64)
50
#define OTYPE_DIR         (128)
51
52
#define MSB_MASK (1ul << 31)
53
54
#define NODE_STRUCT_SIZE (10)	/* (sizeof(struct fsObjectNode)) */
55
#define NODECONT_BLOCK_COUNT ((sb->s_blocksize - sizeof(struct fsNodeContainer)) / sizeof(u32))
56
57
#define ASFS_ALWAYSFREE (16)		/* keep this amount of blocks free */
58
59
#define ASFS_BLOCKCHUNKS (16)		/* try to allocate this number of blocks in one request */
60
61
#ifndef TRUE
62
#define TRUE		1
63
#endif
64
#ifndef FALSE
65
#define FALSE		0
66
#endif
67
68
/* amigados protection bits */
69
70
#define FIBB_SCRIPT    6	/* program is a script (execute) file */
71
#define FIBB_PURE      5	/* program is reentrant and rexecutable */
72
#define FIBB_ARCHIVE   4	/* cleared whenever file is changed */
73
#define FIBB_READ      3	/* ignored by old filesystem */
74
#define FIBB_WRITE     2	/* ignored by old filesystem */
75
#define FIBB_EXECUTE   1	/* ignored by system, used by Shell */
76
#define FIBB_DELETE    0	/* prevent file from being deleted */
77
78
#define FIBF_SCRIPT    (1<<FIBB_SCRIPT)
79
#define FIBF_PURE      (1<<FIBB_PURE)
80
#define FIBF_ARCHIVE   (1<<FIBB_ARCHIVE)
81
#define FIBF_READ      (1<<FIBB_READ)
82
#define FIBF_WRITE     (1<<FIBB_WRITE)
83
#define FIBF_EXECUTE   (1<<FIBB_EXECUTE)
84
#define FIBF_DELETE    (1<<FIBB_DELETE)
85
86
/* name hashing macro */
87
88
#define HASHCHAIN(x) (u16)(x % (u16)(((sb->s_blocksize) - sizeof(struct fsHashTable))>>2))
89
90
/* Each block has its own header with checksum and id, its called fsBlockHeader */
91
92
struct fsBlockHeader {
93
	u32 id;			/* 4 character id string of this block */
94
	u32 checksum;		/* The checksum */
95
	u32 ownblock;		/* The blocknumber of the block this block is stored at */
96
};
97
98
/* On-disk "super block", called fsRootBlock */
99
100
struct fsRootBlock {
101
	struct fsBlockHeader bheader;
102
103
	u16 version;		/* Version number of the filesystem block structure */
104
	u16 sequencenumber;	/* The Root with the highest sequencenumber is valid */
105
106
	u32 datecreated;	/* Creation date (when first formatted).  Cannot be changed. */
107
	u8 bits;		/* various settings, see defines below. */
108
	u8 pad1;
109
	u16 pad2;
110
111
	u32 reserved1[2];
112
113
	u32 firstbyteh;		/* The first byte of our partition from the start of the */
114
	u32 firstbyte;		/* disk.  firstbyteh = upper 32 bits, firstbyte = lower 32 bits. */
115
116
	u32 lastbyteh;		/* The last byte of our partition, excluding this one. */
117
	u32 lastbyte;
118
119
	u32 totalblocks;	/* size of this partition in blocks */
120
	u32 blocksize;		/* blocksize used */
121
122
	u32 reserved2[2];
123
	u32 reserved3[8];
124
125
	u32 bitmapbase;		/* location of the bitmap */
126
	u32 adminspacecontainer;	/* location of first adminspace container */
127
	u32 rootobjectcontainer;	/* location of the root objectcontainer */
128
	u32 extentbnoderoot;	/* location of the root of the extentbnode B-tree */
129
	u32 objectnoderoot;	/* location of the root of the objectnode tree */
130
131
	u32 reserved4[3];
132
};
133
134
/* On disk inode, called fsObject */
135
136
struct fsObject {
137
	u16 owneruid;
138
	u16 ownergid;
139
	u32 objectnode;
140
	u32 protection;
141
142
	union {
143
		struct {
144
			u32 data;
145
			u32 size;
146
		} file;
147
148
		struct {
149
			u32 hashtable;	/* for directories & root, 0 means no hashblock */
150
			u32 firstdirblock;
151
		} dir;
152
	} object;
153
154
	u32 datemodified;
155
	u8 bits;
156
157
	u8 name[0];
158
	u8 comment[0];
159
};
160
161
/* On disk block containging a number of fsObjects */
162
163
struct fsObjectContainer {
164
	struct fsBlockHeader bheader;
165
166
	u32 parent;
167
	u32 next;
168
	u32 previous;		/* 0 for the first block in the directory chain */
169
170
	struct fsObject object[0];
171
};
172
173
/* BTree structures, used to collect file data position on disk */
174
175
struct fsExtentBNode {
176
	u32 key;		/* data! */
177
	u32 next;
178
	u32 prev;
179
	u16 blocks;		/* The size in blocks of the region this Extent controls */
180
};
181
182
struct BNode {
183
	u32 key;
184
	u32 data;
185
};
186
187
struct BTreeContainer {
188
	u16 nodecount;
189
	u8 isleaf;
190
	u8 nodesize;		/* Must be a multiple of 2 */
191
192
	struct BNode bnode[0];
193
};
194
195
/* On disk block with BTreeContainer */
196
197
struct fsBNodeContainer {
198
	struct fsBlockHeader bheader;
199
	struct BTreeContainer btc;
200
};
201
202
/* On disk block  with soft link data */
203
204
struct fsSoftLink {
205
	struct fsBlockHeader bheader;
206
	u32 parent;
207
	u32 next;
208
	u32 previous;
209
	u8 string[0];
210
};
211
212
/* On disk block with hashtable data */
213
214
struct fsHashTable {
215
	struct fsBlockHeader bheader;
216
	u32 parent;
217
	u32 hashentry[0];
218
};
219
220
/* On disk block with node index and some helper structures */
221
222
struct fsNodeContainer {
223
	struct fsBlockHeader bheader;
224
	u32 nodenumber;
225
	u32 nodes;
226
	u32 node[0];
227
};
228
229
struct fsNode {
230
	u32 data;
231
};
232
233
struct fsObjectNode {
234
	struct fsNode node;
235
	u32 next;
236
	u16 hash16;
237
} __attribute__ ((packed));
238
239
/* Some adminspace and bitmap block structures */
240
241
struct fsAdminSpace {
242
	u32 space;
243
	u32 bits;		
244
/* Set bits are used blocks, bit 31 is	the first block in the AdminSpace. */
245
};
246
247
struct fsAdminSpaceContainer {
248
	struct fsBlockHeader bheader;
249
250
	u32 next;
251
	u32 previous;
252
253
	u8 bits;
254
	u8 pad1;
255
	u16 pad2;
256
257
	struct fsAdminSpace adminspace[0];
258
};
259
260
struct fsBitmap {
261
	struct fsBlockHeader bheader;
262
263
	u32 bitmap[0];
264
265
/* Bits are 1 if the block is free, and 0 if full.
266
   Bitmap must consist of an integral number of longwords. */
267
};
268
269
/* The fsRootInfo structure has all kinds of information about the format
270
   of the disk. */
271
272
struct fsRootInfo {
273
	u32 deletedblocks;	/* Amount in blocks which deleted files consume. */
274
	u32 deletedfiles;	/* Number of deleted files in recycled. */
275
	u32 freeblocks;		/* Cached number of free blocks on disk. */
276
277
	u32 datecreated;
278
279
	u32 lastallocatedblock;	/* Block which was most recently allocated */
280
	u32 lastallocatedadminspace;	/* AdminSpaceContainer which most recently was used to allocate a block */
281
	u32 lastallocatedextentnode;	/* ExtentNode which was most recently created */
282
	u32 lastallocatedobjectnode;	/* ObjectNode which was most recently created */
283
284
	u32 rovingpointer;
285
};
286
287
288
#ifdef __KERNEL__
289
290
#include <linux/fs.h>
291
#include <linux/buffer_head.h>
292
293
#include <linux/asfs_fs_i.h>
294
#include <linux/asfs_fs_sb.h>
295
 
296
/* io inline code */
297
298
u32 asfs_calcchecksum(void *block, u32 blocksize);
299
300
static inline int
301
asfs_check_block(struct fsBlockHeader *block, u32 blocksize, u32 n, u32 id)
302
{
303
	if (asfs_calcchecksum(block, blocksize) ==
304
	    be32_to_cpu(((struct fsBlockHeader *) block)->checksum) &&
305
	    n == be32_to_cpu(((struct fsBlockHeader *) block)->ownblock) &&
306
	    id == be32_to_cpu(((struct fsBlockHeader *) block)->id))
307
		return 1;
308
	return 0;
309
}
310
311
/* get fs structure from block and do some checks... */
312
static inline struct buffer_head *
313
asfs_breadcheck(struct super_block *sb, u32 n, u32 type)
314
{
315
	struct buffer_head *bh;
316
	if ((bh = sb_bread(sb, n))) {
317
		if (asfs_check_block ((void *)bh->b_data, sb->s_blocksize, n, type)) {
318
			return bh;	/* all okay */
319
		}
320
		brelse(bh);
321
	}
322
	return NULL;		/* error */
323
}
324
325
static inline struct buffer_head *
326
asfs_getzeroblk(struct super_block *sb, int block)
327
{
328
	struct buffer_head *bh;
329
	bh = sb_getblk(sb, block);
330
	lock_buffer(bh);
331
	memset(bh->b_data, 0, sb->s_blocksize);
332
	set_buffer_uptodate(bh);
333
	unlock_buffer(bh);
334
	return bh;
335
}
336
337
static inline void 
338
asfs_bstore(struct super_block *sb, struct buffer_head *bh)
339
{
340
	((struct fsBlockHeader *) (bh->b_data))->checksum =
341
	    cpu_to_be32(asfs_calcchecksum(bh->b_data, sb->s_blocksize));
342
	mark_buffer_dirty(bh);
343
}
344
345
static inline void asfs_brelse(struct buffer_head *bh)
346
{
347
	brelse(bh);
348
}
349
350
static inline void dec_count(struct inode *inode)
351
{
352
	inode->i_nlink--;
353
	mark_inode_dirty(inode);
354
}
355
356
/* all prototypes */
357
358
/* adminspace.c */
359
int allocadminspace(struct super_block *sb, u32 * block);
360
int freeadminspace(struct super_block *sb, u32 block);
361
int markspace(struct super_block *sb, u32 block, u32 blocks);
362
int freespace(struct super_block *sb, u32 block, u32 blocks);
363
int findspace(struct super_block *sb, u32 maxneeded, u32 start, u32 end,
364
	      u32 * returned_block, u32 * returned_blocks);
365
366
/* bitfuncs.c */
367
s16 bfffz(u32, s16);
368
/* bm??? functions assumes that in-memory bitmap is in bigendian byte order */
369
s32 bmffo(u32 *, s32, s32);
370
s32 bmffz(u32 *, s32, s32);
371
s32 bmclr(u32 *, s32, s32, s32);
372
s32 bmset(u32 *, s32, s32, s32);
373
374
/* dir.c */
375
int asfs_readdir(struct file *filp, void *dirent, filldir_t filldir);
376
struct dentry *asfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd);
377
378
/* extents.c */
379
int getextent(struct super_block *sb, u32 key, struct buffer_head **ret_bh,
380
	      struct fsExtentBNode **ret_ebn);
381
int deletebnode(struct super_block *sb, struct buffer_head *cb, u32 key);
382
int deleteextents(struct super_block *sb, u32 key);
383
int addblocks(struct super_block *sb, u16 blocks, u32 newspace,
384
	      u32 objectnode, u32 * io_lastextentbnode);
385
386
/* file.c */
387
int asfs_readpage(struct file *file, struct page *page);
388
sector_t asfs_bmap(struct address_space *mapping, sector_t block);
389
int asfs_writepage(struct page *page, struct writeback_control *wbc);
390
int asfs_prepare_write(struct file *file, struct page *page, unsigned from,
391
		       unsigned to);
392
void asfs_truncate(struct inode *inode);
393
int asfs_file_open(struct inode *inode, struct file *filp);
394
int asfs_file_release(struct inode *inode, struct file *filp);
395
396
/* inode.c */
397
struct inode *asfs_get_root_inode(struct super_block *sb);
398
void asfs_read_locked_inode(struct inode *inode, void *arg);
399
int asfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd);
400
int asfs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
401
int asfs_rmdir(struct inode *dir, struct dentry *dentry);
402
int asfs_delete(struct inode *dir, struct dentry *dentry);
403
int asfs_rename(struct inode *old_dir, struct dentry *old_dentry,
404
		struct inode *new_dir, struct dentry *new_dentry);
405
int asfs_notify_change(struct dentry *dentry, struct iattr *attr);
406
407
/* namei */
408
u8 asfs_lowerchar(u8 c);
409
int asfs_namecmp(u8 *s, u8 *ct, int casesensitive);
410
u16 asfs_hash(u8 *name, int casesensitive);
411
412
/* nodes */
413
int getnode(struct super_block *sb, u32 nodeno,
414
	    struct buffer_head **ret_bh, struct fsObjectNode **ret_node);
415
int createnode(struct super_block *sb, struct buffer_head **returned_cb,
416
	       struct fsNode **returned_node, u32 * returned_nodeno);
417
int deletenode(struct super_block *sb, u32 objectnode);
418
419
/* objects */
420
struct fsObject *asfs_nextobject(struct fsObject *obj);
421
struct fsObject *find_obj_by_name(struct super_block *sb,
422
				  struct fsObjectContainer *objcont,
423
				  u8 * name);
424
int readobject(struct super_block *sb, u32 objectnode,
425
	       struct buffer_head **cb, struct fsObject **returned_object);
426
int createobject(struct super_block *sb, struct buffer_head **io_cb,
427
		 struct fsObject **io_o, struct fsObject *src_o,
428
		 u8 * objname, int force);
429
int deleteobject(struct super_block *sb, struct buffer_head *cb,
430
		 struct fsObject *o);
431
int renameobject(struct super_block *sb, struct buffer_head *cb1,
432
		 struct fsObject *o1, struct buffer_head *cbparent,
433
		 struct fsObject *oparent, u8 * newname);
434
435
int addblockstofile(struct super_block *sb, struct buffer_head *objcb,
436
		    struct fsObject *o, u32 blocks, u32 * newspace,
437
		    u32 * addedblocks);
438
int truncateblocksinfile(struct super_block *sb, struct buffer_head *bh,
439
			 struct fsObject *o, u32 newsize);
440
441
/* super.c */
442
struct super_block *asfs_read_super(struct super_block *sb, void *data,
443
				    int silent);
444
void asfs_put_super(struct super_block *sb);
445
int asfs_statfs(struct super_block *sb, struct kstatfs *buf);
446
int asfs_remount(struct super_block *sb, int *flags, char *data);
447
struct inode *asfs_alloc_inode(struct super_block *sb);
448
void asfs_destroy_inode(struct inode *inode);
449
450
/* symlink.c */
451
int asfs_symlink_readpage(struct file *file, struct page *page);
452
int asfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
453
454
#endif				/* __KERNEL__ */
455
#endif
(-)kernel-source-2.6.5/include/linux/asfs_fs_i.h (+32 lines)
Line 0 Link Here
1
#ifndef __ASFS_FS_I
2
#define __ASFS_FS_I
3
4
/* Extent structure located in RAM (e.g. inside inode structure), 
5
   currently used to store last used extent */
6
7
struct inramExtent {
8
	u32 startblock;	/* Block from begginig of the file */
9
	u32 key;
10
	u32 next;
11
	u16 blocks;
12
};
13
14
/* inode in-kernel data */
15
16
struct asfs_inode_info {
17
	u32 firstblock;
18
	u32 hashtable;
19
	int modified;
20
	u32 i_opencnt;
21
	loff_t mmu_private;
22
	struct inramExtent ext_cache;
23
	struct inode vfs_inode;
24
};
25
26
/* short cut to get to the asfs specific inode data */
27
static inline struct asfs_inode_info *ASFS_I(struct inode *inode)
28
{
29
   return list_entry(inode, struct asfs_inode_info, vfs_inode);
30
}
31
32
#endif
(-)kernel-source-2.6.5/include/linux/asfs_fs_sb.h (+33 lines)
Line 0 Link Here
1
#ifndef __ASFS_FS_SB
2
#define __ASFS_FS_SB
3
4
/* Amiga SFS superblock in-core data */
5
6
struct asfs_sb_info {
7
	u32 totalblocks;
8
	u32 rootobjectcontainer;
9
	u32 extentbnoderoot;
10
	u32 objectnoderoot;
11
12
	u32 adminspacecontainer;
13
	u32 bitmapbase;
14
	u32 freeblocks;
15
	u32 blocks_inbitmap;
16
	u32 blocks_bitmap;
17
	u32 block_rovingblockptr;
18
19
	uid_t uid;
20
	gid_t gid;
21
	umode_t mode;
22
	u16 flags;
23
	char *prefix;
24
	char *root_volume;		/* Volume prefix for absolute symlinks. */
25
};
26
27
/* short cut to get to the asfs specific sb data */
28
static inline struct asfs_sb_info *ASFS_SB(struct super_block *sb)
29
{
30
	return sb->s_fs_info;
31
}
32
33
#endif

Return to bug 54684