
PRAMFS Overview
===============

Many embedded systems have a block of non-volatile RAM seperate from
normal system memory, i.e. of which the kernel maintains no memory page
descriptors. For such systems it would be beneficial to mount a
fast read/write filesystem over this "I/O memory", for storing frequently
accessed data that must survive system reboots and power cycles. An
example usage might be system logs under /var/log, or a user address
book in a cell phone or PDA.

Linux traditionally had no support for a persistent, non-volatile RAM-based
filesystem, persistent meaning the filesystem survives a system reboot
or power cycle intact. The RAM-based filesystems such as tmpfs and ramfs
have no actual backing store but exist entirely in the page and buffer
caches, hence the filesystem disappears after a system reboot or
power cycle.

A relatively straight-forward solution is to write a simple block driver
for the non-volatile RAM, and mount over it any disk-based filesystem such
as ext2/ext3, reiserfs, etc.

But the disk-based fs over non-volatile RAM block driver approach has
some drawbacks:

1. Disk-based filesystems such as ext2/ext3 were designed for optimum
   performance on spinning disk media, so they implement features such
   as block groups, which attempts to group inode data into a contiguous
   set of data blocks to minimize disk seeking when accessing files. For
   RAM there is no such concern; a file's data blocks can be scattered
   throughout the media with no access speed penalty at all. So block
   groups in a filesystem mounted over RAM just adds unnecessary
   complexity. A better approach is to use a filesystem specifically
   tailored to RAM media which does away with these disk-based features.
   This increases the efficient use of space on the media, i.e. more
   space is dedicated to actual file data storage and less to meta-data
   needed to maintain that file data.

2. If the backing-store RAM is comparable in access speed to system memory,
   there's really no point in caching the file I/O data in the page
   cache. Better to move file data directly between the user buffers
   and the backing store RAM, i.e. use direct I/O. This prevents the
   unnecessary populating of the page cache with dirty pages. However
   direct I/O has to be enabled at every file open. To enable direct
   I/O at all times for all regular files requires either that
   applications be modified to include the O_DIRECT flag on all file
   opens, or that a new filesystem be used that always performs direct
   I/O by default.
    
The Persistent/Protected RAM Special Filesystem (PRAMFS) is a
full-featured read/write filesystem that has been designed to address
these issues. PRAMFS is targeted to fast I/O memory, and if the memory
is non-volatile, the filesystem will be persistent.

In PRAMFS, direct I/O is enabled across all files in the filesystem, in
other words the O_DIRECT flag is forced on every open of a PRAMFS file.
Also, file I/O in the PRAMFS is always synchronous. There is no need
to block the current process while the transfer to/from the PRAMFS
is in progress, since one of the requirements of the PRAMFS is that the
filesystem exist in fast RAM. So file I/O in PRAMFS is always direct,
synchronous, and never blocks.

The data organization in PRAMFS can be thought of as an extremely
simplified version of ext2, such that the ratio of data to meta-data is
very high.

PRAMFS is also write protected. The page table entries that map the
backing-store RAM are normally marked read-only. Write operations into
the filesystem temporarily mark the affected pages as writeable, the
write operation is carried out with locks held, and then the pte is
marked read-only again. This feature provides some protection against
filesystem corruption caused by errant writes into the RAM due to
kernel bugs for instance. In case there are systems where the write
protection is not possible (for instance the RAM cannot be mapped
with page tables), this feature can be disabled with the CONFIG_PRAMFS_NOWP
config option.

In summary, PRAMFS is a light-weight, full-featured, and space-efficient
special filesystem that is ideal for systems with a block of fast
non-volatile RAM that need to access data on it using a standard
filesytem interface.


Supported mount options
=======================

The PRAMFS currently requires one mount option, and there are several
optional mount options:

physaddr=	Required. It tells PRAMFS the physical address of the
		start of the RAM that makes up the filesystem. The
		physical address must be located on a page boundary.

init=		Optional. It is used to initialize the memory to an
		empty filesystem. Any data in an existing filesystem
		will be lost if this option is given. The parameter to
		"init=" is the RAM size in bytes.

bs=		Optional. It is used to specify a block size. It is
		ignored if the "init=" option is not specified, since
		otherwise the block size is read from the PRAMFS
		super-block. The default blocksize is 2048 bytes,
		and the allowed block sizes are 512, 1024, 2048, and
		4096.

bpi=		Optional. It is used to specify the bytes per inode
		ratio, i.e. For every N bytes in the filesystem, an
		inode will be created. This behaves the same as the "-i"
		option to mke2fs. It is ignored if the "init=" option is
		not specified.

N=		Optional. It is used to specify the number of inodes to
		allocate in the inode table. If the option is not
		specified, the bytes-per-inode ratio is used the
		calculate the number of inodes. If neither the "N=" or
		"bpi=" options are specified, the default behavior is to
		reserve 5% of the total space in the filesystem for the
		inode table. This option behaves the same as the "-N"
		option to mke2fs. It is ignored if the "init=" option is
		not specified.

Examples:

mount -t pramfs -o physaddr=0x20000000,init=0x2F000,bs=1024 none /mnt/pram

This example locates the filesystem at physical address 0x20000000, and
also requests an empty filesystem be initialized, of total size 0x2f000
bytes and blocksize 1024. The mount point is /mnt/pram.

mount -t pramfs -o physaddr=0x20000000 none /mnt/pram

This example locates the filesystem at physical address 0x20000000 as in
the first example, but uses the intact filesystem that already exists.


Current Limitations
===================

- The RAM used for PRAMFS must be directly addressable.

- PRAMFS does not support hard links.

- PRAMFS supports only private memory mappings. This allows most
  executables to run, but programs that attempt shared memory
  mappings, such as X apps that use X shared memory, will fail.

Further Documentation
=====================

If you are interested in the internal design of PRAMFS, there is
documentation available at the Sourceforge PRAMFS home page at
http://pramfs.sourceforge.net.

Please send bug reports/comments/feed back to the pramfs development
list at sourceforge: pramfs-devel@lists.sourceforge.net.


ChangeLog
=========

1.0.4:
	- kernel 2.6.10
	- include <asm/tlbflush.h> in wprotect.c for
	  flush_tlb_kernel_range().
	- fixed a bug in pram_mknod(). The pramfs inode needs
	  updating after calling init_special_inode() to update
	  the rdev.
1.0.3:
	- kernel 2.6.9.
	- __ioremap() definition not consistent across archs, use
	  ioremap() instead.
	- flush_tlb_kernel_page() is only available on some archs.
	- fixed bug in pram_fill_super(): root inode pointer needs
	  to be recalculated after remapping whole fs.
1.0.2:
	- kernel 2.6.4.
	- use pram_truncate() in pram_delete_inode().
	- dangling pram_lock_inode() removed in pram_truncate_blocks().
	- edits to this README	

1.0.1:
	- port to kernel 2.6.3.
	- implement direct_IO() method instead of custom file read/write
	  methods.
	- do away with __ioremap_readonly() requirement.
	- implement inode truncate() method.

1.0.0:
	- Started ChangeLog (kernel 2.4.22).

