linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Dave Kleikamp <shaggy@austin.ibm.com>
To: nfsv4 <nfsv4@linux-nfs.org>, fsdevel <linux-fsdevel@vger.kernel.org>
Subject: [RFC] Support for stackable file systems on top of nfs
Date: Thu, 10 Nov 2005 11:32:22 -0600	[thread overview]
Message-ID: <1131643942.9389.17.camel@kleikamp.austin.ibm.com> (raw)

The following patch allows stackable file systems, such as ClearCase's
mvfs, to run atop nfs.  mvfs has it's own file and inode structures, but
points its inode->i_mapping to the lower file system's mapping.  This
causes problems when nfs's address space operations try to extract the
open context from file->private_data.

The patch adds a small overhead of checking the file structure to see if
it contains an inode that is not the mapping's host.

I am curious if there are any other stackable file systems that could
benefit from this.

Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>

diff -Nurp linux-2.6.14-git/fs/nfs/direct.c linux/fs/nfs/direct.c
--- linux-2.6.14-git/fs/nfs/direct.c	2005-11-07 07:53:49.000000000 -0600
+++ linux/fs/nfs/direct.c	2005-11-09 14:58:59.000000000 -0600
@@ -604,7 +604,19 @@ nfs_direct_IO(int rw, struct kiocb *iocb
 	if (!is_sync_kiocb(iocb))
 		return result;
 
-	ctx = (struct nfs_open_context *)file->private_data;
+	if (nfs_is_valid_file(file))
+		ctx = get_nfs_open_context((struct nfs_open_context *)
+				file->private_data);
+	else {
+		/* file belongs to a stackable file system.
+		 * Can't trust the inode either */
+		inode = inode->i_mapping->host;
+
+		ctx = nfs_find_open_context(inode, NULL,
+				(rw == READ) ? FMODE_READ : FMODE_WRITE);
+		if (ctx == NULL)
+			return -EBADF;
+	}
 	switch (rw) {
 	case READ:
 		dprintk("NFS: direct_IO(read) (%s) off/no(%Lu/%lu)\n",
@@ -623,6 +635,7 @@ nfs_direct_IO(int rw, struct kiocb *iocb
 	default:
 		break;
 	}
+	put_nfs_open_context(ctx);
 	return result;
 }
 
diff -Nurp linux-2.6.14-git/fs/nfs/read.c linux/fs/nfs/read.c
--- linux-2.6.14-git/fs/nfs/read.c	2005-11-07 07:53:49.000000000 -0600
+++ linux/fs/nfs/read.c	2005-11-09 11:47:05.000000000 -0600
@@ -506,7 +506,7 @@ int nfs_readpage(struct file *file, stru
 	if (error)
 		goto out_error;
 
-	if (file == NULL) {
+	if (!nfs_is_valid_file(file)) {
 		ctx = nfs_find_open_context(inode, NULL, FMODE_READ);
 		if (ctx == NULL)
 			return -EBADF;
@@ -575,7 +575,7 @@ int nfs_readpages(struct file *filp, str
 			(long long)NFS_FILEID(inode),
 			nr_pages);
 
-	if (filp == NULL) {
+	if (!nfs_is_valid_file(filp)) {
 		desc.ctx = nfs_find_open_context(inode, NULL, FMODE_READ);
 		if (desc.ctx == NULL)
 			return -EBADF;
diff -Nurp linux-2.6.14-git/fs/nfs/write.c linux/fs/nfs/write.c
--- linux-2.6.14-git/fs/nfs/write.c	2005-11-07 07:53:49.000000000 -0600
+++ linux/fs/nfs/write.c	2005-11-09 14:14:33.000000000 -0600
@@ -703,10 +703,16 @@ static struct nfs_page * nfs_update_requ
 
 int nfs_flush_incompatible(struct file *file, struct page *page)
 {
-	struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
+	struct nfs_open_context *ctx;
 	struct inode	*inode = page->mapping->host;
 	struct nfs_page	*req;
 	int		status = 0;
+
+	if (nfs_is_valid_file(file))
+		ctx = (struct nfs_open_context *)file->private_data;
+	else
+		ctx = NULL;
+
 	/*
 	 * Look for a request corresponding to this page. If there
 	 * is one, and it belongs to another file, we flush it out
@@ -733,7 +739,7 @@ int nfs_flush_incompatible(struct file *
 int nfs_updatepage(struct file *file, struct page *page,
 		unsigned int offset, unsigned int count)
 {
-	struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
+	struct nfs_open_context *ctx;
 	struct inode	*inode = page->mapping->host;
 	struct nfs_page	*req;
 	int		status = 0;
@@ -743,14 +749,23 @@ int nfs_updatepage(struct file *file, st
 		file->f_dentry->d_name.name, count,
 		(long long)(page_offset(page) +offset));
 
+	if (nfs_is_valid_file(file))
+		ctx = get_nfs_open_context((struct nfs_open_context *)
+				file->private_data);
+	else {
+		ctx = nfs_find_open_context(inode, NULL, FMODE_WRITE);
+		if (!ctx)
+			return -EBADF;
+	}
+		
 	if (IS_SYNC(inode)) {
 		status = nfs_writepage_sync(ctx, inode, page, offset, count, 0);
 		if (status > 0) {
 			if (offset == 0 && status == PAGE_CACHE_SIZE)
 				SetPageUptodate(page);
-			return 0;
+			status = 0;
 		}
-		return status;
+		goto out;
 	}
 
 	/* If we're not using byte range locks, and we know the page
@@ -803,6 +818,8 @@ done:
 			status, (long long)i_size_read(inode));
 	if (status < 0)
 		ClearPageUptodate(page);
+out:
+	put_nfs_open_context(ctx);
 	return status;
 }
 
diff -Nurp linux-2.6.14-git/include/linux/nfs_fs.h linux/include/linux/nfs_fs.h
--- linux-2.6.14-git/include/linux/nfs_fs.h	2005-11-07 07:53:50.000000000 -0600
+++ linux/include/linux/nfs_fs.h	2005-11-09 11:44:53.000000000 -0600
@@ -350,6 +350,20 @@ static inline struct rpc_cred *nfs_file_
 }
 
 /*
+ * A stackable file system may have it's own file & inode structures, which
+ * point to the local inode's mapping.  The address space operations cannot
+ * use the stackable file system's file structure to get to the open context
+ */
+static inline int nfs_is_valid_file(struct file *file)
+{
+	struct inode *inode;
+	if (!file)
+		return 0;
+	inode = file->f_dentry->d_inode;
+	return (inode == inode->i_mapping->host);
+}
+
+/*
  * linux/fs/nfs/xattr.c
  */
 #ifdef CONFIG_NFS_V3_ACL

-- 
David Kleikamp
IBM Linux Technology Center


             reply	other threads:[~2005-11-10 17:32 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-11-10 17:32 Dave Kleikamp [this message]
2005-11-10 20:07 ` [RFC] Support for stackable file systems on top of nfs Christoph Hellwig
2005-11-10 21:35   ` John T. Kohl
2005-11-10 21:40     ` Shaya Potter
2005-11-10 21:57       ` John T. Kohl
2005-11-10 21:50     ` Christoph Hellwig
2005-11-11  2:31     ` Trond Myklebust
2005-11-11  4:04       ` Trond Myklebust
2005-11-11 13:45         ` John T. Kohl
2005-11-11 15:27           ` Charles P. Wright
2005-11-11 17:38             ` John T. Kohl
2005-11-14 15:56     ` David Howells
2005-11-10 21:24 ` Trond Myklebust
2005-11-10 21:36   ` Shaya Potter
2005-11-10 22:18     ` Trond Myklebust
2005-11-10 22:27       ` Shaya Potter
2005-11-10 22:40         ` Trond Myklebust
2005-11-11  0:12           ` Bryan Henderson
2005-11-11  1:30             ` Brad Boyer
2005-11-11  2:06             ` Trond Myklebust
2005-11-11 18:18               ` Bryan Henderson
2005-11-11 19:22                 ` Trond Myklebust
2005-11-11 21:57                   ` Bryan Henderson
2005-11-11 22:41                     ` Trond Myklebust
2005-11-14 19:02                       ` Bryan Henderson
2005-11-11 16:40             ` Nikita Danilov
2005-11-11 18:45               ` Bryan Henderson
2005-11-11 19:31                 ` Nikita Danilov
2005-11-11 19:42                   ` Trond Myklebust
2005-11-11 23:13                   ` Bryan Henderson
  -- strict thread matches above, loose matches on Subject: below --
2005-11-14  0:44 Nikolai Joukov
2005-11-14 16:02 ` David Howells
2005-11-14 20:48   ` Erez Zadok
2005-11-14 21:13     ` John T. Kohl
2005-11-14 21:32       ` Jamie Lokier
2005-11-14 16:11 ` John T. Kohl

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1131643942.9389.17.camel@kleikamp.austin.ibm.com \
    --to=shaggy@austin.ibm.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=nfsv4@linux-nfs.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).