[PATCH 00/16 v3] pramfs: persistent and protected RAM filesystem

2010-11-13 Thread Marco Stornelli
Hi all,

third round for the patch series (I hope this is the last one :)). I
summarize here the changes to improve the review:

v3:
- fix a possible memory leak in an error path reported by yidong zhang
- fix a warning when using XIP about not used __pram_mmap symbol
- fix test module header description and replaced TEST_MODULE with
PRAMFS_TEST_MODULE in the Kconfig and Makefile according to the comments
done by Randy Dunlap
- fix a compilation warning in super.c reported by James Hogan
- fix a compilation error when XIP was enabled
- removed not used symbol PRAM_XATTR_INDEX_LUSTRE
- fix some comment style issue

v2:
- fix documentation errors reported by Randy Dunlap and Kieran Bingham
- reworked memory write protection functions with the suggestions of
Andi Kleen

v1:
- first draft

Marco
--
To unsubscribe from this list: send the line unsubscribe linux-embedded in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 01/16 v3] pramfs; documentation

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli marco.storne...@gmail.com

Documentation for PRAMFS.

Signed-off-by: Marco Stornelli marco.storne...@gmail.com
---
diff -Nurp linux-2.6.36-orig/Documentation/filesystems/pramfs.txt 
linux-2.6.36/Documentation/filesystems/pramfs.txt
--- linux-2.6.36-orig/Documentation/filesystems/pramfs.txt  1970-01-01 
01:00:00.0 +0100
+++ linux-2.6.36/Documentation/filesystems/pramfs.txt   2010-10-23 
09:04:32.0 +0200
@@ -0,0 +1,296 @@
+
+PRAMFS Overview
+===
+
+Many embedded systems have a block of non-volatile RAM separate 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 straightforward 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, ext4, etc.
+
+But the disk-based fs over non-volatile RAM block driver approach has
+some drawbacks:
+
+1. Complexity of disk-based fs: disk-based filesystems such as ext2/ext3/ext4
+   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. Different problems between disks and RAM: Because PRAMFS attempts to avoid
+   filesystem corruption caused by kernel bugs, dirty pages in the page cache
+   are not allowed to be written back to the backing-store RAM. This way, an
+   errant write into the page cache will not get written back to the 
filesystem.
+   However, if the backing-store RAM is comparable in access speed to system
+   memory, the penalty of not using caching is minimal. With this consideration
+   it's 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 the filesystem used performs direct I/O by default.
+
+The Persistent/Protected RAM Special Filesystem (PRAMFS) is a 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 exists 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 supports the execute-in-place. With XIP, instead of keeping data in the
+page cache, the need to have a page cache copy is eliminated completely.
+Readwrite type operations are performed directly from/to the memory. For file
+mappings, the RAM itself is mapped directly into userspace. XIP, in addition,
+speed up the applications start-up time because it removes the needs of any
+copies.
+
+PRAMFS is 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 page table entries is 
+marked read-only 

[PATCH 03/16 v3] pramfs: inode operations

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli marco.storne...@gmail.com

Inode methods (allocate/free/read/write).

Signed-off-by: Marco Stornelli marco.storne...@gmail.com
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/inode.c linux-2.6.36/fs/pramfs/inode.c
--- linux-2.6.36-orig/fs/pramfs/inode.c 1970-01-01 01:00:00.0 +0100
+++ linux-2.6.36/fs/pramfs/inode.c  2010-09-26 18:04:38.0 +0200
@@ -0,0 +1,710 @@
+/*
+ * FILE NAME fs/pramfs/inode.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * Inode methods (allocate/free/read/write).
+ *
+ * Copyright 2009-2010 Marco Stornelli marco.storne...@gmail.com
+ * Copyright 2003 Sony Corporation
+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed as is without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include linux/fs.h
+#include linux/smp_lock.h
+#include linux/sched.h
+#include linux/highuid.h
+#include linux/quotaops.h
+#include linux/module.h
+#include linux/mpage.h
+#include linux/backing-dev.h
+#include pram.h
+#include xattr.h
+#include xip.h
+#include acl.h
+
+struct backing_dev_info pram_backing_dev_info __read_mostly = {
+   .ra_pages   = 0,/* No readahead */
+   .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK,
+};
+
+/*
+ * allocate a data block for inode and return it's absolute blocknr.
+ * Zeroes out the block if zero set. Increments inode-i_blocks.
+ */
+static int pram_new_data_block(struct inode *inode, unsigned long *blocknr, 
int zero)
+{
+   int errval = pram_new_block(inode-i_sb, blocknr, zero);
+
+   if (!errval) {
+   struct pram_inode *pi = pram_get_inode(inode-i_sb,
+   inode-i_ino);
+   inode-i_blocks++;
+   pram_memunlock_inode(pi);
+   pi-i_blocks = cpu_to_be32(inode-i_blocks);
+   pram_memlock_inode(pi);
+   }
+
+   return errval;
+}
+
+/*
+ * find the offset to the block represented by the given inode's file
+ * relative block number.
+ */
+u64 pram_find_data_block(struct inode *inode, int file_blocknr)
+{
+   struct super_block *sb = inode-i_sb;
+   struct pram_inode *pi;
+   u64 *row; /* ptr to row block */
+   u64 *col; /* ptr to column blocks */
+   u64 bp = 0;
+   int i_row, i_col;
+   int N = sb-s_blocksize  3; /* num block ptrs per block */
+   int Nbits = sb-s_blocksize_bits - 3;
+
+   pi = pram_get_inode(sb, inode-i_ino);
+
+   i_row = file_blocknr  Nbits;
+   i_col  = file_blocknr  (N-1);
+
+   row = pram_get_block(sb, be64_to_cpu(pi-i_type.reg.row_block));
+   if (row) {
+   col = pram_get_block(sb, be64_to_cpu(row[i_row]));
+   if (col)
+   bp = be64_to_cpu(col[i_col]);
+   }
+
+   return bp;
+}
+
+/*
+ * Free data blocks from inode in the range start = end
+ */
+static void __pram_truncate_blocks(struct inode *inode, loff_t start, loff_t 
end)
+{
+   struct super_block *sb = inode-i_sb;
+   struct pram_inode *pi = pram_get_inode(sb, inode-i_ino);
+   int N = sb-s_blocksize  3; /* num block ptrs per block */
+   int Nbits = sb-s_blocksize_bits - 3;
+   int first_row_index, last_row_index, i, j;
+   unsigned long blocknr, first_blocknr, last_blocknr;
+   unsigned int freed = 0;
+   u64 *row; /* ptr to row block */
+   u64 *col; /* ptr to column blocks */
+
+   if (start  end || !inode-i_blocks || !pi-i_type.reg.row_block)
+   return;
+
+   mutex_lock(PRAM_I(inode)-truncate_mutex);
+
+   first_blocknr = (start + sb-s_blocksize - 1)  sb-s_blocksize_bits;
+   last_blocknr = (end + sb-s_blocksize - 1)  sb-s_blocksize_bits;
+   first_row_index = first_blocknr  Nbits;
+   last_row_index  = last_blocknr  Nbits;
+
+   row = pram_get_block(sb, be64_to_cpu(pi-i_type.reg.row_block));
+
+   for (i = first_row_index; i = last_row_index; i++) {
+   int first_col_index = (i == first_row_index) ?
+   first_blocknr  (N-1) : 0;
+   int last_col_index = (i == last_row_index) ?
+   last_blocknr  (N-1) : N-1;
+
+   if (unlikely(!row[i]))
+   continue;
+
+   col = pram_get_block(sb, be64_to_cpu(row[i]));
+
+   for (j = first_col_index; j = last_col_index; j++) {
+
+   if (unlikely(!col[j]))
+   continue;
+
+   blocknr = pram_get_blocknr(sb, be64_to_cpu(col[j]));
+   pram_free_block(sb, blocknr);
+   freed++;
+   pram_memunlock_block(sb, col);
+   col[j] = 0;
+   pram_memlock_block(sb, col);
+   }
+
+   if (first_col_index == 0) {
+ 

[PATCH 04/16 v3] pramfs: file operations

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli marco.storne...@gmail.com

File operations.

Signed-off-by: Marco Stornelli marco.storne...@gmail.com
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/file.c linux-2.6.36/fs/pramfs/file.c
--- linux-2.6.36-orig/fs/pramfs/file.c  1970-01-01 01:00:00.0 +0100
+++ linux-2.6.36/fs/pramfs/file.c   2010-09-24 18:34:03.0 +0200
@@ -0,0 +1,166 @@
+/*
+ * FILE NAME fs/pramfs/file.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * File operations for files.
+ *
+ * Copyright 2009-2010 Marco Stornelli marco.storne...@gmail.com
+ * Copyright 2003 Sony Corporation
+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed as is without any
+ * warranty of any kind, whether express or implied.
+ */
+#include linux/fs.h
+#include linux/sched.h
+#include linux/slab.h
+#include linux/uio.h
+#include linux/mm.h
+#include linux/uaccess.h
+#include pram.h
+#include acl.h
+#include xip.h
+#include xattr.h
+
+static int pram_open_file(struct inode *inode, struct file *filp)
+{
+#ifndef CONFIG_PRAMFS_XIP
+   /* Without XIP we force to use Direct IO */
+   filp-f_flags |= O_DIRECT;
+#endif
+   return generic_file_open(inode, filp);
+}
+
+ssize_t __pram_direct_IO(int rw, struct kiocb *iocb,
+  const struct iovec *iov,
+  loff_t offset, unsigned long nr_segs)
+{
+   struct file *file = iocb-ki_filp;
+   struct inode *inode = file-f_mapping-host;
+   struct super_block *sb = inode-i_sb;
+   int progress = 0, hole = 0;
+   ssize_t retval = 0;
+   void *tmp = NULL;
+   unsigned long blocknr, blockoff;
+   int num_blocks, blocksize_mask, blocksize, blocksize_bits;
+   char __user *buf = iov-iov_base;
+   size_t length = iov_length(iov, nr_segs);
+
+   if (length  0)
+   return -EINVAL;
+   if ((rw == READ)  (offset + length  inode-i_size))
+   length = inode-i_size - offset;
+   if (!length)
+   goto out;
+
+   blocksize_bits = inode-i_sb-s_blocksize_bits;
+   blocksize = 1  blocksize_bits;
+   blocksize_mask = blocksize - 1;
+
+   /* find starting block number to access */
+   blocknr = offset  blocksize_bits;
+   /* find starting offset within starting block */
+   blockoff = offset  blocksize_mask;
+   /* find number of blocks to access */
+   num_blocks = (blockoff + length + blocksize_mask)  blocksize_bits;
+
+   if (rw == WRITE) {
+   /* prepare a temporary buffer to hold a user data block
+  for writing. */
+   tmp = kmalloc(blocksize, GFP_KERNEL);
+   if (!tmp)
+   return -ENOMEM;
+   /* now allocate the data blocks we'll need */
+   retval = pram_alloc_blocks(inode, blocknr, num_blocks);
+   if (retval)
+   goto fail1;
+   }
+
+   while (length) {
+   int count;
+   u8 *bp = NULL;
+   u64 block = pram_find_data_block(inode, blocknr++);
+   if (unlikely(!block  rw == READ)) {
+   /* We are falling in a hole */
+   hole = 1;
+   } else {
+   bp = (u8 *)pram_get_block(sb, block);
+   if (!bp)
+   goto fail2;
+   }
+
+   count = blockoff + length  blocksize ?
+   blocksize - blockoff : length;
+
+   if (rw == READ) {
+   if (unlikely(hole)) {
+   retval = clear_user(buf, count);
+   if (retval) {
+   retval = -EFAULT;
+   goto fail1;
+   }
+   } else {
+   retval = copy_to_user(buf, bp[blockoff], 
count);
+   if (retval) {
+   retval = -EFAULT;
+   goto fail1;
+   }
+   }
+   } else {
+   retval = copy_from_user(tmp, buf, count);
+   if (retval) {
+   retval = -EFAULT;
+   goto fail1;
+   }
+
+   pram_memunlock_block(inode-i_sb, bp);
+   memcpy(bp[blockoff], tmp, count);
+   pram_memlock_block(inode-i_sb, bp);
+   }
+
+   progress += count;
+   buf += count;
+   length -= count;
+   blockoff = 0;
+   hole = 0;
+   }
+
+fail2:
+   retval = progress;
+fail1:
+   kfree(tmp);
+out:
+

[PATCH 07/16 v3] pramfs: symbolic links

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli marco.storne...@gmail.com

Symlink operations.

Signed-off-by: Marco Stornelli marco.storne...@gmail.com
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/symlink.c 
linux-2.6.36/fs/pramfs/symlink.c
--- linux-2.6.36-orig/fs/pramfs/symlink.c   1970-01-01 01:00:00.0 
+0100
+++ linux-2.6.36/fs/pramfs/symlink.c2010-09-14 18:49:52.0 +0200
@@ -0,0 +1,78 @@
+/*
+ * FILE NAME fs/pramfs/symlink.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * Symlink operations
+ *
+ * Copyright 2009-2010 Marco Stornelli marco.storne...@gmail.com
+ * Copyright 2003 Sony Corporation
+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed as is without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include linux/fs.h
+#include pram.h
+#include xattr.h
+
+int pram_block_symlink(struct inode *inode, const char *symname, int len)
+{
+   struct super_block *sb = inode-i_sb;
+   u64 block;
+   char *blockp;
+   int err;
+
+   err = pram_alloc_blocks(inode, 0, 1);
+   if (err)
+   return err;
+
+   block = pram_find_data_block(inode, 0);
+   blockp = pram_get_block(sb, block);
+
+   pram_memunlock_block(sb, blockp);
+   memcpy(blockp, symname, len);
+   blockp[len] = '\0';
+   pram_memlock_block(sb, blockp);
+   return 0;
+}
+
+static int pram_readlink(struct dentry *dentry, char *buffer, int buflen)
+{
+   struct inode *inode = dentry-d_inode;
+   struct super_block *sb = inode-i_sb;
+   u64 block;
+   char *blockp;
+
+   block = pram_find_data_block(inode, 0);
+   blockp = pram_get_block(sb, block);
+   return vfs_readlink(dentry, buffer, buflen, blockp);
+}
+
+static void *pram_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+   struct inode *inode = dentry-d_inode;
+   struct super_block *sb = inode-i_sb;
+   off_t block;
+   int status;
+   char *blockp;
+
+   block = pram_find_data_block(inode, 0);
+   blockp = pram_get_block(sb, block);
+   status = vfs_follow_link(nd, blockp);
+   return ERR_PTR(status);
+}
+
+struct inode_operations pram_symlink_inode_operations = {
+   .readlink   = pram_readlink,
+   .follow_link= pram_follow_link,
+   .setattr= pram_notify_change,
+#ifdef CONFIG_PRAMFS_XATTR
+   .setxattr   = generic_setxattr,
+   .getxattr   = generic_getxattr,
+   .listxattr  = pram_listxattr,
+   .removexattr= generic_removexattr,
+#endif
+};
 
--
To unsubscribe from this list: send the line unsubscribe linux-embedded in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 08/16 v3] pramfs: headers

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli marco.storne...@gmail.com

Definitions for the PRAMFS filesystem.

Signed-off-by: Marco Stornelli marco.storne...@gmail.com
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/pram.h linux-2.6.36/fs/pramfs/pram.h
--- linux-2.6.36-orig/fs/pramfs/pram.h  1970-01-01 01:00:00.0 +0100
+++ linux-2.6.36/fs/pramfs/pram.h   2010-10-30 12:02:45.0 +0200
@@ -0,0 +1,317 @@
+/*
+ * FILE NAME pram.h
+ *
+ * BRIEF DESCRIPTION
+ *
+ * Definitions for the PRAMFS filesystem.
+ *
+ * Copyright 2009-2010 Marco Stornelli marco.storne...@gmail.com
+ * Copyright 2003 Sony Corporation
+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed as is without any
+ * warranty of any kind, whether express or implied.
+ */
+#ifndef __PRAM_H
+#define __PRAM_H
+
+#include linux/buffer_head.h
+#include linux/pram_fs.h
+#include linux/pram_fs_sb.h
+#include linux/crc16.h
+#include linux/mutex.h
+#include linux/types.h
+
+/*
+ * Debug code
+ */
+#define pram_dbg(s, args...)   pr_debug(PRAMFS: s, ## args)
+#define pram_err(s, args...)   pr_err(PRAMFS: s, ## args)
+#define pram_warn(s, args...)  pr_warning(PRAMFS: s, ## args)
+#define pram_info(s, args...)  pr_info(PRAMFS: s, ## args)
+
+/* Function Prototypes */
+
+#ifdef CONFIG_PRAMFS_XIP
+
+#define pram_read  xip_file_read
+#define pram_write xip_file_write
+#define pram_mmap  xip_file_mmap
+#define pram_aio_read  NULL
+#define pram_aio_write NULL
+#define pram_readpage  NULL
+#define pram_direct_IO NULL
+
+#else
+
+#define pram_read  do_sync_read
+#define pram_write do_sync_write
+#define pram_mmap  __pram_mmap
+#define pram_aio_read  generic_file_aio_read
+#define pram_aio_write generic_file_aio_write
+#define pram_direct_IO __pram_direct_IO
+#define pram_readpage  __pram_readpage
+
+extern int pram_get_and_update_block(struct inode *inode, sector_t iblock,
+struct buffer_head *bh, int create);
+
+static inline int __pram_readpage(struct file *file, struct page *page)
+{
+   return block_read_full_page(page, pram_get_and_update_block);
+}
+
+/* file.c */
+extern ssize_t __pram_direct_IO(int rw, struct kiocb *iocb,
+ const struct iovec *iov,
+ loff_t offset, unsigned long nr_segs);
+extern int __pram_mmap(struct file *file, struct vm_area_struct *vma);
+
+#endif /* CONFIG_PRAMFS_XIP */
+
+#define pram_set_bit   ext2_set_bit
+#define pram_clear_bit ext2_clear_bit
+#define pram_find_next_zero_bitext2_find_next_zero_bit
+
+/* balloc.c */
+extern void pram_init_bitmap(struct super_block *sb);
+extern void pram_free_block(struct super_block *sb, unsigned long blocknr);
+extern int pram_new_block(struct super_block *sb, unsigned long *blocknr, int 
zero);
+extern unsigned long pram_count_free_blocks(struct super_block *sb);
+
+/* dir.c */
+extern int pram_add_link(struct dentry *dentry, struct inode *inode);
+extern int pram_remove_link(struct inode *inode);
+
+/* namei.c */
+extern struct dentry *pram_get_parent(struct dentry *child);
+
+/* inode.c */
+extern int pram_alloc_blocks(struct inode *inode, int file_blocknr, int num);
+extern u64 pram_find_data_block(struct inode *inode,
+int file_blocknr);
+
+extern struct inode *pram_iget(struct super_block *sb, unsigned long ino);
+extern void pram_put_inode(struct inode *inode);
+extern void pram_evict_inode(struct inode *inode);
+extern struct inode *pram_new_inode(struct inode *dir, int mode);
+extern int pram_update_inode(struct inode *inode);
+extern int pram_write_inode(struct inode *inode, struct writeback_control 
*wbc);
+extern void pram_dirty_inode(struct inode *inode);
+extern int pram_notify_change(struct dentry *dentry, struct iattr *attr);
+
+
+/* super.c */
+#ifdef CONFIG_PRAMFS_TEST
+extern struct pram_super_block *get_pram_super(void);
+#endif
+extern struct super_block *pram_read_super(struct super_block *sb,
+ void *data,
+ int silent);
+extern int pram_statfs(struct dentry *d, struct kstatfs *buf);
+extern int pram_remount(struct super_block *sb, int *flags, char *data);
+
+/* symlink.c */
+extern int pram_block_symlink(struct inode *inode,
+  const char *symname, int len);
+
+
+#ifdef CONFIG_PRAMFS_WRITE_PROTECT
+extern void pram_writeable(void *vaddr, unsigned long size, int rw);
+
+#define wrprotect(addr, size) pram_writeable(addr, size, 0)
+
+#else
+
+#define wrprotect(addr, size) do {} while (0)
+
+#endif /* CONFIG PRAMFS_WRITE_PROTECT */
+
+/* Inline functions start here */
+
+static inline int pram_calc_checksum(u8 *data, int n)
+{
+   u16 crc = 0;
+   crc = crc16(~0, (__u8 *)data + 

[PATCH 09/16 v3] pramfs: dir operations

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli marco.storne...@gmail.com

File operations for directories.

Signed-off-by: Marco Stornelli marco.storne...@gmail.com
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/dir.c linux-2.6.36/fs/pramfs/dir.c
--- linux-2.6.36-orig/fs/pramfs/dir.c   1970-01-01 01:00:00.0 +0100
+++ linux-2.6.36/fs/pramfs/dir.c2010-09-17 19:08:54.0 +0200
@@ -0,0 +1,215 @@
+/*
+ * FILE NAME fs/pramfs/dir.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * File operations for directories.
+ *
+ * Copyright 2009-2010 Marco Stornelli marco.storne...@gmail.com
+ * Copyright 2003 Sony Corporation
+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed as is without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include linux/fs.h
+#include linux/pagemap.h
+#include pram.h
+
+/*
+ * Parent is locked.
+ */
+int pram_add_link(struct dentry *dentry, struct inode *inode)
+{
+   struct inode *dir = dentry-d_parent-d_inode;
+   struct pram_inode *pidir, *pi, *pitail = NULL;
+   u64 tail_ino, prev_ino;
+
+   const char *name = dentry-d_name.name;
+
+   int namelen = dentry-d_name.len  PRAM_NAME_LEN ?
+   PRAM_NAME_LEN : dentry-d_name.len;
+
+   pidir = pram_get_inode(dir-i_sb, dir-i_ino);
+   pi = pram_get_inode(dir-i_sb, inode-i_ino);
+
+   dir-i_mtime = dir-i_ctime = CURRENT_TIME;
+
+   tail_ino = be64_to_cpu(pidir-i_type.dir.tail);
+   if (tail_ino != 0) {
+   pitail = pram_get_inode(dir-i_sb, tail_ino);
+   pram_memunlock_inode(pitail);
+   pitail-i_d.d_next = cpu_to_be64(inode-i_ino);
+   pram_memlock_inode(pitail);
+
+   prev_ino = tail_ino;
+
+   pram_memunlock_inode(pidir);
+   pidir-i_type.dir.tail = cpu_to_be64(inode-i_ino);
+   pidir-i_mtime = cpu_to_be32(dir-i_mtime.tv_sec);
+   pidir-i_ctime = cpu_to_be32(dir-i_ctime.tv_sec);
+   pram_memlock_inode(pidir);
+   } else {
+   /* the directory is empty */
+   prev_ino = 0;
+
+   pram_memunlock_inode(pidir);
+   pidir-i_type.dir.tail = cpu_to_be64(inode-i_ino);
+   pidir-i_type.dir.head = cpu_to_be64(inode-i_ino);
+   pidir-i_mtime = cpu_to_be32(dir-i_mtime.tv_sec);
+   pidir-i_ctime = cpu_to_be32(dir-i_ctime.tv_sec);
+   pram_memlock_inode(pidir);
+   }
+
+
+   pram_memunlock_inode(pi);
+   pi-i_d.d_prev = cpu_to_be64(prev_ino);
+   pi-i_d.d_parent = cpu_to_be64(dir-i_ino);
+   memcpy(pi-i_d.d_name, name, namelen);
+   pi-i_d.d_name[namelen] = '\0';
+   pram_memlock_inode(pi);
+   return 0;
+}
+
+int pram_remove_link(struct inode *inode)
+{
+   struct super_block *sb = inode-i_sb;
+   struct pram_inode *prev = NULL;
+   struct pram_inode *next = NULL;
+   struct pram_inode *pidir, *pi;
+
+   pi = pram_get_inode(sb, inode-i_ino);
+   pidir = pram_get_inode(sb, be64_to_cpu(pi-i_d.d_parent));
+   if (!pidir)
+   return -EACCES;
+
+   if (inode-i_ino == be64_to_cpu(pidir-i_type.dir.head)) {
+   /* first inode in directory */
+   next = pram_get_inode(sb, be64_to_cpu(pi-i_d.d_next));
+
+   if (next) {
+   pram_memunlock_inode(next);
+   next-i_d.d_prev = 0;
+   pram_memlock_inode(next);
+
+   pram_memunlock_inode(pidir);
+   pidir-i_type.dir.head = pi-i_d.d_next;
+   } else {
+   pram_memunlock_inode(pidir);
+   pidir-i_type.dir.head = 0;
+   pidir-i_type.dir.tail = 0;
+   }
+   pram_memlock_inode(pidir);
+   } else if (inode-i_ino == be64_to_cpu(pidir-i_type.dir.tail)) {
+   /* last inode in directory */
+   prev = pram_get_inode(sb, be64_to_cpu(pi-i_d.d_prev));
+
+   pram_memunlock_inode(prev);
+   prev-i_d.d_next = 0;
+   pram_memlock_inode(prev);
+
+   pram_memunlock_inode(pidir);
+   pidir-i_type.dir.tail = pi-i_d.d_prev;
+   pram_memlock_inode(pidir);
+   } else {
+   /* somewhere in the middle */
+   prev = pram_get_inode(sb, be64_to_cpu(pi-i_d.d_prev));
+   next = pram_get_inode(sb, be64_to_cpu(pi-i_d.d_next));
+
+   if (prev  next) {
+   pram_memunlock_inode(prev);
+   prev-i_d.d_next = pi-i_d.d_next;
+   pram_memlock_inode(prev);
+
+   pram_memunlock_inode(next);
+   next-i_d.d_prev = pi-i_d.d_prev;
+   

[PATCH 10/16 v3] pramfs: XIP operations

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli marco.storne...@gmail.com

XIP operations.

Signed-off-by: Marco Stornelli marco.storne...@gmail.com
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/xip.c linux-2.6.36/fs/pramfs/xip.c
--- linux-2.6.36-orig/fs/pramfs/xip.c   1970-01-01 01:00:00.0 +0100
+++ linux-2.6.36/fs/pramfs/xip.c2010-09-14 18:49:52.0 +0200
@@ -0,0 +1,90 @@
+/*
+ * FILE NAME fs/pramfs/xip.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * XIP operations.
+ *
+ * Copyright 2009-2010 Marco Stornelli marco.storne...@gmail.com
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed as is without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include linux/mm.h
+#include linux/fs.h
+#include linux/genhd.h
+#include linux/buffer_head.h
+#include pram.h
+#include xip.h
+
+static int pram_find_and_alloc_blocks(struct inode *inode, sector_t iblock,
+sector_t *data_block, int create)
+{
+   int err = -EIO;
+   u64 block;
+
+   mutex_lock(PRAM_I(inode)-truncate_mutex);
+
+   block = pram_find_data_block(inode, iblock);
+
+   if (!block) {
+   if (!create) {
+   err = -ENODATA;
+   goto err;
+   }
+
+   err = pram_alloc_blocks(inode, iblock, 1);
+   if (err)
+   goto err;
+
+   block = pram_find_data_block(inode, iblock);
+   if (!block) {
+   err = -ENODATA;
+   goto err;
+   }
+   }
+
+   *data_block = block;
+   err = 0;
+
+ err:
+   mutex_unlock(PRAM_I(inode)-truncate_mutex);
+   return err;
+}
+
+
+static int __pram_get_block(struct inode *inode, pgoff_t pgoff, int create,
+  sector_t *result)
+{
+   int rc = 0;
+   sector_t iblock;
+
+   /* find starting block number to access */
+   iblock = (sector_t)pgoff  (PAGE_CACHE_SHIFT - inode-i_blkbits);
+
+   rc = pram_find_and_alloc_blocks(inode, iblock, result, create);
+
+   if (rc == -ENODATA)
+   BUG_ON(create);
+
+   return rc;
+}
+
+int pram_get_xip_mem(struct address_space *mapping, pgoff_t pgoff, int create,
+   void **kmem, unsigned long *pfn)
+{
+   int rc;
+   sector_t block;
+
+   /* first, retrieve the block */
+   rc = __pram_get_block(mapping-host, pgoff, create, block);
+   if (rc)
+   goto exit;
+
+   *kmem = pram_get_block(mapping-host-i_sb, block);
+   *pfn = page_to_pfn(virt_to_page((unsigned long)*kmem));
+
+exit:
+   return rc;
+}
diff -Nurp linux-2.6.36-orig/fs/pramfs/xip.h linux-2.6.36/fs/pramfs/xip.h
--- linux-2.6.36-orig/fs/pramfs/xip.h   1970-01-01 01:00:00.0 +0100
+++ linux-2.6.36/fs/pramfs/xip.h2010-09-14 18:49:52.0 +0200
@@ -0,0 +1,24 @@
+/*
+ * FILE NAME fs/pramfs/xip.h
+ *
+ * BRIEF DESCRIPTION
+ *
+ * XIP operations.
+ *
+ * Copyright 2009-2010 Marco Stornelli marco.storne...@gmail.com
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed as is without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifdef CONFIG_PRAMFS_XIP
+
+int pram_get_xip_mem(struct address_space *, pgoff_t, int, void **,
+ unsigned long *);
+
+#else
+
+#define pram_get_xip_mem NULL
+
+#endif
+
 
--
To unsubscribe from this list: send the line unsubscribe linux-embedded in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 12/16 v3] pramfs: extended attributes

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli marco.storne...@gmail.com

Extended attributes operations.

Signed-off-by: Marco Stornelli marco.storne...@gmail.com
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/xattr.c linux-2.6.36/fs/pramfs/xattr.c
--- linux-2.6.36-orig/fs/pramfs/xattr.c 1970-01-01 01:00:00.0 +0100
+++ linux-2.6.36/fs/pramfs/xattr.c  2010-09-14 19:45:40.0 +0200
@@ -0,0 +1,1108 @@
+/*
+ * FILE NAME fs/pramfs/xattr.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * Extended attributes operations.
+ *
+ * Copyright 2010 Marco Stornelli marco.storne...@gmail.com
+ *
+ * based on fs/ext2/xattr.c with the following copyright:
+ *
+ * Fix by Harrison Xing harri...@mountainviewdata.com.
+ * Extended attributes for symlinks and special files added per
+ *  suggestion of Luka Renko luka.re...@hermes.si.
+ * xattr consolidation Copyright (c) 2004 James Morris jmor...@redhat.com,
+ *  Red Hat Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed as is without any
+ * warranty of any kind, whether express or implied.
+ */
+
+/*
+ * Extended attributes are stored in blocks allocated outside of
+ * any inode. The i_xattr field is then made to point to this allocated
+ * block. If all extended attributes of an inode are identical, these
+ * inodes may share the same extended attribute block. Such situations
+ * are automatically detected by keeping a cache of recent attribute block
+ * numbers and hashes over the block's contents in memory.
+ *
+ *
+ * Extended attribute block layout:
+ *
+ *   +--+
+ *   | header   |
+ *   | entry 1  | |
+ *   | entry 2  | | growing downwards
+ *   | entry 3  | v
+ *   | four null bytes  |
+ *   | . . .|
+ *   | value 1  | ^
+ *   | value 3  | | growing upwards
+ *   | value 2  | |
+ *   +--+
+ *
+ * The block header is followed by multiple entry descriptors. These entry
+ * descriptors are variable in size, and alligned to PRAM_XATTR_PAD
+ * byte boundaries. The entry descriptors are sorted by attribute name,
+ * so that two extended attribute blocks can be compared efficiently.
+ *
+ * Attribute values are aligned to the end of the block, stored in
+ * no specific order. They are also padded to PRAM_XATTR_PAD byte
+ * boundaries. No additional gaps are left between them.
+ *
+ * Locking strategy
+ * 
+ * pi-i_xattr is protected by PRAM_I(inode)-xattr_sem.
+ * EA blocks are only changed if they are exclusive to an inode, so
+ * holding xattr_sem also means that nothing but the EA block's reference
+ * count will change. Multiple writers to an EA block are synchronized
+ * by the mutex in each block descriptor. Block descriptors are kept in a
+ * red black tree and the key is the absolute block number.
+ */
+
+#include linux/module.h
+#include linux/init.h
+#include linux/mbcache.h
+#include linux/rwsem.h
+#include linux/security.h
+#include pram.h
+#include xattr.h
+#include acl.h
+#include desctree.h
+
+#define HDR(bp) ((struct pram_xattr_header *)(bp))
+#define ENTRY(ptr) ((struct pram_xattr_entry *)(ptr))
+#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
+#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
+#define GET_DESC(sbi, blocknr) lookup_xblock_desc(sbi, blocknr, 
pram_xblock_desc_cache, 1)
+#define LOOKUP_DESC(sbi, blocknr) lookup_xblock_desc(sbi, blocknr, NULL, 0)
+
+#ifdef PRAM_XATTR_DEBUG
+# define ea_idebug(inode, f...) do { \
+   printk(KERN_DEBUG inode %ld: , inode-i_ino); \
+   printk(f); \
+   printk(\n); \
+   } while (0)
+# define ea_bdebug(blocknr, f...) do { \
+   printk(KERN_DEBUG block %lu: , blocknr); \
+   printk(f); \
+   printk(\n); \
+   } while (0)
+#else
+# define ea_idebug(f...)
+# define ea_bdebug(f...)
+#endif
+
+static int pram_xattr_set2(struct inode *, char *, struct pram_xblock_desc *, 
struct pram_xattr_header *);
+
+static int pram_xattr_cache_insert(struct super_block *sb, unsigned long 
blocknr, u32 xhash);
+static struct pram_xblock_desc *pram_xattr_cache_find(struct inode *,
+struct pram_xattr_header *);
+static void pram_xattr_rehash(struct pram_xattr_header *,
+ struct pram_xattr_entry *);
+
+static struct mb_cache *pram_xattr_cache;
+static struct kmem_cache *pram_xblock_desc_cache;
+
+static const struct xattr_handler *pram_xattr_handler_map[] = {
+   [PRAM_XATTR_INDEX_USER]  = pram_xattr_user_handler,
+#ifdef CONFIG_PRAMFS_POSIX_ACL
+   [PRAM_XATTR_INDEX_POSIX_ACL_ACCESS]  = pram_xattr_acl_access_handler,
+   [PRAM_XATTR_INDEX_POSIX_ACL_DEFAULT] = pram_xattr_acl_default_handler,
+#endif
+   [PRAM_XATTR_INDEX_TRUSTED]   = pram_xattr_trusted_handler,
+#ifdef CONFIG_PRAMFS_SECURITY
+   [PRAM_XATTR_INDEX_SECURITY]  = pram_xattr_security_handler,
+#endif
+};
+
+const 

[PATCH 13/16 v3] pramfs: xattr attributes block descriptors tree

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli marco.storne...@gmail.com

Extended attributes block descriptors tree.

Signed-off-by: Marco Stornelli marco.storne...@gmail.com
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/desctree.c 
linux-2.6.36/fs/pramfs/desctree.c
--- linux-2.6.36-orig/fs/pramfs/desctree.c  1970-01-01 01:00:00.0 
+0100
+++ linux-2.6.36/fs/pramfs/desctree.c   2010-09-14 18:49:52.0 +0200
@@ -0,0 +1,183 @@
+/*
+ * FILE NAME fs/pramfs/desctree.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * Extended attributes block descriptors tree.
+ *
+ * Copyright 2010 Marco Stornelli marco.storne...@gmail.com
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed as is without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include linux/spinlock.h
+#include desctree.h
+#include pram.h
+
+/* xblock_desc_init_always()
+ *
+ * These are initializations that need to be done on every
+ * descriptor allocation as the fields are not initialised
+ * by slab allocation.
+ */
+void xblock_desc_init_always(struct pram_xblock_desc *desc)
+{
+   atomic_set(desc-refcount, 0);
+   desc-blocknr = 0;
+   desc-flags = 0;
+}
+
+/* xblock_desc_init_once()
+ *
+ * These are initializations that only need to be done
+ * once, because the fields are idempotent across use
+ * of the descriptor, so let the slab aware of that.
+ */
+void xblock_desc_init_once(struct pram_xblock_desc *desc)
+{
+   mutex_init(desc-lock);
+}
+
+/* __insert_xblock_desc()
+ *
+ * Insert a new descriptor in the tree.
+ */
+static void __insert_xblock_desc(struct pram_sb_info *sbi,
+unsigned long blocknr, struct rb_node *node)
+{
+   struct rb_node **p = (sbi-desc_tree.rb_node);
+   struct rb_node *parent = NULL;
+   struct pram_xblock_desc *desc;
+
+   while (*p) {
+   parent = *p;
+   desc = rb_entry(parent, struct pram_xblock_desc, node);
+
+   if (blocknr  desc-blocknr)
+   p = (*p)-rb_left;
+   else if (blocknr  desc-blocknr)
+   p = (*p)-rb_right;
+   else
+   /* Oops...an other descriptor for the same block ? */
+   BUG();
+   }
+
+   rb_link_node(node, parent, p);
+   rb_insert_color(node, sbi-desc_tree);
+}
+
+void insert_xblock_desc(struct pram_sb_info *sbi, struct pram_xblock_desc 
*desc)
+{
+   spin_lock(sbi-desc_tree_lock);
+   __insert_xblock_desc(sbi, desc-blocknr, desc-node);
+   spin_unlock(sbi-desc_tree_lock);
+};
+
+/* __lookup_xblock_desc()
+ *
+ * Search an extended attribute descriptor in the tree via the
+ * block number. It returns the descriptor if it's found or
+ * NULL. If not found it creates a new descriptor if create is not 0.
+ */
+static struct pram_xblock_desc *__lookup_xblock_desc(struct pram_sb_info *sbi,
+   unsigned long blocknr,
+   struct kmem_cache *cache,
+   int create)
+{
+   struct rb_node *n = sbi-desc_tree.rb_node;
+   struct pram_xblock_desc *desc = NULL;
+
+   while (n) {
+   desc = rb_entry(n, struct pram_xblock_desc, node);
+
+   if (blocknr  desc-blocknr)
+   n = n-rb_left;
+   else if (blocknr  desc-blocknr)
+   n = n-rb_right;
+   else {
+   atomic_inc(desc-refcount);
+   goto out;
+   }
+   }
+
+   /* not found */
+   if (create) {
+   desc = kmem_cache_alloc(cache, GFP_NOFS);
+   if (!desc)
+   return ERR_PTR(-ENOMEM);
+   xblock_desc_init_always(desc);
+   atomic_set(desc-refcount, 1);
+   desc-blocknr = blocknr;
+   __insert_xblock_desc(sbi, desc-blocknr, desc-node);
+   }
+out:
+   return desc;
+}
+
+struct pram_xblock_desc *lookup_xblock_desc(struct pram_sb_info *sbi,
+   unsigned long blocknr,
+   struct kmem_cache *cache,
+   int create)
+{
+   struct pram_xblock_desc *desc = NULL;
+
+   spin_lock(sbi-desc_tree_lock);
+   desc = __lookup_xblock_desc(sbi, blocknr, cache, create);
+   spin_unlock(sbi-desc_tree_lock);
+   return desc;
+}
+
+/* put_xblock_desc()
+ *
+ * Decrement the reference count and if it reaches zero and the
+ * desciptor has been marked to be free, then we free it.
+ * It returns 0 if the descriptor has been deleted and 1 otherwise.
+ */
+int put_xblock_desc(struct pram_sb_info *sbi, struct pram_xblock_desc *desc)
+{
+   int ret = 1;
+   if (!desc)
+   return ret;
+
+   if (atomic_dec_and_lock(desc-refcount, sbi-desc_tree_lock)) {
+   

[PATCH 14/16 v3] pramfs: memory protection

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli marco.storne...@gmail.com

Memory write protection.

Signed-off-by: Marco Stornelli marco.storne...@gmail.com
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/wprotect.c 
linux-2.6.36/fs/pramfs/wprotect.c
--- linux-2.6.36-orig/fs/pramfs/wprotect.c  1970-01-01 01:00:00.0 
+0100
+++ linux-2.6.36/fs/pramfs/wprotect.c   2010-10-30 11:59:54.0 +0200
@@ -0,0 +1,41 @@
+/*
+ * FILE NAME fs/pramfs/wprotect.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * Write protection for the filesystem pages.
+ *
+ * Copyright 2009-2010 Marco Stornelli marco.storne...@gmail.com
+ * Copyright 2003 Sony Corporation
+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed as is without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include linux/module.h
+#include linux/fs.h
+#include linux/mm.h
+#include linux/io.h
+#include pram.h
+
+void pram_writeable(void *vaddr, unsigned long size, int rw)
+{
+   int ret = 0;
+   unsigned long nrpages = size  PAGE_SHIFT;
+   unsigned long addr = (unsigned long)vaddr;
+
+   /* Page aligned */
+   addr = PAGE_MASK;
+
+   if (size  (PAGE_SIZE - 1))
+   nrpages++;
+
+   if (rw)
+   ret = set_memory_rw(addr, nrpages);
+   else
+   ret = set_memory_ro(addr, nrpages);
+
+   BUG_ON(ret);
+}
--
To unsubscribe from this list: send the line unsubscribe linux-embedded in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 16/16 v3] pramfs: makefile and Kconfig

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli marco.storne...@gmail.com

Makefile and Kconfig.

Signed-off-by: Marco Stornelli marco.storne...@gmail.com
---
diff -Nurp linux-2.6.36-orig/fs/Makefile linux-2.6.36/fs/Makefile
--- linux-2.6.36-orig/fs/Makefile   2010-09-13 01:07:37.0 +0200
+++ linux-2.6.36/fs/Makefile2010-09-14 18:49:52.0 +0200
@@ -126,3 +126,4 @@ obj-$(CONFIG_BTRFS_FS)  += btrfs/
 obj-$(CONFIG_GFS2_FS)   += gfs2/
 obj-$(CONFIG_EXOFS_FS)  += exofs/
 obj-$(CONFIG_CEPH_FS)  += ceph/
+obj-$(CONFIG_PRAMFS)   += pramfs/
diff -Nurp linux-2.6.36-orig/fs/Kconfig linux-2.6.36/fs/Kconfig
--- linux-2.6.36-orig/fs/Kconfig2010-09-13 01:07:37.0 +0200
+++ linux-2.6.36/fs/Kconfig 2010-09-14 18:49:52.0 +0200
@@ -13,7 +13,7 @@ source fs/ext4/Kconfig
 config FS_XIP
 # execute in place
bool
-   depends on EXT2_FS_XIP
+   depends on EXT2_FS_XIP || PRAMFS_XIP
default y
  source fs/jbd/Kconfig
@@ -25,13 +25,14 @@ config FS_MBCACHE
default y if EXT2_FS=y  EXT2_FS_XATTR
default y if EXT3_FS=y  EXT3_FS_XATTR
default y if EXT4_FS=y  EXT4_FS_XATTR
-   default m if EXT2_FS_XATTR || EXT3_FS_XATTR || EXT4_FS_XATTR
+   default y if PRAMFS=y  PRAMFS_XATTR
+   default m if EXT2_FS_XATTR || EXT3_FS_XATTR || EXT4_FS_XATTR || 
PRAMFS_XATTR
  source fs/reiserfs/Kconfig
 source fs/jfs/Kconfig
  config FS_POSIX_ACL
-# Posix ACL utility routines (for now, only ext2/ext3/jfs/reiserfs/nfs4)
+# Posix ACL utility routines (for now, only ext2/ext3/jfs/reiserfs/nfs4/pramfs)
 #
 # NOTE: you can implement Posix ACLs without these helpers (XFS does).
 #  Never use this symbol for ifdefs.
@@ -189,6 +190,7 @@ source fs/romfs/Kconfig
 source fs/sysv/Kconfig
 source fs/ufs/Kconfig
 source fs/exofs/Kconfig
+source fs/pramfs/Kconfig
  endif # MISC_FILESYSTEMS
 diff -Nurp linux-2.6.36-orig/fs/pramfs/Kconfig linux-2.6.36/fs/pramfs/Kconfig
--- linux-2.6.36-orig/fs/pramfs/Kconfig 1970-01-01 01:00:00.0 +0100
+++ linux-2.6.36/fs/pramfs/Kconfig  2010-10-30 10:30:19.0 +0200
@@ -0,0 +1,72 @@
+config PRAMFS
+   tristate Persistent and Protected RAM file system support
+   depends on HAS_IOMEM  EXPERIMENTAL
+   select CRC16
+   help
+  If your system has a block of fast (comparable in access speed to
+  system memory) and non-volatile RAM and you wish to mount a
+  light-weight, full-featured, and space-efficient filesystem over it,
+  say Y here, and read file:Documentation/filesystems/pramfs.txt.
+
+  To compile this as a module,  choose M here: the module will be
+  called pramfs.
+
+config PRAMFS_XIP
+   bool Enable Execute-in-place in PRAMFS
+   depends on PRAMFS  !PRAMFS_WRITE_PROTECT
+   help
+  Say Y here to enable XIP feature of PRAMFS.
+
+config PRAMFS_WRITE_PROTECT
+   bool Enable PRAMFS write protection
+   depends on PRAMFS  MMU  HAVE_SET_MEMORY_RO
+   default y
+   help
+  Say Y here to enable the write protect feature of PRAMFS.
+
+config PRAMFS_XATTR
+   bool PRAMFS extended attributes
+   depends on PRAMFS
+   help
+ Extended attributes are name:value pairs associated with inodes by
+ the kernel or by users (see the attr(5) manual page, or visit
+ http://acl.bestbits.at/ for details).
+
+ If unsure, say N.
+
+config PRAMFS_POSIX_ACL
+   bool PRAMFS POSIX Access Control Lists
+   depends on PRAMFS_XATTR
+   select FS_POSIX_ACL
+   help
+ Posix Access Control Lists (ACLs) support permissions for users and
+ groups beyond the owner/group/world scheme.
+
+ To learn more about Access Control Lists, visit the Posix ACLs for
+ Linux website http://acl.bestbits.at/.
+
+ If you don't know what Access Control Lists are, say N.
+
+config PRAMFS_SECURITY
+   bool PRAMFS Security Labels
+   depends on PRAMFS_XATTR
+   help
+ Security labels support alternative access control models
+ implemented by security modules like SELinux.  This option
+ enables an extended attribute handler for file security
+ labels in the pram filesystem.
+
+ If you are not using a security module that requires using
+ extended attributes for file security labels, say N.
+
+config PRAMFS_TEST
+   boolean
+   depends on PRAMFS
+
+config PRAMFS_TEST_MODULE
+   tristate PRAMFS Test
+   depends on PRAMFS  m
+   select PRAMFS_TEST
+   help
+ Say Y here to build a simple module to test the protection of
+ PRAMFS. The module will be called pramfs_test.
diff -Nurp linux-2.6.36-orig/fs/pramfs/Makefile linux-2.6.36/fs/pramfs/Makefile
--- linux-2.6.36-orig/fs/pramfs/Makefile1970-01-01 01:00:00.0 
+0100
+++ linux-2.6.36/fs/pramfs/Makefile 2010-09-14 18:49:52.0 +0200
@@ -0,0 +1,14 @@
+#
+# Makefile for the 

[PATCH 15/16 v3] pramfs: test module

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli marco.storne...@gmail.com

Test module.

Signed-off-by: Marco Stornelli marco.storne...@gmail.com
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/pramfs_test.c 
linux-2.6.36/fs/pramfs/pramfs_test.c
--- linux-2.6.36-orig/fs/pramfs/pramfs_test.c   1970-01-01 01:00:00.0 
+0100
+++ linux-2.6.36/fs/pramfs/pramfs_test.c2010-09-14 18:49:52.0 
+0200
@@ -0,0 +1,49 @@
+/*
+ * FILE NAME fs/pramfs/pramfs_test.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * Pramfs test module.
+ *
+ * Copyright 2009-2010 Marco Stornelli marco.storne...@gmail.com
+ * Copyright 2003 Sony Corporation
+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed as is without any
+ * warranty of any kind, whether express or implied.
+ */
+#include linux/module.h
+#include linux/version.h
+#include linux/init.h
+#include linux/fs.h
+#include pram.h
+
+int __init test_pramfs_write(void)
+{
+   struct pram_super_block *psb;
+
+   psb = get_pram_super();
+   if (!psb) {
+   printk(KERN_ERR
+   %s: PRAMFS super block not found (not mounted?)\n,
+   __func__);
+   return 1;
+   }
+
+   /*
+* Attempt an unprotected clear of checksum information in the
+* superblock, this should cause a kernel page protection fault.
+*/
+   printk(%s: writing to kernel VA %p\n, __func__, psb);
+   psb-s_sum = 0;
+
+   return 0;
+}
+
+void test_pramfs_write_cleanup(void) {}
+
+/* Module information */
+MODULE_LICENSE(GPL);
+module_init(test_pramfs_write);
+module_exit(test_pramfs_write_cleanup);
 
--
To unsubscribe from this list: send the line unsubscribe linux-embedded in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html