Skip to contentSkip to conversation

Pramfs: File operations for files

PATCH In review Marco 2 participants 2 messages Jun 13, 2009 VFS

lore
Share & tools
lore

Marco

author
#0 lore raw

PATCH 5/14 Pramfs: File operations for files

From: Marco Stornelli <[email protected]>

File operations for files.

---

fs/pramfs/file.c +141 -0
diff -uprN linux-2.6.30-orig/fs/pramfs/file.c linux-2.6.30/fs/pramfs/file.c
@@ -0,0 +1,141 @@
+/*
+ * FILE NAME fs/pramfs/file.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * File operations for files.
+ *
+ * Copyright 2009 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/uaccess.h>
+#include "pram_fs.h"
+#include "xip.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);
+}
+
+/*
+ * Called when an inode is released. Note that this is different
+ * from pram_open_file: open gets called at every open, but release
+ * gets called only when /all/ the files are closed.
+ */
+static int pram_release_file(struct inode *inode, struct file *filp)
+{
+	return 0;
+}
+
+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;
+	ssize_t retval = 0;
+	struct pram_inode *pi;
+	void *tmp = NULL;
+	unsigned long flags;
+	unsigned long blocknr, blockoff;
+	int num_blocks, blocksize_mask, blocksize, blocksize_bits;
+	char __user *buf = iov->iov_base;
+	size_t length = iov->iov_len;
+
+	flags = 0;
+
+	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 fail;
+	}
+
+	pi = pram_get_inode(inode->i_sb, inode->i_ino);
+
+	while (length) {
+		int count;
+		off_t block = pram_find_data_block(inode, blocknr++);
+		u8 *bp = (u8 *)pram_get_block(sb, block);
+		if (!bp)
+			goto fail;
+
+		count = blockoff + length > blocksize ?
+			blocksize - blockoff : length;
+
+		if (rw == READ) {
+			copy_to_user(buf, &bp[blockoff], count);
+		} else {
+			copy_from_user(tmp, buf, count);
+
+			pram_lock_block(inode->i_sb, bp, flags);
+			memcpy(&bp[blockoff], tmp, count);
+			pram_unlock_block(inode->i_sb, bp, flags);
+		}
+
+		progress += count;
+		buf += count;
+		length -= count;
+		blockoff = 0;
+	}
+
+	retval = progress;
+ fail:
+	kfree(tmp);
+ out:
+	return retval;
+}
+
+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,
+	.release	= pram_release_file,
+	.fsync		= simple_sync_file,
+};
+
+struct inode_operations pram_file_inode_operations = {
+	.truncate	= pram_truncate,
+};
#1 lore raw
Quoted 23 lines · Marco

From: Marco Stornelli <[email protected]>

File operations for files.

---

diff -uprN linux-2.6.30-orig/fs/pramfs/file.c linux-2.6.30/fs/pramfs/file.c

fs/pramfs/file.c +12 -0
@@ -0,0 +1,141 @@
+/*
+ * FILE NAME fs/pramfs/file.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * File operations for files.
+ *
+ * Copyright 2009 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

fs/pramfs/file.c line 22

Quoted 10 lines
fs/pramfs/file.c +10 -0
+ * 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/uaccess.h>
+#include "pram_fs.h"
+#include "xip.h"

It would be cleaner if the xip.h include was added in patch 14 of 14, since that's the XIP support patch.

fs/pramfs/file.c line 29

Quoted 6 lines
fs/pramfs/file.c +6 -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

Same as above .. It's better to have all the support for a given feature all in the same patch. The rest of your patches are dotted with these bits of code that should really be refactored into other patches.

Daniel