pramfs: file operations
PATCH v4 4/16 pramfs: file operations
From: Marco Stornelli <[email protected]>
File operations.
---
fs/pramfs/file.c +166 -0
@@ -0,0 +1,166 @@ +/* +* FILE NAME fs/pramfs/file.c +* +* BRIEF DESCRIPTION +* +* File operations for files. +* +* Copyright 2009-2010 Marco Stornelli <[email protected]> +* Copyright 2003 Sony Corporation +* Copyright 2003 Matsushita Electric Industrial Co., Ltd. +* 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam +* This file is licensed under the terms of the GNU General Public +* License version 2. This program is licensed "as is" without any +* warranty of any kind, whether express or implied. +*/ +#include <linux/fs.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include <linux/uio.h> +#include <linux/mm.h> +#include <linux/uaccess.h> +#include "pram.h" +#include "acl.h" +#include "xip.h" +#include "xattr.h" + +static int pram_open_file (struct inode *inode,struct file *filp) +{ +#ifndef CONFIG_PRAMFS_XIP +/* Without XIP we force to use Direct IO */ + filp->f_flags |=O_DIRECT ; +#endif +return generic_file_open (inode, filp); +} + +ssize_t __pram_direct_IO (int rw,struct kiocb *iocb, +const struct iovec *iov, +loff_t offset,unsigned long nr_segs) +{ +struct file *file = iocb->ki_filp; +struct inode *inode = file->f_mapping->host; +struct super_block *sb = inode->i_sb; +int progress =0 , hole =0 ; +ssize_t retval =0 ; +void *tmp =NULL ; +unsigned long blocknr, blockoff; +int num_blocks, blocksize_mask, blocksize, blocksize_bits; +char __user *buf = iov->iov_base; +size_t length =iov_length (iov, nr_segs); + +if (length <0 ) +return -EINVAL ; +if ((rw ==READ ) && (offset + length > inode->i_size)) + length = inode->i_size - offset; +if (!length) + goto out; + + blocksize_bits = inode->i_sb->s_blocksize_bits; + blocksize =1 << blocksize_bits; + blocksize_mask = blocksize -1 ; + +/* find starting block number to access */ + blocknr = offset >> blocksize_bits; +/* find starting offset within starting block */ + blockoff = offset & blocksize_mask; +/* find number of blocks to access */ + num_blocks = (blockoff + length + blocksize_mask) >> blocksize_bits; + +if (rw ==WRITE ) { +/* prepare a temporary buffer to hold a user data block +for writing. */ + tmp =kmalloc (blocksize,GFP_KERNEL ); +if (!tmp) +return -ENOMEM ; +/* now allocate the data blocks we'll need */ + retval =pram_alloc_blocks (inode, blocknr, num_blocks); +if (retval) + goto fail1; + } + +while (length) { +int count; +u8 *bp =NULL ; +u64 block =pram_find_data_block (inode, blocknr++); +if (unlikely (!block && rw ==READ )) { +/* We are falling in a hole */ + hole =1 ; + }else { + bp = (u8 *)pram_get_block (sb, block); +if (!bp) + goto fail2; + } + + count = blockoff + length > blocksize ? + blocksize - blockoff : length; + +if (rw ==READ ) { +if (unlikely (hole)) { + retval =clear_user (buf, count); +if (retval) { + retval = -EFAULT ; + goto fail1; + } + }else { + retval =copy_to_user (buf, &bp[blockoff], count); +if (retval) { + retval = -EFAULT ; + goto fail1; + } + } + }else { + retval =copy_from_user (tmp, buf, count); +if (retval) { + retval = -EFAULT ; + goto fail1; + } + +pram_memunlock_block (inode->i_sb, bp); +memcpy (&bp[blockoff], tmp, count); +pram_memlock_block (inode->i_sb, bp); + } + + progress += count; + buf += count; + length -= count; + blockoff =0 ; + hole =0 ; + } + +fail2: + retval = progress; +fail1: +kfree (tmp); +out: +return retval; +} + +int __pram_mmap (struct file *file,struct vm_area_struct *vma) +{ +/* Only private mappings */ +if (vma->vm_flags &VM_SHARED ) +return -EINVAL ; +return generic_file_mmap (file, vma); +} + +struct file_operations pram_file_operations = { + .llseek = generic_file_llseek, + .read = pram_read, + .write = pram_write, + .aio_read = pram_aio_read, + .aio_write = pram_aio_write, + .mmap = pram_mmap, + .open = pram_open_file, + .fsync = noop_fsync, +}; + +struct inode_operations pram_file_inode_operations = { +#ifdef CONFIG_PRAMFS_XATTR + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, + .listxattr = pram_listxattr, + .removexattr = generic_removexattr, +#endif + .setattr = pram_notify_change, + .check_acl = pram_check_acl, +};
fs/pramfs/file.c line 7
Quoted 11 lines · Marco Stornelli
diff -Nurp
linux-2.6.36-orig/fs/pramfs/file.clinux-2.6.36/fs/pramfs/file.cfs/pramfs/file.c +7
-0@@ -0,0 +1,166 @@ +/* +* FILE NAME fs/pramfs/file.c +* +* BRIEF DESCRIPTION +* +* File operations for files. +*
This FILE NAME / BRIEF DESCRIPTION thing should probably die, it's also not used consistently throughout the series.
fs/pramfs/file.c line 35
Quoted 9 lines
fs/pramfs/file.c +9
-0+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); +} +
Relying on a config option for this is in violently poor taste. Rely on the config option to enable/disable XIP support as you like, but whether it's actually mounted XIP or not should really depend be determined by a mount option. Presently you have no way of dealing with the file system being mounted multiple times with mixed XIP and non-XIP, which doesn't seem like a particularly exotic configuration. As you seem to have copied most of this from ext2, I'm curious why you opted to hardcode this instead of maintaining the flexibility that ext2 XIP has over this.
2010/11/24 Paul Mundt <[email protected]>:
Quoted 6 lines · Marco Stornelli
Quoted 5 lines
diff -Nurp
linux-2.6.36-orig/fs/pramfs/file.clinux-2.6.36/fs/pramfs/file.cfs/pramfs/file.c 2010-09-24 18:34:03.000000000 +0200 renamed from fs/pramfs/file.c 1970-01-01 01:00:00.000000000 +0100 +1
-0@@ -0,0 +1,166 @@ +/*
Quoted 8 lines
fs/pramfs/file.c 2010-09-24 18:34:03.000000000 +0200 line 7
Quoted 6 lines
fs/pramfs/file.c 2010-09-24 18:34:03.000000000 +0200 renamed from fs/pramfs/file.c 1970-01-01 01:00:00.000000000 +0100 +6
-0+ * FILE NAME fs/pramfs/file.c + * + * BRIEF DESCRIPTION + * + * File operations for files. + *This FILE NAME / BRIEF DESCRIPTION thing should probably die, it's also not used consistently throughout the series.
Maybe yes, it's more a problem then a advantage :)
Quoted 16 lines
fs/pramfs/file.c 2010-09-24 18:34:03.000000000 +0200 line 16
Quoted 10 lines
fs/pramfs/file.c 2010-09-24 18:34:03.000000000 +0200 renamed from fs/pramfs/file.c 1970-01-01 01:00:00.000000000 +0100 +9
-0+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); +} +Relying on a config option for this is in violently poor taste. Rely on the config option to enable/disable XIP support as you like, but whether it's actually mounted XIP or not should really depend be determined by a mount option. Presently you have no way of dealing with the file system being mounted multiple times with mixed XIP and non-XIP, which doesn't seem like a particularly exotic configuration. As you seem to have copied
Maybe on embedded, it could be.
Quoted 3 lines
most of this from ext2, I'm curious why you opted to hardcode this instead of maintaining the flexibility that ext2 XIP has over this.
First of all because it was simpler :) In addition there was some design problem to use it in combination with the memory protection. The difference with ext2 is that we aren't talking about a general purpose fs used (mainly) on normal desktop/server systems, but a specific fs for embedded world, so I think some little constraints are ok.
Marco
Quoted 6 lines · Marco Stornelli
2010/11/24 Paul Mundt <[email protected]>:
Quoted 2 lines
most of this from ext2, I'm curious why you opted to hardcode this instead of maintaining the flexibility that ext2 XIP has over this.
First of all because it was simpler :) In addition there was some design problem to use it in combination with the memory protection.
Do you have more details on this? You can easily check for unsupportable configurations with mount options and bail out accordingly.
Quoted 5 lines
The difference with ext2 is that we aren't talking about a general purpose fs used (mainly) on normal desktop/server systems, but a specific fs for embedded world, so I think some little constraints are ok.
I'm not sure what your point is. It's not a general purpose file system, but that's not an excuse for taking shortcuts. Out of the boards on my desk, I have at least 3 that could make use of this file system where I could use both XIP and non-XIP for different stores out of the box. I wouldn't exactly call it a corner case. Also, as Tony's patch set demonstrates, these sorts of non-volatile data stores are common enough in the server space to make pramfs an option there, too. Please lose this mentality that because something was originally tasked for embedded it's perfectly acceptable to ship a crippled interface.
As it is, this is something that will have to be rewritten one way or the other, but whether that happens in or out of staging/ is not such a big concern.
2010/11/24 Paul Mundt <[email protected]>:
Quoted 16 lines · Marco Stornelli
Quoted 6 lines
2010/11/24 Paul Mundt <[email protected]>:
Quoted 2 lines
most of this from ext2, I'm curious why you opted to hardcode this instead of maintaining the flexibility that ext2 XIP has over this.
First of all because it was simpler :) In addition there was some design problem to use it in combination with the memory protection.
Do you have more details on this? You can easily check for unsupportable configurations with mount options and bail out accordingly.
Quoted 5 lines
The difference with ext2 is that we aren't talking about a general purpose fs used (mainly) on normal desktop/server systems, but a specific fs for embedded world, so I think some little constraints are ok.
Quoted 9 lines
I'm not sure what your point is. It's not a general purpose file system, but that's not an excuse for taking shortcuts. Out of the boards on my desk, I have at least 3 that could make use of this file system where I could use both XIP and non-XIP for different stores out of the box. I wouldn't exactly call it a corner case. Also, as Tony's patch set demonstrates, these sorts of non-volatile data stores are common enough in the server space to make pramfs an option there, too. Please lose this mentality that because something was originally tasked for embedded it's perfectly acceptable to ship a crippled interface.
I'm not responsible if someone uses something outside its scope, you can use FAT on a flash but you can't claim reliability. However since I'm a collaborative person I'll try to fix it, implementing where possible a mount option.
Quoted 5 lines
As it is, this is something that will have to be rewritten one way or the other, but whether that happens in or out of staging/ is not such a big concern.
Good.
Marco