]> git.pld-linux.org Git - packages/kernel.git/blob - pramfs-2.6.4.patch
- obsolete
[packages/kernel.git] / pramfs-2.6.4.patch
1 diff -Nuar -X /home/stevel/dontdiff main.orig/Documentation/filesystems/pramfs.txt main/Documentation/filesystems/pramfs.txt
2 --- main.orig/Documentation/filesystems/pramfs.txt      1969-12-31 16:00:00.000000000 -0800
3 +++ main/Documentation/filesystems/pramfs.txt   2004-03-05 09:25:23.000000000 -0800
4 @@ -0,0 +1,176 @@
5 +PRAMFS Overview
6 +===============
7 +
8 +Many embedded systems have a block of non-volatile RAM seperate from
9 +normal system memory, i.e. of which the kernel maintains no memory page
10 +descriptors. For such systems it would be beneficial to mount a
11 +fast read/write filesystem over this "I/O memory", for storing frequently
12 +accessed data that must survive system reboots and power cycles. An
13 +example usage might be system logs under /var/log, or a user address
14 +book in a cell phone or PDA.
15 +
16 +Linux traditionally had no support for a persistent, non-volatile RAM-based
17 +filesystem, persistent meaning the filesystem survives a system reboot
18 +or power cycle intact. The RAM-based filesystems such as tmpfs and ramfs
19 +have no actual backing store but exist entirely in the page and buffer
20 +caches, hence the filesystem disappears after a system reboot or
21 +power cycle.
22 +
23 +A relatively straight-forward solution is to write a simple block driver
24 +for the non-volatile RAM, and mount over it any disk-based filesystem such
25 +as ext2/ext3, reiserfs, etc.
26 +
27 +But the disk-based fs over non-volatile RAM block driver approach has
28 +some drawbacks:
29 +
30 +1. Disk-based filesystems such as ext2/ext3 were designed for optimum
31 +   performance on spinning disk media, so they implement features such
32 +   as block groups, which attempts to group inode data into a contiguous
33 +   set of data blocks to minimize disk seeking when accessing files. For
34 +   RAM there is no such concern; a file's data blocks can be scattered
35 +   throughout the media with no access speed penalty at all. So block
36 +   groups in a filesystem mounted over RAM just adds unnecessary
37 +   complexity. A better approach is to use a filesystem specifically
38 +   tailored to RAM media which does away with these disk-based features.
39 +   This increases the efficient use of space on the media, i.e. more
40 +   space is dedicated to actual file data storage and less to meta-data
41 +   needed to maintain that file data.
42 +
43 +2. If the backing-store RAM is comparable in access speed to system memory,
44 +   there's really no point in caching the file I/O data in the page
45 +   cache. Better to move file data directly between the user buffers
46 +   and the backing store RAM, i.e. use direct I/O. This prevents the
47 +   unnecessary populating of the page cache with dirty pages. However
48 +   direct I/O has to be enabled at every file open. To enable direct
49 +   I/O at all times for all regular files requires either that
50 +   applications be modified to include the O_DIRECT flag on all file
51 +   opens, or that a new filesystem be used that always performs direct
52 +   I/O by default.
53 +    
54 +The Persistent/Protected RAM Special Filesystem (PRAMFS) is a
55 +full-featured read/write filesystem that has been designed to address
56 +these issues. PRAMFS is targeted to fast I/O memory, and if the memory
57 +is non-volatile, the filesystem will be persistent.
58 +
59 +In PRAMFS, direct I/O is enabled across all files in the filesystem, in
60 +other words the O_DIRECT flag is forced on every open of a PRAMFS file.
61 +Also, file I/O in the PRAMFS is always synchronous. There is no need
62 +to block the current process while the transfer to/from the PRAMFS
63 +is in progress, since one of the requirements of the PRAMFS is that the
64 +filesystem exist in fast RAM. So file I/O in PRAMFS is always direct,
65 +synchronous, and never blocks.
66 +
67 +The data organization in PRAMFS can be thought of as an extremely
68 +simplified version of ext2, such that the ratio of data to meta-data is
69 +very high.
70 +
71 +PRAMFS is also write protected. The page table entries that map the
72 +backing-store RAM are normally marked read-only. Write operations into
73 +the filesystem temporarily mark the affected pages as writeable, the
74 +write operation is carried out with locks held, and then the pte is
75 +marked read-only again. This feature provides some protection against
76 +filesystem corruption caused by errant writes into the RAM due to
77 +kernel bugs for instance. In case there are systems where the write
78 +protection is not possible (for instance the RAM cannot be mapped
79 +with page tables), this feature can be disabled with the CONFIG_PRAMFS_NOWP
80 +config option.
81 +
82 +In summary, PRAMFS is a light-weight, full-featured, and space-efficient
83 +special filesystem that is ideal for systems with a block of fast
84 +non-volatile RAM that need to access data on it using a standard
85 +filesytem interface.
86 +
87 +
88 +Supported mount options
89 +=======================
90 +
91 +The PRAMFS currently requires one mount option, and there are several
92 +optional mount options:
93 +
94 +physaddr=      Required. It tells PRAMFS the physical address of the
95 +               start of the RAM that makes up the filesystem. The
96 +               physical address must be located on a page boundary.
97 +
98 +init=          Optional. It is used to initialize the memory to an
99 +               empty filesystem. Any data in an existing filesystem
100 +               will be lost if this option is given. The parameter to
101 +               "init=" is the RAM size in bytes.
102 +
103 +bs=            Optional. It is used to specify a block size. It is
104 +               ignored if the "init=" option is not specified, since
105 +               otherwise the block size is read from the PRAMFS
106 +               super-block. The default blocksize is 2048 bytes,
107 +               and the allowed block sizes are 512, 1024, 2048, and
108 +               4096.
109 +
110 +bpi=           Optional. It is used to specify the bytes per inode
111 +               ratio, i.e. For every N bytes in the filesystem, an
112 +               inode will be created. This behaves the same as the "-i"
113 +               option to mke2fs. It is ignored if the "init=" option is
114 +               not specified.
115 +
116 +N=             Optional. It is used to specify the number of inodes to
117 +               allocate in the inode table. If the option is not
118 +               specified, the bytes-per-inode ratio is used the
119 +               calculate the number of inodes. If neither the "N=" or
120 +               "bpi=" options are specified, the default behavior is to
121 +               reserve 5% of the total space in the filesystem for the
122 +               inode table. This option behaves the same as the "-N"
123 +               option to mke2fs. It is ignored if the "init=" option is
124 +               not specified.
125 +
126 +Examples:
127 +
128 +mount -t pramfs -o physaddr=0x20000000,init=0x2F000,bs=1024 none /mnt/pram
129 +
130 +This example locates the filesystem at physical address 0x20000000, and
131 +also requests an empty filesystem be initialized, of total size 0x2f000
132 +bytes and blocksize 1024. The mount point is /mnt/pram.
133 +
134 +mount -t pramfs -o physaddr=0x20000000 none /mnt/pram
135 +
136 +This example locates the filesystem at physical address 0x20000000 as in
137 +the first example, but uses the intact filesystem that already exists.
138 +
139 +
140 +Current Limitations
141 +===================
142 +
143 +- The RAM used for PRAMFS must be directly addressable.
144 +
145 +- PRAMFS does not support hard links.
146 +
147 +- PRAMFS supports only private memory mappings. This allows most
148 +  executables to run, but programs that attempt shared memory
149 +  mappings, such as X apps that use X shared memory, will fail.
150 +
151 +Further Documentation
152 +=====================
153 +
154 +If you are interested in the internal design of PRAMFS, there is
155 +documentation available at the Sourceforge PRAMFS home page at
156 +http://pramfs.sourceforge.net.
157 +
158 +Please send bug reports/comments/feed back to the pramfs development
159 +list at sourceforge: pramfs-devel@lists.sourceforge.net.
160 +
161 +
162 +ChangeLog
163 +=========
164 +
165 +1.0.2:
166 +       - kernel 2.6.4.
167 +       - use pram_truncate() in pram_delete_inode().
168 +       - dangling pram_lock_inode() removed in pram_truncate_blocks().
169 +       - edits to this README  
170 +
171 +1.0.1:
172 +       - port to kernel 2.6.3.
173 +       - implement direct_IO() method instead of custom file read/write
174 +         methods.
175 +       - do away with __ioremap_readonly() requirement.
176 +       - implement inode truncate() method.
177 +
178 +1.0.0:
179 +       - Started ChangeLog (kernel 2.4.22).
180 +
181 diff -Nuar -X /home/stevel/dontdiff main.orig/fs/Kconfig main/fs/Kconfig
182 --- main.orig/fs/Kconfig        2004-03-04 17:15:10.000000000 -0800
183 +++ main/fs/Kconfig     2004-03-04 15:58:57.000000000 -0800
184 @@ -885,6 +885,27 @@
185           To compile this as a module, choose M here: the module will be called
186           ramfs.
187  
188 +config PRAMFS
189 +       tristate "Persistent and Protected RAM file system support"
190 +       help
191 +         If your system has a block of fast (comparable in access speed to
192 +        system memory) and non-volatile RAM and you wish to mount a
193 +        light-weight, full-featured, and space-efficient filesystem over it,
194 +        say Y here, and read <file:Documentation/filesystems/pramfs.txt>.
195 +
196 +        To compile this as a module,  choose M here: the module will be
197 +        called pramfs.
198 +
199 +config PRAMFS_NOWP
200 +       bool "Disable write protection (default is enabled)"
201 +       depends on PRAMFS
202 +       help
203 +         Say Y here to disable the write protect feature of PRAMFS.
204 +
205 +config ROOT_PRAMFS
206 +       bool "Root file system on pramfs"
207 +       depends on PRAMFS
208 +       
209  endmenu
210  
211  menu "Miscellaneous filesystems"
212 diff -Nuar -X /home/stevel/dontdiff main.orig/fs/Makefile main/fs/Makefile
213 --- main.orig/fs/Makefile       2004-03-04 17:15:10.000000000 -0800
214 +++ main/fs/Makefile    2004-03-04 15:58:57.000000000 -0800
215 @@ -51,6 +51,7 @@
216  obj-$(CONFIG_EXT2_FS)          += ext2/
217  obj-$(CONFIG_CRAMFS)           += cramfs/
218  obj-$(CONFIG_RAMFS)            += ramfs/
219 +obj-$(CONFIG_PRAMFS)           += pramfs/
220  obj-$(CONFIG_HUGETLBFS)                += hugetlbfs/
221  obj-$(CONFIG_CODA_FS)          += coda/
222  obj-$(CONFIG_INTERMEZZO_FS)    += intermezzo/
223 diff -Nuar -X /home/stevel/dontdiff main.orig/fs/pramfs/balloc.c main/fs/pramfs/balloc.c
224 --- main.orig/fs/pramfs/balloc.c        1969-12-31 16:00:00.000000000 -0800
225 +++ main/fs/pramfs/balloc.c     2004-03-04 15:59:03.000000000 -0800
226 @@ -0,0 +1,163 @@
227 +/*
228 + * balloc.c
229 + *
230 + * The blocks allocation and deallocation routines.
231 + *
232 + * Author: Steve Longerbeam <stevel@mvista.com, or source@mvista.com>
233 + *
234 + * 2003 (c) MontaVista Software, Inc.
235 + * Copyright 2003 Sony Corporation
236 + * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
237 + *
238 + * This software is being distributed under the terms of the GNU General Public
239 + * License version 2.  Some or all of the technology encompassed by this
240 + * software may be subject to one or more patents pending as of the date of
241 + * this notice.  No additional patent license will be required for GPL
242 + * implementations of the technology.  If you want to create a non-GPL
243 + * implementation of the technology encompassed by this software, please
244 + * contact legal@mvista.com for details including licensing terms and fees.
245 + *
246 + * This file is licensed under the terms of the GNU General Public License
247 + * version 2. This program is licensed "as is" without any warranty of any
248 + * kind, whether express or implied.
249 + */
250 +#include <linux/config.h>
251 +#include <linux/fs.h>
252 +#include <linux/pram_fs.h>
253 +#include <linux/quotaops.h>
254 +#include <asm/bitops.h>
255 +
256 +
257 +/*
258 + * This just marks in-use the blocks that make up the bitmap.
259 + * The bitmap must be writeable before calling.
260 + */
261 +void pram_init_bitmap(struct super_block * sb)
262 +{
263 +       struct pram_super_block * ps = pram_get_super(sb);
264 +       u32* bitmap = pram_get_bitmap(sb);
265 +       int blocks = ps->s_bitmap_blocks;
266 +
267 +       memset(bitmap, 0, blocks<<sb->s_blocksize_bits);
268 +       
269 +       while (blocks >= 32) {
270 +               *bitmap++ = 0xffffffff;
271 +               blocks -= 32;
272 +       }
273 +
274 +       if (blocks)
275 +               *bitmap = (1<<blocks) - 1;
276 +}
277 +
278 +
279 +/* Free absolute blocknr */
280 +void pram_free_block (struct super_block * sb, int blocknr)
281 +{
282 +       struct pram_super_block * ps;
283 +       pram_off_t bitmap_block;
284 +       unsigned long flags;
285 +       int bitmap_bnr;
286 +       void* bitmap;
287 +       void* bp;
288 +
289 +       lock_super (sb);
290 +
291 +       bitmap = pram_get_bitmap(sb);
292 +       /*
293 +        * find the block within the bitmap that contains the inuse bit
294 +        * for the block we need to free. We need to unlock this bitmap
295 +        * block to clear the inuse bit.
296 +        */
297 +       bitmap_bnr = blocknr >> (3 + sb->s_blocksize_bits);
298 +       bitmap_block = pram_get_block_off(sb, bitmap_bnr);
299 +       bp = pram_get_block(sb, bitmap_block);
300 +       
301 +       pram_lock_block(sb, bp);
302 +       clear_bit(blocknr, bitmap); // mark the block free
303 +       pram_unlock_block(sb, bp);
304 +
305 +       ps = pram_get_super(sb);
306 +       pram_lock_super(ps);
307 +       if (blocknr < ps->s_free_blocknr_hint)
308 +               ps->s_free_blocknr_hint = blocknr;
309 +       ps->s_free_blocks_count++;
310 +       pram_unlock_super(ps);
311 +
312 +       unlock_super (sb);
313 +}
314 +
315 +
316 +/*
317 + * allocate a block and return it's absolute blocknr. Zeroes out the
318 + * block if zero set.
319 + */
320 +int pram_new_block (struct super_block * sb, int* blocknr, int zero)
321 +{
322 +       struct pram_super_block * ps;
323 +       pram_off_t bitmap_block;
324 +       unsigned long flags;
325 +       int bnr, bitmap_bnr, errval;
326 +       void* bitmap;
327 +       void* bp;
328 +       
329 +       lock_super (sb);
330 +       ps = pram_get_super(sb);
331 +       bitmap = pram_get_bitmap(sb);
332 +
333 +       if (ps->s_free_blocks_count) {
334 +               /* find the oldest unused block */
335 +               bnr = find_next_zero_bit(bitmap,
336 +                                        ps->s_blocks_count,
337 +                                        ps->s_free_blocknr_hint);
338 +               
339 +               if (bnr < ps->s_bitmap_blocks || bnr >= ps->s_blocks_count) {
340 +                       pram_err("no free blocks found!\n");
341 +                       errval = -ENOSPC;
342 +                       goto fail;
343 +               }
344 +
345 +               pram_dbg ("allocating blocknr %d\n", bnr);
346 +               pram_lock_super(ps);
347 +               ps->s_free_blocks_count--;
348 +               ps->s_free_blocknr_hint =
349 +                       (bnr < ps->s_blocks_count-1) ? bnr+1 : 0;
350 +                pram_unlock_super(ps);
351 +       } else {
352 +               pram_err("all blocks allocated\n");
353 +               errval = -ENOSPC;
354 +               goto fail;
355 +       }
356 +
357 +       /*
358 +        * find the block within the bitmap that contains the inuse bit
359 +        * for the unused block we just found. We need to unlock it to
360 +        * set the inuse bit.
361 +        */
362 +       bitmap_bnr = bnr >> (3 + sb->s_blocksize_bits);
363 +       bitmap_block = pram_get_block_off(sb, bitmap_bnr);
364 +       bp = pram_get_block(sb, bitmap_block);
365 +       
366 +       pram_lock_block(sb, bp);
367 +       set_bit(bnr, bitmap); // mark the new block in use
368 +       pram_unlock_block(sb, bp);
369 +
370 +       if (zero) {
371 +               bp = pram_get_block(sb, pram_get_block_off(sb, bnr));
372 +               pram_lock_block(sb, bp);
373 +               memset(bp, 0, sb->s_blocksize);
374 +               pram_unlock_block(sb, bp);
375 +       }
376 +               
377 +       *blocknr = bnr;
378 +       errval = 0;
379 + fail:
380 +       unlock_super (sb);
381 +       return errval;
382 +}
383 +
384 +
385 +unsigned long pram_count_free_blocks (struct super_block * sb)
386 +{
387 +       struct pram_super_block * ps = pram_get_super(sb);
388 +       return ps->s_free_blocks_count;
389 +}
390 diff -Nuar -X /home/stevel/dontdiff main.orig/fs/pramfs/dir.c main/fs/pramfs/dir.c
391 --- main.orig/fs/pramfs/dir.c   1969-12-31 16:00:00.000000000 -0800
392 +++ main/fs/pramfs/dir.c        2004-03-04 15:59:03.000000000 -0800
393 @@ -0,0 +1,225 @@
394 +/*
395 + * dir.c
396 + *
397 + * File operations for directories.
398 + *
399 + * Author: Steve Longerbeam <stevel@mvista.com, or source@mvista.com>
400 + *
401 + * 2003 (c) MontaVista Software, Inc.
402 + * Copyright 2003 Sony Corporation
403 + * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
404 + *
405 + * This software is being distributed under the terms of the GNU General Public
406 + * License version 2.  Some or all of the technology encompassed by this
407 + * software may be subject to one or more patents pending as of the date of
408 + * this notice.  No additional patent license will be required for GPL
409 + * implementations of the technology.  If you want to create a non-GPL
410 + * implementation of the technology encompassed by this software, please
411 + * contact legal@mvista.com for details including licensing terms and fees.
412 + *
413 + * This file is licensed under the terms of the GNU General Public License
414 + * version 2. This program is licensed "as is" without any warranty of any
415 + * kind, whether express or implied.
416 + */
417 +
418 +#include <linux/fs.h>
419 +#include <linux/pram_fs.h>
420 +#include <linux/pagemap.h>
421 +
422 +
423 +/*
424 + *     Parent is locked.
425 + */
426 +int pram_add_link (struct dentry * dentry, struct inode * inode)
427 +{
428 +       struct inode * dir = dentry->d_parent->d_inode;
429 +       struct pram_inode * pidir, * pi, * pitail = NULL;
430 +       unsigned long flags;
431 +       pram_off_t tail_ino, prev_ino;
432 +       const char *name = dentry->d_name.name;
433 +       int namelen = dentry->d_name.len > PRAM_NAME_LEN ?
434 +               PRAM_NAME_LEN : dentry->d_name.len;
435 +       
436 +       pidir = pram_get_inode(dir->i_sb, dir->i_ino);
437 +       pi = pram_get_inode(dir->i_sb, inode->i_ino);
438 +       
439 +       dir->i_mtime = dir->i_ctime = CURRENT_TIME;
440 +
441 +       tail_ino = pidir->i_type.dir.tail;
442 +       if (tail_ino != 0) {
443 +               pitail = pram_get_inode(dir->i_sb, tail_ino);
444 +               pram_lock_inode(pitail);
445 +               pitail->i_d.d_next = inode->i_ino;
446 +               pram_unlock_inode(pitail);
447 +
448 +               prev_ino = tail_ino;
449 +
450 +               pram_lock_inode(pidir);
451 +               pidir->i_type.dir.tail = inode->i_ino;
452 +               pidir->i_mtime = dir->i_mtime.tv_sec;
453 +               pidir->i_ctime = dir->i_ctime.tv_sec;
454 +               pram_unlock_inode(pidir);
455 +       } else {
456 +               // the directory is empty
457 +               prev_ino = 0;
458 +
459 +               pram_lock_inode(pidir);
460 +               pidir->i_type.dir.head = pidir->i_type.dir.tail = inode->i_ino;
461 +               pidir->i_mtime = dir->i_mtime.tv_sec;
462 +               pidir->i_ctime = dir->i_ctime.tv_sec;
463 +               pram_unlock_inode(pidir);
464 +       }
465 +
466 +
467 +       pram_lock_inode(pi);
468 +       pi->i_d.d_prev = prev_ino;
469 +       pi->i_d.d_parent = dir->i_ino;
470 +       memcpy(pi->i_d.d_name, name, namelen);
471 +       pi->i_d.d_name[namelen] = '\0';
472 +       pram_unlock_inode(pi);
473 +       return 0;
474 +}
475 +
476 +int pram_remove_link(struct inode * inode)
477 +{
478 +       struct super_block * sb = inode->i_sb;
479 +       struct pram_inode * prev = NULL;
480 +       struct pram_inode * next = NULL;
481 +       struct pram_inode * pidir, * pi;
482 +       unsigned long flags;
483 +
484 +       pi = pram_get_inode(sb, inode->i_ino);
485 +       pidir = pram_get_inode(sb, pi->i_d.d_parent);
486 +       if (!pidir)
487 +               return -EACCES;
488 +       
489 +       if (inode->i_ino == pidir->i_type.dir.head) {
490 +               // first inode in directory
491 +               next = pram_get_inode(sb, pi->i_d.d_next);
492 +
493 +               if (next) {
494 +                       pram_lock_inode(next);
495 +                       next->i_d.d_prev = 0;
496 +                       pram_unlock_inode(next);
497 +
498 +                       pram_lock_inode(pidir);
499 +                       pidir->i_type.dir.head = pi->i_d.d_next;
500 +               } else {
501 +                       pram_lock_inode(pidir);
502 +                       pidir->i_type.dir.head = pidir->i_type.dir.tail = 0;
503 +               }
504 +               pram_unlock_inode(pidir);
505 +       } else if (inode->i_ino == pidir->i_type.dir.tail) {
506 +               // last inode in directory
507 +               prev = pram_get_inode(sb, pi->i_d.d_prev);
508 +
509 +               pram_lock_inode(prev);
510 +               prev->i_d.d_next = 0;
511 +               pram_unlock_inode(prev);
512 +
513 +               pram_lock_inode(pidir);
514 +               pidir->i_type.dir.tail = pi->i_d.d_prev;
515 +               pram_unlock_inode(pidir);
516 +       } else {
517 +               // somewhere in the middle
518 +               prev = pram_get_inode(sb, pi->i_d.d_prev);
519 +               next = pram_get_inode(sb, pi->i_d.d_next);
520 +
521 +               if (prev && next) {
522 +                       pram_lock_inode(prev);
523 +                       prev->i_d.d_next = pi->i_d.d_next;
524 +                       pram_unlock_inode(prev);
525 +                       
526 +                       pram_lock_inode(next);
527 +                       next->i_d.d_prev = pi->i_d.d_prev;
528 +                       pram_unlock_inode(next);
529 +               }
530 +       }
531 +       
532 +       pram_lock_inode(pi);
533 +       pi->i_d.d_next = pi->i_d.d_prev = pi->i_d.d_parent = 0;
534 +       pram_unlock_inode(pi);
535 +
536 +       return 0;
537 +}
538 +
539 +#define S_SHIFT 12
540 +static unsigned int dtype_by_mode[S_IFMT >> S_SHIFT] = {
541 +        [S_IFREG >> S_SHIFT]    DT_REG,
542 +        [S_IFDIR >> S_SHIFT]    DT_DIR,
543 +        [S_IFCHR >> S_SHIFT]    DT_CHR,
544 +        [S_IFBLK >> S_SHIFT]    DT_BLK,
545 +        [S_IFIFO >> S_SHIFT]    DT_FIFO,
546 +        [S_IFSOCK >> S_SHIFT]   DT_SOCK,
547 +        [S_IFLNK >> S_SHIFT]    DT_LNK,
548 +};
549 +       
550 +static int
551 +pram_readdir (struct file * filp, void * dirent, filldir_t filldir)
552 +{
553 +       struct inode *inode = filp->f_dentry->d_inode;
554 +       struct super_block * sb = inode->i_sb;
555 +       struct pram_inode * pi;
556 +       int namelen, ret=0;
557 +       char *name;
558 +       ino_t ino;
559 +
560 +       if (filp->f_pos >> 32)
561 +               return 0;
562 +
563 +       pi = pram_get_inode(sb, inode->i_ino);
564 +
565 +       switch ((unsigned long)filp->f_pos) {
566 +       case 0:
567 +               ret = filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR);
568 +               filp->f_pos++;
569 +               return ret;
570 +       case 1:
571 +               ret = filldir(dirent, "..", 2, 1, pi->i_d.d_parent, DT_DIR);
572 +               ino = pi->i_type.dir.head;
573 +               filp->f_pos = ino ? ino : 2;
574 +               return ret;
575 +       case 2:
576 +               ino = pi->i_type.dir.head;
577 +               if (ino) {
578 +                       filp->f_pos = ino;
579 +                       pi = pram_get_inode(sb, ino);
580 +                       break;
581 +               } else {
582 +                       /* the directory is empty */
583 +                       filp->f_pos = 2;
584 +                       return 0;
585 +               }
586 +       case 3:
587 +               return 0;
588 +       default:
589 +               ino = filp->f_pos;
590 +               pi = pram_get_inode(sb, ino);
591 +               break;
592 +       }
593 +       
594 +       while (pi && !pi->i_links_count) {
595 +               ino = filp->f_pos = pi->i_d.d_next;
596 +               pi = pram_get_inode(sb, ino);
597 +       }
598 +       
599 +       if (pi) {
600 +               name = pi->i_d.d_name;
601 +               namelen = strlen(name);
602 +               
603 +               ret = filldir(dirent, name, namelen,
604 +                             filp->f_pos, ino,
605 +                             dtype_by_mode[(pi->i_mode & S_IFMT)>>S_SHIFT]);
606 +               filp->f_pos = pi->i_d.d_next ? pi->i_d.d_next : 3;
607 +       } else
608 +               filp->f_pos = 3;
609 +       
610 +       return ret;
611 +}
612 +
613 +struct file_operations pram_dir_operations = {
614 +       read:           generic_read_dir,
615 +       readdir:        pram_readdir,
616 +       ioctl:          pram_ioctl,
617 +       fsync:          pram_sync_file,
618 +};
619 diff -Nuar -X /home/stevel/dontdiff main.orig/fs/pramfs/file.c main/fs/pramfs/file.c
620 --- main.orig/fs/pramfs/file.c  1969-12-31 16:00:00.000000000 -0800
621 +++ main/fs/pramfs/file.c       2004-03-04 15:59:03.000000000 -0800
622 @@ -0,0 +1,143 @@
623 +/*
624 + * file.c
625 + *
626 + * File operations for regular files.
627 + *
628 + * Author: Steve Longerbeam <stevel@mvista.com, or source@mvista.com>
629 + *
630 + * 2003 (c) MontaVista Software, Inc.
631 + * Copyright 2003 Sony Corporation
632 + * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
633 + *
634 + * This software is being distributed under the terms of the GNU General Public
635 + * License version 2.  Some or all of the technology encompassed by this
636 + * software may be subject to one or more patents pending as of the date of
637 + * this notice.  No additional patent license will be required for GPL
638 + * implementations of the technology.  If you want to create a non-GPL
639 + * implementation of the technology encompassed by this software, please
640 + * contact legal@mvista.com for details including licensing terms and fees.
641 + *
642 + * This file is licensed under the terms of the GNU General Public License
643 + * version 2. This program is licensed "as is" without any warranty of any
644 + * kind, whether express or implied.
645 + */
646 +#include <linux/fs.h>
647 +#include <linux/pram_fs.h>
648 +#include <linux/sched.h>
649 +#include <linux/slab.h>
650 +#include <linux/uio.h>
651 +#include <asm/uaccess.h>
652 +
653 +static int pram_open_file(struct inode * inode, struct file * filp)
654 +{
655 +       filp->f_flags |= O_DIRECT;
656 +       return generic_file_open(inode, filp);
657 +}
658 +
659 +/*
660 + * Called when an inode is released. Note that this is different
661 + * from pram_open_file: open gets called at every open, but release
662 + * gets called only when /all/ the files are closed.
663 + */
664 +static int pram_release_file (struct inode * inode, struct file * filp)
665 +{
666 +       return 0;
667 +}
668 +
669 +int pram_direct_IO(int rw, struct kiocb *iocb,
670 +                  const struct iovec *iov,
671 +                  loff_t offset, unsigned long nr_segs)
672 +{
673 +       struct file *file = iocb->ki_filp;
674 +       struct inode *inode = file->f_mapping->host;
675 +       struct super_block * sb = inode->i_sb;
676 +       int progress = 0, retval = 0;
677 +       struct pram_inode * pi;
678 +       void * tmp = NULL;
679 +       unsigned long blocknr, blockoff, flags;
680 +       int num_blocks, blocksize_mask, blocksize, blocksize_bits;
681 +       char __user *buf = iov->iov_base;
682 +       size_t length = iov->iov_len;
683 +       
684 +       if (length < 0)
685 +                return -EINVAL;
686 +       if ((rw == READ) && (offset + length > inode->i_size))
687 +               length = inode->i_size - offset;
688 +       if (!length)
689 +               goto out;
690 +
691 +       blocksize_bits = inode->i_sb->s_blocksize_bits;
692 +       blocksize = 1 << blocksize_bits;
693 +       blocksize_mask = blocksize - 1;
694 +
695 +       /* find starting block number to access */
696 +       blocknr = offset >> blocksize_bits;
697 +       /* find starting offset within starting block */
698 +       blockoff = offset & blocksize_mask;
699 +       /* find number of blocks to access */
700 +       num_blocks = (blockoff + length + blocksize_mask) >> blocksize_bits;
701 +               
702 +       if (rw == WRITE) {
703 +               // prepare a temporary buffer to hold a user data block
704 +               // for writing.
705 +               tmp = kmalloc(blocksize, GFP_KERNEL);
706 +               if (!tmp)
707 +                       return -ENOMEM;
708 +               /* now allocate the data blocks we'll need */
709 +               retval = pram_alloc_blocks(inode, blocknr, num_blocks);
710 +               if (retval)
711 +                       goto fail;
712 +       }
713 +       
714 +       pi = pram_get_inode(inode->i_sb, inode->i_ino);
715 +       
716 +       while (length) {
717 +               int count;
718 +               pram_off_t block = pram_find_data_block(inode, blocknr++);
719 +               u8* bp = (u8*)pram_get_block(sb, block);
720 +               if (!bp)
721 +                       goto fail;
722 +               
723 +               count = blockoff + length > blocksize ?
724 +                       blocksize - blockoff : length;
725 +               
726 +               if (rw == READ) {
727 +                       copy_to_user(buf, &bp[blockoff], count);
728 +               } else {
729 +                       copy_from_user(tmp, buf, count);
730 +
731 +                       pram_lock_block(inode->i_sb, bp);
732 +                       memcpy(&bp[blockoff], tmp, count);
733 +                       pram_unlock_block(inode->i_sb, bp);
734 +               }
735 +
736 +               progress += count;
737 +               buf += count;
738 +               length -= count;
739 +               blockoff = 0;
740 +       }
741 +       
742 +       retval = progress;
743 + fail:
744 +       if (tmp)
745 +               kfree(tmp);
746 + out:
747 +       return retval;
748 +}
749 +
750 +
751 +
752 +struct file_operations pram_file_operations = {
753 +       llseek:         generic_file_llseek,
754 +       read:           generic_file_read,
755 +       write:          generic_file_write,
756 +       ioctl:          pram_ioctl,
757 +       mmap:           generic_file_mmap,
758 +       open:           pram_open_file,
759 +       release:        pram_release_file,
760 +       fsync:          pram_sync_file,
761 +};
762 +
763 +struct inode_operations pram_file_inode_operations = {
764 +       truncate:       pram_truncate,
765 +};
766 diff -Nuar -X /home/stevel/dontdiff main.orig/fs/pramfs/fsync.c main/fs/pramfs/fsync.c
767 --- main.orig/fs/pramfs/fsync.c 1969-12-31 16:00:00.000000000 -0800
768 +++ main/fs/pramfs/fsync.c      2004-03-04 15:59:03.000000000 -0800
769 @@ -0,0 +1,37 @@
770 +/*
771 + * fsync.c
772 + *
773 + * fsync operation for directory and regular files.
774 + *
775 + * Author: Steve Longerbeam <stevel@mvista.com, or source@mvista.com>
776 + *
777 + * 2003 (c) MontaVista Software, Inc.
778 + * Copyright 2003 Sony Corporation
779 + * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
780 + *
781 + * This software is being distributed under the terms of the GNU General Public
782 + * License version 2.  Some or all of the technology encompassed by this
783 + * software may be subject to one or more patents pending as of the date of
784 + * this notice.  No additional patent license will be required for GPL
785 + * implementations of the technology.  If you want to create a non-GPL
786 + * implementation of the technology encompassed by this software, please
787 + * contact legal@mvista.com for details including licensing terms and fees.
788 + *
789 + * This file is licensed under the terms of the GNU General Public License
790 + * version 2. This program is licensed "as is" without any warranty of any
791 + * kind, whether express or implied.
792 + */
793 +#include <linux/fs.h>
794 +#include <linux/pram_fs.h>
795 +
796 +/*
797 + *     File may be NULL when we are called. Perhaps we shouldn't
798 + *     even pass file to fsync ?
799 + */
800 +
801 +int pram_sync_file(struct file * file, struct dentry *dentry, int datasync)
802 +{
803 +       // FIXME: check
804 +       return 0;
805 +}
806 +
807 diff -Nuar -X /home/stevel/dontdiff main.orig/fs/pramfs/inode.c main/fs/pramfs/inode.c
808 --- main.orig/fs/pramfs/inode.c 1969-12-31 16:00:00.000000000 -0800
809 +++ main/fs/pramfs/inode.c      2004-03-04 16:45:11.000000000 -0800
810 @@ -0,0 +1,649 @@
811 +/*
812 + * inode.c
813 + *
814 + * Inode methods (allocate/free/read/write).
815 + *
816 + * Author: Steve Longerbeam <stevel@mvista.com, or source@mvista.com>
817 + *
818 + * 2003 (c) MontaVista Software, Inc.
819 + * Copyright 2003 Sony Corporation
820 + * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
821 + *
822 + * This software is being distributed under the terms of the GNU General Public
823 + * License version 2.  Some or all of the technology encompassed by this
824 + * software may be subject to one or more patents pending as of the date of
825 + * this notice.  No additional patent license will be required for GPL
826 + * implementations of the technology.  If you want to create a non-GPL
827 + * implementation of the technology encompassed by this software, please
828 + * contact legal@mvista.com for details including licensing terms and fees.
829 + *
830 + * This file is licensed under the terms of the GNU General Public License
831 + * version 2. This program is licensed "as is" without any warranty of any
832 + * kind, whether express or implied.
833 + */
834 +#include <linux/fs.h>
835 +#include <linux/pram_fs.h>
836 +#include <linux/smp_lock.h>
837 +#include <linux/sched.h>
838 +#include <linux/highuid.h>
839 +#include <linux/quotaops.h>
840 +#include <linux/module.h>
841 +#include <linux/buffer_head.h>
842 +#include <linux/mpage.h>
843 +#include <linux/backing-dev.h>
844 +
845 +
846 +static struct backing_dev_info pram_backing_dev_info = {
847 +       .ra_pages       = 0,    /* No readahead */
848 +       .memory_backed  = 1,    /* Does not contribute to dirty memory */
849 +};
850 +
851 +/*
852 + * allocate a data block for inode and return it's absolute blocknr.
853 + * Zeroes out the block if zero set. Increments inode->i_blocks.
854 + */
855 +static int
856 +pram_new_data_block (struct inode * inode, int* blocknr, int zero)
857 +{
858 +       unsigned long flags;
859 +       int errval = pram_new_block(inode->i_sb, blocknr, zero);
860 +       
861 +       if (!errval) {
862 +               struct pram_inode * pi = pram_get_inode(inode->i_sb,
863 +                                                       inode->i_ino);
864 +               inode->i_blocks++;
865 +               pram_lock_inode(pi);
866 +               pi->i_blocks = inode->i_blocks;
867 +               pram_unlock_inode(pi);
868 +       }
869 +
870 +       return errval;
871 +}
872 +
873 +/*
874 + * find the offset to the block represented by the given inode's file
875 + * relative block number.
876 + */
877 +pram_off_t pram_find_data_block(struct inode * inode, int file_blocknr)
878 +{
879 +       struct super_block * sb = inode->i_sb;
880 +       struct pram_inode * pi;
881 +       pram_off_t * row; /* ptr to row block */
882 +       pram_off_t * col; /* ptr to column blocks */
883 +       pram_off_t bp = 0;
884 +       int i_row, i_col;
885 +       int N = sb->s_blocksize >> 2; // num block ptrs per block
886 +       int Nbits = sb->s_blocksize_bits - 2;
887 +
888 +       pi = pram_get_inode(sb, inode->i_ino);
889 +
890 +       i_row = file_blocknr >> Nbits;
891 +       i_col  = file_blocknr & (N-1);
892 +
893 +       row = pram_get_block(sb, pi->i_type.reg.row_block);
894 +       if (row) {
895 +               col = pram_get_block(sb, row[i_row]);
896 +               if (col)
897 +                       bp = col[i_col];
898 +       }
899 +
900 +       return bp;
901 +}
902 +
903 +
904 +/*
905 + * Free data blocks from inode starting at first_trunc_block.
906 + */
907 +static void
908 +pram_truncate_blocks(struct inode * inode, int first_trunc_block)
909 +{
910 +       struct super_block * sb = inode->i_sb;
911 +       struct pram_inode * pi = pram_get_inode(sb, inode->i_ino);
912 +       int N = sb->s_blocksize >> 2; // num block ptrs per block
913 +       int Nbits = sb->s_blocksize_bits - 2;
914 +       int first_row_index, last_row_index;
915 +       int i, j, first_blocknr, last_blocknr, blocknr;
916 +       unsigned long flags;
917 +       pram_off_t * row; /* ptr to row block */
918 +       pram_off_t * col; /* ptr to column blocks */
919 +       
920 +       if (first_trunc_block >= inode->i_blocks ||
921 +           !inode->i_blocks || !pi->i_type.reg.row_block) {
922 +               return;
923 +       }
924 +
925 +       first_blocknr = first_trunc_block;
926 +       last_blocknr = inode->i_blocks - 1;
927 +       first_row_index = first_blocknr >> Nbits;
928 +       last_row_index  = last_blocknr >> Nbits;
929 +       
930 +       row = pram_get_block(sb, pi->i_type.reg.row_block);
931 +       
932 +       for (i=first_row_index; i <= last_row_index; i++) {
933 +               int first_col_index = (i == first_row_index) ?
934 +                       first_blocknr & (N-1) : 0;
935 +               int last_col_index = (i == last_row_index) ?
936 +                       last_blocknr & (N-1) : N-1;
937 +
938 +               col = pram_get_block(sb, row[i]);
939 +               for (j=first_col_index; j <= last_col_index; j++) {
940 +                       blocknr = pram_get_blocknr(sb, col[j]);
941 +                       pram_free_block(sb, blocknr);
942 +                       pram_lock_block(sb, col);
943 +                       col[j] = 0;
944 +                       pram_unlock_block(sb, col);
945 +               }
946 +               
947 +               if (first_col_index == 0) {
948 +                       blocknr = pram_get_blocknr(sb, row[i]);
949 +                       pram_free_block(sb, blocknr);
950 +                       pram_lock_block(sb, row);
951 +                       row[i] = 0;
952 +                       pram_unlock_block(sb, row);
953 +               }
954 +       }
955 +       
956 +       inode->i_blocks -= (last_blocknr - first_blocknr + 1);
957 +
958 +       if (first_row_index == 0) {
959 +               blocknr = pram_get_blocknr(sb, pi->i_type.reg.row_block);
960 +               pram_free_block(sb, blocknr);
961 +               pram_lock_inode(pi);
962 +               pi->i_type.reg.row_block = 0;
963 +               pram_unlock_inode(pi);
964 +       }
965 +       pram_lock_inode(pi);
966 +       pi->i_blocks = inode->i_blocks;
967 +       pram_unlock_inode(pi);
968 +}
969 +
970 +/*
971 + * Allocate num data blocks for inode, starting at given file-relative
972 + * block number. Any unallocated file blocks before file_blocknr
973 + * are allocated. All blocks except the last are zeroed out.
974 + */
975 +int pram_alloc_blocks(struct inode * inode, int file_blocknr, int num)
976 +{
977 +       struct super_block * sb = inode->i_sb;
978 +       struct pram_inode * pi = pram_get_inode(sb, inode->i_ino);
979 +       int N = sb->s_blocksize >> 2; // num block ptrs per block
980 +       int Nbits = sb->s_blocksize_bits - 2;
981 +       int first_file_blocknr;
982 +       int last_file_blocknr;
983 +       int first_row_index, last_row_index;
984 +       int i, j, blocknr, errval;
985 +       unsigned long flags;
986 +       pram_off_t * row;
987 +       pram_off_t * col;
988 +       
989 +       if (!pi->i_type.reg.row_block) {
990 +               /* alloc the 2nd order array block */
991 +               errval = pram_new_block(sb, &blocknr, 1);
992 +               if (errval) {
993 +                       pram_err("failed to alloc 2nd order array block\n");
994 +                       goto fail;
995 +               }
996 +               pram_lock_inode(pi);
997 +               pi->i_type.reg.row_block = pram_get_block_off(sb, blocknr);
998 +               pram_unlock_inode(pi);
999 +       }
1000 +
1001 +       row = pram_get_block(sb, pi->i_type.reg.row_block);
1002 +       
1003 +       first_file_blocknr = (file_blocknr > inode->i_blocks) ?
1004 +               inode->i_blocks : file_blocknr;
1005 +       last_file_blocknr = file_blocknr + num - 1;
1006 +       
1007 +       first_row_index = first_file_blocknr >> Nbits;
1008 +       last_row_index  = last_file_blocknr >> Nbits;
1009 +       
1010 +       for (i=first_row_index; i<=last_row_index; i++) {
1011 +               int first_col_index, last_col_index;
1012 +               /*
1013 +                * we are starting a new row, so make sure
1014 +                * there is a block allocated for the row.
1015 +                */
1016 +               if (!row[i]) {
1017 +                       /* allocate the row block */
1018 +                       errval = pram_new_block(sb, &blocknr, 1);
1019 +                       if (errval) {
1020 +                               pram_err("failed to alloc row block\n");
1021 +                               goto fail;
1022 +                       }
1023 +                       pram_lock_block(sb, row);
1024 +                       row[i] = pram_get_block_off(sb, blocknr);
1025 +                       pram_unlock_block(sb, row);
1026 +               }
1027 +               col = pram_get_block(sb, row[i]);
1028 +
1029 +               first_col_index = (i == first_row_index) ?
1030 +                       first_file_blocknr & (N-1) : 0;
1031 +
1032 +               last_col_index = (i == last_row_index) ?
1033 +                       last_file_blocknr & (N-1) : N-1;
1034 +
1035 +               for (j=first_col_index; j<=last_col_index; j++) {
1036 +                       int last_block =
1037 +                               (i==last_row_index) && (j==last_col_index);
1038 +                       if (!col[j]) {
1039 +                               errval = pram_new_data_block(inode,
1040 +                                                             &blocknr,
1041 +                                                             !last_block);
1042 +                               if (errval) {
1043 +                                       pram_err("failed to alloc "
1044 +                                                 "data block\n");
1045 +                                       goto fail;
1046 +                               }
1047 +                               pram_lock_block(sb, col);
1048 +                               col[j] = pram_get_block_off(sb, blocknr);
1049 +                               pram_unlock_block(sb, col);
1050 +                       }
1051 +               }
1052 +       }
1053 +       
1054 +       errval = 0;
1055 + fail:
1056 +       return errval;
1057 +}
1058 +
1059 +
1060 +static int
1061 +pram_fill_inode(struct inode * inode, struct pram_inode * pi)
1062 +{
1063 +       int ret = -EIO;
1064 +       
1065 +       if (pram_calc_checksum((u32*)pi, PRAM_INODE_SIZE>>2)) {
1066 +               pram_err("checksum error in inode %08x\n",
1067 +                         (u32)inode->i_ino);
1068 +               goto bad_inode;
1069 +       }
1070 +       
1071 +       inode->i_mode = pi->i_mode;
1072 +       inode->i_uid = pi->i_uid;
1073 +       inode->i_gid = pi->i_gid;
1074 +       inode->i_nlink = pi->i_links_count;
1075 +       inode->i_size = pi->i_size;
1076 +       inode->i_atime.tv_sec = pi->i_atime;
1077 +       inode->i_ctime.tv_sec = pi->i_ctime;
1078 +       inode->i_mtime.tv_sec = pi->i_mtime;
1079 +       inode->i_atime.tv_nsec = inode->i_mtime.tv_nsec =
1080 +               inode->i_ctime.tv_nsec = 0;
1081 +
1082 +       /* check if the inode is active. */
1083 +       if (inode->i_nlink == 0 && (inode->i_mode == 0 || pi->i_dtime)) {
1084 +               /* this inode is deleted */
1085 +               ret = -EINVAL;
1086 +               goto bad_inode;
1087 +       }
1088 +       
1089 +       inode->i_blocks = pi->i_blocks;
1090 +       inode->i_blksize = inode->i_sb->s_blocksize;
1091 +       inode->i_ino = pram_get_inodenr(inode->i_sb, pi);
1092 +       inode->i_mapping->a_ops = &pram_aops;
1093 +       inode->i_mapping->backing_dev_info = &pram_backing_dev_info;
1094 +
1095 +       insert_inode_hash(inode);
1096 +       switch (inode->i_mode & S_IFMT) {
1097 +       case S_IFREG:
1098 +               inode->i_op = &pram_file_inode_operations;
1099 +               inode->i_fop = &pram_file_operations;
1100 +               break;
1101 +       case S_IFDIR:
1102 +               inode->i_op = &pram_dir_inode_operations;
1103 +               inode->i_fop = &pram_dir_operations;
1104 +               break;
1105 +       case S_IFLNK:
1106 +               inode->i_op = &pram_symlink_inode_operations;
1107 +               break;
1108 +       default:
1109 +               inode->i_size = 0;
1110 +               init_special_inode(inode, inode->i_mode,
1111 +                                  pi->i_type.dev.rdev);
1112 +               break;
1113 +       }
1114 +
1115 +       return 0;
1116 +
1117 + bad_inode:
1118 +       make_bad_inode(inode);
1119 +       return ret;
1120 +}
1121 +
1122 +static int pram_update_inode(struct inode * inode)
1123 +{
1124 +       struct pram_inode * pi;
1125 +       unsigned long flags;
1126 +       int retval = 0;
1127 +
1128 +       pi = pram_get_inode(inode->i_sb, inode->i_ino);
1129 +       
1130 +       pram_lock_inode(pi);
1131 +       pi->i_mode = inode->i_mode;
1132 +       pi->i_uid = inode->i_uid;
1133 +       pi->i_gid = inode->i_gid;
1134 +       pi->i_links_count = inode->i_nlink;
1135 +       pi->i_size = inode->i_size;
1136 +       pi->i_blocks = inode->i_blocks;
1137 +       pi->i_atime = inode->i_atime.tv_sec;
1138 +       pi->i_ctime = inode->i_ctime.tv_sec;
1139 +       pi->i_mtime = inode->i_mtime.tv_sec;
1140 +
1141 +       if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
1142 +               pi->i_type.dev.rdev = inode->i_rdev;
1143 +       
1144 +       pram_unlock_inode(pi);
1145 +       return retval;
1146 +}
1147 +
1148 +/*
1149 + * NOTE! When we get the inode, we're the only people
1150 + * that have access to it, and as such there are no
1151 + * race conditions we have to worry about. The inode
1152 + * is not on the hash-lists, and it cannot be reached
1153 + * through the filesystem because the directory entry
1154 + * has been deleted earlier.
1155 + */
1156 +static void pram_free_inode (struct inode * inode)
1157 +{
1158 +       struct super_block * sb = inode->i_sb;
1159 +       struct pram_super_block * ps;
1160 +       struct pram_inode * pi;
1161 +       unsigned long flags, inode_nr;
1162 +
1163 +       /*
1164 +        * Note: we must free any quota before locking the superblock,
1165 +        * as writing the quota to disk may need the lock as well.
1166 +        */
1167 +       if (!is_bad_inode(inode)) {
1168 +               /* Quota is already initialized in iput() */
1169 +               DQUOT_FREE_INODE(inode);
1170 +               DQUOT_DROP(inode);
1171 +       }
1172 +
1173 +       lock_super (sb);
1174 +       clear_inode (inode);
1175 +
1176 +       inode_nr = (inode->i_ino - PRAM_ROOT_INO) >> PRAM_INODE_BITS;
1177 +
1178 +       pi = pram_get_inode(sb, inode->i_ino);
1179 +       pram_lock_inode(pi);
1180 +       pi->i_dtime = get_seconds();
1181 +       pi->i_type.reg.row_block = 0;
1182 +       pram_unlock_inode(pi);
1183 +
1184 +       // increment s_free_inodes_count
1185 +       ps = pram_get_super(sb);
1186 +       pram_lock_super(ps);
1187 +       if (inode_nr < ps->s_free_inode_hint)
1188 +               ps->s_free_inode_hint = inode_nr;
1189 +       ps->s_free_inodes_count++;
1190 +       if (ps->s_free_inodes_count == ps->s_inodes_count - 1) {
1191 +               // filesystem is empty
1192 +               pram_dbg ("fs is empty!\n");
1193 +               ps->s_free_inode_hint = 1;
1194 +       }
1195 +       pram_unlock_super(ps);
1196 +
1197 +       unlock_super (sb);
1198 +}
1199 +
1200 +
1201 +struct inode *
1202 +pram_fill_new_inode(struct super_block *sb,
1203 +                    struct pram_inode * pi)
1204 +{
1205 +       struct inode * inode = new_inode(sb);
1206 +       
1207 +       if (inode)
1208 +               pram_fill_inode(inode, pi);
1209 +
1210 +       return inode;
1211 +}
1212 +
1213 +
1214 +/*
1215 + * Called at each iput()
1216 + */
1217 +void pram_put_inode (struct inode * inode)
1218 +{
1219 +       // nothing to do
1220 +}
1221 +
1222 +/*
1223 + * Called at the last iput() if i_nlink is zero.
1224 + */
1225 +void pram_delete_inode (struct inode * inode)
1226 +{
1227 +       lock_kernel();
1228 +
1229 +       if (is_bad_inode(inode))
1230 +               goto no_delete;
1231 +
1232 +       // unlink from chain in the inode's directory
1233 +       pram_remove_link(inode);
1234 +       inode->i_size = 0;
1235 +       if (inode->i_blocks)
1236 +               pram_truncate(inode);
1237 +       pram_free_inode(inode);
1238 +
1239 +       unlock_kernel();
1240 +       return;
1241 + no_delete:
1242 +       unlock_kernel();
1243 +       clear_inode(inode);  /* We must guarantee clearing of inode... */
1244 +}
1245 +
1246 +
1247 +struct inode * pram_new_inode (const struct inode * dir, int mode)
1248 +{
1249 +       struct super_block * sb;
1250 +       struct pram_super_block * ps;
1251 +       struct inode * inode;
1252 +       struct pram_inode * pi = NULL;
1253 +       unsigned long flags;
1254 +       int i, errval;
1255 +       ino_t ino=0;
1256 +
1257 +       sb = dir->i_sb;
1258 +       inode = new_inode(sb);
1259 +       if (!inode)
1260 +               return ERR_PTR(-ENOMEM);
1261 +
1262 +       lock_super (sb);
1263 +       ps = pram_get_super(sb);
1264 +
1265 +       if (ps->s_free_inodes_count) {
1266 +               /* find the oldest unused pram inode */
1267 +               for (i=ps->s_free_inode_hint; i < ps->s_inodes_count; i++) {
1268 +                       ino = PRAM_ROOT_INO + (i << PRAM_INODE_BITS);
1269 +                       pi = pram_get_inode(sb, ino);
1270 +                       /* check if the inode is active. */
1271 +                       if (pi->i_links_count == 0 && (pi->i_mode == 0 ||
1272 +                                                      pi->i_dtime)) {
1273 +                               /* this inode is deleted */
1274 +                               break;
1275 +                       }
1276 +               }
1277 +               
1278 +               if (i >= ps->s_inodes_count) {
1279 +                       pram_err("s_free_inodes_count!=0 but none free!?\n");
1280 +                       errval = -ENOSPC;
1281 +                       goto fail;
1282 +               }
1283 +
1284 +               pram_dbg ("allocating inode %lu\n", ino);
1285 +               pram_lock_super(ps);
1286 +               ps->s_free_inodes_count--;
1287 +               ps->s_free_inode_hint = (i < ps->s_inodes_count-1) ? i+1 : 0;
1288 +               pram_unlock_super(ps);
1289 +       } else {
1290 +               pram_err("no space left to create new inode!\n");
1291 +               errval = -ENOSPC;
1292 +               goto fail;
1293 +       }
1294 +
1295 +       // chosen inode is in ino
1296 +       
1297 +       inode->i_ino = ino;
1298 +       inode->i_uid = current->fsuid;
1299 +
1300 +       if (dir->i_mode & S_ISGID) {
1301 +               inode->i_gid = dir->i_gid;
1302 +               if (S_ISDIR(mode))
1303 +                       mode |= S_ISGID;
1304 +       } else
1305 +               inode->i_gid = current->fsgid;
1306 +       inode->i_mode = mode;
1307 +
1308 +       inode->i_blksize = sb->s_blocksize;
1309 +       inode->i_blocks = inode->i_size = 0;
1310 +       inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
1311 +
1312 +       pram_lock_inode(pi);
1313 +       pi->i_d.d_next = 0;
1314 +       pi->i_d.d_prev = 0;
1315 +       pram_unlock_inode(pi);
1316 +
1317 +       insert_inode_hash(inode);
1318 +       pram_write_inode(inode, 0);
1319 +       
1320 +       unlock_super (sb);
1321 +
1322 +       if(DQUOT_ALLOC_INODE(inode)) {
1323 +               DQUOT_DROP(inode);
1324 +               inode->i_flags |= S_NOQUOTA;
1325 +               inode->i_nlink = 0;
1326 +               iput(inode);
1327 +               return ERR_PTR(-EDQUOT);
1328 +       }
1329 +       return inode;
1330 +
1331 +fail:
1332 +       unlock_super(sb);
1333 +       make_bad_inode(inode);
1334 +       iput(inode);
1335 +       return ERR_PTR(errval);
1336 +}
1337 +
1338 +
1339 +void pram_read_inode (struct inode * inode)
1340 +{
1341 +       struct pram_inode * pi;
1342 +
1343 +       pi = pram_get_inode(inode->i_sb, inode->i_ino);
1344 +       pram_fill_inode(inode, pi);
1345 +}
1346 +
1347 +void pram_truncate (struct inode * inode)
1348 +{
1349 +       int blocksize, blocksize_bits;
1350 +       int blocknr;
1351 +       
1352 +       if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
1353 +             S_ISLNK(inode->i_mode)))
1354 +               return;
1355 +       if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
1356 +               return;
1357 +
1358 +       blocksize_bits = inode->i_sb->s_blocksize_bits;
1359 +       blocksize = 1 << blocksize_bits;
1360 +       blocknr = (inode->i_size + blocksize-1) >> blocksize_bits;
1361 +
1362 +       lock_kernel();
1363 +       pram_truncate_blocks(inode, blocknr);
1364 +       inode->i_mtime = inode->i_ctime = CURRENT_TIME;
1365 +       pram_update_inode(inode);
1366 +       unlock_kernel();
1367 +}
1368 +
1369 +
1370 +void pram_write_inode (struct inode * inode, int wait)
1371 +{
1372 +       lock_kernel();
1373 +       pram_update_inode(inode);
1374 +       unlock_kernel();
1375 +}
1376 +
1377 +/*
1378 + * dirty_inode() is called from __mark_inode_dirty()
1379 + */
1380 +void pram_dirty_inode(struct inode * inode)
1381 +{
1382 +       pram_write_inode(inode, 0);
1383 +}
1384 +
1385 +
1386 +static int pram_get_and_update_block(struct inode *inode, sector_t iblock,
1387 +                                    struct buffer_head *bh, int create)
1388 +{
1389 +       struct super_block * sb = inode->i_sb;
1390 +       unsigned int blocksize = 1 << inode->i_blkbits;
1391 +       int err = -EIO;
1392 +       unsigned long flags;
1393 +       pram_off_t block;
1394 +       void* bp;
1395 +       
1396 +       lock_kernel();
1397 +
1398 +       block = pram_find_data_block(inode, iblock);
1399 +       
1400 +       if (!block) {
1401 +               if (!create)
1402 +                       goto out;
1403 +               
1404 +               err = pram_alloc_blocks(inode, iblock, 1);
1405 +               if (err)
1406 +                       goto out;
1407 +               block = pram_find_data_block(inode, iblock);
1408 +               if (!block) {
1409 +                       err = -EIO;
1410 +                       goto out;
1411 +               }
1412 +               set_buffer_new(bh);
1413 +       }
1414 +
1415 +       bh->b_blocknr = block;
1416 +       set_buffer_mapped(bh);
1417 +
1418 +       /* now update the buffer synchronously */
1419 +       bp = pram_get_block(sb, block);
1420 +       if (buffer_new(bh)) {
1421 +               pram_lock_block(sb, bp);
1422 +               memset(bp, 0, blocksize);
1423 +               pram_unlock_block(sb, bp);
1424 +               memset(bh->b_data, 0, blocksize);
1425 +       } else {
1426 +               memcpy(bh->b_data, bp, blocksize);
1427 +       }
1428 +
1429 +       set_buffer_uptodate(bh);
1430 +       err = 0;
1431 +       
1432 + out:
1433 +       unlock_kernel();
1434 +       return err;
1435 +}
1436 +
1437 +#if 0
1438 +static int pram_writepage(struct page *page)
1439 +{
1440 +       return 0;
1441 +}
1442 +
1443 +static int pram_bmap(struct address_space *mapping, long block)
1444 +{
1445 +       return 0;
1446 +}
1447 +#endif
1448 +
1449 +static int pram_readpage(struct file *file, struct page *page)
1450 +{
1451 +       return block_read_full_page(page, pram_get_and_update_block);
1452 +}
1453 +
1454 +struct address_space_operations pram_aops = {
1455 +       readpage: pram_readpage,
1456 +//     writepage: pram_writepage,
1457 +//     bmap: pram_bmap,
1458 +       direct_IO: pram_direct_IO,
1459 +};
1460 diff -Nuar -X /home/stevel/dontdiff main.orig/fs/pramfs/ioctl.c main/fs/pramfs/ioctl.c
1461 --- main.orig/fs/pramfs/ioctl.c 1969-12-31 16:00:00.000000000 -0800
1462 +++ main/fs/pramfs/ioctl.c      2004-03-04 15:59:03.000000000 -0800
1463 @@ -0,0 +1,35 @@
1464 +/*
1465 + * ioctl.c
1466 + *
1467 + * Ioctl method for directory and regular files.
1468 + *
1469 + * Author: Steve Longerbeam <stevel@mvista.com, or source@mvista.com>
1470 + *
1471 + * 2003 (c) MontaVista Software, Inc.
1472 + * Copyright 2003 Sony Corporation
1473 + * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
1474 + *
1475 + * This software is being distributed under the terms of the GNU General Public
1476 + * License version 2.  Some or all of the technology encompassed by this
1477 + * software may be subject to one or more patents pending as of the date of
1478 + * this notice.  No additional patent license will be required for GPL
1479 + * implementations of the technology.  If you want to create a non-GPL
1480 + * implementation of the technology encompassed by this software, please
1481 + * contact legal@mvista.com for details including licensing terms and fees.
1482 + *
1483 + * This file is licensed under the terms of the GNU General Public License
1484 + * version 2. This program is licensed "as is" without any warranty of any
1485 + * kind, whether express or implied.
1486 + */
1487 +#include <linux/fs.h>
1488 +#include <linux/pram_fs.h>
1489 +#include <linux/sched.h>
1490 +#include <asm/uaccess.h>
1491 +
1492 +
1493 +int pram_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
1494 +               unsigned long arg)
1495 +{
1496 +       // FIXME: need any special ioctl's?
1497 +       return 0;
1498 +}
1499 diff -Nuar -X /home/stevel/dontdiff main.orig/fs/pramfs/Makefile main/fs/pramfs/Makefile
1500 --- main.orig/fs/pramfs/Makefile        1969-12-31 16:00:00.000000000 -0800
1501 +++ main/fs/pramfs/Makefile     2004-03-04 15:59:03.000000000 -0800
1502 @@ -0,0 +1,11 @@
1503 +#
1504 +# Makefile for the linux pram-filesystem routines.
1505 +#
1506 +
1507 +obj-$(CONFIG_PRAMFS) += pramfs.o
1508 +
1509 +pramfs-objs := balloc.o dir.o file.o fsync.o inode.o ioctl.o namei.o \
1510 +               super.o symlink.o
1511 +ifndef CONFIG_PRAMFS_NOWP
1512 +pramfs-objs += wprotect.o
1513 +endif
1514 diff -Nuar -X /home/stevel/dontdiff main.orig/fs/pramfs/namei.c main/fs/pramfs/namei.c
1515 --- main.orig/fs/pramfs/namei.c 1969-12-31 16:00:00.000000000 -0800
1516 +++ main/fs/pramfs/namei.c      2004-03-04 15:59:03.000000000 -0800
1517 @@ -0,0 +1,331 @@
1518 +/*
1519 + * namei.c
1520 + *
1521 + * Inode operations for directories.
1522 + *
1523 + * Author: Steve Longerbeam <stevel@mvista.com, or source@mvista.com>
1524 + *
1525 + * 2003 (c) MontaVista Software, Inc.
1526 + * Copyright 2003 Sony Corporation
1527 + * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
1528 + *
1529 + * This software is being distributed under the terms of the GNU General Public
1530 + * License version 2.  Some or all of the technology encompassed by this
1531 + * software may be subject to one or more patents pending as of the date of
1532 + * this notice.  No additional patent license will be required for GPL
1533 + * implementations of the technology.  If you want to create a non-GPL
1534 + * implementation of the technology encompassed by this software, please
1535 + * contact legal@mvista.com for details including licensing terms and fees.
1536 + *
1537 + * This file is licensed under the terms of the GNU General Public License
1538 + * version 2. This program is licensed "as is" without any warranty of any
1539 + * kind, whether express or implied.
1540 + */
1541 +#include <linux/fs.h>
1542 +#include <linux/pram_fs.h>
1543 +#include <linux/pagemap.h>
1544 +
1545 +
1546 +/*
1547 + * Couple of helper functions - make the code slightly cleaner.
1548 + */
1549 +
1550 +static inline void pram_inc_count(struct inode *inode)
1551 +{
1552 +       inode->i_nlink++;
1553 +       pram_write_inode(inode, 0);
1554 +}
1555 +
1556 +static inline void pram_dec_count(struct inode *inode)
1557 +{
1558 +       if (inode->i_nlink) {
1559 +               inode->i_nlink--;
1560 +               pram_write_inode(inode, 0);
1561 +       }
1562 +}
1563 +
1564 +static inline int pram_add_nondir(struct inode * dir,
1565 +                                  struct dentry * dentry,
1566 +                                  struct inode * inode)
1567 +{
1568 +       int err = pram_add_link(dentry, inode);
1569 +       if (!err) {
1570 +               d_instantiate(dentry, inode);
1571 +               return 0;
1572 +       }
1573 +       pram_dec_count(inode);
1574 +       iput(inode);
1575 +       return err;
1576 +}
1577 +
1578 +/*
1579 + * Methods themselves.
1580 + */
1581 +
1582 +static ino_t
1583 +pram_inode_by_name(struct inode * dir,
1584 +                  struct dentry * dentry)
1585 +{
1586 +       struct pram_inode * pi;
1587 +       ino_t ino;
1588 +       int namelen;
1589 +
1590 +       pi = pram_get_inode(dir->i_sb, dir->i_ino);
1591 +       ino = pi->i_type.dir.head;
1592 +       
1593 +       while (ino) {
1594 +               pi = pram_get_inode(dir->i_sb, ino);
1595 +
1596 +               if (pi->i_links_count) {
1597 +                       namelen = strlen(pi->i_d.d_name);
1598 +               
1599 +                       if (namelen == dentry->d_name.len &&
1600 +                           !memcmp(dentry->d_name.name,
1601 +                                   pi->i_d.d_name, namelen))
1602 +                               break;
1603 +               }
1604 +               
1605 +               ino = pi->i_d.d_next;
1606 +       }
1607 +       
1608 +       return ino;
1609 +}
1610 +
1611 +static struct dentry *
1612 +pram_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
1613 +{
1614 +       struct inode * inode = NULL;
1615 +       ino_t ino;
1616 +
1617 +       if (dentry->d_name.len > PRAM_NAME_LEN)
1618 +               return ERR_PTR(-ENAMETOOLONG);
1619 +
1620 +       ino = pram_inode_by_name(dir, dentry);
1621 +       if (ino) {
1622 +               struct pram_inode * pi = pram_get_inode(dir->i_sb, ino);
1623 +               inode = pram_fill_new_inode(dir->i_sb, pi);
1624 +               if (!inode)
1625 +                       return ERR_PTR(-EACCES);
1626 +       }
1627 +
1628 +       d_add(dentry, inode);
1629 +       return NULL;
1630 +}
1631 +
1632 +
1633 +/*
1634 + * By the time this is called, we already have created
1635 + * the directory cache entry for the new file, but it
1636 + * is so far negative - it has no inode.
1637 + *
1638 + * If the create succeeds, we fill in the inode information
1639 + * with d_instantiate(). 
1640 + */
1641 +static int pram_create (struct inode * dir, struct dentry * dentry,
1642 +                       int mode, struct nameidata *nd)
1643 +{
1644 +       struct inode * inode = pram_new_inode (dir, mode);
1645 +       int err = PTR_ERR(inode);
1646 +       if (!IS_ERR(inode)) {
1647 +               inode->i_op = &pram_file_inode_operations;
1648 +               inode->i_fop = &pram_file_operations;
1649 +               inode->i_mapping->a_ops = &pram_aops;
1650 +               err = pram_add_nondir(dir, dentry, inode);
1651 +       }
1652 +       return err;
1653 +}
1654 +
1655 +static int pram_mknod (struct inode * dir, struct dentry *dentry, int mode,
1656 +                      dev_t rdev)
1657 +{
1658 +       struct inode * inode = pram_new_inode (dir, mode);
1659 +       int err = PTR_ERR(inode);
1660 +       if (!IS_ERR(inode)) {
1661 +               init_special_inode(inode, mode, rdev);
1662 +               err = pram_add_nondir(dir, dentry, inode);
1663 +       }
1664 +       return err;
1665 +}
1666 +
1667 +static int pram_symlink (struct inode * dir,
1668 +                         struct dentry * dentry,
1669 +                         const char * symname)
1670 +{
1671 +       struct super_block * sb = dir->i_sb;
1672 +       int err = -ENAMETOOLONG;
1673 +       unsigned len = strlen(symname);
1674 +       struct inode * inode;
1675 +
1676 +       if (len+1 > sb->s_blocksize)
1677 +               goto out;
1678 +
1679 +       inode = pram_new_inode (dir, S_IFLNK | S_IRWXUGO);
1680 +       err = PTR_ERR(inode);
1681 +       if (IS_ERR(inode))
1682 +               goto out;
1683 +
1684 +       inode->i_op = &pram_symlink_inode_operations;
1685 +       inode->i_mapping->a_ops = &pram_aops;
1686 +       err = pram_block_symlink(inode, symname, len);
1687 +       if (err)
1688 +               goto out_fail;
1689 +
1690 +       inode->i_size = len;
1691 +       pram_write_inode(inode, 0);
1692 +
1693 +       err = pram_add_nondir(dir, dentry, inode);
1694 +out:
1695 +       return err;
1696 +
1697 +out_fail:
1698 +       pram_dec_count(inode);
1699 +       iput (inode);
1700 +       goto out;
1701 +}
1702 +
1703 +static int pram_link (struct dentry * dest_dentry,
1704 +                      struct inode * dir,
1705 +                      struct dentry * dentry)
1706 +{
1707 +       pram_dbg ("hard links not supported\n");
1708 +       return -ENOSYS;
1709 +}
1710 +
1711 +static int pram_unlink(struct inode * dir, struct dentry *dentry)
1712 +{
1713 +       struct inode * inode = dentry->d_inode;
1714 +       inode->i_ctime = dir->i_ctime;
1715 +       pram_dec_count(inode);
1716 +
1717 +       return 0;
1718 +}
1719 +
1720 +static int pram_mkdir(struct inode * dir, struct dentry * dentry, int mode)
1721 +{
1722 +       struct inode * inode;
1723 +       struct pram_inode * pi;
1724 +       unsigned long flags;
1725 +       int err = -EMLINK;
1726 +
1727 +       if (dir->i_nlink >= PRAM_LINK_MAX)
1728 +               goto out;
1729 +
1730 +       pram_inc_count(dir);
1731 +       
1732 +       inode = pram_new_inode (dir, S_IFDIR | mode);
1733 +       err = PTR_ERR(inode);
1734 +       if (IS_ERR(inode))
1735 +               goto out_dir;
1736 +
1737 +       inode->i_op = &pram_dir_inode_operations;
1738 +       inode->i_fop = &pram_dir_operations;
1739 +       inode->i_mapping->a_ops = &pram_aops;
1740 +
1741 +       pram_inc_count(inode);
1742 +
1743 +       // make the new directory empty
1744 +       pi = pram_get_inode(dir->i_sb, inode->i_ino);
1745 +       pram_lock_inode(pi);
1746 +       pi->i_type.dir.head = pi->i_type.dir.tail = 0;
1747 +       pram_unlock_inode(pi);
1748 +
1749 +       err = pram_add_link(dentry, inode);
1750 +       if (err)
1751 +               goto out_fail;
1752 +
1753 +       d_instantiate(dentry, inode);
1754 +out:
1755 +       return err;
1756 +
1757 +out_fail:
1758 +       pram_dec_count(inode);
1759 +       pram_dec_count(inode);
1760 +       iput(inode);
1761 +out_dir:
1762 +       pram_dec_count(dir);
1763 +       goto out;
1764 +}
1765 +
1766 +static int pram_rmdir (struct inode * dir, struct dentry *dentry)
1767 +{
1768 +       struct inode * inode = dentry->d_inode;
1769 +       struct pram_inode * pi;
1770 +       int err = -ENOTEMPTY;
1771 +       
1772 +       if (!inode)
1773 +               return -ENOENT;
1774 +
1775 +       pi = pram_get_inode(dir->i_sb, inode->i_ino);
1776 +
1777 +       // directory to delete is empty?
1778 +       if (pi->i_type.dir.tail == 0) {
1779 +               inode->i_ctime = dir->i_ctime;
1780 +               inode->i_size = 0;
1781 +               inode->i_nlink = 0;
1782 +               pram_write_inode(inode, 0);
1783 +               pram_dec_count(dir);
1784 +               err = 0;
1785 +       } else {
1786 +               pram_dbg("dir not empty\n");
1787 +       }
1788 +       
1789 +       return err;
1790 +}
1791 +
1792 +static int pram_rename (struct inode  * old_dir,
1793 +                       struct dentry * old_dentry,
1794 +                       struct inode  * new_dir,
1795 +                       struct dentry * new_dentry)
1796 +{
1797 +       struct inode * old_inode = old_dentry->d_inode;
1798 +       struct inode * new_inode = new_dentry->d_inode;
1799 +       struct pram_inode * pi_new;
1800 +       int err = -ENOENT;
1801 +
1802 +       if (new_inode) {
1803 +               err = -ENOTEMPTY;
1804 +               pi_new = pram_get_inode(new_dir->i_sb, new_inode->i_ino);
1805 +               if (S_ISDIR(old_inode->i_mode)) {
1806 +                       if (pi_new->i_type.dir.tail != 0)
1807 +                               goto out;
1808 +                       if (new_inode->i_nlink)
1809 +                               new_inode->i_nlink--;
1810 +               }
1811 +
1812 +               new_inode->i_ctime = CURRENT_TIME;
1813 +               pram_dec_count(new_inode);
1814 +       } else {
1815 +               if (S_ISDIR(old_inode->i_mode)) {
1816 +                       err = -EMLINK;
1817 +                       if (new_dir->i_nlink >= PRAM_LINK_MAX)
1818 +                               goto out;
1819 +                       pram_dec_count(old_dir);
1820 +                       pram_inc_count(new_dir);
1821 +               }
1822 +       }
1823 +
1824 +       /* unlink the inode from the old directory ... */
1825 +       if ((err = pram_remove_link(old_inode))) {
1826 +               goto out;
1827 +       }
1828 +       /* and link it into the new directory. */
1829 +       if ((err = pram_add_link(new_dentry, old_inode))) {
1830 +               goto out;
1831 +       }
1832 +
1833 +       err = 0;
1834 + out:
1835 +       return err;
1836 +}
1837 +
1838 +struct inode_operations pram_dir_inode_operations = {
1839 +       create:         pram_create,
1840 +       lookup:         pram_lookup,
1841 +       link:           pram_link,
1842 +       unlink:         pram_unlink,
1843 +       symlink:        pram_symlink,
1844 +       mkdir:          pram_mkdir,
1845 +       rmdir:          pram_rmdir,
1846 +       mknod:          pram_mknod,
1847 +       rename:         pram_rename,
1848 +};
1849 diff -Nuar -X /home/stevel/dontdiff main.orig/fs/pramfs/super.c main/fs/pramfs/super.c
1850 --- main.orig/fs/pramfs/super.c 1969-12-31 16:00:00.000000000 -0800
1851 +++ main/fs/pramfs/super.c      2004-03-04 15:59:03.000000000 -0800
1852 @@ -0,0 +1,393 @@
1853 +/*
1854 + * super.c
1855 + *
1856 + * Super block operations.
1857 + *
1858 + * Author: Steve Longerbeam <stevel@mvista.com, or source@mvista.com>
1859 + *
1860 + * 2003 (c) MontaVista Software, Inc.
1861 + * Copyright 2003 Sony Corporation
1862 + * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
1863 + *
1864 + * This software is being distributed under the terms of the GNU General Public
1865 + * License version 2.  Some or all of the technology encompassed by this
1866 + * software may be subject to one or more patents pending as of the date of
1867 + * this notice.  No additional patent license will be required for GPL
1868 + * implementations of the technology.  If you want to create a non-GPL
1869 + * implementation of the technology encompassed by this software, please
1870 + * contact legal@mvista.com for details including licensing terms and fees.
1871 + *
1872 + * This file is licensed under the terms of the GNU General Public License
1873 + * version 2. This program is licensed "as is" without any warranty of any
1874 + * kind, whether express or implied.
1875 + */
1876 +#include <linux/config.h>
1877 +#include <linux/module.h>
1878 +#include <linux/string.h>
1879 +#include <linux/slab.h>
1880 +#include <linux/init.h>
1881 +#include <linux/blkdev.h>
1882 +#include <linux/parser.h>
1883 +#include <linux/vfs.h>
1884 +#include <linux/pram_fs.h>
1885 +#include <asm/uaccess.h>
1886 +
1887 +MODULE_AUTHOR("Steve Longerbeam, stevel@mvista.com");
1888 +MODULE_DESCRIPTION("Protected/Persistent RAM Filesystem");
1889 +MODULE_LICENSE("GPL");
1890 +
1891 +static struct super_operations pram_sops;
1892 +
1893 +#ifndef MODULE
1894 +extern struct list_head super_blocks;
1895 +
1896 +struct super_block * find_pramfs_super(void)
1897 +{
1898 +       struct list_head *p;
1899 +       list_for_each(p, &super_blocks) {
1900 +               struct super_block * s = sb_entry(p);
1901 +               if (s->s_magic == PRAM_SUPER_MAGIC)
1902 +                       return s;
1903 +       }
1904 +       return NULL;
1905 +}
1906 +EXPORT_SYMBOL(find_pramfs_super);
1907 +#endif
1908 +
1909 +static void pram_set_blocksize(struct super_block * sb, unsigned long size)
1910 +{
1911 +       int bits;
1912 +       for (bits = 9, size >>= 9; size >>= 1; bits++)
1913 +               ;
1914 +       if (bits > 12)
1915 +               bits = 12;
1916 +       sb->s_blocksize_bits = bits;
1917 +       sb->s_blocksize = (1<<bits);
1918 +}
1919 +
1920 +static inline void * pram_ioremap(unsigned long phys_addr, size_t size,
1921 +                                 unsigned long flags)
1922 +{
1923 +       void * retval =  __ioremap(phys_addr, size, flags);
1924 +#ifndef CONFIG_PRAMFS_NOWP
1925 +       if (retval) {
1926 +               spin_lock(&init_mm.page_table_lock);
1927 +               pram_writeable(retval, size, 0);
1928 +               spin_unlock(&init_mm.page_table_lock);
1929 +       }
1930 +#endif
1931 +       return retval;
1932 +}
1933 +
1934 +
1935 +static int pram_fill_super (struct super_block * sb, void * data, int silent)
1936 +{
1937 +       char *p;
1938 +       struct pram_super_block * super;
1939 +       struct pram_inode * root_i;
1940 +       struct pram_sb_info * sbi=NULL;
1941 +       pram_off_t root_offset;
1942 +       unsigned long flags;
1943 +       unsigned long maxsize, blocksize;
1944 +       int retval = -EINVAL;
1945 +       
1946 +       /*
1947 +        * The physical location of the pram image is specified as
1948 +        * a mount parameter.  This parameter is mandatory for obvious
1949 +        * reasons.  Some validation is made on the phys address but this
1950 +        * is not exhaustive and we count on the fact that someone using
1951 +        * this feature is supposed to know what he/she's doing.
1952 +        */
1953 +       if (!data || !(p = strstr((char *)data, "physaddr="))) {
1954 +               pram_err("unknown physical address for pramfs image\n");
1955 +               goto out;
1956 +       }
1957 +
1958 +       sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
1959 +       if (!sbi)
1960 +               return -ENOMEM;
1961 +       sb->s_fs_info = sbi;
1962 +       memset(sbi, 0, sizeof(*sbi));
1963 +
1964 +       sbi->phys_addr = simple_strtoul(p + 9, NULL, 0);
1965 +       if (sbi->phys_addr & (PAGE_SIZE-1)) {
1966 +               pram_err("physical address 0x%lx for pramfs isn't "
1967 +                         "aligned to a page boundary\n",
1968 +                         sbi->phys_addr);
1969 +               goto out;
1970 +       }
1971 +
1972 +       if (sbi->phys_addr == 0) {
1973 +               pram_err("physical address for pramfs image can't be 0\n");
1974 +               goto out;
1975 +       }
1976 +
1977 +       if ((p = strstr((char *)data, "init="))) {
1978 +               unsigned long bpi, num_inodes, bitmap_size;
1979 +               unsigned long num_blocks;
1980 +               pram_off_t bitmap_start;
1981 +
1982 +               maxsize = simple_strtoul(p + 5, NULL, 0);
1983 +               pram_info("creating an empty pramfs of size %lu\n", maxsize);
1984 +               
1985 +               sbi->virt_addr = pram_ioremap(sbi->phys_addr, maxsize, 0);
1986 +               if (!sbi->virt_addr) {
1987 +                       pram_err("ioremap of the pramfs image failed\n");
1988 +                       goto out;
1989 +               }
1990 +               
1991 +               if ((p = strstr((char *)data, "bs=")))
1992 +                       blocksize = simple_strtoul(p + 3, NULL, 0);
1993 +               else
1994 +                       blocksize = PRAM_DEF_BLOCK_SIZE;
1995 +
1996 +               pram_set_blocksize(sb, blocksize);
1997 +               blocksize = sb->s_blocksize;
1998 +               
1999 +               if ((p = strstr((char *)data, "bpi=")))
2000 +                       bpi = simple_strtoul(p + 4, NULL, 0);
2001 +               else {
2002 +                       /* default is that 5% of the filesystem is
2003 +                          devoted to the inode table */
2004 +                       bpi = 20 * PRAM_INODE_SIZE;
2005 +               }
2006 +               
2007 +               if ((p = strstr((char *)data, "N=")))
2008 +                       num_inodes = simple_strtoul(p + 2, NULL, 0);
2009 +               else
2010 +                       num_inodes = maxsize / bpi;
2011 +
2012 +               /* up num_inodes such that the end of the inode table
2013 +                  (and start of bitmap) is on a block boundary */
2014 +               bitmap_start = PRAM_SB_SIZE + (num_inodes<<PRAM_INODE_BITS);
2015 +               if (bitmap_start & (blocksize - 1))
2016 +                       bitmap_start = (bitmap_start + blocksize) &
2017 +                               ~(blocksize-1);
2018 +               num_inodes = (bitmap_start - PRAM_SB_SIZE) >> PRAM_INODE_BITS;
2019 +               
2020 +               num_blocks = (maxsize - bitmap_start) >> sb->s_blocksize_bits;
2021 +               
2022 +               /* calc the data blocks in-use bitmap size in bytes */
2023 +               if (num_blocks & 7)
2024 +                       bitmap_size = ((num_blocks + 8) & ~7) >> 3;
2025 +               else
2026 +                       bitmap_size = num_blocks >> 3;
2027 +               /* round it up to the nearest blocksize boundary */
2028 +               if (bitmap_size & (blocksize - 1))
2029 +                       bitmap_size = (bitmap_size + blocksize) &
2030 +                               ~(blocksize-1);
2031 +               
2032 +               pram_info("blocksize %lu, num inodes %lu, num blocks %lu\n",
2033 +                         blocksize, num_inodes, num_blocks);
2034 +               pram_dbg("bitmap start 0x%08x, bitmap size %lu\n",
2035 +                        (unsigned long)bitmap_start, bitmap_size);
2036 +               pram_dbg("max name length %d\n", PRAM_NAME_LEN);
2037 +
2038 +               super = pram_get_super(sb);
2039 +               pram_lock_range(super, bitmap_start + bitmap_size);
2040 +
2041 +               /* clear out super-block and inode table */
2042 +               memset(super, 0, bitmap_start);
2043 +               super->s_size = maxsize;
2044 +               super->s_blocksize = blocksize;
2045 +               super->s_inodes_count = num_inodes;
2046 +               super->s_blocks_count = num_blocks;
2047 +               super->s_free_inodes_count = num_inodes - 1;
2048 +               super->s_bitmap_blocks = bitmap_size >> sb->s_blocksize_bits;
2049 +               super->s_free_blocks_count =
2050 +                       num_blocks - super->s_bitmap_blocks;
2051 +               super->s_free_inode_hint = 1;
2052 +               super->s_bitmap_start = bitmap_start;
2053 +               super->s_magic = PRAM_SUPER_MAGIC;
2054 +               pram_sync_super(super);
2055 +
2056 +               root_i = pram_get_inode(sb, PRAM_ROOT_INO);
2057 +               root_i->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
2058 +               root_i->i_links_count = 2;
2059 +               root_i->i_d.d_parent = PRAM_ROOT_INO;
2060 +               pram_sync_inode(root_i);
2061 +
2062 +               pram_init_bitmap(sb);
2063 +
2064 +               pram_unlock_range(super, bitmap_start + bitmap_size);
2065 +
2066 +               goto setup_sb;
2067 +       }
2068 +
2069 +       pram_info("checking physical address 0x%lx for pramfs image\n",
2070 +                  sbi->phys_addr);
2071 +       
2072 +       /* Map only one page for now. Will remap it when fs size is known. */
2073 +       sbi->virt_addr = pram_ioremap(sbi->phys_addr, PAGE_SIZE, 0);
2074 +       if (!sbi->virt_addr) {
2075 +               pram_err("ioremap of the pramfs image failed\n");
2076 +               goto out;
2077 +       }
2078 +
2079 +       super = pram_get_super(sb);
2080 +       
2081 +       /* Do sanity checks on the superblock */
2082 +       if (super->s_magic != PRAM_SUPER_MAGIC) {
2083 +               pram_err("wrong magic\n");
2084 +               goto out;
2085 +       }
2086 +       /* Read the superblock */
2087 +       if (pram_calc_checksum((u32*)super, PRAM_SB_SIZE>>2)) {
2088 +               pram_err("checksum error in super block!\n");
2089 +               goto out;
2090 +       }
2091 +
2092 +       /* get feature flags first */
2093 +       // FIXME: implement fs features?
2094 +#if 0
2095 +       if (super->s_features & ~PRAM_SUPPORTED_FLAGS) {
2096 +               pram_err("unsupported filesystem features\n");
2097 +               goto out;
2098 +       }
2099 +#endif
2100 +       
2101 +       blocksize = super->s_blocksize;
2102 +       pram_set_blocksize(sb, blocksize);
2103 +       
2104 +       maxsize = super->s_size;
2105 +       pram_info("pramfs image appears to be %lu KB in size\n", maxsize>>10);
2106 +       pram_info("blocksize %lu\n", blocksize);
2107 +
2108 +       /* Read the root inode */
2109 +       root_i = pram_get_inode(sb, PRAM_ROOT_INO);
2110 +       
2111 +       if (pram_calc_checksum((u32*)root_i, PRAM_INODE_SIZE>>2)) {
2112 +               pram_err("checksum error in root inode!\n");
2113 +               goto out;
2114 +       }
2115 +
2116 +       /* Check that the root inode is in a sane state */
2117 +       if (root_i->i_d.d_next) {
2118 +               pram_err("root->next not NULL??!!\n");
2119 +               goto out;
2120 +       }
2121 +
2122 +       if (!S_ISDIR(root_i->i_mode)) {
2123 +               pram_err("root is not a directory!\n");
2124 +               goto out;
2125 +       }
2126 +
2127 +       root_offset = root_i->i_type.dir.head;
2128 +       if (root_offset == 0)
2129 +               pram_info("empty filesystem\n");
2130 +
2131 +       /* Remap the whole filesystem now */
2132 +       iounmap(sbi->virt_addr);
2133 +       sbi->virt_addr = pram_ioremap(sbi->phys_addr, maxsize, 0);
2134 +       if (!sbi->virt_addr) {
2135 +               pram_err("ioremap of the pramfs image failed\n");
2136 +               goto out;
2137 +       }
2138 +       super = pram_get_super(sb);
2139 +
2140 +       /* Set it all up.. */
2141 + setup_sb:
2142 +       sbi->maxsize = maxsize;
2143 +       sb->s_magic = sbi->magic = super->s_magic;
2144 +       sbi->features = super->s_features;
2145 +
2146 +       sb->s_op = &pram_sops;
2147 +       sb->s_root = d_alloc_root(pram_fill_new_inode(sb, root_i));
2148 +
2149 +       retval = 0;
2150 + out:
2151 +       if (retval && sbi->virt_addr)
2152 +               iounmap(sbi->virt_addr);
2153 +
2154 +       return retval;
2155 +}
2156 +
2157 +//static void pram_write_super (struct super_block * sb)
2158 +//{
2159 +//}
2160 +
2161 +int pram_statfs (struct super_block * sb, struct kstatfs * buf)
2162 +{
2163 +       struct pram_super_block * ps = pram_get_super(sb);
2164 +
2165 +       buf->f_type = PRAM_SUPER_MAGIC;
2166 +       buf->f_bsize = sb->s_blocksize;
2167 +       buf->f_blocks = ps->s_blocks_count;
2168 +       buf->f_bfree = buf->f_bavail = ps->s_free_blocks_count;
2169 +       buf->f_files = ps->s_inodes_count;
2170 +       buf->f_ffree = ps->s_free_inodes_count;
2171 +       buf->f_namelen = PRAM_NAME_LEN;
2172 +       return 0;
2173 +}
2174 +
2175 +int pram_remount (struct super_block * sb, int * mntflags, char * data)
2176 +{
2177 +       struct pram_super_block * ps;
2178 +       unsigned long flags;
2179 +
2180 +       if ((*mntflags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) {
2181 +               ps = pram_get_super(sb);
2182 +               pram_lock_super(ps);
2183 +               ps->s_mtime = get_seconds(); // update mount time
2184 +               pram_unlock_super(ps);
2185 +       }
2186 +       return 0;
2187 +}
2188 +
2189 +void pram_put_super (struct super_block * sb)
2190 +{
2191 +       struct pram_sb_info * sbi = (struct pram_sb_info *)sb->s_fs_info;
2192 +
2193 +       /* It's unmount time, so unmap the pramfs memory */
2194 +       if (sbi->virt_addr) {
2195 +               iounmap(sbi->virt_addr);
2196 +               sbi->virt_addr = NULL;
2197 +       }
2198 +
2199 +       sb->s_fs_info = NULL;
2200 +       kfree(sbi);
2201 +}
2202 +
2203 +/*
2204 + * the super block writes are all done "on the fly", so the
2205 + * super block is never in a "dirty" state, so there's no need
2206 + * for write_super.
2207 + */
2208 +static struct super_operations pram_sops = {
2209 +       read_inode:     pram_read_inode,
2210 +       write_inode:    pram_write_inode,
2211 +       dirty_inode:    pram_dirty_inode,
2212 +       put_inode:      pram_put_inode,
2213 +       delete_inode:   pram_delete_inode,
2214 +       put_super:      pram_put_super,
2215 +       //write_super:  pram_write_super,
2216 +       statfs:         pram_statfs,
2217 +       remount_fs:     pram_remount,
2218 +};
2219 +
2220 +static struct super_block *pram_get_sb(struct file_system_type *fs_type,
2221 +                                      int flags, const char *dev_name,
2222 +                                      void *data)
2223 +{
2224 +       return get_sb_single(fs_type, flags, data, pram_fill_super);
2225 +}
2226 +
2227 +static struct file_system_type pram_fs_type = {
2228 +       .owner          = THIS_MODULE,
2229 +       .name           = "pramfs",
2230 +       .get_sb         = pram_get_sb,
2231 +       .kill_sb        = kill_anon_super,
2232 +};
2233 +
2234 +static int __init init_pram_fs(void)
2235 +{
2236 +        return register_filesystem(&pram_fs_type);
2237 +}
2238 +
2239 +static void __exit exit_pram_fs(void)
2240 +{
2241 +       unregister_filesystem(&pram_fs_type);
2242 +}
2243 +
2244 +module_init(init_pram_fs)
2245 +module_exit(exit_pram_fs)
2246 diff -Nuar -X /home/stevel/dontdiff main.orig/fs/pramfs/symlink.c main/fs/pramfs/symlink.c
2247 --- main.orig/fs/pramfs/symlink.c       1969-12-31 16:00:00.000000000 -0800
2248 +++ main/fs/pramfs/symlink.c    2004-03-04 15:59:03.000000000 -0800
2249 @@ -0,0 +1,76 @@
2250 +/*
2251 + * symlink.c
2252 + *
2253 + * Symlink methods.
2254 + *
2255 + * Author: Steve Longerbeam <stevel@mvista.com, or source@mvista.com>
2256 + *
2257 + * 2003 (c) MontaVista Software, Inc.
2258 + * Copyright 2003 Sony Corporation
2259 + * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
2260 + *
2261 + * This software is being distributed under the terms of the GNU General Public
2262 + * License version 2.  Some or all of the technology encompassed by this
2263 + * software may be subject to one or more patents pending as of the date of
2264 + * this notice.  No additional patent license will be required for GPL
2265 + * implementations of the technology.  If you want to create a non-GPL
2266 + * implementation of the technology encompassed by this software, please
2267 + * contact legal@mvista.com for details including licensing terms and fees.
2268 + *
2269 + * This file is licensed under the terms of the GNU General Public License
2270 + * version 2. This program is licensed "as is" without any warranty of any
2271 + * kind, whether express or implied.
2272 + */
2273 +#include <linux/fs.h>
2274 +#include <linux/pram_fs.h>
2275 +
2276 +int pram_block_symlink(struct inode *inode, const char *symname, int len)
2277 +{
2278 +       struct super_block * sb = inode->i_sb;
2279 +       pram_off_t block;
2280 +       char* blockp;
2281 +       unsigned long flags;
2282 +       int err;
2283 +       
2284 +       err = pram_alloc_blocks (inode, 0, 1);
2285 +       if (err)
2286 +               return err;
2287 +
2288 +       block = pram_find_data_block(inode, 0);
2289 +       blockp = pram_get_block(sb, block);
2290 +       
2291 +       pram_lock_block(sb, blockp);
2292 +       memcpy(blockp, symname, len);
2293 +       blockp[len] = '\0';
2294 +       pram_unlock_block(sb, blockp);
2295 +       return 0;
2296 +}
2297 +
2298 +static int pram_readlink(struct dentry *dentry, char *buffer, int buflen)
2299 +{
2300 +       struct inode * inode = dentry->d_inode;
2301 +       struct super_block * sb = inode->i_sb;
2302 +       pram_off_t block;
2303 +       char* blockp;
2304 +       
2305 +       block = pram_find_data_block(inode, 0);
2306 +       blockp = pram_get_block(sb, block);
2307 +       return vfs_readlink(dentry, buffer, buflen, blockp);
2308 +}
2309 +
2310 +static int pram_follow_link(struct dentry *dentry, struct nameidata *nd)
2311 +{
2312 +       struct inode * inode = dentry->d_inode;
2313 +       struct super_block * sb = inode->i_sb;
2314 +       pram_off_t block;
2315 +       char* blockp;
2316 +
2317 +       block = pram_find_data_block(inode, 0);
2318 +       blockp = pram_get_block(sb, block);
2319 +       return vfs_follow_link(nd, blockp);
2320 +}
2321 +
2322 +struct inode_operations pram_symlink_inode_operations = {
2323 +       readlink:       pram_readlink,
2324 +       follow_link:    pram_follow_link,
2325 +};
2326 diff -Nuar -X /home/stevel/dontdiff main.orig/fs/pramfs/wprotect.c main/fs/pramfs/wprotect.c
2327 --- main.orig/fs/pramfs/wprotect.c      1969-12-31 16:00:00.000000000 -0800
2328 +++ main/fs/pramfs/wprotect.c   2004-03-04 15:59:03.000000000 -0800
2329 @@ -0,0 +1,80 @@
2330 +/*
2331 + * wprotect.c
2332 + *
2333 + * Write protection for the filesystem pages.
2334 + *
2335 + * Author: Steve Longerbeam <stevel@mvista.com, or source@mvista.com>
2336 + *
2337 + * 2003 (c) MontaVista Software, Inc.
2338 + * Copyright 2003 Sony Corporation
2339 + * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
2340 + *
2341 + * This software is being distributed under the terms of the GNU General Public
2342 + * License version 2.  Some or all of the technology encompassed by this
2343 + * software may be subject to one or more patents pending as of the date of
2344 + * this notice.  No additional patent license will be required for GPL
2345 + * implementations of the technology.  If you want to create a non-GPL
2346 + * implementation of the technology encompassed by this software, please
2347 + * contact legal@mvista.com for details including licensing terms and fees.
2348 + *
2349 + * This file is licensed under the terms of the GNU General Public License
2350 + * version 2. This program is licensed "as is" without any warranty of any
2351 + * kind, whether express or implied.
2352 + */
2353 +#include <linux/config.h>
2354 +#include <linux/module.h>
2355 +#include <linux/fs.h>
2356 +#include <linux/pram_fs.h>
2357 +#include <linux/mm.h>
2358 +#include <asm/pgtable.h>
2359 +#include <asm/pgalloc.h>
2360 +
2361 +// init_mm.page_table_lock must be held before calling!
2362 +static void pram_page_writeable(unsigned long addr, int rw)
2363 +{
2364 +       pgd_t *pgdp;
2365 +       pmd_t *pmdp;
2366 +       pte_t *ptep;
2367 +       
2368 +       pgdp = pgd_offset_k(addr);
2369 +       if (!pgd_none(*pgdp)) {
2370 +               pmdp = pmd_offset(pgdp, addr);
2371 +               if (!pmd_none(*pmdp)) {
2372 +                       pte_t pte;
2373 +                       ptep = pte_offset_kernel(pmdp, addr);
2374 +                       pte = *ptep;
2375 +                       if (pte_present(pte)) {
2376 +                               pte = rw ? pte_mkwrite(pte) :
2377 +                                       pte_wrprotect(pte);
2378 +                               set_pte(ptep, pte);
2379 +                       }
2380 +               }
2381 +       }
2382 +}
2383 +
2384 +
2385 +// init_mm.page_table_lock must be held before calling!
2386 +void pram_writeable(void * vaddr, unsigned long size, int rw)
2387 +{
2388 +        unsigned long addr = (unsigned long)vaddr & PAGE_MASK;
2389 +       unsigned long end = (unsigned long)vaddr + size;
2390 +       unsigned long start = addr;
2391 +
2392 +       do {
2393 +               pram_page_writeable(addr, rw);
2394 +               addr += PAGE_SIZE;
2395 +       } while (addr && (addr < end));
2396 +
2397 +
2398 +       /*
2399 +        * NOTE: we will always flush just one page (one TLB
2400 +        * entry) except possibly in one case: when a new
2401 +        * filesystem is initialized at mount time, when pram_read_super
2402 +        * calls pram_lock_range to make the super block, inode
2403 +        * table, and bitmap writeable.
2404 +        */
2405 +       if (end <= start + PAGE_SIZE)
2406 +               flush_tlb_kernel_page(start);
2407 +       else
2408 +               flush_tlb_kernel_range(start, end);
2409 +}
2410 diff -Nuar -X /home/stevel/dontdiff main.orig/include/linux/pram_fs.h main/include/linux/pram_fs.h
2411 --- main.orig/include/linux/pram_fs.h   1969-12-31 16:00:00.000000000 -0800
2412 +++ main/include/linux/pram_fs.h        2004-03-04 15:59:35.000000000 -0800
2413 @@ -0,0 +1,378 @@
2414 +/*
2415 + * pram_fs.h
2416 + *
2417 + * Definitions for the PRAMFS filesystem.
2418 + *
2419 + * Author: Steve Longerbeam <stevel@mvista.com, or source@mvista.com>
2420 + *
2421 + * 2003 (c) MontaVista Software, Inc.
2422 + * Copyright 2003 Sony Corporation
2423 + * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
2424 + *
2425 + * This software is being distributed under the terms of the GNU General Public
2426 + * License version 2.  Some or all of the technology encompassed by this
2427 + * software may be subject to one or more patents pending as of the date of
2428 + * this notice.  No additional patent license will be required for GPL
2429 + * implementations of the technology.  If you want to create a non-GPL
2430 + * implementation of the technology encompassed by this software, please
2431 + * contact legal@mvista.com for details including licensing terms and fees.
2432 + *
2433 + * This file is licensed under the terms of the GNU General Public License
2434 + * version 2. This program is licensed "as is" without any warranty of any
2435 + * kind, whether express or implied.
2436 + */
2437 +#ifndef _LINUX_PRAM_FS_H
2438 +#define _LINUX_PRAM_FS_H
2439 +
2440 +#include <linux/types.h>
2441 +#include <linux/pram_fs_sb.h>
2442 +
2443 +#ifdef __KERNEL__
2444 +#include <linux/sched.h>
2445 +#endif
2446 +
2447 +/*
2448 + * The PRAM filesystem constants/structures
2449 + */
2450 +
2451 +/*
2452 + * Define PRAMFS_DEBUG to produce debug messages
2453 + */
2454 +#undef PRAMFS_DEBUG
2455 +
2456 +/*
2457 + * The PRAM filesystem version
2458 + */
2459 +#define PRAMFS_DATE            "2003/06/15"
2460 +#define PRAMFS_VERSION         "0.1b"
2461 +
2462 +/*
2463 + * Debug code
2464 + */
2465 +#ifdef __KERNEL__
2466 +#define PFX "pramfs"
2467 +#ifdef PRAMFS_DEBUG
2468 +#define pram_dbg(format, arg...) \
2469 +    printk(KERN_DEBUG PFX ": " format , ## arg)
2470 +#else
2471 +#define pram_dbg(format, arg...) do {} while (0)
2472 +#endif
2473 +#define pram_err(format, arg...) \
2474 +    printk(KERN_ERR PFX ": " format , ## arg)
2475 +#define pram_info(format, arg...) \
2476 +    printk(KERN_INFO PFX ": " format , ## arg)
2477 +#define pram_warn(format, arg...) \
2478 +    printk(KERN_WARNING PFX ": " format , ## arg)
2479 +#endif
2480 +
2481 +/*
2482 + * The PRAM file system magic number
2483 + */
2484 +#define PRAM_SUPER_MAGIC       0xEFFA
2485 +
2486 +/*
2487 + * Maximal count of links to a file
2488 + */
2489 +#define PRAM_LINK_MAX          32000
2490 +
2491 +typedef unsigned long pram_off_t;
2492 +
2493 +#define PRAM_MIN_BLOCK_SIZE 512
2494 +#define        PRAM_MAX_BLOCK_SIZE 4096
2495 +#define PRAM_DEF_BLOCK_SIZE 2048
2496 +
2497 +#define PRAM_INODE_SIZE 128 // must be power of two
2498 +#define PRAM_INODE_BITS   7
2499 +
2500 +/*
2501 + * Structure of a directory entry in PRAMFS.
2502 + * Offsets are to the inode that holds the referenced dentry.
2503 + */
2504 +struct pram_dentry {
2505 +       pram_off_t d_next;     /* next dentry in this directory */
2506 +       pram_off_t d_prev;     /* previous dentry in this directory */
2507 +       pram_off_t d_parent;   /* parent directory */
2508 +       char       d_name[0];
2509 +};
2510 +
2511 +
2512 +/*
2513 + * Structure of an inode in PRAMFS
2514 + */
2515 +struct pram_inode {
2516 +       __u32   i_sum;          /* checksum of this inode */
2517 +       __u32   i_uid;          /* Owner Uid */
2518 +       __u32   i_gid;          /* Group Id */
2519 +       __u16   i_mode;         /* File mode */
2520 +       __u16   i_links_count;  /* Links count */
2521 +       __u32   i_blocks;       /* Blocks count */
2522 +       __u32   i_size;         /* Size of data in bytes */
2523 +       __u32   i_atime;        /* Access time */
2524 +       __u32   i_ctime;        /* Creation time */
2525 +       __u32   i_mtime;        /* Modification time */
2526 +       __u32   i_dtime;        /* Deletion Time */
2527 +
2528 +       union {
2529 +               struct {
2530 +                       /*
2531 +                        * ptr to row block of 2D block pointer array,
2532 +                        * file block #'s 0 to (blocksize/4)^2 - 1.
2533 +                        */
2534 +                       pram_off_t row_block;
2535 +               } reg;   // regular file or symlink inode
2536 +               struct {
2537 +                       pram_off_t head; /* first entry in this directory */
2538 +                       pram_off_t tail; /* last entry in this directory */
2539 +               } dir;
2540 +               struct {
2541 +                       __u32 rdev; /* major/minor # */
2542 +               } dev;   // device inode
2543 +       } i_type;
2544 +
2545 +       struct pram_dentry i_d;
2546 +};
2547 +
2548 +#define PRAM_NAME_LEN \
2549 +    (PRAM_INODE_SIZE - offsetof(struct pram_inode, i_d.d_name) - 1)
2550 +
2551 +
2552 +/*
2553 + * Behaviour when detecting errors
2554 + */
2555 +#define PRAM_ERRORS_CONTINUE           1       /* Continue execution */
2556 +#define PRAM_ERRORS_RO                 2       /* Remount fs read-only */
2557 +#define PRAM_ERRORS_PANIC              3       /* Panic */
2558 +#define PRAM_ERRORS_DEFAULT            PRAM_ERRORS_CONTINUE
2559 +
2560 +#define PRAM_SB_SIZE 128 // must be power of two
2561 +#define PRAM_SB_BITS   7
2562 +
2563 +/*
2564 + * Structure of the super block in PRAMFS
2565 + */
2566 +struct pram_super_block {
2567 +       __u32   s_size;         /* total size of fs in bytes */
2568 +       __u32   s_blocksize;    /* blocksize in bytes */
2569 +       __u32   s_features;     /* feature flags */
2570 +       __u32   s_inodes_count; /* total inodes count (used or free) */
2571 +       __u32   s_free_inodes_count;/* free inodes count */
2572 +       __u32   s_free_inode_hint;  /* start hint for locating free inodes */
2573 +       __u32   s_blocks_count; /* total data blocks count (used or free) */
2574 +       __u32   s_free_blocks_count;/* free data blocks count */
2575 +       __u32   s_free_blocknr_hint;/* free data blocks count */
2576 +       pram_off_t s_bitmap_start; /* data block in-use bitmap location */
2577 +       __u32   s_bitmap_blocks;/* size of bitmap in number of blocks */
2578 +       __u32   s_mtime;        /* Mount time */
2579 +       __u32   s_wtime;        /* Write time */
2580 +       __u32   s_rev_level;    /* Revision level */
2581 +       __u16   s_magic;        /* Magic signature */
2582 +       __u16   s_state;        /* File system state */
2583 +       __u16   s_errors;       /* Behaviour when detecting errors */
2584 +       char    s_volume_name[16]; /* volume name */
2585 +       __u32   s_sum;          /* checksum of this sb, including padding */
2586 +};
2587 +
2588 +/* The root inode follows immediately after the super block */
2589 +#define PRAM_ROOT_INO PRAM_SB_SIZE
2590 +
2591 +#ifdef __KERNEL__
2592 +
2593 +/* Function Prototypes */
2594 +
2595 +/* balloc.c */
2596 +extern void pram_init_bitmap(struct super_block * sb);
2597 +extern void pram_free_block (struct super_block * sb, int blocknr);
2598 +extern int pram_new_block (struct super_block * sb, int* blocknr, int zero);
2599 +extern unsigned long pram_count_free_blocks (struct super_block * sb);
2600 +
2601 +/* dir.c */
2602 +extern int pram_add_link (struct dentry * dentry, struct inode *inode);
2603 +extern int pram_remove_link(struct inode * inode);
2604 +
2605 +/* file.c */
2606 +extern int pram_direct_IO(int rw, struct kiocb *iocb,
2607 +                         const struct iovec *iov,
2608 +                         loff_t offset, unsigned long nr_segs);
2609 +
2610 +/* fsync.c */
2611 +extern int pram_sync_file (struct file *, struct dentry *, int);
2612 +extern int pram_fsync_inode (struct inode *, int);
2613 +
2614 +/* inode.c */
2615 +extern int pram_alloc_blocks(struct inode * inode, int file_blocknr, int num);
2616 +extern pram_off_t pram_find_data_block(struct inode * inode,
2617 +                                        int file_blocknr);
2618 +extern struct inode * pram_fill_new_inode(struct super_block *sb,
2619 +                                          struct pram_inode * raw_inode);
2620 +extern void pram_put_inode (struct inode * inode);
2621 +extern void pram_delete_inode (struct inode * inode);
2622 +extern struct inode * pram_new_inode (const struct inode * dir, int mode);
2623 +extern void pram_read_inode (struct inode * inode);
2624 +extern void pram_truncate (struct inode * inode);
2625 +extern void pram_write_inode (struct inode * inode, int wait);
2626 +extern void pram_dirty_inode(struct inode * inode);
2627 +
2628 +/* ioctl.c */
2629 +extern int pram_ioctl (struct inode *, struct file *, unsigned int,
2630 +                       unsigned long);
2631 +
2632 +/* super.c */
2633 +extern struct super_block * find_pramfs_super(void);
2634 +extern struct super_block * pram_read_super (struct super_block * sb,
2635 +                                             void * data,
2636 +                                             int silent);
2637 +extern int pram_statfs (struct super_block * sb, struct kstatfs * buf);
2638 +extern int pram_remount (struct super_block * sb, int * flags, char * data);
2639 +
2640 +/* symlink.c */
2641 +extern int pram_block_symlink(struct inode *inode,
2642 +                              const char *symname, int len);
2643 +
2644 +/* wprotect.c */
2645 +#ifndef CONFIG_PRAMFS_NOWP
2646 +extern void pram_writeable (void * vaddr, unsigned long size, int rw);
2647 +#endif
2648 +
2649 +/* Inline functions start here */
2650 +
2651 +static inline u32 pram_calc_checksum(u32* buf, int n)
2652 +{
2653 +       u32 sum = 0;
2654 +       while (n--)
2655 +               sum += *buf++;
2656 +       return sum;
2657 +}
2658 +
2659 +// If this is part of a read-modify-write of the super block,
2660 +// pram_lock_super() before calling!
2661 +static inline struct pram_super_block *
2662 +pram_get_super(struct super_block * sb)
2663 +{
2664 +       struct pram_sb_info * sbi = (struct pram_sb_info *)sb->s_fs_info;
2665 +       return (struct pram_super_block *)sbi->virt_addr;
2666 +}
2667 +
2668 +// pram_lock_super() before calling!
2669 +static inline void pram_sync_super(struct pram_super_block * ps)
2670 +{
2671 +       ps->s_wtime = get_seconds();
2672 +       ps->s_sum = 0;
2673 +       ps->s_sum = - pram_calc_checksum((u32*)ps, PRAM_SB_SIZE>>2);
2674 +}
2675 +
2676 +// pram_lock_inode() before calling!
2677 +static inline void pram_sync_inode(struct pram_inode * pi)
2678 +{
2679 +       //pi->i_mtime = CURRENT_TIME;
2680 +       pi->i_sum = 0;
2681 +       pi->i_sum = - pram_calc_checksum((u32*)pi, PRAM_INODE_SIZE>>2);
2682 +}
2683 +
2684 +#ifndef CONFIG_PRAMFS_NOWP
2685 +#define pram_lock_range(p, len) {\
2686 +       spin_lock_irqsave(&init_mm.page_table_lock, flags);\
2687 +       pram_writeable((p), (len), 1);\
2688 +}
2689 +
2690 +#define pram_unlock_range(p, len) {\
2691 +       pram_writeable((p), (len), 0);\
2692 +       spin_unlock_irqrestore(&init_mm.page_table_lock, flags);\
2693 +}
2694 +#else
2695 +#define pram_lock_range(p, len) do {} while (0)
2696 +#define pram_unlock_range(p, len) do {} while (0)
2697 +#endif
2698 +
2699 +// write protection for super block
2700 +#define pram_lock_super(ps) \
2701 +        pram_lock_range((ps), PRAM_SB_SIZE)
2702 +#define pram_unlock_super(ps) {\
2703 +       pram_sync_super(ps);\
2704 +        pram_unlock_range((ps), PRAM_SB_SIZE);\
2705 +}
2706 +
2707 +// write protection for inode metadata
2708 +#define pram_lock_inode(pi) \
2709 +        pram_lock_range((pi), PRAM_INODE_SIZE)
2710 +#define pram_unlock_inode(pi) {\
2711 +       pram_sync_inode(pi);\
2712 +        pram_unlock_range((pi), PRAM_SB_SIZE);\
2713 +}
2714 +
2715 +// write protection for a data block
2716 +#define pram_lock_block(sb, bp) \
2717 +        pram_lock_range((bp), (sb)->s_blocksize)
2718 +#define pram_unlock_block(sb, bp) \
2719 +        pram_unlock_range((bp), (sb)->s_blocksize)
2720 +
2721 +static inline void *
2722 +pram_get_bitmap(struct super_block * sb)
2723 +{
2724 +       struct pram_super_block * ps = pram_get_super(sb);
2725 +       return ((void*)ps + ps->s_bitmap_start);
2726 +}
2727 +
2728 +// If this is part of a read-modify-write of the inode metadata,
2729 +// pram_lock_inode() before calling!
2730 +static inline struct pram_inode *
2731 +pram_get_inode(struct super_block * sb, pram_off_t ino)
2732 +{
2733 +       struct pram_super_block * ps = pram_get_super(sb);
2734 +       return ino ? (struct pram_inode *)((void*)ps + ino) : NULL;
2735 +}
2736 +
2737 +static inline ino_t
2738 +pram_get_inodenr(struct super_block * sb, struct pram_inode * pi)
2739 +{
2740 +       struct pram_super_block * ps = pram_get_super(sb);
2741 +       return (ino_t)((unsigned long)pi - (unsigned long)ps);
2742 +}
2743 +
2744 +static inline pram_off_t
2745 +pram_get_block_off(struct super_block * sb, unsigned long blocknr)
2746 +{
2747 +       struct pram_super_block * ps = pram_get_super(sb);
2748 +       return (pram_off_t)(ps->s_bitmap_start +
2749 +                            (blocknr << sb->s_blocksize_bits));
2750 +}
2751 +
2752 +static inline unsigned long
2753 +pram_get_blocknr(struct super_block * sb, pram_off_t block)
2754 +{
2755 +       struct pram_super_block * ps = pram_get_super(sb);
2756 +       return (block - ps->s_bitmap_start) >> sb->s_blocksize_bits;
2757 +}
2758 +
2759 +// If this is part of a read-modify-write of the block,
2760 +// pram_lock_block() before calling!
2761 +static inline void *
2762 +pram_get_block(struct super_block * sb, pram_off_t block)
2763 +{
2764 +       struct pram_super_block * ps = pram_get_super(sb);
2765 +       return block ? ((void*)ps + block) : NULL;
2766 +}
2767 +
2768 +
2769 +/*
2770 + * Inodes and files operations
2771 + */
2772 +
2773 +/* dir.c */
2774 +extern struct file_operations pram_dir_operations;
2775 +
2776 +/* file.c */
2777 +extern struct inode_operations pram_file_inode_operations;
2778 +extern struct file_operations pram_file_operations;
2779 +
2780 +/* inode.c */
2781 +extern struct address_space_operations pram_aops;
2782 +
2783 +/* namei.c */
2784 +extern struct inode_operations pram_dir_inode_operations;
2785 +
2786 +/* symlink.c */
2787 +extern struct inode_operations pram_symlink_inode_operations;
2788 +
2789 +#endif /* __KERNEL__ */
2790 +
2791 +#endif /* _LINUX_PRAM_FS_H */
2792 diff -Nuar -X /home/stevel/dontdiff main.orig/include/linux/pram_fs_sb.h main/include/linux/pram_fs_sb.h
2793 --- main.orig/include/linux/pram_fs_sb.h        1969-12-31 16:00:00.000000000 -0800
2794 +++ main/include/linux/pram_fs_sb.h     2004-03-04 15:59:35.000000000 -0800
2795 @@ -0,0 +1,43 @@
2796 +/*
2797 + * pram_fs_sb.h
2798 + *
2799 + * Definitions for the PRAM filesystem.
2800 + *
2801 + * Author: Steve Longerbeam <stevel@mvista.com, or source@mvista.com>
2802 + *
2803 + * 2003 (c) MontaVista Software, Inc.
2804 + * Copyright 2003 Sony Corporation
2805 + * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
2806 + *
2807 + * This software is being distributed under the terms of the GNU General Public
2808 + * License version 2.  Some or all of the technology encompassed by this
2809 + * software may be subject to one or more patents pending as of the date of
2810 + * this notice.  No additional patent license will be required for GPL
2811 + * implementations of the technology.  If you want to create a non-GPL
2812 + * implementation of the technology encompassed by this software, please
2813 + * contact legal@mvista.com for details including licensing terms and fees.
2814 + *
2815 + * This file is licensed under the terms of the GNU General Public License
2816 + * version 2. This program is licensed "as is" without any warranty of any
2817 + * kind, whether express or implied.
2818 + */
2819 +#ifndef _LINUX_PRAM_FS_SB
2820 +#define _LINUX_PRAM_FS_SB
2821 +
2822 +/*
2823 + * PRAM filesystem super-block data in memory
2824 + */
2825 +struct pram_sb_info {
2826 +       /*
2827 +        * base physical and virtual address of PRAMFS (which is also
2828 +        * the pointer to the super block)
2829 +        */
2830 +       unsigned long phys_addr;
2831 +       void * virt_addr;
2832 +
2833 +       u32 maxsize;
2834 +       u32 features;
2835 +       u16 magic;
2836 +};
2837 +
2838 +#endif /* _LINUX_PRAM_FS_SB */
2839 diff -Nuar -X /home/stevel/dontdiff main.orig/init/do_mounts.c main/init/do_mounts.c
2840 --- main.orig/init/do_mounts.c  2004-03-04 17:17:14.000000000 -0800
2841 +++ main/init/do_mounts.c       2004-03-04 15:59:38.000000000 -0800
2842 @@ -322,6 +322,17 @@
2843  }
2844  #endif
2845  
2846 +#ifdef CONFIG_ROOT_PRAMFS
2847 +static int __init mount_pramfs_root(void)
2848 +{
2849 +       create_dev("/dev/root", ROOT_DEV, NULL);
2850 +       if (do_mount_root("/dev/root", "pramfs",
2851 +                         root_mountflags, root_mount_data) == 0)
2852 +               return 1;
2853 +       return 0;
2854 +}
2855 +#endif
2856 +
2857  #if defined(CONFIG_BLK_DEV_RAM) || defined(CONFIG_BLK_DEV_FD)
2858  void __init change_floppy(char *fmt, ...)
2859  {
2860 @@ -363,6 +374,15 @@
2861                 ROOT_DEV = Root_FD0;
2862         }
2863  #endif
2864 +#ifdef CONFIG_ROOT_PRAMFS
2865 +       if (ROOT_DEV == MKDEV(0, 0)) {
2866 +               if (mount_pramfs_root())
2867 +                       return;
2868 +               
2869 +               printk (KERN_ERR "VFS: Unable to mount PRAMFS root\n");
2870 +               ROOT_DEV = Root_FD0;
2871 +       }
2872 +#endif
2873  #ifdef CONFIG_BLK_DEV_FD
2874         if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
2875                 /* rd_doload is 2 for a dual initrd/ramload setup */
This page took 0.740951 seconds and 3 git commands to generate.