Re: [PATCH 1/5] printk: introduce CONFIG_PRINTK_VERBOSITY

2009-09-02 Thread Marco Stornelli
Marc Andre Tanner ha scritto:
> Introduce a config option which allows to selectively compile out
> printk messages based on a specified verbosity level.
> 
> Signed-off-by: Marc Andre Tanner 
> ---
>  init/Kconfig |   29 +
>  1 files changed, 29 insertions(+), 0 deletions(-)
> 
> diff --git a/init/Kconfig b/init/Kconfig
> index 3f7e609..549ed95 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -833,6 +833,35 @@ config PRINTK
> very difficult to diagnose system problems, saying N here is
> strongly discouraged.
>  
> +config PRINTK_VERBOSITY
> + int "Printk compile time verbosity"
> + depends on EMBEDDED && PRINTK
> + range 0 7
> + default 0
> + help
> +
> +   Select the maximum printk verbosity level to be compiled into
> +   the kernel.
> +
> +   Messages above the specified verbosity level are removed from
> +   the kernel at compile time. This reduces the kernel image size
> +   at the cost of a calmer kernel.
> +
> +   Possible verbosity levels are listed below. Note that messages
> +   without an explicit loglevel will be classified as KERN_WARNING.
> +
> +0  Disable this feature and compile all messages in.
> +
> +1  KERN_ALERT/* action must be taken immediately  */
> +2  KERN_CRIT /* critical conditions   */
> +3  KERN_ERR  /* error conditions  */
> +4  KERN_WARNING  /* warning conditions*/
> +5  KERN_NOTICE   /* normal but significant condition  */
> +6  KERN_INFO /* informational */
> +7  KERN_DEBUG/* debug-level messages  */
> +
> +   If unsure, just move on and leave this option alone.
> +
>  config BUG
>   bool "BUG() support" if EMBEDDED
>   default y

If there are some problems to handle KERN_CONT you should say something
here. You should even add in cc: the kernel ML, however it seems a good
work.

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


Re: [PATCH 5/5] printk: provide a filtering macro for printk

2009-09-02 Thread Marco Stornelli


Marc Andre Tanner ha scritto:
> +#define printk(fmt, ...) (   
> \

Shouldn't it be an and?

> + (!__builtin_constant_p(PRINTK_FILTER((fmt))) || PRINTK_FILTER((fmt))) ? 
> \
> + printk((fmt), ##__VA_ARGS__) : 0
> \
> +)
> +
> +#endif /* CONFIG_PRINTK_VERBOSITY */
> +


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


Re: [PATCH 5/5] printk: provide a filtering macro for printk

2009-09-02 Thread Marco Stornelli
2009/9/2 Marc Andre Tanner :
> On Wed, Sep 02, 2009 at 06:44:19PM +0200, Marco Stornelli wrote:
>>
>>
>> Marc Andre Tanner ha scritto:
>> > +#define printk(fmt, ...) (                                                
>> >          \
>>
>> Shouldn't it be an and?
>
> Don't think so. If the expression isn't constant we are unable to filter it
> and therefore printk is called anyway. However if the expression is constant
> the second part of the condition is evaluated and we filter based on the
> verbosity level.
>

Yes, you're right.

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


Re: [PATCH, RFC] panic-note: Annotation from user space for panics

2009-11-12 Thread Marco Stornelli
Sincerely, I don't understand why we should involve the kernel to gather
this kind of information when we can use other (user-space) tools, only
to have "all" in a single report maybe? I think it's a bit weak reason
to include this additional behavior in the kernel.

David VomLehn ha scritto:
> Allows annotation of panics to include platform information. It's no big
> deal to collect information, but way helpful when you are collecting
> failure reports from a eventual base of millions of systems deployed in
> other people's homes.
> 

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


Re: [PATCH, RFC] panic-note: Annotation from user space for panics

2009-11-14 Thread Marco Stornelli
I think in general the procedure should be: at startup or event (for
example acquired IP address from DHCP) user applications write in flash
(better in persistent ram) a log with a tag or a timestamp or something
like this, when there is a kernel panic, it is captured in a file stored
together the log and when possible the system should send all via
network for example. Are there problems that I can't see to follow this
approach? When David says "...so this looks much more like a real file
than a sysctl file" I quite agree, it seems a normal application/system
log indeed.

Marco

Artem Bityutskiy wrote:
> On Fri, 2009-11-13 at 09:10 +0100, Simon Kagstrom wrote:
>> On Thu, 12 Nov 2009 16:56:49 -0500
>> David VomLehn  wrote:
>>
>>> Good question. Some more detail on our application might help. In some
>>> situations, we may have no disk and only enough flash for the bootloader.
>>> The kernel is downloaded over the network. When we get to user space, we
>>> initialize a number of things dynamically. For example, we dynamically
>>> compute some MAC address, and most of the IP addresses are obtained with
>>> DHCP. This are very useful to have for panic analysis.
>>>
>>> Since there is neither flash nor disk, user space has no place to store
>>> this information, should the kernel panic. When we come back up, we will get
>>> different MAC and IP addresses. Storing them in memory is our only hope.
>>>
>>> Fortunately, there is a section of RAM that the bootloader promises not
>>> to overwrite. On a panic, we capture the messages written on the console
>>> and store them in the protected area. If the information from the
>>> /proc file is written as part of the panic, we will capture it, too.
>> Can't you solve this completely from userspace using phram and mtdoops
>> instead? I.e., setup two phram areas
>>
>>  modprobe phram 4...@start-of-your-area,4...@start-of-your-area+4k# 
>> Can't remember the exact syntax!
>>
>> you'll then get /dev/mtdX and /dev/mtdX+1 for these two. You can then do
>>
>>  modprobe mtdoops mtddev=/dev/mtdX+1 dump_oops=0
>>
>> to load mtdoops to catch the panic in the second area, and just write
>> your userspace messages to /dev/mtdX.
> 
> This might work for them, not sure, but not for us. We store panics on
> flash, and later they are automatically sent to the panic collection
> system via the network. And the complications are:
> 
> 1. There may be many panics before the device has network access and has
> a chance to send the panics.
> 2. User can re-flash the device with different SW inbetween.
> 
> So we really need to print some user-space supplied information during
> the panic, and then we store it on flash with mtdoops, and the later,
> when the device has network access we send whole bunch of oopses via the
> network.
> 
>> One thing probably have to be fixed though: I don't think phram has a
>> panic_write, which will be needed by mtdoops to catch the panic - this
>> should be trivial to add though since it's plain RAM.
> 
--
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


Re: [PATCH, RFC] panic-note: Annotation from user space for panics

2009-11-17 Thread Marco Stornelli
2009/11/17 Artem Bityutskiy :
> Take a look at my mails where I describe different complications we have
> in our system. We really want to have an OOPS/panic + our environment
> stuff to go together, at once. This makes things so much simpler.
>
> Really, what is the problem providing this trivial panic-note
> capability, where user-space can give the kernel a small buffer, and ask
> the kernel to print this buffer at the oops/panic time. Very simple and
> elegant, and just solves the problem.
>
> Why perversions with time-stamps, separate storages are needed?
>
> IOW, you suggest a complicated approach, and demand explaining why we do
> not go for it. Simply because it is unnecessarily complex.

I don't think it's a complicated approach we are talking of a system
log like syslog with a temporal information, nothing more.

> This patch solves the problem gracefully, and I'd rather demand you to point 
> what
> is the technical problem with the patches.
>

Simply because I think that we should avoid to include in the kernel
things we can do in a simply way at user space level. I think this
patch is well done but it's one of the patches that are solutions "for
embedded only", but it's only my opinion.

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


Re: [PATCH, RFC] panic-note: Annotation from user space for panics

2009-11-17 Thread Marco Stornelli
Artem Bityutskiy wrote:
> On Tue, 2009-11-17 at 13:45 +0100, Marco Stornelli wrote:
>> 2009/11/17 Artem Bityutskiy :
>
> We need to store this information of NAND flash. Implementing logs on
> NAND flash is about handling bad blocks, choosing format of records, and
> may be even handling wear-levelling. This is not that simple.
> 
> And then I have match oops to the userspace environment prints, using I
> guess timestamps, which is also about complications in userspace.
> 

Indeed my suggestion was to use a persistent ram, not difficult to use.

>>> This patch solves the problem gracefully, and I'd rather demand you to 
>>> point what
>>> is the technical problem with the patches.
>>>
>> Simply because I think that we should avoid to include in the kernel
>> things we can do in a simply way at user space level.
> 
> If it is much easier to have in the kernel, then this argument does not
> work, IMHO.
> 
>>  I think this
>> patch is well done but it's one of the patches that are solutions "for
>> embedded only", but it's only my opinion.
> 
> Also IMHO, but having embedded-only things is not bad at all.
> 

In the past other patches are not accepted in main line for this, maybe
you'll be luckier.

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


How to store kernel pranic/oops

2009-12-28 Thread Marco Stornelli
Hi,

I know the open project proposal 2010 is closed, but it's just to start
a discussion. It would be nice to save oops/panic automatically in a
structure/file in ram. At the moment there are two way to save
information: mtdoops (save the information in flash), with kdump/kexec
(we can extract the dmesg from vmcore file). With these tools there are
some drawbacks:

1) There are embedded systems without a flash where to save the information;
2) we could consider this kind of logs too volatile for a flash, I mean
there's no reason to store it for a long time, it's important to recover
and read them as soon as possible, at next boot for example.
3) kdump requires a lot of ram and resources for embedded systems.
4) kexec is available only for some archs.

It would be nice to have a "ramoops" to save in a circular buffer in a
persistent ram this kind of information. Any comments? Is there already
anything similar out-of-tree?

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


Re: Re: How to store kernel panic/oops

2009-12-28 Thread Marco Stornelli
David Woodhouse wrote:

> Can't it be done with what's in the tree already? Just create an MTD
> device using phram or something else, then point mtdoops at it

Yes of course, if possible we shouldn't reinvent the wheel but I
wondered if there was something more specific. To add mtdoops (more or
less 1k) we have to add mtd subsys (more or less 14k) to the kernel to
achieve this and it's all overhead.

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


Re: [PATCH V2 6/8] lzma: Make lzma ... thunderbird ok

2010-01-07 Thread Marco Stornelli
Il 07/01/2010 08:43, Hein_Tibosch ha scritto:
> On 7-1-2010 08:37, Phillip Lougher wrote:
>> Sorry, I was worried it might do that - the curse of Thunderbird.  I
>> normally use a
>> really dumb client like mailx to send patches, but I obviously didn't have 
>> the
>> email thread under mailx to do that.
>>   
> Thunderbird: not a real curse for patches. Try the following:
> 
> Tools -> Options -> Advanced -> General -> Config Editor
> 
> mailnews.send_plaintext_flowed  user  boolean  false
> mailnews.display.disable_flowed_support user  boolean  true
> mailnews.wraplength user integer 512
> 
> And see this patch below:
> 
> ---
> diff --git a/thunderbird b/thunderbird
> +++
> ---
>   if (using_thunderbird) {
>   you can send patches safely
>   }
> ---
> 
> Hein
> 

And with pasteCode and Toggle Word Wrap extensions it is even more easier ;)

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


Re: mount ramdisk rootfs /etc directory to jffs2 filesystem.

2010-01-19 Thread Marco Stornelli
2010/1/20 Johnny Hung :
> 2010/1/19 Matthias Kaehlcke :
>> El Tue, Jan 19, 2010 at 02:17:22PM +0100 Ricard Wanderlof ha dit:
>>
> I consider to use ramdisk as rootfs because worry about wrong
> operation in rootfs (is use jffs2 rootfs) and it will cause system
> boot up failed.
> Another query, does the syslogd/klogd log files also store in jffs2
> rootfs? Write to jffs2 frequently will reduce flash life cycle.
>
> BRs, H. Johnny
>>
>> --

In general a good splitting for rootfs could be: squashfs for rootfs,
tmpfs for volatile data (/tmp), ubifs (with a flash partition) for
"strong" permanent data (/etc, ) and pramfs for "light" permanent
data (/var/log, .).
I think you should "split" your rootfs. Ramdisk is an old approach
with some drawbacks.

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


Re: mount ramdisk rootfs /etc directory to jffs2 filesystem.

2010-01-20 Thread Marco Stornelli
2010/1/20 Matthias Kaehlcke :
> El Wed, Jan 20, 2010 at 08:57:44AM +0100 Marco Stornelli ha dit:
>
>> 2010/1/20 Johnny Hung :
>> > 2010/1/19 Matthias Kaehlcke :
>> >> El Tue, Jan 19, 2010 at 02:17:22PM +0100 Ricard Wanderlof ha dit:
>> >>
>> > I consider to use ramdisk as rootfs because worry about wrong
>> > operation in rootfs (is use jffs2 rootfs) and it will cause system
>> > boot up failed.
>> > Another query, does the syslogd/klogd log files also store in jffs2
>> > rootfs? Write to jffs2 frequently will reduce flash life cycle.
>> >
>> > BRs, H. Johnny
>> >>
>> >> --
>>
>> In general a good splitting for rootfs could be: squashfs for rootfs,
>> tmpfs for volatile data (/tmp), ubifs (with a flash partition) for
>> "strong" permanent data (/etc, ) and pramfs for "light" permanent
>> data (/var/log, .).
>
> if ubifs is a good choice depends on the size of the partition, iirc
> it has a significant overhead for very small partitions.
>
> once using ubi it could be interesting to set up the read-only rootfs
> partition upon ubi in order to spread the wear out over a maximum of blocks.
>

I don't know the size constraints of Johnny, so it can be useful to use jffs2.

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


Re: mount ramdisk rootfs /etc directory to jffs2 filesystem.

2010-01-22 Thread Marco Stornelli
2010/1/22 Johnny Hung :
> 2010/1/20 Marco Stornelli :
>> 2010/1/20 Johnny Hung :
>>> 2010/1/19 Matthias Kaehlcke :
>>>> El Tue, Jan 19, 2010 at 02:17:22PM +0100 Ricard Wanderlof ha dit:
>>>>
>>> I consider to use ramdisk as rootfs because worry about wrong
>>> operation in rootfs (is use jffs2 rootfs) and it will cause system
>>> boot up failed.
>>> Another query, does the syslogd/klogd log files also store in jffs2
>>> rootfs? Write to jffs2 frequently will reduce flash life cycle.
>>>
>>> BRs, H. Johnny
>>>>
>>>> --
>>
>
> It seems there are a lot of file-systems I have to study :P. The same
> question is
> how to split my rootfs? Re-mount /etc, /var to another file-sysyem mtd part 
> when
> system boot up?
>

Simply, you can mount each mount point with the fstab file and a
script, same approach of every linux distribution, nothing more. Even
in the pc world you can mount your /home on a partition with ext3,
/var in a partition with ext4, and so on. A very simple approach to
setup the system, it is to start with NFS for example with "whole" fs,
copy what you need in the right place, setup the start-up script and
reboot.

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]: Ram oops/panic logger

2010-03-06 Thread Marco Stornelli
Ramoops, like mtdoops, can log oops/panic information but in RAM. It can
be used with persistent RAM for systems without flash support. In
addition, for this systems, with this driver, it's no more needed
add to the kernel the mtd subsystem with advantage in footprint.

Signed-off-by: Marco Stornelli 
--

diff -Nuar linux-2.6.33-orig/drivers/char/Kconfig 
linux-2.6.33/drivers/char/Kconfig
--- linux-2.6.33-orig/drivers/char/Kconfig  2010-02-24 19:52:17.0 
+0100
+++ linux-2.6.33/drivers/char/Kconfig   2010-02-28 10:47:29.0 +0100
@@ -1105,5 +1105,12 @@
 
 source "drivers/s390/char/Kconfig"
 
+config RAMOOPS
+   tristate "Log panic/oops to a RAM buffer"
+   default n
+   help
+ This enables panic and oops messages to be logged to a circular
+ buffer in RAM where it can be read back at some later point.
+
 endmenu
 
diff -Nuar linux-2.6.33-orig/drivers/char/Makefile 
linux-2.6.33/drivers/char/Makefile
--- linux-2.6.33-orig/drivers/char/Makefile 2010-02-24 19:52:17.0 
+0100
+++ linux-2.6.33/drivers/char/Makefile  2010-02-28 10:49:17.0 +0100
@@ -107,6 +107,7 @@
 obj-$(CONFIG_TCG_TPM)  += tpm/
 
 obj-$(CONFIG_PS3_FLASH)+= ps3flash.o
+obj-$(CONFIG_RAMOOPS)  += ramoops.o
 
 obj-$(CONFIG_JS_RTC)   += js-rtc.o
 js-rtc-y = rtc.o
diff -Nuar linux-2.6.33-orig/drivers/char/ramoops.c 
linux-2.6.33/drivers/char/ramoops.c
--- linux-2.6.33-orig/drivers/char/ramoops.c1970-01-01 01:00:00.0 
+0100
+++ linux-2.6.33/drivers/char/ramoops.c 2010-03-06 13:36:31.0 +0100
@@ -0,0 +1,163 @@
+/*
+ * RAM Oops/Panic logger
+ *
+ * Copyright (C) 2009 Marco Stornelli 
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define RAMOOPS_KERNMSG_HDR ""
+#define RAMOOPS_HEADER_SIZE   (5 + sizeof(struct timeval))
+
+#define RECORD_SIZE 4096
+
+static ulong mem_address;
+module_param(mem_address, ulong, 0600);
+MODULE_PARM_DESC(mem_address,
+   "start of reserved RAM used to store oops/panic logs");
+
+static ulong mem_size;
+module_param(mem_size, ulong, 0600);
+MODULE_PARM_DESC(mem_size,
+   "size of reserved RAM used to store oops/panic logs");
+
+static int dump_oops = 1;
+module_param(dump_oops, int, 0600);
+MODULE_PARM_DESC(dump_oops,
+   "set to 1 to dump oopses, 0 to only dump panics (default 1)");
+
+static struct ramoops_context {
+   struct kmsg_dumper dump;
+   void *virt_addr;
+   phys_addr_t phys_addr;
+   unsigned long size;
+   int count;
+   int max_count;
+} oops_cxt;
+
+static void ramoops_do_dump(struct kmsg_dumper *dumper,
+   enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
+   const char *s2, unsigned long l2)
+{
+   struct ramoops_context *cxt = container_of(dumper,
+   struct ramoops_context, dump);
+   unsigned long s1_start, s2_start;
+   unsigned long l1_cpy, l2_cpy;
+   int res;
+   char *buf;
+   struct timeval timestamp;
+
+   /* Only dump oopses if dump_oops is set */
+   if (reason == KMSG_DUMP_OOPS && !dump_oops)
+   return;
+
+   buf = (char *)(cxt->virt_addr + (cxt->count * RECORD_SIZE));
+   memset(buf, '\0', RECORD_SIZE);
+   res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR);
+   buf += res;
+   do_gettimeofday(×tamp);
+   res = sprintf(buf, "%lu.%lu\n", (long)timestamp.tv_sec, 
(long)timestamp.tv_usec);
+   buf += res;
+
+   l2_cpy = min(l2, (unsigned long)(RECORD_SIZE - RAMOOPS_HEADER_SIZE));
+   l1_cpy = min(l1, (unsigned long)(RECORD_SIZE - RAMOOPS_HEADER_SIZE) - 
l2_cpy);
+
+   s2_start = l2 - l2_cpy;
+   s1_start = l1 - l1_cpy;
+
+   memcpy(buf, s1 + s1_start, l1_cpy);
+   memcpy(buf + l1_cpy, s2 + s2_start, l2_cpy);
+
+   cxt->count = (cxt->count + 1) % cxt->max_count;
+}
+
+static int __init ramoops_init(void)
+{
+   struct ramoops_context *cxt = &oops_cxt;
+   int err = -EINVAL;
+
+   if (!mem_size) {
+   printk(KERN_ERR "Invalid size specification");
+   goto fail3;
+   }
+
+   rounddown_pow_of_

[PATCH v2] char drivers: Ram oops/panic logger

2010-03-09 Thread Marco Stornelli
Ramoops, like mtdoops, can log oops/panic information but in RAM. It can
be used with persistent RAM for systems without flash support. In
addition, for this systems, with this driver, it's no more needed
add to the kernel the mtd subsystem with advantage in footprint.

Signed-off-by: Marco Stornelli 
---

diff -uprN linux-2.6.33-orig/drivers/char/Kconfig 
linux-2.6.33/drivers/char/Kconfig
--- linux-2.6.33-orig/drivers/char/Kconfig  2010-02-24 19:52:17.0 
+0100
+++ linux-2.6.33/drivers/char/Kconfig   2010-02-28 10:47:29.0 +0100
@@ -1105,5 +1105,12 @@ config DEVPORT
 
 source "drivers/s390/char/Kconfig"
 
+config RAMOOPS
+   tristate "Log panic/oops to a RAM buffer"
+   default n
+   help
+ This enables panic and oops messages to be logged to a circular
+ buffer in RAM where it can be read back at some later point.
+
 endmenu
 
diff -uprN linux-2.6.33-orig/drivers/char/Makefile 
linux-2.6.33/drivers/char/Makefile
--- linux-2.6.33-orig/drivers/char/Makefile 2010-02-24 19:52:17.0 
+0100
+++ linux-2.6.33/drivers/char/Makefile  2010-02-28 10:49:17.0 +0100
@@ -107,6 +107,7 @@ obj-$(CONFIG_HANGCHECK_TIMER)   += hangche
 obj-$(CONFIG_TCG_TPM)  += tpm/
 
 obj-$(CONFIG_PS3_FLASH)+= ps3flash.o
+obj-$(CONFIG_RAMOOPS)  += ramoops.o
 
 obj-$(CONFIG_JS_RTC)   += js-rtc.o
 js-rtc-y = rtc.o
diff -uprN linux-2.6.33-orig/drivers/char/ramoops.c 
linux-2.6.33/drivers/char/ramoops.c
--- linux-2.6.33-orig/drivers/char/ramoops.c1970-01-01 01:00:00.0 
+0100
+++ linux-2.6.33/drivers/char/ramoops.c 2010-03-07 10:41:10.0 +0100
@@ -0,0 +1,162 @@
+/*
+ * RAM Oops/Panic logger
+ *
+ * Copyright (C) 2009 Marco Stornelli 
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define RAMOOPS_KERNMSG_HDR ""
+#define RAMOOPS_HEADER_SIZE   (5 + sizeof(struct timeval))
+
+#define RECORD_SIZE 4096
+
+static ulong mem_address;
+module_param(mem_address, ulong, 0600);
+MODULE_PARM_DESC(mem_address,
+   "start of reserved RAM used to store oops/panic logs");
+
+static ulong mem_size;
+module_param(mem_size, ulong, 0600);
+MODULE_PARM_DESC(mem_size,
+   "size of reserved RAM used to store oops/panic logs");
+
+static int dump_oops = 1;
+module_param(dump_oops, int, 0600);
+MODULE_PARM_DESC(dump_oops,
+   "set to 1 to dump oopses, 0 to only dump panics (default 1)");
+
+static struct ramoops_context {
+   struct kmsg_dumper dump;
+   void *virt_addr;
+   phys_addr_t phys_addr;
+   unsigned long size;
+   int count;
+   int max_count;
+} oops_cxt;
+
+static void ramoops_do_dump(struct kmsg_dumper *dumper,
+   enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
+   const char *s2, unsigned long l2)
+{
+   struct ramoops_context *cxt = container_of(dumper,
+   struct ramoops_context, dump);
+   unsigned long s1_start, s2_start;
+   unsigned long l1_cpy, l2_cpy;
+   int res;
+   char *buf;
+   struct timeval timestamp;
+
+   /* Only dump oopses if dump_oops is set */
+   if (reason == KMSG_DUMP_OOPS && !dump_oops)
+   return;
+
+   buf = (char *)(cxt->virt_addr + (cxt->count * RECORD_SIZE));
+   memset(buf, '\0', RECORD_SIZE);
+   res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR);
+   buf += res;
+   do_gettimeofday(×tamp);
+   res = sprintf(buf, "%lu.%lu\n", (long)timestamp.tv_sec, 
(long)timestamp.tv_usec);
+   buf += res;
+
+   l2_cpy = min(l2, (unsigned long)(RECORD_SIZE - RAMOOPS_HEADER_SIZE));
+   l1_cpy = min(l1, (unsigned long)(RECORD_SIZE - RAMOOPS_HEADER_SIZE) - 
l2_cpy);
+
+   s2_start = l2 - l2_cpy;
+   s1_start = l1 - l1_cpy;
+
+   memcpy(buf, s1 + s1_start, l1_cpy);
+   memcpy(buf + l1_cpy, s2 + s2_start, l2_cpy);
+
+   cxt->count = (cxt->count + 1) % cxt->max_count;
+}
+
+static int __init ramoops_init(void)
+{
+   struct ramoops_context *cxt = &oops_cxt;
+   int err = -EINVAL;
+
+   if (!mem_size) {
+   printk(KERN_ERR "Invalid size specification");
+ 

Re: [PATCH v2] char drivers: Ram oops/panic logger

2010-03-10 Thread Marco Stornelli
2010/3/10 Yuasa Yoichi :
> Hi,
>
> 2010/3/10 Marco Stornelli :
>> Ramoops, like mtdoops, can log oops/panic information but in RAM.
>
> What is different from mtdoops + mtd-ram?
>
> Yoichi
>

It can be used in a very easy way with persistent RAM for systems
without flash support. For this systems, with this driver, it's no
more needed add to the kernel the mtd subsystem with advantage in
footprint as I said in the description. In addition, you can save
flash space and store this information only in RAM. I think it's very
useful for embedded systems.

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


Re: [PATCH v2] char drivers: Ram oops/panic logger

2010-03-10 Thread Marco Stornelli
2010/3/10 Yuasa Yoichi :
> 2010/3/10 Marco Stornelli :
>> 2010/3/10 Yuasa Yoichi :
>>> Hi,
>>>
>>> 2010/3/10 Marco Stornelli :
>>>> Ramoops, like mtdoops, can log oops/panic information but in RAM.
>>>
>>> What is different from mtdoops + mtd-ram?
>>>
>>> Yoichi
>>>
>>
>> It can be used in a very easy way with persistent RAM for systems
>> without flash support. For this systems, with this driver, it's no
>> more needed add to the kernel the mtd subsystem with advantage in
>> footprint as I said in the description.
>
> right.
> But,
>
>> In addition, you can save
>> flash space and store this information only in RAM. I think it's very
>> useful for embedded systems.
>
> CONFIG_MTD_RAM uses only RAM.
> I think there's no big difference about this point.
>

I meant with the "classic" use of mtdoops, therefore with a flash
partition without use MTD_RAM. Using MTD_RAM, it's more or less the
same thing, with the exception of "where" you want deploy the log. For
example: if in your system you have got a nvram you can use it without
problem, you need to specify the address of the nvram to the module.
Very simple. I  think it's a small driver but very useful, feedback
from other embedded guys are welcome.

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


Re: [PATCH v2] char drivers: Ram oops/panic logger

2010-03-13 Thread Marco Stornelli
Il 13/03/2010 00:31, Jamie Lokier ha scritto:
> That'd be fine if the kernel link scripts choose the address, as long
> as it's consistent between different compiles and similar
> configurations.  That'd be a bit simpler than the admin having to know
> the memory map well enough to choose an address.
> 
> -- Jamie
> 

I agree, but the bootloader should be aware of it. I mean, usually
bootloaders at boot, reset the RAM, so you have to tell to the
bootloader that you are using a piece of RAM as persistent RAM, for
example U-Boot has got a specific option CONFIG_PRAM. I don't know if
all the process can be completely transparent to the admin in all
situations.

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


Re: [PATCH v2] char drivers: Ram oops/panic logger

2010-03-13 Thread Marco Stornelli
Il 12/03/2010 23:48, Andrew Morton ha scritto:
> On Wed, 10 Mar 2010 13:15:25 +0100
> Marco Stornelli  wrote:
> 
>> 2010/3/10 Yuasa Yoichi :
>>> 2010/3/10 Marco Stornelli :
>>>> 2010/3/10 Yuasa Yoichi :
>> I meant with the "classic" use of mtdoops, therefore with a flash
>> partition without use MTD_RAM. Using MTD_RAM, it's more or less the
>> same thing, with the exception of "where" you want deploy the log. For
>> example: if in your system you have got a nvram you can use it without
>> problem, you need to specify the address of the nvram to the module.
>> Very simple. I  think it's a small driver but very useful, feedback
>> from other embedded guys are welcome.
> 
> Seems sensible to me.  If you have a machine whose memory is persistent
> across reboots then you reserve an arbitrary 4k hunk of memory for
> collecting oops traces, yes?

Yes.

> 
> What tools are used for displaying that memory on the next boot?  How
> do those tools distinguish between "valid oops trace" and "garbage
> because it was just powered on"?  A magic signature?

For my test I used the program devmem2 to dump the log. In general, you
can read the memory via /dev/mem. There's an header plus a timestamp of
the log. The memory is initialized with blank spaces and the size of the
record is fixed at 4k, so if a program/script doesn't find the header at
next 4k, it means there's garbage and it can stop the read operation.

> 
> Should the kernel provide the 4k of memory rather than (or in addition
> to) requiring that the system administrator reserve it and tell the
> kernel about it?  That'd be a matter of creating a linker section which
> isn't cleared out by the startup code.
> 
> 

Yes, it can be an option. My first idea was to write a "general" driver,
with an address in input that it can be related to the reserved RAM as
an NVRAM in the system, however it can be a good idea, why not.

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


Re: [PATCH v2] char drivers: Ram oops/panic logger

2010-03-15 Thread Marco Stornelli
2010/3/15 Jamie Lokier :
> Marco Stornelli wrote:
>> Il 13/03/2010 00:31, Jamie Lokier ha scritto:
>> I agree, but the bootloader should be aware of it. I mean, usually
>> bootloaders at boot, reset the RAM, so you have to tell to the
>> bootloader that you are using a piece of RAM as persistent RAM, for
>> example U-Boot has got a specific option CONFIG_PRAM. I don't know if
>> all the process can be completely transparent to the admin in all
>> situations.
>
> Sometimes you can't change the bootloader (they don't always come with
> source code).  Or you could, but you don't want to risk it (there
> isn't always a way to recover if you break it).
>
> Obviously then the feature is only useful when the bootloader doesn't
> clear all the RAM :-)
>
> On slow boards in consumer devices, they sometimes avoid clearing the
> RAM because that adds measurable boot time.
>

In the embedded world, usually, you can change/write the fw and you
know well the memory map, so no problem to know the address to use. In
other cases, it can be possible to use a "transparent" approach, but
in my opinion the general approach used by the driver is enough.

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 v3] char drivers: Ram oops/panic logger

2010-03-21 Thread Marco Stornelli
From: Marco Stornelli 

Ramoops, like mtdoops, can log oops/panic information but in RAM. It can
be used with persistent RAM for systems without flash support. In
addition, for this systems, with this driver, it's no more needed
add to the kernel the mtd subsystem with advantage in footprint.

Signed-off-by: Marco Stornelli 
---
Changelog:
-v1: first draft
-v2: fixed compilation warning when using request_mem_region
-v3: changed permissions from 0600 to 0400 for size and address
of ram buffer. Fixed the lack of 'ramoops:' in some printk.

--- linux-2.6.33-orig/drivers/char/Kconfig  2010-02-24 19:52:17.0 
+0100
+++ linux-2.6.33/drivers/char/Kconfig   2010-02-28 10:47:29.0 +0100
@@ -1105,5 +1105,12 @@ config DEVPORT
 
 source "drivers/s390/char/Kconfig"
 
+config RAMOOPS
+   tristate "Log panic/oops to a RAM buffer"
+   default n
+   help
+ This enables panic and oops messages to be logged to a circular
+ buffer in RAM where it can be read back at some later point.
+
 endmenu
 
--- linux-2.6.33-orig/drivers/char/Makefile 2010-02-24 19:52:17.0 
+0100
+++ linux-2.6.33/drivers/char/Makefile  2010-02-28 10:49:17.0 +0100
@@ -107,6 +107,7 @@ obj-$(CONFIG_HANGCHECK_TIMER)   += hangche
 obj-$(CONFIG_TCG_TPM)  += tpm/
 
 obj-$(CONFIG_PS3_FLASH)+= ps3flash.o
+obj-$(CONFIG_RAMOOPS)  += ramoops.o
 
 obj-$(CONFIG_JS_RTC)   += js-rtc.o
 js-rtc-y = rtc.o
--- linux-2.6.33-orig/drivers/char/ramoops.c2009-12-16 00:58:07.0 
+0100
+++ linux-2.6.33/drivers/char/ramoops.c 2010-03-21 11:06:40.0 +0100
@@ -0,0 +1,162 @@
+/*
+ * RAM Oops/Panic logger
+ *
+ * Copyright (C) 2010 Marco Stornelli 
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define RAMOOPS_KERNMSG_HDR ""
+#define RAMOOPS_HEADER_SIZE   (5 + sizeof(struct timeval))
+
+#define RECORD_SIZE 4096
+
+static ulong mem_address;
+module_param(mem_address, ulong, 0400);
+MODULE_PARM_DESC(mem_address,
+   "start of reserved RAM used to store oops/panic logs");
+
+static ulong mem_size;
+module_param(mem_size, ulong, 0400);
+MODULE_PARM_DESC(mem_size,
+   "size of reserved RAM used to store oops/panic logs");
+
+static int dump_oops = 1;
+module_param(dump_oops, int, 0600);
+MODULE_PARM_DESC(dump_oops,
+   "set to 1 to dump oopses, 0 to only dump panics (default 1)");
+
+static struct ramoops_context {
+   struct kmsg_dumper dump;
+   void *virt_addr;
+   phys_addr_t phys_addr;
+   unsigned long size;
+   int count;
+   int max_count;
+} oops_cxt;
+
+static void ramoops_do_dump(struct kmsg_dumper *dumper,
+   enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
+   const char *s2, unsigned long l2)
+{
+   struct ramoops_context *cxt = container_of(dumper,
+   struct ramoops_context, dump);
+   unsigned long s1_start, s2_start;
+   unsigned long l1_cpy, l2_cpy;
+   int res;
+   char *buf;
+   struct timeval timestamp;
+
+   /* Only dump oopses if dump_oops is set */
+   if (reason == KMSG_DUMP_OOPS && !dump_oops)
+   return;
+
+   buf = (char *)(cxt->virt_addr + (cxt->count * RECORD_SIZE));
+   memset(buf, '\0', RECORD_SIZE);
+   res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR);
+   buf += res;
+   do_gettimeofday(×tamp);
+   res = sprintf(buf, "%lu.%lu\n", (long)timestamp.tv_sec, 
(long)timestamp.tv_usec);
+   buf += res;
+
+   l2_cpy = min(l2, (unsigned long)(RECORD_SIZE - RAMOOPS_HEADER_SIZE));
+   l1_cpy = min(l1, (unsigned long)(RECORD_SIZE - RAMOOPS_HEADER_SIZE) - 
l2_cpy);
+
+   s2_start = l2 - l2_cpy;
+   s1_start = l1 - l1_cpy;
+
+   memcpy(buf, s1 + s1_start, l1_cpy);
+   memcpy(buf + l1_cpy, s2 + s2_start, l2_cpy);
+
+   cxt->count = (cxt->count + 1) % cxt->max_count;
+}
+
+static int __init ramoops_init(void)
+{
+   struct ramoops_context *cxt = &oops_cxt;
+   int err = -EINVAL;
+
+   if (!mem_size) {
+   printk(KERN_ERR "ramoops: invalid size specification");
+   go

Re: [PATCH 0/3] RFC: direct MTD support for SquashFS

2010-03-30 Thread Marco Stornelli
2010/3/30 Ferenc Wagner :
>
> Extra question: does squashfs_put_super require BKL protection?
>

We should get rid off of BKL, so if you need a lock, you should use a
local mutex.

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


Re: [PATCH] Pseudo-console for capture and redirection of console output

2010-04-12 Thread Marco Stornelli
2010/4/12 David VomLehn :
> Provide functions for capturing console output for storage. The primary user
> is likely to be embedded systems that don't have the storage for core dumps
> but do have a need to log kernel panic information for later evaluation. It
> offers two main areas of functionality:
>
> o       It can maintain a circular log of console output so that kernel log
>        messages written before panic() was called can be retrieved to be
>        added to the failure log.
> o       A function can be registered to store output from printk() in a
>        persistent location, such as a reserved location in RAM.  Then,
>        printk() can be used either directly, to print state information, or
>        indirectly, through standard functions like dump_stack() and
>        show_regs().
>
> During normal operation, we use the circular logging. When we crash, almost
> the first thing we do is to switch to storing output. This goes in a memory
> buffer that is preserved over reboots. We then write a detailed crash
> report using printk() and functions that use printk(). We retrieve the last
> n lines of the log before the crash and print it, so that gets captured
> in the log, too.
>

It's very similar to my driver ramoops, have you already seen it?
Currently it's in the mm tree, I think it will be included in mainline
early.

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


Re: Can I manage/modify console baud rates from userspace?

2010-05-02 Thread Marco Stornelli
02/05/2010 02:02, Paul Smith wrote:
> I've looked at setserial and it supports a baud_base parameter but that
> doesn't appear to be what I want (I tried it anyway: changing it didn't
> work, my console output was still screwed up).
> 
> Trying to do something like creating customized PXE configs on the
> server based on the MAC addresses of the blades that are "new" (or old)
> would be an absolute nightmare as people swap blades between chassis,
> add new ones, etc. all the time.
> 
> 
> Please help me find a better way... :-(
> 

It's strange that it's not possible to change the baud rate, but I'm not
an expert of tty layer. A naive implementation could be patch the kernel
to choose a well-known baud rate for your hw reading a revision register
or something like that.

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


Re: [PATCH] console logging detour via printk

2010-05-02 Thread Marco Stornelli
01/05/2010 20:48, Samo Pogacnik wrote:
> Dne 01.05.2010 (sob) ob 12:04 +0100 je Alan Cox zapisal(a):
>>> while i was searching for effective logging of complete console output
>>> produced by the kernel and user phase of the boot process, it turned out
>>> that only kernel messages imho get systematically cached and stored into
>>> log files (if needed). All userspace processes are on their own to use
>>> syslog, which is fine, but there are also many console messages
>>> reporting the boot status via init scripts,  I came across the
>>> bootlogd daemo, which handles the job of redirecting console output into
>>> a log file, but i find it problematic to use especialy, when using
>>> initial ram disk image.
>>
>> So you want to patch the kernel because you can't work out how to do this
>> in userspace ? The distributions seem to have no problem doing this in
>> user space that I can see. It doesn't seem to be a hard user space
>> problem, and there are a ton of things you want to do with this sort of
>> stuff (like network logging) that you can't do in kernel space.
> 
> The distros have no problem logging complete console output into log
> files or over the network, because they simply do not do it at least for
> the initrd part of the boot process (i'd be glad, if i'm wrong). 

Mmm...It's an interesting problem. I see in my distro (openSuse) a
script called boot.klog that it seems to perform that (even initrd
part). In the file boot.msg I can see the initial prints of the kernel
and user space scripts.

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


Re: [PATCH] console logging detour via printk

2010-05-03 Thread Marco Stornelli
Il 02/05/2010 15:29, Samo Pogacnik ha scritto:
> Dne 02.05.2010 (ned) ob 11:58 +0200 je Marco Stornelli zapisal(a):
>> 01/05/2010 20:48, Samo Pogacnik wrote:
>>
>> Mmm...It's an interesting problem. I see in my distro (openSuse) a
>> script called boot.klog that it seems to perform that (even initrd
>> part). In the file boot.msg I can see the initial prints of the kernel
>> and user space scripts.
>>
> Thanks for the info. 
> Is this boot.klog script from the initrd image or from the real rootfs?
> As you can see, i am still suspicious about the initrd part user console
> messages:)
> 
> Samo
> 
> 

In the initrd there's the script blogd.sh:

if test -z "$fboot" -a -z "$quiet" -a -z "$REDIRECT" ; then
REDIRECT=$(showconsole 2>/dev/null)
if test -n "$REDIRECT" ; then
if test "$devpts" != "yes" ; then
mount -t devpts devpts /dev/pts
devpts=yes
fi
> /dev/shm/initrd.msg
ln -sf /dev/shm/initrd.msg /var/log/boot.msg
mkdir -p /var/run
/sbin/blogd $REDIRECT
fi
fi

And in the rootfs the boot.klog script:

# Read all kernel messages generated until now and put them in one file.
test -s /var/log/boot.msg && mv -f /var/log/boot.msg /var/log/boot.omsg
echo Creating /var/log/boot.msg
if test -x /sbin/klogd ; then
# klogd syncs out the file
/sbin/klogd -s -o -n -f /var/log/boot.msg
test -s /var/log/boot.msg
rc_status -v1 -r
elif test -x /bin/dmesg ; then
/bin/dmesg > /var/log/boot.msg
/bin/sync
test -s /var/log/boot.msg
rc_status -v1 -r
fi
if test -e /dev/shm/initrd.msg ; then
cat /dev/shm/initrd.msg >> /var/log/boot.msg
rm -f /dev/shm/initrd.msg
fi
[ --- cut here --- ]

Regards,

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


omap udc driver problem with beagle board

2010-05-30 Thread Marco Stornelli
Hi,

I'm using the kernel 2.6.34 with the beagle board rev. c4. I have got
some problems with the ethernet gadget to use nfs over usb. The problem
is with the usb. When the g_ether driver register itself, the omap udc
driver returns ENODEV because the kernel didn't call the probe for
this driver. Looking at the code, it seems the problem is in board
specific management of the usb. There isn't the registration of the
platform device to match the omap udc platform driver. It should be done
in the omap_usb_init() but in case of beagle board this function is
never called, so omap udc driver cannot work. Is it a regression? Is
there any workaround?

Thanks.

Regards,

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


omap nand driver problem with beagle board

2010-05-30 Thread Marco Stornelli
Hi,

I'm using the kernel 2.6.34 with beagle board rev. c4. The omap nand
driver fails the probe because the field phys_base in the
omap_nand_platform_data struct is never set in the board specific code.
Indeed, the driver fails because the read address is 0x0. Is it a
regression? Has someone the same problem? What is phys address of nand
in this board to fix the problem?

Thanks.

Regards,

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


Re: omap udc driver problem with beagle board

2010-05-30 Thread Marco Stornelli
2010/5/30 Felipe Balbi :
> On Sun, May 30, 2010 at 11:53:49AM +0200, Marco Stornelli wrote:
>
> beagle board uses musb. You shouldn't be relying on the udc controller.
> Your Kconfig is just wrong.
>
> --
> balbi
>

Mmmdoes it mean that it's not possible to use g_ether driver? I
read in several docs/wiki that it's possible.

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


Re: omap udc driver problem with beagle board

2010-05-31 Thread Marco Stornelli
2010/5/30 Felipe Balbi :
> On Sun, May 30, 2010 at 11:53:49AM +0200, Marco Stornelli wrote:
> beagle board uses musb. You shouldn't be relying on the udc controller.
> Your Kconfig is just wrong.
>
> --
> balbi
>

Oops, my fault. I see the error in the configuration. Thank you very
much for your response. I'll try again.

Regards,

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


Re: [PATCH] detour TTY driver - now ttyprintk

2010-08-24 Thread Marco Stornelli
2010/8/25 Greg KH :
> On Wed, Aug 25, 2010 at 12:51:52AM +0100, Alan Cox wrote:
>
> Seriously, look at how Fedora 14 handles this, why can't you do the same
> for embedded systems all from userspace, no additional code needed
> anywhere.
>
> thanks,
>
> greg k-h
> --

Samo sometimes ago I gave you some information on the system startup
about OpenSuse, have you look at it? It's possible that what Greg
said, it's true.

Regards,

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] pramfs: Persistent and protected RAM filesystem

2010-10-05 Thread Marco Stornelli
Hi all,

after a lot of improvement, test, bug fix and new features, it's the
moment for third round with the kernel community to submit PRAMFS for
mainline. First of all, I have to say thanks to Tim Bird and CELF to
actively support the project.

Since the last review (June 2009) a lot of things are changed:

- removed any reference of BKL
- fixed the endianess for the fs layout
- added support for extended attributes, ACLs and security labels
- moved out any pte manipulations from fs and inserted them in mm
- implemented the new truncate convention
- fixed problems with 64bit archs

...and much more. Complete "story" in the ChangeLog inserted in the
documentation file.

Since the patch is long, you can download and review the patch from
the project site: http:\\pramfs.sourceforge.net. The patch version is
1.2.1 for kernel 2.6.36.
In addition, in the web site tech page, you can find a lot of
information about implementation, technical details, benchemarking and
so on.

Regards,

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 00/16] pramfs: persistent and protected RAM Filesystem

2010-10-10 Thread Marco Stornelli
Hi all,

after a lot of improvement, test, bug fix and new features, it's the
moment for third round with the kernel community to submit PRAMFS for
mainline.

Since the last review (June 2009) a lot of things are changed:

- removed any reference of BKL
- fixed the endianess for the fs layout
- added support for extended attributes, ACLs and security labels
- moved out any pte manipulations from fs and inserted them in mm
- implemented the new truncate convention
- fixed problems with 64bit archs

...and much more. Complete "story" in the ChangeLog inserted in the
documentation file.

In addition, in the web site tech page (http:\\pramfs.sourceforge.net),
you can find a lot of information about implementation, technical
details, benchmarking and so on.

All the work to mainline this feature is sponsored by the CE Linux Forum.

Regards,
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] pramfs: documentation

2010-10-10 Thread Marco Stornelli
From: Marco Stornelli 

Documentation for PRAMFS.

Signed-off-by: Marco Stornelli 
---
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-09-25 
15:10:41.0 +0200
@@ -0,0 +1,295 @@
+
+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, 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
+   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 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 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.
+Read&write 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 pte is marked read-only again.
+This feature provides protection against fi

[PATCH 03/17] pramfs: inode operations

2010-10-10 Thread Marco Stornelli
From: Marco Stornelli 

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

Signed-off-by: Marco Stornelli 
---
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 
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#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_blo

[PATCH 02/16] pramfs: super block operations

2010-10-10 Thread Marco Stornelli
From: Marco Stornelli 

Super block operations.

Signed-off-by: Marco Stornelli 
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/super.c linux-2.6.36/fs/pramfs/super.c
--- linux-2.6.36-orig/fs/pramfs/super.c 1970-01-01 01:00:00.0 +0100
+++ linux-2.6.36/fs/pramfs/super.c  2010-09-25 14:09:47.0 +0200
@@ -0,0 +1,740 @@
+/*
+ * FILE NAME fs/pramfs/super.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * Super block operations.
+ *
+ * Copyright 2009-2010 Marco Stornelli 
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "xattr.h"
+#include "pram.h"
+
+static struct super_operations pram_sops;
+static const struct export_operations pram_export_ops;
+static struct kmem_cache *pram_inode_cachep;
+
+#ifdef CONFIG_PRAMFS_TEST
+static void *first_pram_super;
+
+struct pram_super_block *get_pram_super(void)
+{
+   return (struct pram_super_block *)first_pram_super;
+}
+EXPORT_SYMBOL(get_pram_super);
+#endif
+
+static void pram_set_blocksize(struct super_block *sb, unsigned long size)
+{
+   int bits;
+
+   /*
+   * We've already validated the user input and the value here must be
+   * between PRAM_MAX_BLOCK_SIZE and PRAM_MIN_BLOCK_SIZE
+   * and it must be a power of 2.
+   */
+   bits = fls(size) - 1;
+   sb->s_blocksize_bits = bits;
+   sb->s_blocksize = (1< MAX_LFS_FILESIZE)
+   res = MAX_LFS_FILESIZE;
+
+   pram_info("Max file size %llu bytes", res);
+   return res;
+}
+
+enum {
+   Opt_addr, Opt_bpi, Opt_size,
+   Opt_num_inodes, Opt_mode, Opt_uid,
+   Opt_gid, Opt_blocksize, Opt_err
+};
+
+static const match_table_t tokens = {
+   {Opt_bpi,   "physaddr=%x"},
+   {Opt_bpi,   "bpi=%u"},
+   {Opt_size,  "init=%s"},
+   {Opt_num_inodes, "N=%u"},
+   {Opt_mode,  "mode=%o"},
+   {Opt_uid,   "uid=%u"},
+   {Opt_gid,   "gid=%u"},
+   {Opt_blocksize, "bs=%s"},
+   {Opt_err,   NULL},
+};
+
+static phys_addr_t get_phys_addr(void **data)
+{
+   phys_addr_t phys_addr;
+   char *options = (char *) *data;
+
+   if (!options || strncmp(options, "physaddr=", 9) != 0)
+   return (phys_addr_t)ULLONG_MAX;
+   options += 9;
+   phys_addr = (phys_addr_t)simple_strtoull(options, &options, 0);
+   if (*options && *options != ',') {
+   pram_err("Invalid phys addr specification: %s\n",
+  (char *) *data);
+   return (phys_addr_t)ULLONG_MAX;
+   }
+   if (phys_addr & (PAGE_SIZE - 1)) {
+   pram_err("physical address 0x%16llx for pramfs isn't "
+ "aligned to a page boundary\n",
+ (u64)phys_addr);
+   return (phys_addr_t)ULLONG_MAX;
+   }
+   if (*options == ',')
+   options++;
+   *data = (void *) options;
+   return phys_addr;
+}
+
+static int pram_parse_options(char *options, struct pram_sb_info *sbi)
+{
+   char *p, *rest;
+   substring_t args[MAX_OPT_ARGS];
+   int option;
+
+   if (!options)
+   return 0;
+
+   while ((p = strsep(&options, ",")) != NULL) {
+   int token;
+   if (!*p)
+   continue;
+
+   token = match_token(p, tokens, args);
+   switch (token) {
+   case Opt_addr: {
+   /* physaddr managed in get_phys_addr() */
+   break;
+   }
+   case Opt_bpi: {
+   if (match_int(&args[0], &option))
+   goto bad_val;
+   sbi->bpi = option;
+   break;
+   }
+   case Opt_uid: {
+   if (match_int(&args[0], &option))
+   goto bad_val;
+   sbi->uid = option;
+   break;
+   }
+   case Opt_gid: {
+   if (match_int(&args[0], &option))
+   goto bad_val;
+ 

[PATCH 06/16] pramfs: inode operations for dirs

2010-10-10 Thread Marco Stornelli
From: Marco Stornelli 

Inode operations for directories.

Signed-off-by: Marco Stornelli 
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/namei.c linux-2.6.36/fs/pramfs/namei.c
--- linux-2.6.36-orig/fs/pramfs/namei.c 1970-01-01 01:00:00.0 +0100
+++ linux-2.6.36/fs/pramfs/namei.c  2010-09-18 12:00:35.0 +0200
@@ -0,0 +1,363 @@
+/*
+ * FILE NAME fs/pramfs/namei.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * Inode operations for directories.
+ *
+ * Copyright 2009-2010 Marco Stornelli 
+ * 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 
+#include 
+#include "pram.h"
+#include "acl.h"
+#include "xattr.h"
+
+/*
+ * Couple of helper functions - make the code slightly cleaner.
+ */
+
+static inline void pram_inc_count(struct inode *inode)
+{
+   inode->i_nlink++;
+   pram_write_inode(inode, 0);
+}
+
+static inline void pram_dec_count(struct inode *inode)
+{
+   if (inode->i_nlink) {
+   inode->i_nlink--;
+   pram_write_inode(inode, 0);
+   }
+}
+
+static inline int pram_add_nondir(struct inode *dir,
+  struct dentry *dentry,
+  struct inode *inode)
+{
+   int err = pram_add_link(dentry, inode);
+   if (!err) {
+   d_instantiate(dentry, inode);
+   unlock_new_inode(inode);
+   return 0;
+   }
+   pram_dec_count(inode);
+   unlock_new_inode(inode);
+   iput(inode);
+   return err;
+}
+
+/*
+ * Methods themselves.
+ */
+
+static ino_t
+pram_inode_by_name(struct inode *dir,
+  struct dentry *dentry)
+{
+   struct pram_inode *pi;
+   ino_t ino;
+   int namelen;
+
+   pi = pram_get_inode(dir->i_sb, dir->i_ino);
+   ino = be64_to_cpu(pi->i_type.dir.head);
+
+   while (ino) {
+   pi = pram_get_inode(dir->i_sb, ino);
+
+   if (pi->i_links_count) {
+   namelen = strlen(pi->i_d.d_name);
+
+   if (namelen == dentry->d_name.len &&
+   !memcmp(dentry->d_name.name,
+   pi->i_d.d_name, namelen))
+   break;
+   }
+
+   ino = be64_to_cpu(pi->i_d.d_next);
+   }
+
+   return ino;
+}
+
+static struct dentry *
+pram_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+{
+   struct inode *inode = NULL;
+   ino_t ino;
+
+   if (dentry->d_name.len > PRAM_NAME_LEN)
+   return ERR_PTR(-ENAMETOOLONG);
+
+   ino = pram_inode_by_name(dir, dentry);
+   if (ino) {
+   inode = pram_iget(dir->i_sb, ino);
+   if (!inode)
+   return ERR_PTR(-EACCES);
+   }
+
+   d_splice_alias(inode, dentry);
+   return NULL;
+}
+
+
+/*
+ * By the time this is called, we already have created
+ * the directory cache entry for the new file, but it
+ * is so far negative - it has no inode.
+ *
+ * If the create succeeds, we fill in the inode information
+ * with d_instantiate().
+ */
+static int pram_create(struct inode *dir, struct dentry *dentry,
+   int mode, struct nameidata *nd)
+{
+   struct inode *inode = pram_new_inode(dir, mode);
+   int err = PTR_ERR(inode);
+   if (!IS_ERR(inode)) {
+
+   inode->i_op = &pram_file_inode_operations;
+   inode->i_fop = &pram_file_operations;
+   inode->i_mapping->a_ops = &pram_aops;
+   err = pram_add_nondir(dir, dentry, inode);
+   }
+   return err;
+}
+
+static int pram_mknod(struct inode *dir, struct dentry *dentry, int mode,
+  dev_t rdev)
+{
+   struct inode *inode = pram_new_inode(dir, mode);
+   int err = PTR_ERR(inode);
+   if (!IS_ERR(inode)) {
+   init_special_inode(inode, mode, rdev);
+   pram_write_inode(inode, 0); /* update rdev */
+   err = pram_add_nondir(dir, dentry, inode);
+   }
+   return err;
+}
+
+static int pram_symlink(struct inode *dir,
+ struct dentry *dentry,
+ const char *symname)
+{
+   struct super_block *sb = dir->i_sb;
+   int err = -ENAMETOOLONG;
+   unsigned len = strlen(symname);
+   struct inode *inode;
+
+   if (len+1 > sb->s_blocksize)
+   goto out;
+
+   inode = pram_new_inode(dir, S_IFLNK | S_IRWXUGO);
+   err = PTR_ERR(inode);
+   if (IS_ERR(inode))
+   goto out;
+
+   inode->i_op = 

[PATCH 05/16] pramfs: block allocation

2010-10-10 Thread Marco Stornelli
From: Marco Stornelli 

Block allocation operations.

Signed-off-by: Marco Stornelli 
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/balloc.c linux-2.6.36/fs/pramfs/balloc.c
--- linux-2.6.36-orig/fs/pramfs/balloc.c1970-01-01 01:00:00.0 
+0100
+++ linux-2.6.36/fs/pramfs/balloc.c 2010-09-26 18:05:06.0 +0200
@@ -0,0 +1,155 @@
+/*
+ * FILE NAME fs/pramfs/balloc.c
+ *
+ * BRIEF MODULE DESCRIPTION
+ *
+ * The blocks allocation and deallocation routines.
+ *
+ * Copyright 2009-2010 Marco Stornelli 
+ * 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 
+#include 
+#include "pram.h"
+
+/*
+ * This just marks in-use the blocks that make up the bitmap.
+ * The bitmap must be writeable before calling.
+ */
+void pram_init_bitmap(struct super_block *sb)
+{
+   struct pram_super_block *ps = pram_get_super(sb);
+   u64 *bitmap = pram_get_bitmap(sb);
+   int blocks = be32_to_cpu(ps->s_bitmap_blocks);
+
+   memset(bitmap, 0, blocks << sb->s_blocksize_bits);
+
+   while (blocks >= 64) {
+   *bitmap++ = (u64)ULLONG_MAX;
+   blocks -= 64;
+   }
+
+   if (blocks)
+   *bitmap = cpu_to_le64((1ULL << blocks) - 1);
+}
+
+
+/* Free absolute blocknr */
+void pram_free_block(struct super_block *sb, unsigned long blocknr)
+{
+   struct pram_super_block *ps;
+   u64 bitmap_block;
+   unsigned long bitmap_bnr;
+   void *bitmap;
+   void *bp;
+
+   lock_super(sb);
+
+   bitmap = pram_get_bitmap(sb);
+   /*
+* find the block within the bitmap that contains the inuse bit
+* for the block we need to free. We need to unlock this bitmap
+* block to clear the inuse bit.
+*/
+   bitmap_bnr = blocknr >> (3 + sb->s_blocksize_bits);
+   bitmap_block = pram_get_block_off(sb, bitmap_bnr);
+   bp = pram_get_block(sb, bitmap_block);
+
+   pram_memunlock_block(sb, bp);
+   pram_clear_bit(blocknr, bitmap); /* mark the block free */
+   pram_memlock_block(sb, bp);
+
+   ps = pram_get_super(sb);
+   pram_memunlock_super(ps);
+   if (blocknr < be32_to_cpu(ps->s_free_blocknr_hint))
+   ps->s_free_blocknr_hint = cpu_to_be32(blocknr);
+   be32_add_cpu(&ps->s_free_blocks_count, 1);
+   pram_memlock_super(ps);
+
+   unlock_super(sb);
+}
+
+
+/*
+ * allocate a block and return it's absolute blocknr. Zeroes out the
+ * block if zero set.
+ */
+int pram_new_block(struct super_block *sb, unsigned long *blocknr, int zero)
+{
+   struct pram_super_block *ps;
+   off_t bitmap_block;
+   unsigned long bnr, bitmap_bnr;
+   int errval;
+   void *bitmap;
+   void *bp;
+
+   lock_super(sb);
+   ps = pram_get_super(sb);
+   bitmap = pram_get_bitmap(sb);
+
+   if (ps->s_free_blocks_count) {
+   /* find the oldest unused block */
+   bnr = pram_find_next_zero_bit(bitmap,
+be32_to_cpu(ps->s_blocks_count),
+be32_to_cpu(ps->s_free_blocknr_hint));
+
+   if (bnr < be32_to_cpu(ps->s_bitmap_blocks) ||
+   bnr >= be32_to_cpu(ps->s_blocks_count)) {
+   pram_err("no free blocks found!\n");
+   errval = -ENOSPC;
+   goto fail;
+   }
+
+   pram_dbg("allocating blocknr %lu\n", bnr);
+   pram_memunlock_super(ps);
+   be32_add_cpu(&ps->s_free_blocks_count, -1);
+   if (bnr < (be32_to_cpu(ps->s_blocks_count)-1))
+   ps->s_free_blocknr_hint = cpu_to_be32(bnr+1);
+   else
+   ps->s_free_blocknr_hint = 0;
+   pram_memlock_super(ps);
+   } else {
+   pram_err("all blocks allocated\n");
+   errval = -ENOSPC;
+   goto fail;
+   }
+
+   /*
+* find the block within the bitmap that contains the inuse bit
+* for the unused block we just found. We need to unlock it to
+* set the inuse bit.
+*/
+   bitmap_bnr = bnr >> (3 + sb->s_blocksize_bits);
+   bitmap_block = pram_get_block_off(sb, bitmap_bnr);
+   bp = pram_get_block(sb, bitmap_block);
+
+   pram_memunlock_block(sb, bp);
+   pram_set_bit(bnr, bitmap); /* mark the new block in use */
+   pram_memlock_block(sb, bp);
+
+   if (zero) {
+   bp = pram_get_block(sb, pram_get_block_off(sb, bnr));
+   

[PATCH 08/16] pramfs: headers

2010-10-10 Thread Marco Stornelli
From: Marco Stornelli 

Definitions for the PRAMFS filesystem.

Signed-off-by: Marco Stornelli 
---
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-09-23 21:04:20.0 +0200
@@ -0,0 +1,316 @@
+/*
+ * FILE NAME pram.h
+ *
+ * BRIEF DESCRIPTION
+ *
+ * Definitions for the PRAMFS filesystem.
+ *
+ * Copyright 2009-2010 Marco Stornelli 
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * 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);
+
+
+#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 + sizeof(__be16), n - sizeof(__be16));
+   if (*((__be16 *)data) == cpu_to_be16(crc))
+   return 0;
+   else
+   return 1;
+}
+
+/* If this

[PATCH 07/16] pramfs: symbolic links

2010-10-10 Thread Marco Stornelli
From: Marco Stornelli 

Symlink operations.

Signed-off-by: Marco Stornelli 
---
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 
+ * 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 
+#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 09/16] pramfs: dir operations

2010-10-10 Thread Marco Stornelli
From: Marco Stornelli 

File operations for directories.

Signed-off-by: Marco Stornelli 
---
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 
+ * 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 
+#include 
+#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;
+   

[PATCH 12/16] pramfs: extended attributes

2010-10-10 Thread Marco Stornelli
From: Marco Stornelli 

Extended attributes operations.

Signed-off-by: Marco Stornelli 
---
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 
+ *
+ * based on fs/ext2/xattr.c with the following copyright:
+ *
+ * Fix by Harrison Xing .
+ * Extended attributes for symlinks and special files added per
+ *  suggestion of Luka Renko .
+ * xattr consolidation Copyright (c) 2004 James Morris ,
+ *  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 
+#include 
+#include 
+#include 
+#include 
+#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 struct xattr_handler 

[PATCH 14(16] pramfs: memory protection

2010-10-10 Thread Marco Stornelli
From: Marco Stornelli 

Memory write protection.

Signed-off-by: Marco Stornelli 
---
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-09-26 18:04:07.0 +0200
@@ -0,0 +1,31 @@
+/*
+ * FILE NAME fs/pramfs/wprotect.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * Write protection for the filesystem pages.
+ *
+ * Copyright 2009-2010 Marco Stornelli 
+ * 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 
+#include 
+#include 
+#include 
+#include "pram.h"
+
+void pram_writeable(void *vaddr, unsigned long size, int rw)
+{
+   int ret = 0;
+
+   ret = rw ? write_on_kernel_pte_range((unsigned long)vaddr, size) :
+   write_off_kernel_pte_range((unsigned long)vaddr, size);
+
+   BUG_ON(ret);
+}
diff -Nurp linux-2.6.36-orig/include/linux/mm.h linux-2.6.36/include/linux/mm.h
--- linux-2.6.36-orig/include/linux/mm.h2010-09-13 01:07:37.0 
+0200
+++ linux-2.6.36/include/linux/mm.h 2010-09-14 18:49:52.0 +0200
@@ -811,6 +811,11 @@ int follow_phys(struct vm_area_struct *v
unsigned int flags, unsigned long *prot, resource_size_t *phys);
 int generic_access_phys(struct vm_area_struct *vma, unsigned long addr,
void *buf, int len, int write);
+int writeable_kernel_pte_range(unsigned long address, unsigned long size,
+   unsigned int rw);
+
+#define write_on_kernel_pte_range(addr, size) writeable_kernel_pte_range(addr, 
size, 1)
+#define write_off_kernel_pte_range(addr, size) 
writeable_kernel_pte_range(addr, size, 0)
  static inline void unmap_shared_mapping_range(struct address_space *mapping,
loff_t const holebegin, loff_t const holelen)
diff -Nurp linux-2.6.36-orig/mm/memory.c linux-2.6.36/mm/memory.c
--- linux-2.6.36-orig/mm/memory.c   2010-09-13 01:07:37.0 +0200
+++ linux-2.6.36/mm/memory.c2010-09-14 18:49:52.0 +0200
@@ -3587,3 +3587,49 @@ void might_fault(void)
 }
 EXPORT_SYMBOL(might_fault);
 #endif
+
+int writeable_kernel_pte_range(unsigned long address, unsigned long size,
+ unsigned int rw)
+{
+
+   unsigned long addr = address & PAGE_MASK;
+   unsigned long end = address + size;
+   unsigned long start = addr;
+   int ret = -EINVAL;
+   pgd_t *pgd;
+   pud_t *pud;
+   pmd_t *pmd;
+   pte_t *ptep, pte;
+
+   spin_lock_irq(&init_mm.page_table_lock);
+
+   do {
+   pgd = pgd_offset(&init_mm, address);
+   if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
+   goto out;
+
+   pud = pud_offset(pgd, address);
+   if (pud_none(*pud) || unlikely(pud_bad(*pud)))
+   goto out;
+
+   pmd = pmd_offset(pud, address);
+   if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
+   goto out;
+
+   ptep = pte_offset_kernel(pmd, addr);
+   pte = *ptep;
+   if (pte_present(pte)) {
+ pte = rw ? pte_mkwrite(pte) : pte_wrprotect(pte);
+ *ptep = pte;
+   }
+   addr += PAGE_SIZE;
+   } while (addr && (addr < end));
+
+   ret = 0;
+
+out:
+   flush_tlb_kernel_range(start, end);
+   spin_unlock_irq(&init_mm.page_table_lock);
+   return ret;
+}
+EXPORT_SYMBOL(writeable_kernel_pte_range);
 
--
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] pramfs Makefile and Kconfig

2010-10-10 Thread Marco Stornelli
From: Marco Stornelli 

Makefile and Kconfig.

Signed-off-by: Marco Stornelli 
---
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-09-14 18:49:52.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 .
+
+  To compile this as a module,  choose M here: the module will be
+  called pramfs.ko.
+
+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
+   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 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.ko.
diff -Nurp linux-2.6.36-orig/fs/pramfs/Makefile linux-2.6.36/fs/pramfs/Makefile
--- linux-2.6.36-

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

2010-10-10 Thread Marco Stornelli
From: Marco Stornelli 

Extended attributes block descriptors tree.

Signed-off-by: Marco Stornelli 
---
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,184 @@
+/*
+ * FILE NAME fs/pramfs/desctree.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * Extended attributes block descriptors tree.
+ *
+ * Copyright 2010 Marco Stornelli 
+ *
+ * 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 
+#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)
+{
+ 

[PATCH 11/16] pramfs: ACL management

2010-10-10 Thread Marco Stornelli
From: Marco Stornelli 

ACL operations.

Signed-off-by: Marco Stornelli 
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/acl.c linux-2.6.36/fs/pramfs/acl.c
--- linux-2.6.36-orig/fs/pramfs/acl.c   1970-01-01 01:00:00.0 +0100
+++ linux-2.6.36/fs/pramfs/acl.c2010-09-14 18:49:52.0 +0200
@@ -0,0 +1,418 @@
+/*
+ * FILE NAME fs/pramfs/acl.h
+ *
+ * BRIEF MODULE DESCRIPTION
+ *
+ * POSIX ACL operations
+ *
+ * Copyright 2010 Marco Stornelli 
+ *
+ * based on fs/ext2/acl.c with the following copyright:
+ *
+ * Copyright (C) 2001-2003 Andreas Gruenbacher, 
+ *
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include "pram.h"
+#include "xattr.h"
+#include "acl.h"
+
+/*
+ * Load ACL information from filesystem.
+ */
+static struct posix_acl *pram_acl_load(const void *value, size_t size)
+{
+   const char *end = (char *)value + size;
+   int n, count;
+   struct posix_acl *acl;
+
+   if (!value)
+   return NULL;
+   if (size < sizeof(struct pram_acl_header))
+return ERR_PTR(-EINVAL);
+   if (((struct pram_acl_header *)value)->a_version !=
+   cpu_to_be32(PRAM_ACL_VERSION))
+   return ERR_PTR(-EINVAL);
+   value = (char *)value + sizeof(struct pram_acl_header);
+   count = pram_acl_count(size);
+   if (count < 0)
+   return ERR_PTR(-EINVAL);
+   if (count == 0)
+   return NULL;
+   acl = posix_acl_alloc(count, GFP_KERNEL);
+   if (!acl)
+   return ERR_PTR(-ENOMEM);
+   for (n = 0; n < count; n++) {
+   struct pram_acl_entry *entry = (struct pram_acl_entry *)value;
+   if ((char *)value + sizeof(struct pram_acl_entry_short) > end)
+   goto fail;
+   acl->a_entries[n].e_tag  = be16_to_cpu(entry->e_tag);
+   acl->a_entries[n].e_perm = be16_to_cpu(entry->e_perm);
+   switch (acl->a_entries[n].e_tag) {
+   case ACL_USER_OBJ:
+   case ACL_GROUP_OBJ:
+   case ACL_MASK:
+   case ACL_OTHER:
+   value = (char *)value +
+   sizeof(struct pram_acl_entry_short);
+   acl->a_entries[n].e_id = ACL_UNDEFINED_ID;
+   break;
+   case ACL_USER:
+   case ACL_GROUP:
+   value = (char *)value + sizeof(struct pram_acl_entry);
+   if ((char *)value > end)
+   goto fail;
+   acl->a_entries[n].e_id =
+   be32_to_cpu(entry->e_id);
+   break;
+   default:
+   goto fail;
+   }
+   }
+   if (value != end)
+   goto fail;
+   return acl;
+
+fail:
+   posix_acl_release(acl);
+   return ERR_PTR(-EINVAL);
+}
+
+/*
+ * Save ACL information into the filesystem.
+ */
+static void *pram_acl_save(const struct posix_acl *acl, size_t *size)
+{
+   struct pram_acl_header *ext_acl;
+   char *e;
+   size_t n;
+
+   *size = pram_acl_size(acl->a_count);
+   ext_acl = kmalloc(sizeof(struct pram_acl_header) + acl->a_count *
+   sizeof(struct pram_acl_entry), GFP_KERNEL);
+   if (!ext_acl)
+   return ERR_PTR(-ENOMEM);
+   ext_acl->a_version = cpu_to_be32(PRAM_ACL_VERSION);
+   e = (char *)ext_acl + sizeof(struct pram_acl_header);
+   for (n = 0; n < acl->a_count; n++) {
+   struct pram_acl_entry *entry = (struct pram_acl_entry *)e;
+   entry->e_tag  = cpu_to_be16(acl->a_entries[n].e_tag);
+   entry->e_perm = cpu_to_be16(acl->a_entries[n].e_perm);
+   switch (acl->a_entries[n].e_tag) {
+   case ACL_USER:
+   case ACL_GROUP:
+   entry->e_id =
+   cpu_to_be32(acl->a_entries[n].e_id);
+   e += sizeof(struct pram_acl_entry);
+   break;
+   case ACL_USER_OBJ:
+   case ACL_GROUP_OBJ:
+   case ACL_MASK:
+   case ACL_OTHER:
+   e += sizeof(struct pram_acl_entry_short);
+   break;
+   default:
+   goto fail;
+   }
+   }
+   return (char *)ext_acl;
+
+fail:
+   kfree(ext_acl);
+   return ERR_PTR(-EINVAL);
+}
+
+/*
+ * inode->i_mutex: don't care
+ */
+static struct posix_acl *pram_get_acl(struct inode *inode, int type)
+{
+   int name_index;
+   char *value = NULL;
+  

[PATCH 15/16] pramfs: test module

2010-10-10 Thread Marco Stornelli
From: Marco Stornelli 

Test module.

Signed-off-by: Marco Stornelli 
---
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/namei.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * Pramfs test module.
+ *
+ * Copyright 2009-2010 Marco Stornelli 
+ * 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 
+#include 
+#include 
+#include 
+#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


[PATCH 04/16] pramfs: file operations

2010-10-10 Thread Marco Stornelli
From: Marco Stornelli 

File operations.

Signed-off-by: Marco Stornelli 
---
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 
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#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:
+   retv

[PATCH 10/16] pramfs: xip operations

2010-10-10 Thread Marco Stornelli
From: Marco Stornelli 

XIP operations.

Signed-off-by: Marco Stornelli 
---
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 
+ * 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 
+#include 
+#include 
+#include 
+#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_lock);
+
+   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_lock);
+   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 
+ * 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


Re: [PATCH 14(16] pramfs: memory protection

2010-10-10 Thread Marco Stornelli
2010/10/10 Andi Kleen :
> Marco Stornelli  writes:
>> +
>> +     do {
>> +             pgd = pgd_offset(&init_mm, address);
>> +             if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
>> +                     goto out;
>> +
>> +             pud = pud_offset(pgd, address);
>> +             if (pud_none(*pud) || unlikely(pud_bad(*pud)))
>> +                     goto out;
>> +
>> +             pmd = pmd_offset(pud, address);
>> +             if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
>> +                     goto out;
>> +
>> +             ptep = pte_offset_kernel(pmd, addr);
>> +             pte = *ptep;
>> +             if (pte_present(pte)) {
>
> This won't work at all on x86 because you don't handle large
> pages.

On x86 works because I tested. Maybe there's a particular
configuration with large pages. Sincerly I'm only an "user", so if
you/Linus or others want to change it or rewrite it, for me it's ok.
The pte manipulation are a bit out of scope for a fs, so I let the
things to the mm experts.
--
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


Re: [PATCH 15/16] pramfs: test module

2010-10-11 Thread Marco Stornelli
2010/10/10 Randy Dunlap :
> On Sun, 10 Oct 2010 18:37:49 +0200 Marco Stornelli wrote:
>
> Above 2 lines need to indented more.
>

Ack.

>> +             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


Re: [PATCH 16/16] pramfs Makefile and Kconfig

2010-10-11 Thread Marco Stornelli
2010/10/10 Randy Dunlap :
> On Sun, 10 Oct 2010 18:39:11 +0200 Marco Stornelli wrote:
>
>> From: Marco Stornelli 
>>
>> Makefile and Kconfig.
>>
>> Signed-off-by: Marco Stornelli 
>> ---
>>  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-09-14 18:49:52.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 .
>> +
>> +        To compile this as a module,  choose M here: the module will be
>> +        called pramfs.ko.
>
>          called pramfs.
>
> (we don't add the .ko suffix; well, we try not to do that)

Ok.

>
>> +
>> +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.
>
>                                XIP

Ok.

>
>> +
>> +config PRAMFS_WRITE_PROTECT
>> +     bool "Enable PRAMFS write protection"
>> +     depends on PRAMFS && MMU
>> +     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
>
> end sentence with period ('.').

Ok.
--
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


Re: [PATCH 11/16] pramfs: ACL management

2010-10-11 Thread Marco Stornelli
Il 11/10/2010 14:26, Kieran Bingham ha scritto:
>  On 10/10/2010 17:33, Marco Stornelli wrote:
>> From: Marco Stornelli
>>
>> ACL operations.
>>
>> Signed-off-by: Marco Stornelli
>> ---
>> diff -Nurp linux-2.6.36-orig/fs/pramfs/acl.c linux-2.6.36/fs/pramfs/acl.c
>> --- linux-2.6.36-orig/fs/pramfs/acl.c1970-01-01 01:00:00.0
>> +0100
>> +++ linux-2.6.36/fs/pramfs/acl.c2010-09-14 18:49:52.0 +0200
>> @@ -0,0 +1,418 @@
>> +/*
>> + * FILE NAME fs/pramfs/acl.h
> Found another one :)
> FILE NAME != acl.h ...
> -- 
> KB
> 

Oops, damn copy&paste ;) I'll fix it asap.

Thanks.

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


Re: [PATCH 14(16] pramfs: memory protection

2010-10-11 Thread Marco Stornelli
Il 10/10/2010 18:46, Andi Kleen ha scritto:
> This won't work at all on x86 because you don't handle large 
> pages.
> 
> And it doesn't work on x86-64 because the first 2GB are double
> mapped (direct and kernel text mapping)
> 
> Thirdly I expect it won't either on architectures that map
> the direct mapping with special registers (like IA64 or MIPS)

Andi, what do you think to use the already implemented follow_pte
instead? 

int writeable_kernel_pte_range(unsigned long address, unsigned long size,
  unsigned int rw)
{

unsigned long addr = address & PAGE_MASK;
unsigned long end = address + size;
unsigned long start = addr;
int ret = -EINVAL;
pte_t *ptep, pte;
spinlock_t *lock = &init_mm.page_table_lock;

do {
ret = follow_pte(&init_mm, addr, &ptep, &lock);
if (ret)
goto out;
pte = *ptep;
if (pte_present(pte)) {
  pte = rw ? pte_mkwrite(pte) : pte_wrprotect(pte);
  *ptep = pte;
}
pte_unmap_unlock(ptep, lock);
addr += PAGE_SIZE;
} while (addr && (addr < end));

ret = 0;

out:
flush_tlb_kernel_range(start, end);
return ret;
}


> 
> I'm not sure this is very useful anyways. It doesn't protect
> against stray DMA and it doesn't protect against writes through
> broken user PTEs.
> 
> -Andi
> 

It's a way to have more protection against kernel bug, for a 
in-memory fs can be important. However this option can be 
enabled/disabled at fs level.

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


Re: [PATCH 14(16] pramfs: memory protection

2010-10-12 Thread Marco Stornelli
2010/10/12 Andi Kleen :
> On Mon, Oct 11, 2010 at 07:32:10PM +0200, Marco Stornelli wrote:
>> Il 10/10/2010 18:46, Andi Kleen ha scritto:
>> > This won't work at all on x86 because you don't handle large
>> > pages.
>> >
>> > And it doesn't work on x86-64 because the first 2GB are double
>> > mapped (direct and kernel text mapping)
>> >
>> > Thirdly I expect it won't either on architectures that map
>> > the direct mapping with special registers (like IA64 or MIPS)
>>
>> Andi, what do you think to use the already implemented follow_pte
>> instead?
>
> Has all the same problems. Really you need an per architecture
> function. Perhaps some architectures could use a common helper,
> but certainly not all.
>

per-arch?! Wow. Mmm...maybe I have to change something at fs level to
avoid that. An alternative could be to use the follow_pte solution but
avoid the protection via Kconfig if the fs is used on some archs (ia64
or MIPS), with large pages and so on. An help of the kernel community
to know all these particular cases is welcome.

Regards,

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


Re: [PATCH 01/16] pramfs: documentation

2010-10-21 Thread Marco Stornelli
2010/10/20 Randy Dunlap :
> On Sun, 10 Oct 2010 18:27:34 +0200 Marco Stornelli wrote:
>
>> From: Marco Stornelli 
>>
>> Documentation for PRAMFS.
>>
>> Signed-off-by: Marco Stornelli 
>> ---

Ack for all the remarks, thank for the review.

Regards,

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 00/16 v2] pramfs: persistent and protected RAM Filesystem

2010-11-06 Thread Marco Stornelli
Hi all,

I send the patch series again. I fix documentation problems reported by
Randy Dunlap and Kieran Bingham. I reworked the memory protection
functions according to the suggestions of Andi Kleen.

I ask to Andrew to evaluate to insert this fs in mainline.

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 v2] pramfs: documentation

2010-11-06 Thread Marco Stornelli
From: Marco Stornelli 

Documentation for PRAMFS.

Signed-off-by: Marco Stornelli 
---
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.
+Read&write 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 again.
+This feature pro

[PATCH 02/16 v2] pramfs: super block operations

2010-11-06 Thread Marco Stornelli
From: Marco Stornelli 

Super block operations.

Signed-off-by: Marco Stornelli 
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/super.c linux-2.6.36/fs/pramfs/super.c
--- linux-2.6.36-orig/fs/pramfs/super.c 1970-01-01 01:00:00.0 +0100
+++ linux-2.6.36/fs/pramfs/super.c  2010-09-25 14:09:47.0 +0200
@@ -0,0 +1,740 @@
+/*
+ * FILE NAME fs/pramfs/super.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * Super block operations.
+ *
+ * Copyright 2009-2010 Marco Stornelli 
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "xattr.h"
+#include "pram.h"
+
+static struct super_operations pram_sops;
+static const struct export_operations pram_export_ops;
+static struct kmem_cache *pram_inode_cachep;
+
+#ifdef CONFIG_PRAMFS_TEST
+static void *first_pram_super;
+
+struct pram_super_block *get_pram_super(void)
+{
+   return (struct pram_super_block *)first_pram_super;
+}
+EXPORT_SYMBOL(get_pram_super);
+#endif
+
+static void pram_set_blocksize(struct super_block *sb, unsigned long size)
+{
+   int bits;
+
+   /*
+   * We've already validated the user input and the value here must be
+   * between PRAM_MAX_BLOCK_SIZE and PRAM_MIN_BLOCK_SIZE
+   * and it must be a power of 2.
+   */
+   bits = fls(size) - 1;
+   sb->s_blocksize_bits = bits;
+   sb->s_blocksize = (1< MAX_LFS_FILESIZE)
+   res = MAX_LFS_FILESIZE;
+
+   pram_info("Max file size %llu bytes", res);
+   return res;
+}
+
+enum {
+   Opt_addr, Opt_bpi, Opt_size,
+   Opt_num_inodes, Opt_mode, Opt_uid,
+   Opt_gid, Opt_blocksize, Opt_err
+};
+
+static const match_table_t tokens = {
+   {Opt_bpi,   "physaddr=%x"},
+   {Opt_bpi,   "bpi=%u"},
+   {Opt_size,  "init=%s"},
+   {Opt_num_inodes, "N=%u"},
+   {Opt_mode,  "mode=%o"},
+   {Opt_uid,   "uid=%u"},
+   {Opt_gid,   "gid=%u"},
+   {Opt_blocksize, "bs=%s"},
+   {Opt_err,   NULL},
+};
+
+static phys_addr_t get_phys_addr(void **data)
+{
+   phys_addr_t phys_addr;
+   char *options = (char *) *data;
+
+   if (!options || strncmp(options, "physaddr=", 9) != 0)
+   return (phys_addr_t)ULLONG_MAX;
+   options += 9;
+   phys_addr = (phys_addr_t)simple_strtoull(options, &options, 0);
+   if (*options && *options != ',') {
+   pram_err("Invalid phys addr specification: %s\n",
+  (char *) *data);
+   return (phys_addr_t)ULLONG_MAX;
+   }
+   if (phys_addr & (PAGE_SIZE - 1)) {
+   pram_err("physical address 0x%16llx for pramfs isn't "
+ "aligned to a page boundary\n",
+ (u64)phys_addr);
+   return (phys_addr_t)ULLONG_MAX;
+   }
+   if (*options == ',')
+   options++;
+   *data = (void *) options;
+   return phys_addr;
+}
+
+static int pram_parse_options(char *options, struct pram_sb_info *sbi)
+{
+   char *p, *rest;
+   substring_t args[MAX_OPT_ARGS];
+   int option;
+
+   if (!options)
+   return 0;
+
+   while ((p = strsep(&options, ",")) != NULL) {
+   int token;
+   if (!*p)
+   continue;
+
+   token = match_token(p, tokens, args);
+   switch (token) {
+   case Opt_addr: {
+   /* physaddr managed in get_phys_addr() */
+   break;
+   }
+   case Opt_bpi: {
+   if (match_int(&args[0], &option))
+   goto bad_val;
+   sbi->bpi = option;
+   break;
+   }
+   case Opt_uid: {
+   if (match_int(&args[0], &option))
+   goto bad_val;
+   sbi->uid = option;
+   break;
+   }
+   case Opt_gid: {
+   if (match_int(&args[0], &option))
+   goto bad_val;
+ 

[PATCH 03/16 v2] pramfs: inode operations

2010-11-06 Thread Marco Stornelli
From: Marco Stornelli 

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

Signed-off-by: Marco Stornelli 
---
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 
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#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_blo

[PATCH 04/16 v2] pramfs: file operations

2010-11-06 Thread Marco Stornelli
From: Marco Stornelli 

File operations.

Signed-off-by: Marco Stornelli 
---
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 
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#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:
+   retv

[PATCH 05/16 v2] pramfs: block allocation

2010-11-06 Thread Marco Stornelli
From: Marco Stornelli 

Block allocation operations.

Signed-off-by: Marco Stornelli 
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/balloc.c linux-2.6.36/fs/pramfs/balloc.c
--- linux-2.6.36-orig/fs/pramfs/balloc.c1970-01-01 01:00:00.0 
+0100
+++ linux-2.6.36/fs/pramfs/balloc.c 2010-09-26 18:05:06.0 +0200
@@ -0,0 +1,155 @@
+/*
+ * FILE NAME fs/pramfs/balloc.c
+ *
+ * BRIEF MODULE DESCRIPTION
+ *
+ * The blocks allocation and deallocation routines.
+ *
+ * Copyright 2009-2010 Marco Stornelli 
+ * 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 
+#include 
+#include "pram.h"
+
+/*
+ * This just marks in-use the blocks that make up the bitmap.
+ * The bitmap must be writeable before calling.
+ */
+void pram_init_bitmap(struct super_block *sb)
+{
+   struct pram_super_block *ps = pram_get_super(sb);
+   u64 *bitmap = pram_get_bitmap(sb);
+   int blocks = be32_to_cpu(ps->s_bitmap_blocks);
+
+   memset(bitmap, 0, blocks << sb->s_blocksize_bits);
+
+   while (blocks >= 64) {
+   *bitmap++ = (u64)ULLONG_MAX;
+   blocks -= 64;
+   }
+
+   if (blocks)
+   *bitmap = cpu_to_le64((1ULL << blocks) - 1);
+}
+
+
+/* Free absolute blocknr */
+void pram_free_block(struct super_block *sb, unsigned long blocknr)
+{
+   struct pram_super_block *ps;
+   u64 bitmap_block;
+   unsigned long bitmap_bnr;
+   void *bitmap;
+   void *bp;
+
+   lock_super(sb);
+
+   bitmap = pram_get_bitmap(sb);
+   /*
+* find the block within the bitmap that contains the inuse bit
+* for the block we need to free. We need to unlock this bitmap
+* block to clear the inuse bit.
+*/
+   bitmap_bnr = blocknr >> (3 + sb->s_blocksize_bits);
+   bitmap_block = pram_get_block_off(sb, bitmap_bnr);
+   bp = pram_get_block(sb, bitmap_block);
+
+   pram_memunlock_block(sb, bp);
+   pram_clear_bit(blocknr, bitmap); /* mark the block free */
+   pram_memlock_block(sb, bp);
+
+   ps = pram_get_super(sb);
+   pram_memunlock_super(ps);
+   if (blocknr < be32_to_cpu(ps->s_free_blocknr_hint))
+   ps->s_free_blocknr_hint = cpu_to_be32(blocknr);
+   be32_add_cpu(&ps->s_free_blocks_count, 1);
+   pram_memlock_super(ps);
+
+   unlock_super(sb);
+}
+
+
+/*
+ * allocate a block and return it's absolute blocknr. Zeroes out the
+ * block if zero set.
+ */
+int pram_new_block(struct super_block *sb, unsigned long *blocknr, int zero)
+{
+   struct pram_super_block *ps;
+   off_t bitmap_block;
+   unsigned long bnr, bitmap_bnr;
+   int errval;
+   void *bitmap;
+   void *bp;
+
+   lock_super(sb);
+   ps = pram_get_super(sb);
+   bitmap = pram_get_bitmap(sb);
+
+   if (ps->s_free_blocks_count) {
+   /* find the oldest unused block */
+   bnr = pram_find_next_zero_bit(bitmap,
+be32_to_cpu(ps->s_blocks_count),
+be32_to_cpu(ps->s_free_blocknr_hint));
+
+   if (bnr < be32_to_cpu(ps->s_bitmap_blocks) ||
+   bnr >= be32_to_cpu(ps->s_blocks_count)) {
+   pram_err("no free blocks found!\n");
+   errval = -ENOSPC;
+   goto fail;
+   }
+
+   pram_dbg("allocating blocknr %lu\n", bnr);
+   pram_memunlock_super(ps);
+   be32_add_cpu(&ps->s_free_blocks_count, -1);
+   if (bnr < (be32_to_cpu(ps->s_blocks_count)-1))
+   ps->s_free_blocknr_hint = cpu_to_be32(bnr+1);
+   else
+   ps->s_free_blocknr_hint = 0;
+   pram_memlock_super(ps);
+   } else {
+   pram_err("all blocks allocated\n");
+   errval = -ENOSPC;
+   goto fail;
+   }
+
+   /*
+* find the block within the bitmap that contains the inuse bit
+* for the unused block we just found. We need to unlock it to
+* set the inuse bit.
+*/
+   bitmap_bnr = bnr >> (3 + sb->s_blocksize_bits);
+   bitmap_block = pram_get_block_off(sb, bitmap_bnr);
+   bp = pram_get_block(sb, bitmap_block);
+
+   pram_memunlock_block(sb, bp);
+   pram_set_bit(bnr, bitmap); /* mark the new block in use */
+   pram_memlock_block(sb, bp);
+
+   if (zero) {
+   bp = pram_get_block(sb, pram_get_block_off(sb, bnr));
+   

[PATCH 06/16 v2] pramfs: inode operations for dirs

2010-11-06 Thread Marco Stornelli
From: Marco Stornelli 

Inode operations for directories.

Signed-off-by: Marco Stornelli 
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/namei.c linux-2.6.36/fs/pramfs/namei.c
--- linux-2.6.36-orig/fs/pramfs/namei.c 1970-01-01 01:00:00.0 +0100
+++ linux-2.6.36/fs/pramfs/namei.c  2010-09-18 12:00:35.0 +0200
@@ -0,0 +1,363 @@
+/*
+ * FILE NAME fs/pramfs/namei.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * Inode operations for directories.
+ *
+ * Copyright 2009-2010 Marco Stornelli 
+ * 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 
+#include 
+#include "pram.h"
+#include "acl.h"
+#include "xattr.h"
+
+/*
+ * Couple of helper functions - make the code slightly cleaner.
+ */
+
+static inline void pram_inc_count(struct inode *inode)
+{
+   inode->i_nlink++;
+   pram_write_inode(inode, 0);
+}
+
+static inline void pram_dec_count(struct inode *inode)
+{
+   if (inode->i_nlink) {
+   inode->i_nlink--;
+   pram_write_inode(inode, 0);
+   }
+}
+
+static inline int pram_add_nondir(struct inode *dir,
+  struct dentry *dentry,
+  struct inode *inode)
+{
+   int err = pram_add_link(dentry, inode);
+   if (!err) {
+   d_instantiate(dentry, inode);
+   unlock_new_inode(inode);
+   return 0;
+   }
+   pram_dec_count(inode);
+   unlock_new_inode(inode);
+   iput(inode);
+   return err;
+}
+
+/*
+ * Methods themselves.
+ */
+
+static ino_t
+pram_inode_by_name(struct inode *dir,
+  struct dentry *dentry)
+{
+   struct pram_inode *pi;
+   ino_t ino;
+   int namelen;
+
+   pi = pram_get_inode(dir->i_sb, dir->i_ino);
+   ino = be64_to_cpu(pi->i_type.dir.head);
+
+   while (ino) {
+   pi = pram_get_inode(dir->i_sb, ino);
+
+   if (pi->i_links_count) {
+   namelen = strlen(pi->i_d.d_name);
+
+   if (namelen == dentry->d_name.len &&
+   !memcmp(dentry->d_name.name,
+   pi->i_d.d_name, namelen))
+   break;
+   }
+
+   ino = be64_to_cpu(pi->i_d.d_next);
+   }
+
+   return ino;
+}
+
+static struct dentry *
+pram_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+{
+   struct inode *inode = NULL;
+   ino_t ino;
+
+   if (dentry->d_name.len > PRAM_NAME_LEN)
+   return ERR_PTR(-ENAMETOOLONG);
+
+   ino = pram_inode_by_name(dir, dentry);
+   if (ino) {
+   inode = pram_iget(dir->i_sb, ino);
+   if (!inode)
+   return ERR_PTR(-EACCES);
+   }
+
+   d_splice_alias(inode, dentry);
+   return NULL;
+}
+
+
+/*
+ * By the time this is called, we already have created
+ * the directory cache entry for the new file, but it
+ * is so far negative - it has no inode.
+ *
+ * If the create succeeds, we fill in the inode information
+ * with d_instantiate().
+ */
+static int pram_create(struct inode *dir, struct dentry *dentry,
+   int mode, struct nameidata *nd)
+{
+   struct inode *inode = pram_new_inode(dir, mode);
+   int err = PTR_ERR(inode);
+   if (!IS_ERR(inode)) {
+
+   inode->i_op = &pram_file_inode_operations;
+   inode->i_fop = &pram_file_operations;
+   inode->i_mapping->a_ops = &pram_aops;
+   err = pram_add_nondir(dir, dentry, inode);
+   }
+   return err;
+}
+
+static int pram_mknod(struct inode *dir, struct dentry *dentry, int mode,
+  dev_t rdev)
+{
+   struct inode *inode = pram_new_inode(dir, mode);
+   int err = PTR_ERR(inode);
+   if (!IS_ERR(inode)) {
+   init_special_inode(inode, mode, rdev);
+   pram_write_inode(inode, 0); /* update rdev */
+   err = pram_add_nondir(dir, dentry, inode);
+   }
+   return err;
+}
+
+static int pram_symlink(struct inode *dir,
+ struct dentry *dentry,
+ const char *symname)
+{
+   struct super_block *sb = dir->i_sb;
+   int err = -ENAMETOOLONG;
+   unsigned len = strlen(symname);
+   struct inode *inode;
+
+   if (len+1 > sb->s_blocksize)
+   goto out;
+
+   inode = pram_new_inode(dir, S_IFLNK | S_IRWXUGO);
+   err = PTR_ERR(inode);
+   if (IS_ERR(inode))
+   goto out;
+
+   inode->i_op = 

[PATCH 07/16 v2] pramfs: symbolic links

2010-11-06 Thread Marco Stornelli
From: Marco Stornelli 

Symlink operations.

Signed-off-by: Marco Stornelli 
---
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 
+ * 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 
+#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 v2] pramfs: headers

2010-11-06 Thread Marco Stornelli
From: Marco Stornelli 

Definitions for the PRAMFS filesystem.

Signed-off-by: Marco Stornelli 
---
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 
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * 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);
+
+
+#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 + sizeof(__be16), n - sizeof(__be16));
+   if (*((__be16 *)data) == cpu_to_be16(crc))
+   return 0;
+   else
+   return 1;
+}
+
+/* If this

[PATCH 09/16 v2] pramfs: dir operations

2010-11-06 Thread Marco Stornelli
From: Marco Stornelli 

File operations for directories.

Signed-off-by: Marco Stornelli 
---
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 
+ * 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 
+#include 
+#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;
+   

[PATCH 10/16 v2] pramfs: XIP operations

2010-11-06 Thread Marco Stornelli
From: Marco Stornelli 

XIP operations.

Signed-off-by: Marco Stornelli 
---
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 
+ * 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 
+#include 
+#include 
+#include 
+#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_lock);
+
+   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_lock);
+   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 
+ * 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 11/16 v2] pramfs: ACL management

2010-11-06 Thread Marco Stornelli
From: Marco Stornelli 

ACL operations.

Signed-off-by: Marco Stornelli 
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/acl.c linux-2.6.36/fs/pramfs/acl.c
--- linux-2.6.36-orig/fs/pramfs/acl.c   1970-01-01 01:00:00.0 +0100
+++ linux-2.6.36/fs/pramfs/acl.c2010-09-14 18:49:52.0 +0200
@@ -0,0 +1,418 @@
+/*
+ * FILE NAME fs/pramfs/acl.c
+ *
+ * BRIEF MODULE DESCRIPTION
+ *
+ * POSIX ACL operations
+ *
+ * Copyright 2010 Marco Stornelli 
+ *
+ * based on fs/ext2/acl.c with the following copyright:
+ *
+ * Copyright (C) 2001-2003 Andreas Gruenbacher, 
+ *
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include "pram.h"
+#include "xattr.h"
+#include "acl.h"
+
+/*
+ * Load ACL information from filesystem.
+ */
+static struct posix_acl *pram_acl_load(const void *value, size_t size)
+{
+   const char *end = (char *)value + size;
+   int n, count;
+   struct posix_acl *acl;
+
+   if (!value)
+   return NULL;
+   if (size < sizeof(struct pram_acl_header))
+return ERR_PTR(-EINVAL);
+   if (((struct pram_acl_header *)value)->a_version !=
+   cpu_to_be32(PRAM_ACL_VERSION))
+   return ERR_PTR(-EINVAL);
+   value = (char *)value + sizeof(struct pram_acl_header);
+   count = pram_acl_count(size);
+   if (count < 0)
+   return ERR_PTR(-EINVAL);
+   if (count == 0)
+   return NULL;
+   acl = posix_acl_alloc(count, GFP_KERNEL);
+   if (!acl)
+   return ERR_PTR(-ENOMEM);
+   for (n = 0; n < count; n++) {
+   struct pram_acl_entry *entry = (struct pram_acl_entry *)value;
+   if ((char *)value + sizeof(struct pram_acl_entry_short) > end)
+   goto fail;
+   acl->a_entries[n].e_tag  = be16_to_cpu(entry->e_tag);
+   acl->a_entries[n].e_perm = be16_to_cpu(entry->e_perm);
+   switch (acl->a_entries[n].e_tag) {
+   case ACL_USER_OBJ:
+   case ACL_GROUP_OBJ:
+   case ACL_MASK:
+   case ACL_OTHER:
+   value = (char *)value +
+   sizeof(struct pram_acl_entry_short);
+   acl->a_entries[n].e_id = ACL_UNDEFINED_ID;
+   break;
+   case ACL_USER:
+   case ACL_GROUP:
+   value = (char *)value + sizeof(struct pram_acl_entry);
+   if ((char *)value > end)
+   goto fail;
+   acl->a_entries[n].e_id =
+   be32_to_cpu(entry->e_id);
+   break;
+   default:
+   goto fail;
+   }
+   }
+   if (value != end)
+   goto fail;
+   return acl;
+
+fail:
+   posix_acl_release(acl);
+   return ERR_PTR(-EINVAL);
+}
+
+/*
+ * Save ACL information into the filesystem.
+ */
+static void *pram_acl_save(const struct posix_acl *acl, size_t *size)
+{
+   struct pram_acl_header *ext_acl;
+   char *e;
+   size_t n;
+
+   *size = pram_acl_size(acl->a_count);
+   ext_acl = kmalloc(sizeof(struct pram_acl_header) + acl->a_count *
+   sizeof(struct pram_acl_entry), GFP_KERNEL);
+   if (!ext_acl)
+   return ERR_PTR(-ENOMEM);
+   ext_acl->a_version = cpu_to_be32(PRAM_ACL_VERSION);
+   e = (char *)ext_acl + sizeof(struct pram_acl_header);
+   for (n = 0; n < acl->a_count; n++) {
+   struct pram_acl_entry *entry = (struct pram_acl_entry *)e;
+   entry->e_tag  = cpu_to_be16(acl->a_entries[n].e_tag);
+   entry->e_perm = cpu_to_be16(acl->a_entries[n].e_perm);
+   switch (acl->a_entries[n].e_tag) {
+   case ACL_USER:
+   case ACL_GROUP:
+   entry->e_id =
+   cpu_to_be32(acl->a_entries[n].e_id);
+   e += sizeof(struct pram_acl_entry);
+   break;
+   case ACL_USER_OBJ:
+   case ACL_GROUP_OBJ:
+   case ACL_MASK:
+   case ACL_OTHER:
+   e += sizeof(struct pram_acl_entry_short);
+   break;
+   default:
+   goto fail;
+   }
+   }
+   return (char *)ext_acl;
+
+fail:
+   kfree(ext_acl);
+   return ERR_PTR(-EINVAL);
+}
+
+/*
+ * inode->i_mutex: don't care
+ */
+static struct posix_acl *pram_get_acl(struct inode *inode, int type)
+{
+   int name_index;
+   char *value = NULL;
+  

[PATCH 12/16 v2] pramfs: extended attributes

2010-11-06 Thread Marco Stornelli
From: Marco Stornelli 

Extended attributes operations.

Signed-off-by: Marco Stornelli 
---
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 
+ *
+ * based on fs/ext2/xattr.c with the following copyright:
+ *
+ * Fix by Harrison Xing .
+ * Extended attributes for symlinks and special files added per
+ *  suggestion of Luka Renko .
+ * xattr consolidation Copyright (c) 2004 James Morris ,
+ *  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 
+#include 
+#include 
+#include 
+#include 
+#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 struct xattr_handler 

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

2010-11-06 Thread Marco Stornelli
From: Marco Stornelli 

Extended attributes block descriptors tree.

Signed-off-by: Marco Stornelli 
---
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,184 @@
+/*
+ * FILE NAME fs/pramfs/desctree.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * Extended attributes block descriptors tree.
+ *
+ * Copyright 2010 Marco Stornelli 
+ *
+ * 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 
+#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)
+{
+ 

[PATCH 14/16 v2] pramfs: write protection

2010-11-06 Thread Marco Stornelli
From: Marco Stornelli 

Memory write protection.

Signed-off-by: Marco Stornelli 
---
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 
+ * 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 
+#include 
+#include 
+#include 
+#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 15/16 v2] pramfs: test module

2010-11-06 Thread Marco Stornelli
From: Marco Stornelli 

Test module.

Signed-off-by: Marco Stornelli 
---
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/namei.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * Pramfs test module.
+ *
+ * Copyright 2009-2010 Marco Stornelli 
+ * 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 
+#include 
+#include 
+#include 
+#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


[PATCH 16/16 v2] pramfs: Makefile and Kconfig

2010-11-06 Thread Marco Stornelli
From: Marco Stornelli 

Makefile and Kconfig.

Signed-off-by: Marco Stornelli 
---
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 .
+
+  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 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/Ma

Re: [PATCH 01/16 v2] pramfs: documentation

2010-11-06 Thread Marco Stornelli
Il 06/11/2010 11:39, James Hogan ha scritto:
> Hi,
> 
> On Sat, Nov 06, 2010 at 09:56:18AM +0100, Marco Stornelli wrote:
>> From: Marco Stornelli 
>> +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 again.
>> +This feature provides protection against filesystem corruption caused by 
>> errant
> 
> Looks like an accidental lost newline in the patch here, should that be
> "are marked" or is there some text missing?
> 

My fault, a problem during email formatting. I'll resend this patch.

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


Re: [PATCH 02/16 v2] pramfs: super block operations

2010-11-06 Thread Marco Stornelli
Il 06/11/2010 14:12, James Hogan ha scritto:
> Hi,
> 
> On Sat, Nov 06, 2010 at 09:56:39AM +0100, Marco Stornelli wrote:
>> From: Marco Stornelli 
>>
>> Super block operations.
>>
>> Signed-off-by: Marco Stornelli 
>> ---
>> diff -Nurp linux-2.6.36-orig/fs/pramfs/super.c linux-2.6.36/fs/pramfs/super.c
>> --- linux-2.6.36-orig/fs/pramfs/super.c  1970-01-01 01:00:00.0 
>> +0100
>> +++ linux-2.6.36/fs/pramfs/super.c   2010-09-25 14:09:47.0 +0200
> 
>> +pram_dbg("max name length %d\n", PRAM_NAME_LEN);
> 
> I get a warning on this line that could be avoided:
> 
> fs/pramfs/super.c: In function ‘pram_init’:
> fs/pramfs/super.c:308: warning: format ‘%d’ expects type ‘int’, but
> argument 2 has type ‘long unsigned int’
> 
> Cheers
> James
> 


Mmmm, very strange, I don't have that warning, maybe the compiler
version. I'll fix it with an int cast to avoid it.

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


Re: [PATCH 02/16 v2] pramfs: super block operations

2010-11-06 Thread Marco Stornelli
Il 06/11/2010 12:16, James Hogan ha scritto:
> Hi Marco,
> 
> On Sat, Nov 06, 2010 at 09:56:39AM +0100, Marco Stornelli wrote:
>> From: Marco Stornelli 
>> +static void pram_set_blocksize(struct super_block *sb, unsigned long size)
>> +{
>> +int bits;
>> +
>> +/*
>> +* We've already validated the user input and the value here must be
>> +* between PRAM_MAX_BLOCK_SIZE and PRAM_MIN_BLOCK_SIZE
>> +* and it must be a power of 2.
>> +*/
> 
> Should this comment have spaces after the tabs to be consistent with the
> other multiline comments (pram_ioremap) and the coding style?
> 

Ok, no problem.

Thanks for the review.

Regards,

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


Re: [PATCH 10/16 v2] pramfs: XIP operations

2010-11-06 Thread Marco Stornelli
Il 06/11/2010 14:33, James Hogan ha scritto:
> Hi,
> 
> On Sat, Nov 06, 2010 at 09:59:27AM +0100, Marco Stornelli wrote:
>> 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.c1970-01-01 01:00:00.0 
>> +0100
>> +++ linux-2.6.36/fs/pramfs/xip.c 2010-09-14 18:49:52.0 +0200
> 
>> +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_lock);
> 
> fs/pramfs/xip.c: In function ‘pram_find_and_alloc_blocks’:
> fs/pramfs/xip.c:27: error: ‘struct pram_inode_vfs’ has no member named
> ‘truncate_lock’
> fs/pramfs/xip.c:52: error: ‘struct pram_inode_vfs’ has no member named
> ‘truncate_lock’
> 
> i guess that should be truncate_mutex.
> 

Oops, my fault, yes it's truncate_mutex. I'll fix it asap.

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


Re: [PATCH 08/16 v2] pramfs: headers

2010-11-07 Thread Marco Stornelli
2010/11/7 Ryan Mallon :
> On 11/06/2010 09:58 PM, Marco Stornelli wrote:
>> From: Marco Stornelli 
>>
>> Definitions for the PRAMFS filesystem.
>>
>> Signed-off-by: Marco Stornelli 
>> ---
>> 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 @@
>
>> +/*
>> + * Structure of the super block in PRAMFS
>> + */
>> +struct pram_super_block {
>> +     __be16  s_sum;          /* checksum of this sb, including padding */
>> +     __be64  s_size;         /* total size of fs in bytes */
>> +     __be32  s_blocksize;    /* blocksize in bytes */
>> +     __be32  s_inodes_count; /* total inodes count (used or free) */
>> +     __be32  s_free_inodes_count;/* free inodes count */
>> +     __be32  s_free_inode_hint;  /* start hint for locating free inodes */
>> +     __be32  s_blocks_count; /* total data blocks count (used or free) */
>> +     __be32  s_free_blocks_count;/* free data blocks count */
>> +     __be32  s_free_blocknr_hint;/* free data blocks count */
>> +     __be64  s_bitmap_start; /* data block in-use bitmap location */
>> +     __be32  s_bitmap_blocks;/* size of bitmap in number of blocks */
>> +     __be32  s_mtime;        /* Mount time */
>> +     __be32  s_wtime;        /* Write time */
>> +     __be16  s_magic;        /* Magic signature */
>> +     char    s_volume_name[16]; /* volume name */
>> +};
>
> Is there a particular reason to use big endian types for the data
> structures? On a little endian machine you will end up converting values
> everywhere. I assume that you don't expect the machine to change
> endianess between reboots :-). If this is for generating/reading
> filesystems from userspace, wouldn't it be better to have the userspace
> tools specify the target endianess and do the conversions there?
>
> ~Ryan

Yes, there is a reason. In the first review a comment was: the fs must
have a fix endianess layout. This fs is designed for the embedded
world mainly. Since most of cpus used in this case are big-endian, it
means that for typical use case, there is no cost for endianess
conversion.

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


Re: [PATCH 08/16 v2] pramfs: headers

2010-11-09 Thread Marco Stornelli
2010/11/8 Ryan Mallon :
> On 11/08/2010 08:49 PM, Marco Stornelli wrote:
>> 2010/11/7 Ryan Mallon :
>>> On 11/06/2010 09:58 PM, Marco Stornelli wrote:
>>>> From: Marco Stornelli 
>>>>
>>>> Definitions for the PRAMFS filesystem.
>>>>
>>>> Signed-off-by: Marco Stornelli 
>>>> ---
>>>> 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 @@
>>>
>>>> +/*
>>>> + * Structure of the super block in PRAMFS
>>>> + */
>>>> +struct pram_super_block {
>>>> +     __be16  s_sum;          /* checksum of this sb, including padding */
>>>> +     __be64  s_size;         /* total size of fs in bytes */
>>>> +     __be32  s_blocksize;    /* blocksize in bytes */
>>>> +     __be32  s_inodes_count; /* total inodes count (used or free) */
>>>> +     __be32  s_free_inodes_count;/* free inodes count */
>>>> +     __be32  s_free_inode_hint;  /* start hint for locating free inodes */
>>>> +     __be32  s_blocks_count; /* total data blocks count (used or free) */
>>>> +     __be32  s_free_blocks_count;/* free data blocks count */
>>>> +     __be32  s_free_blocknr_hint;/* free data blocks count */
>>>> +     __be64  s_bitmap_start; /* data block in-use bitmap location */
>>>> +     __be32  s_bitmap_blocks;/* size of bitmap in number of blocks */
>>>> +     __be32  s_mtime;        /* Mount time */
>>>> +     __be32  s_wtime;        /* Write time */
>>>> +     __be16  s_magic;        /* Magic signature */
>>>> +     char    s_volume_name[16]; /* volume name */
>>>> +};
>>>
>>> Is there a particular reason to use big endian types for the data
>>> structures? On a little endian machine you will end up converting values
>>> everywhere. I assume that you don't expect the machine to change
>>> endianess between reboots :-). If this is for generating/reading
>>> filesystems from userspace, wouldn't it be better to have the userspace
>>> tools specify the target endianess and do the conversions there?
>>>
>>> ~Ryan
>>
>> Yes, there is a reason. In the first review a comment was: the fs must
>> have a fix endianess layout. This fs is designed for the embedded
>> world mainly. Since most of cpus used in this case are big-endian, it
>> means that for typical use case, there is no cost for endianess
>> conversion.
>
> ARM, which is a large portion of the embedded space, is typically little
> endian.

Not always. Indeed, I didn't say *all* cpu used are big-endian.

>
> Why does a filesystem need to have a specific endianess layout?
> Especially for a highly specialised filesystem like this.
>

I didn't agree with it, but in the first review there was more than
one developer that said this thing. The main reason was to read the
format (for example with JTAG) or to create an image with a fix
format. I remember that someone said that there was a similar problem
with jffs2 and the experience tell to us that a fix endianess is
important. At that point I decided to use big-endian. You can see all
the discussion in lkml. The review has been done at June 2009.

Regards,

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


Re: [PATCH 08/16 v2] pramfs: headers

2010-11-10 Thread Marco Stornelli
2010/11/9 Geert Uytterhoeven :
> On Tue, Nov 9, 2010 at 21:35, Ryan Mallon  wrote:
>> You can still do all of those things without having a fixed endianess.
>> You just have to have one extra step of telling the external tools what
>> the endianess is. IMHO, it is better to have the overhead of the endian
>> conversion in the tools since it is less costly there than an the
>> embedded system.
>>
>> I'm just trying to understand why the fixed endianess rule cannot be
>> bent for such a specialised filesystem.
>
> When it was decided that filesystems should be fixed-endian and support for
> big-endian ext2 was dropped, the overhead of doing the fixed conversions was
> deetermined negligible due to compiler optimization.
> That was ages ago, and current embedded systems run circles around the
> machines of those days.
>
> Note that this is about metadata only. Actual file contents are always just
> byte streams.
>

I can add that the penalties in this case are  negligible due to the
compensation of the very fast access of the media. In addition, from
performance point of view I'm pretty happy (you can see the some
benchmark on the project web site).

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 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 

Documentation for PRAMFS.

Signed-off-by: Marco Stornelli 
---
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.
+Read&write 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 again.
+This feature pro

[PATCH 02/16 v3] pramfs: super operations

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli 

Super block operations.

Signed-off-by: Marco Stornelli 
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/super.c linux-2.6.36/fs/pramfs/super.c
--- linux-2.6.36-orig/fs/pramfs/super.c 1970-01-01 01:00:00.0 +0100
+++ linux-2.6.36/fs/pramfs/super.c  2010-09-25 14:09:47.0 +0200
@@ -0,0 +1,745 @@
+/*
+ * FILE NAME fs/pramfs/super.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * Super block operations.
+ *
+ * Copyright 2009-2010 Marco Stornelli 
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "xattr.h"
+#include "pram.h"
+
+static struct super_operations pram_sops;
+static const struct export_operations pram_export_ops;
+static struct kmem_cache *pram_inode_cachep;
+
+#ifdef CONFIG_PRAMFS_TEST
+static void *first_pram_super;
+
+struct pram_super_block *get_pram_super(void)
+{
+   return (struct pram_super_block *)first_pram_super;
+}
+EXPORT_SYMBOL(get_pram_super);
+#endif
+
+static void pram_set_blocksize(struct super_block *sb, unsigned long size)
+{
+   int bits;
+
+   /*
+* We've already validated the user input and the value here must be
+* between PRAM_MAX_BLOCK_SIZE and PRAM_MIN_BLOCK_SIZE
+* and it must be a power of 2.
+*/
+   bits = fls(size) - 1;
+   sb->s_blocksize_bits = bits;
+   sb->s_blocksize = (1< MAX_LFS_FILESIZE)
+   res = MAX_LFS_FILESIZE;
+
+   pram_info("Max file size %llu bytes", res);
+   return res;
+}
+
+enum {
+   Opt_addr, Opt_bpi, Opt_size,
+   Opt_num_inodes, Opt_mode, Opt_uid,
+   Opt_gid, Opt_blocksize, Opt_err
+};
+
+static const match_table_t tokens = {
+   {Opt_bpi,   "physaddr=%x"},
+   {Opt_bpi,   "bpi=%u"},
+   {Opt_size,  "init=%s"},
+   {Opt_num_inodes, "N=%u"},
+   {Opt_mode,  "mode=%o"},
+   {Opt_uid,   "uid=%u"},
+   {Opt_gid,   "gid=%u"},
+   {Opt_blocksize, "bs=%s"},
+   {Opt_err,   NULL},
+};
+
+static phys_addr_t get_phys_addr(void **data)
+{
+   phys_addr_t phys_addr;
+   char *options = (char *) *data;
+
+   if (!options || strncmp(options, "physaddr=", 9) != 0)
+   return (phys_addr_t)ULLONG_MAX;
+   options += 9;
+   phys_addr = (phys_addr_t)simple_strtoull(options, &options, 0);
+   if (*options && *options != ',') {
+   pram_err("Invalid phys addr specification: %s\n",
+  (char *) *data);
+   return (phys_addr_t)ULLONG_MAX;
+   }
+   if (phys_addr & (PAGE_SIZE - 1)) {
+   pram_err("physical address 0x%16llx for pramfs isn't "
+ "aligned to a page boundary\n",
+ (u64)phys_addr);
+   return (phys_addr_t)ULLONG_MAX;
+   }
+   if (*options == ',')
+   options++;
+   *data = (void *) options;
+   return phys_addr;
+}
+
+static int pram_parse_options(char *options, struct pram_sb_info *sbi)
+{
+   char *p, *rest;
+   substring_t args[MAX_OPT_ARGS];
+   int option;
+
+   if (!options)
+   return 0;
+
+   while ((p = strsep(&options, ",")) != NULL) {
+   int token;
+   if (!*p)
+   continue;
+
+   token = match_token(p, tokens, args);
+   switch (token) {
+   case Opt_addr: {
+   /* physaddr managed in get_phys_addr() */
+   break;
+   }
+   case Opt_bpi: {
+   if (match_int(&args[0], &option))
+   goto bad_val;
+   sbi->bpi = option;
+   break;
+   }
+   case Opt_uid: {
+   if (match_int(&args[0], &option))
+   goto bad_val;
+   sbi->uid = option;
+   break;
+   }
+   case Opt_gid: {
+   if (match_int(&args[0], &option))
+   goto bad_val;
+ 

[PATCH 03/16 v3] pramfs: inode operations

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli 

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

Signed-off-by: Marco Stornelli 
---
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 
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#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_blo

[PATCH 04/16 v3] pramfs: file operations

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli 

File operations.

Signed-off-by: Marco Stornelli 
---
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 
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#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

[PATCH 05/16 v3] pramfs: block allocation

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli 

Block allocation operations.

Signed-off-by: Marco Stornelli 
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/balloc.c linux-2.6.36/fs/pramfs/balloc.c
--- linux-2.6.36-orig/fs/pramfs/balloc.c1970-01-01 01:00:00.0 
+0100
+++ linux-2.6.36/fs/pramfs/balloc.c 2010-09-26 18:05:06.0 +0200
@@ -0,0 +1,155 @@
+/*
+ * FILE NAME fs/pramfs/balloc.c
+ *
+ * BRIEF MODULE DESCRIPTION
+ *
+ * The blocks allocation and deallocation routines.
+ *
+ * Copyright 2009-2010 Marco Stornelli 
+ * 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 
+#include 
+#include "pram.h"
+
+/*
+ * This just marks in-use the blocks that make up the bitmap.
+ * The bitmap must be writeable before calling.
+ */
+void pram_init_bitmap(struct super_block *sb)
+{
+   struct pram_super_block *ps = pram_get_super(sb);
+   u64 *bitmap = pram_get_bitmap(sb);
+   int blocks = be32_to_cpu(ps->s_bitmap_blocks);
+
+   memset(bitmap, 0, blocks << sb->s_blocksize_bits);
+
+   while (blocks >= 64) {
+   *bitmap++ = (u64)ULLONG_MAX;
+   blocks -= 64;
+   }
+
+   if (blocks)
+   *bitmap = cpu_to_le64((1ULL << blocks) - 1);
+}
+
+
+/* Free absolute blocknr */
+void pram_free_block(struct super_block *sb, unsigned long blocknr)
+{
+   struct pram_super_block *ps;
+   u64 bitmap_block;
+   unsigned long bitmap_bnr;
+   void *bitmap;
+   void *bp;
+
+   lock_super(sb);
+
+   bitmap = pram_get_bitmap(sb);
+   /*
+* find the block within the bitmap that contains the inuse bit
+* for the block we need to free. We need to unlock this bitmap
+* block to clear the inuse bit.
+*/
+   bitmap_bnr = blocknr >> (3 + sb->s_blocksize_bits);
+   bitmap_block = pram_get_block_off(sb, bitmap_bnr);
+   bp = pram_get_block(sb, bitmap_block);
+
+   pram_memunlock_block(sb, bp);
+   pram_clear_bit(blocknr, bitmap); /* mark the block free */
+   pram_memlock_block(sb, bp);
+
+   ps = pram_get_super(sb);
+   pram_memunlock_super(ps);
+   if (blocknr < be32_to_cpu(ps->s_free_blocknr_hint))
+   ps->s_free_blocknr_hint = cpu_to_be32(blocknr);
+   be32_add_cpu(&ps->s_free_blocks_count, 1);
+   pram_memlock_super(ps);
+
+   unlock_super(sb);
+}
+
+
+/*
+ * allocate a block and return it's absolute blocknr. Zeroes out the
+ * block if zero set.
+ */
+int pram_new_block(struct super_block *sb, unsigned long *blocknr, int zero)
+{
+   struct pram_super_block *ps;
+   off_t bitmap_block;
+   unsigned long bnr, bitmap_bnr;
+   int errval;
+   void *bitmap;
+   void *bp;
+
+   lock_super(sb);
+   ps = pram_get_super(sb);
+   bitmap = pram_get_bitmap(sb);
+
+   if (ps->s_free_blocks_count) {
+   /* find the oldest unused block */
+   bnr = pram_find_next_zero_bit(bitmap,
+be32_to_cpu(ps->s_blocks_count),
+be32_to_cpu(ps->s_free_blocknr_hint));
+
+   if (bnr < be32_to_cpu(ps->s_bitmap_blocks) ||
+   bnr >= be32_to_cpu(ps->s_blocks_count)) {
+   pram_err("no free blocks found!\n");
+   errval = -ENOSPC;
+   goto fail;
+   }
+
+   pram_dbg("allocating blocknr %lu\n", bnr);
+   pram_memunlock_super(ps);
+   be32_add_cpu(&ps->s_free_blocks_count, -1);
+   if (bnr < (be32_to_cpu(ps->s_blocks_count)-1))
+   ps->s_free_blocknr_hint = cpu_to_be32(bnr+1);
+   else
+   ps->s_free_blocknr_hint = 0;
+   pram_memlock_super(ps);
+   } else {
+   pram_err("all blocks allocated\n");
+   errval = -ENOSPC;
+   goto fail;
+   }
+
+   /*
+* find the block within the bitmap that contains the inuse bit
+* for the unused block we just found. We need to unlock it to
+* set the inuse bit.
+*/
+   bitmap_bnr = bnr >> (3 + sb->s_blocksize_bits);
+   bitmap_block = pram_get_block_off(sb, bitmap_bnr);
+   bp = pram_get_block(sb, bitmap_block);
+
+   pram_memunlock_block(sb, bp);
+   pram_set_bit(bnr, bitmap); /* mark the new block in use */
+   pram_memlock_block(sb, bp);
+
+   if (zero) {
+   bp = pram_get_block(sb, pram_get_block_off(sb, bnr));
+   

[PATCH 06/16 v3] pramfs: inode operations for dirs

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli 

Inode operations for directories.

Signed-off-by: Marco Stornelli 
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/namei.c linux-2.6.36/fs/pramfs/namei.c
--- linux-2.6.36-orig/fs/pramfs/namei.c 1970-01-01 01:00:00.0 +0100
+++ linux-2.6.36/fs/pramfs/namei.c  2010-09-18 12:00:35.0 +0200
@@ -0,0 +1,363 @@
+/*
+ * FILE NAME fs/pramfs/namei.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * Inode operations for directories.
+ *
+ * Copyright 2009-2010 Marco Stornelli 
+ * 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 
+#include 
+#include "pram.h"
+#include "acl.h"
+#include "xattr.h"
+
+/*
+ * Couple of helper functions - make the code slightly cleaner.
+ */
+
+static inline void pram_inc_count(struct inode *inode)
+{
+   inode->i_nlink++;
+   pram_write_inode(inode, 0);
+}
+
+static inline void pram_dec_count(struct inode *inode)
+{
+   if (inode->i_nlink) {
+   inode->i_nlink--;
+   pram_write_inode(inode, 0);
+   }
+}
+
+static inline int pram_add_nondir(struct inode *dir,
+  struct dentry *dentry,
+  struct inode *inode)
+{
+   int err = pram_add_link(dentry, inode);
+   if (!err) {
+   d_instantiate(dentry, inode);
+   unlock_new_inode(inode);
+   return 0;
+   }
+   pram_dec_count(inode);
+   unlock_new_inode(inode);
+   iput(inode);
+   return err;
+}
+
+/*
+ * Methods themselves.
+ */
+
+static ino_t
+pram_inode_by_name(struct inode *dir,
+  struct dentry *dentry)
+{
+   struct pram_inode *pi;
+   ino_t ino;
+   int namelen;
+
+   pi = pram_get_inode(dir->i_sb, dir->i_ino);
+   ino = be64_to_cpu(pi->i_type.dir.head);
+
+   while (ino) {
+   pi = pram_get_inode(dir->i_sb, ino);
+
+   if (pi->i_links_count) {
+   namelen = strlen(pi->i_d.d_name);
+
+   if (namelen == dentry->d_name.len &&
+   !memcmp(dentry->d_name.name,
+   pi->i_d.d_name, namelen))
+   break;
+   }
+
+   ino = be64_to_cpu(pi->i_d.d_next);
+   }
+
+   return ino;
+}
+
+static struct dentry *
+pram_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+{
+   struct inode *inode = NULL;
+   ino_t ino;
+
+   if (dentry->d_name.len > PRAM_NAME_LEN)
+   return ERR_PTR(-ENAMETOOLONG);
+
+   ino = pram_inode_by_name(dir, dentry);
+   if (ino) {
+   inode = pram_iget(dir->i_sb, ino);
+   if (!inode)
+   return ERR_PTR(-EACCES);
+   }
+
+   d_splice_alias(inode, dentry);
+   return NULL;
+}
+
+
+/*
+ * By the time this is called, we already have created
+ * the directory cache entry for the new file, but it
+ * is so far negative - it has no inode.
+ *
+ * If the create succeeds, we fill in the inode information
+ * with d_instantiate().
+ */
+static int pram_create(struct inode *dir, struct dentry *dentry,
+   int mode, struct nameidata *nd)
+{
+   struct inode *inode = pram_new_inode(dir, mode);
+   int err = PTR_ERR(inode);
+   if (!IS_ERR(inode)) {
+
+   inode->i_op = &pram_file_inode_operations;
+   inode->i_fop = &pram_file_operations;
+   inode->i_mapping->a_ops = &pram_aops;
+   err = pram_add_nondir(dir, dentry, inode);
+   }
+   return err;
+}
+
+static int pram_mknod(struct inode *dir, struct dentry *dentry, int mode,
+  dev_t rdev)
+{
+   struct inode *inode = pram_new_inode(dir, mode);
+   int err = PTR_ERR(inode);
+   if (!IS_ERR(inode)) {
+   init_special_inode(inode, mode, rdev);
+   pram_write_inode(inode, 0); /* update rdev */
+   err = pram_add_nondir(dir, dentry, inode);
+   }
+   return err;
+}
+
+static int pram_symlink(struct inode *dir,
+ struct dentry *dentry,
+ const char *symname)
+{
+   struct super_block *sb = dir->i_sb;
+   int err = -ENAMETOOLONG;
+   unsigned len = strlen(symname);
+   struct inode *inode;
+
+   if (len+1 > sb->s_blocksize)
+   goto out;
+
+   inode = pram_new_inode(dir, S_IFLNK | S_IRWXUGO);
+   err = PTR_ERR(inode);
+   if (IS_ERR(inode))
+   goto out;
+
+   inode->i_op = 

[PATCH 07/16 v3] pramfs: symbolic links

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli 

Symlink operations.

Signed-off-by: Marco Stornelli 
---
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 
+ * 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 
+#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 

Definitions for the PRAMFS filesystem.

Signed-off-by: Marco Stornelli 
---
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 
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * 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 + sizeof(__be16), n - sizeof(__be16));
+   if (*((__be16 *)data) == cpu_to_be16(crc))
+   return 0;

[PATCH 09/16 v3] pramfs: dir operations

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli 

File operations for directories.

Signed-off-by: Marco Stornelli 
---
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 
+ * 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 
+#include 
+#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;
+   

[PATCH 10/16 v3] pramfs: XIP operations

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli 

XIP operations.

Signed-off-by: Marco Stornelli 
---
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 
+ * 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 
+#include 
+#include 
+#include 
+#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 
+ * 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 11/16 v3] pramfs: ACL management

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli 

ACL operations.

Signed-off-by: Marco Stornelli 
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/acl.c linux-2.6.36/fs/pramfs/acl.c
--- linux-2.6.36-orig/fs/pramfs/acl.c   1970-01-01 01:00:00.0 +0100
+++ linux-2.6.36/fs/pramfs/acl.c2010-09-14 18:49:52.0 +0200
@@ -0,0 +1,418 @@
+/*
+ * FILE NAME fs/pramfs/acl.c
+ *
+ * BRIEF MODULE DESCRIPTION
+ *
+ * POSIX ACL operations
+ *
+ * Copyright 2010 Marco Stornelli 
+ *
+ * based on fs/ext2/acl.c with the following copyright:
+ *
+ * Copyright (C) 2001-2003 Andreas Gruenbacher, 
+ *
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include "pram.h"
+#include "xattr.h"
+#include "acl.h"
+
+/*
+ * Load ACL information from filesystem.
+ */
+static struct posix_acl *pram_acl_load(const void *value, size_t size)
+{
+   const char *end = (char *)value + size;
+   int n, count;
+   struct posix_acl *acl;
+
+   if (!value)
+   return NULL;
+   if (size < sizeof(struct pram_acl_header))
+return ERR_PTR(-EINVAL);
+   if (((struct pram_acl_header *)value)->a_version !=
+   cpu_to_be32(PRAM_ACL_VERSION))
+   return ERR_PTR(-EINVAL);
+   value = (char *)value + sizeof(struct pram_acl_header);
+   count = pram_acl_count(size);
+   if (count < 0)
+   return ERR_PTR(-EINVAL);
+   if (count == 0)
+   return NULL;
+   acl = posix_acl_alloc(count, GFP_KERNEL);
+   if (!acl)
+   return ERR_PTR(-ENOMEM);
+   for (n = 0; n < count; n++) {
+   struct pram_acl_entry *entry = (struct pram_acl_entry *)value;
+   if ((char *)value + sizeof(struct pram_acl_entry_short) > end)
+   goto fail;
+   acl->a_entries[n].e_tag  = be16_to_cpu(entry->e_tag);
+   acl->a_entries[n].e_perm = be16_to_cpu(entry->e_perm);
+   switch (acl->a_entries[n].e_tag) {
+   case ACL_USER_OBJ:
+   case ACL_GROUP_OBJ:
+   case ACL_MASK:
+   case ACL_OTHER:
+   value = (char *)value +
+   sizeof(struct pram_acl_entry_short);
+   acl->a_entries[n].e_id = ACL_UNDEFINED_ID;
+   break;
+   case ACL_USER:
+   case ACL_GROUP:
+   value = (char *)value + sizeof(struct pram_acl_entry);
+   if ((char *)value > end)
+   goto fail;
+   acl->a_entries[n].e_id =
+   be32_to_cpu(entry->e_id);
+   break;
+   default:
+   goto fail;
+   }
+   }
+   if (value != end)
+   goto fail;
+   return acl;
+
+fail:
+   posix_acl_release(acl);
+   return ERR_PTR(-EINVAL);
+}
+
+/*
+ * Save ACL information into the filesystem.
+ */
+static void *pram_acl_save(const struct posix_acl *acl, size_t *size)
+{
+   struct pram_acl_header *ext_acl;
+   char *e;
+   size_t n;
+
+   *size = pram_acl_size(acl->a_count);
+   ext_acl = kmalloc(sizeof(struct pram_acl_header) + acl->a_count *
+   sizeof(struct pram_acl_entry), GFP_KERNEL);
+   if (!ext_acl)
+   return ERR_PTR(-ENOMEM);
+   ext_acl->a_version = cpu_to_be32(PRAM_ACL_VERSION);
+   e = (char *)ext_acl + sizeof(struct pram_acl_header);
+   for (n = 0; n < acl->a_count; n++) {
+   struct pram_acl_entry *entry = (struct pram_acl_entry *)e;
+   entry->e_tag  = cpu_to_be16(acl->a_entries[n].e_tag);
+   entry->e_perm = cpu_to_be16(acl->a_entries[n].e_perm);
+   switch (acl->a_entries[n].e_tag) {
+   case ACL_USER:
+   case ACL_GROUP:
+   entry->e_id =
+   cpu_to_be32(acl->a_entries[n].e_id);
+   e += sizeof(struct pram_acl_entry);
+   break;
+   case ACL_USER_OBJ:
+   case ACL_GROUP_OBJ:
+   case ACL_MASK:
+   case ACL_OTHER:
+   e += sizeof(struct pram_acl_entry_short);
+   break;
+   default:
+   goto fail;
+   }
+   }
+   return (char *)ext_acl;
+
+fail:
+   kfree(ext_acl);
+   return ERR_PTR(-EINVAL);
+}
+
+/*
+ * inode->i_mutex: don't care
+ */
+static struct posix_acl *pram_get_acl(struct inode *inode, int type)
+{
+   int name_index;
+   char *value = NULL;
+  

[PATCH 12/16 v3] pramfs: extended attributes

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli 

Extended attributes operations.

Signed-off-by: Marco Stornelli 
---
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 
+ *
+ * based on fs/ext2/xattr.c with the following copyright:
+ *
+ * Fix by Harrison Xing .
+ * Extended attributes for symlinks and special files added per
+ *  suggestion of Luka Renko .
+ * xattr consolidation Copyright (c) 2004 James Morris ,
+ *  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 
+#include 
+#include 
+#include 
+#include 
+#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 struct xattr_handler 

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

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli 

Extended attributes block descriptors tree.

Signed-off-by: Marco Stornelli 
---
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 
+ *
+ * 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 
+#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 r

[PATCH 14/16 v3] pramfs: memory protection

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli 

Memory write protection.

Signed-off-by: Marco Stornelli 
---
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 
+ * 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 
+#include 
+#include 
+#include 
+#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 

Makefile and Kconfig.

Signed-off-by: Marco Stornelli 
---
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 .
+
+  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/f

[PATCH 15/16 v3] pramfs: test module

2010-11-13 Thread Marco Stornelli
From: Marco Stornelli 

Test module.

Signed-off-by: Marco Stornelli 
---
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 
+ * 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 
+#include 
+#include 
+#include 
+#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


Re: [PATCH 02/16 v3] pramfs: super operations

2010-11-14 Thread Marco Stornelli
2010/11/15 yidong zhang :
> hi Marco
>
>> +       retval = 0;
>> + out:
>> +       if (retval && sbi->virt_addr) {
>> +               iounmap(sbi->virt_addr);
>> +               release_mem_region(sbi->phys_addr, initsize);
>> +               kfree(sbi);
>> +       }
>> +
>> +       return retval;
>> +}
>> +
>  I think kfree(sbi) should not be put here. In case of
> pram_parse_options failure, sbi should also be freed too.  How about
> change it to the list below? And change some “goto out”   branches to
> “goto out_free”.
>
>  //    retval = 0;
>     return 0;
>  out:
>        if (retval && sbi->virt_addr) {
>                iounmap(sbi->virt_addr);
>                release_mem_region(sbi->phys_addr, initsize);
>        }
> out_free:
>                kfree(sbi);
>        return retval;
> }
>

Yeah, you're right. It's not always true that virt addr is valid,
kfree should be used out of this if. I'll fix it.

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 00/16 v4] pramfs: persistent and protected RAM filesystem

2010-11-20 Thread Marco Stornelli
Hi all,

fourth round for the patch series. I summarize here the changes to
improve the review:

v4:
- in bitmap init used already present bitmap_set function
- fix a possible memory leak in an error path reported by yidong zhang

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

Andrew/Greg, can you insert the code in the mm/staging tree?

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 v4] pramfs: documentation

2010-11-20 Thread Marco Stornelli
From: Marco Stornelli 

Documentation for PRAMFS.

Signed-off-by: Marco Stornelli 
---
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.
+Read&write 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 again.
+This feature pro

  1   2   3   >