LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [RFC PATCH -V1 0/7] Buffered write and writeable mmap support for 9P
@ 2011-01-29 19:26 Aneesh Kumar K.V
  2011-01-29 19:26 ` [RFC PATCH -V1 1/7] fs/9p: set the cached file_operations struct during inode init Aneesh Kumar K.V
                   ` (7 more replies)
  0 siblings, 8 replies; 10+ messages in thread
From: Aneesh Kumar K.V @ 2011-01-29 19:26 UTC (permalink / raw)
  To: v9fs-developer; +Cc: linux-fsdevel, linux-kernel

The patch series implement buffered write and writeable mmap for 9P

-aneesh


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH -V1 1/7] fs/9p: set the cached file_operations struct during inode init
  2011-01-29 19:26 [RFC PATCH -V1 0/7] Buffered write and writeable mmap support for 9P Aneesh Kumar K.V
@ 2011-01-29 19:26 ` Aneesh Kumar K.V
  2011-01-29 19:26 ` [RFC PATCH -V1 2/7] fs/9p: set fs cache cookie in create path also Aneesh Kumar K.V
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Aneesh Kumar K.V @ 2011-01-29 19:26 UTC (permalink / raw)
  To: v9fs-developer; +Cc: linux-fsdevel, linux-kernel, Aneesh Kumar K.V

With the old code we were not setting the file->f_op
with cached file operations during creat.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 fs/9p/v9fs_vfs.h  |    2 ++
 fs/9p/vfs_file.c  |   18 ++++--------------
 fs/9p/vfs_inode.c |   10 ++++++++--
 3 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index b789f8e..e4d5540 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -45,6 +45,8 @@ extern const struct file_operations v9fs_dir_operations;
 extern const struct file_operations v9fs_dir_operations_dotl;
 extern const struct dentry_operations v9fs_dentry_operations;
 extern const struct dentry_operations v9fs_cached_dentry_operations;
+extern const struct file_operations v9fs_cached_file_operations;
+extern const struct file_operations v9fs_cached_file_operations_dotl;
 
 #ifdef CONFIG_9P_FSCACHE
 struct inode *v9fs_alloc_inode(struct super_block *sb);
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 240c306..6a67100 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -44,9 +44,6 @@
 #include "fid.h"
 #include "cache.h"
 
-static const struct file_operations v9fs_cached_file_operations;
-static const struct file_operations v9fs_cached_file_operations_dotl;
-
 /**
  * v9fs_file_open - open a file (or directory)
  * @inode: inode to be opened
@@ -89,19 +86,12 @@ int v9fs_file_open(struct inode *inode, struct file *file)
 	}
 
 	file->private_data = fid;
+#ifdef CONFIG_9P_FSCACHE
 	if ((fid->qid.version) && (v9ses->cache)) {
 		P9_DPRINTK(P9_DEBUG_VFS, "cached");
-		/* enable cached file options */
-		if(file->f_op == &v9fs_file_operations)
-			file->f_op = &v9fs_cached_file_operations;
-		else if (file->f_op == &v9fs_file_operations_dotl)
-			file->f_op = &v9fs_cached_file_operations_dotl;
-
-#ifdef CONFIG_9P_FSCACHE
 		v9fs_cache_inode_set_cookie(inode, file);
-#endif
 	}
-
+#endif
 	return 0;
 }
 
@@ -505,7 +495,7 @@ int v9fs_file_fsync_dotl(struct file *filp, int datasync)
 	return retval;
 }
 
-static const struct file_operations v9fs_cached_file_operations = {
+const struct file_operations v9fs_cached_file_operations = {
 	.llseek = generic_file_llseek,
 	.read = do_sync_read,
 	.aio_read = generic_file_aio_read,
@@ -517,7 +507,7 @@ static const struct file_operations v9fs_cached_file_operations = {
 	.fsync = v9fs_file_fsync,
 };
 
-static const struct file_operations v9fs_cached_file_operations_dotl = {
+const struct file_operations v9fs_cached_file_operations_dotl = {
 	.llseek = generic_file_llseek,
 	.read = do_sync_read,
 	.aio_read = generic_file_aio_read,
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index b76a40b..45e7ea4 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -292,10 +292,16 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
 	case S_IFREG:
 		if (v9fs_proto_dotl(v9ses)) {
 			inode->i_op = &v9fs_file_inode_operations_dotl;
-			inode->i_fop = &v9fs_file_operations_dotl;
+			if (v9ses->cache)
+				inode->i_fop = &v9fs_cached_file_operations_dotl;
+			else
+				inode->i_fop = &v9fs_file_operations_dotl;
 		} else {
 			inode->i_op = &v9fs_file_inode_operations;
-			inode->i_fop = &v9fs_file_operations;
+			if (v9ses->cache)
+				inode->i_fop = &v9fs_cached_file_operations;
+			else
+				inode->i_fop = &v9fs_file_operations;
 		}
 
 		break;
-- 
1.7.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH -V1 2/7] fs/9p: set fs cache cookie in create path also
  2011-01-29 19:26 [RFC PATCH -V1 0/7] Buffered write and writeable mmap support for 9P Aneesh Kumar K.V
  2011-01-29 19:26 ` [RFC PATCH -V1 1/7] fs/9p: set the cached file_operations struct during inode init Aneesh Kumar K.V
@ 2011-01-29 19:26 ` Aneesh Kumar K.V
  2011-01-29 19:26 ` [RFC PATCH -V1 3/7] fs/9p: increment inode->i_count in cached mode Aneesh Kumar K.V
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Aneesh Kumar K.V @ 2011-01-29 19:26 UTC (permalink / raw)
  To: v9fs-developer; +Cc: linux-fsdevel, linux-kernel, Aneesh Kumar K.V

We need to call v9fs_cache_inode_set_cookie in create
path also

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 fs/9p/vfs_file.c       |    4 +---
 fs/9p/vfs_inode.c      |    4 ++++
 fs/9p/vfs_inode_dotl.c |    4 ++++
 3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 6a67100..ce1eae4 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -87,10 +87,8 @@ int v9fs_file_open(struct inode *inode, struct file *file)
 
 	file->private_data = fid;
 #ifdef CONFIG_9P_FSCACHE
-	if ((fid->qid.version) && (v9ses->cache)) {
-		P9_DPRINTK(P9_DEBUG_VFS, "cached");
+	if (v9ses->cache)
 		v9fs_cache_inode_set_cookie(inode, file);
-	}
 #endif
 	return 0;
 }
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 45e7ea4..b6b939b 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -607,6 +607,10 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
 		}
 
 		filp->private_data = fid;
+#ifdef CONFIG_9P_FSCACHE
+		if (v9ses->cache)
+			v9fs_cache_inode_set_cookie(inode, filp);
+#endif
 	} else
 		p9_client_clunk(fid);
 
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index fe3ffa9..fbe9572 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -226,6 +226,10 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
 		return PTR_ERR(filp);
 	}
 	filp->private_data = ofid;
+#ifdef CONFIG_9P_FSCACHE
+	if (v9ses->cache)
+		v9fs_cache_inode_set_cookie(inode, filp);
+#endif
 	return 0;
 
 error:
-- 
1.7.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH -V1 3/7] fs/9p: increment inode->i_count in cached mode.
  2011-01-29 19:26 [RFC PATCH -V1 0/7] Buffered write and writeable mmap support for 9P Aneesh Kumar K.V
  2011-01-29 19:26 ` [RFC PATCH -V1 1/7] fs/9p: set the cached file_operations struct during inode init Aneesh Kumar K.V
  2011-01-29 19:26 ` [RFC PATCH -V1 2/7] fs/9p: set fs cache cookie in create path also Aneesh Kumar K.V
@ 2011-01-29 19:26 ` Aneesh Kumar K.V
  2011-01-29 19:26 ` [RFC PATCH -V1 4/7] fs/9p: [fscache] wait for page write " Aneesh Kumar K.V
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Aneesh Kumar K.V @ 2011-01-29 19:26 UTC (permalink / raw)
  To: v9fs-developer; +Cc: linux-fsdevel, linux-kernel, Aneesh Kumar K.V

We need to ihold even in cached mode

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 fs/9p/vfs_inode_dotl.c |    7 +------
 1 files changed, 1 insertions(+), 6 deletions(-)

diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index fbe9572..265f583 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -636,13 +636,8 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
 		v9fs_stat2inode_dotl(st, old_dentry->d_inode);
 
 		kfree(st);
-	} else {
-		/* Caching disabled. No need to get upto date stat info.
-		 * This dentry will be released immediately. So, just hold the
-		 * inode
-		 */
-		ihold(old_dentry->d_inode);
 	}
+	ihold(old_dentry->d_inode);
 	d_instantiate(dentry, old_dentry->d_inode);
 
 	return err;
-- 
1.7.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH -V1 4/7] fs/9p: [fscache] wait for page write in cached mode
  2011-01-29 19:26 [RFC PATCH -V1 0/7] Buffered write and writeable mmap support for 9P Aneesh Kumar K.V
                   ` (2 preceding siblings ...)
  2011-01-29 19:26 ` [RFC PATCH -V1 3/7] fs/9p: increment inode->i_count in cached mode Aneesh Kumar K.V
@ 2011-01-29 19:26 ` Aneesh Kumar K.V
  2011-01-29 19:26 ` [RFC PATCH -V1 5/7] fs/9p: Add read write helper function Aneesh Kumar K.V
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Aneesh Kumar K.V @ 2011-01-29 19:26 UTC (permalink / raw)
  To: v9fs-developer; +Cc: linux-fsdevel, linux-kernel, Aneesh Kumar K.V

We need to call fscache_wait_on_page_write in launder_page
for fscache

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 fs/9p/cache.c    |   11 +++++++++++
 fs/9p/cache.h    |   12 ++++++++++++
 fs/9p/vfs_addr.c |    1 +
 3 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/fs/9p/cache.c b/fs/9p/cache.c
index 0dbe0d1..610913d 100644
--- a/fs/9p/cache.c
+++ b/fs/9p/cache.c
@@ -461,3 +461,14 @@ void __v9fs_readpage_to_fscache(struct inode *inode, struct page *page)
 	if (ret != 0)
 		v9fs_uncache_page(inode, page);
 }
+
+/*
+ * wait for a page to complete writing to the cache
+ */
+void __v9fs_fscache_wait_on_page_write(struct inode *inode, struct page *page)
+{
+	const struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
+	P9_DPRINTK(P9_DEBUG_FSC, "inode %p page %p", inode, page);
+	if (PageFsCache(page))
+		fscache_wait_on_page_write(vcookie->fscache, page);
+}
diff --git a/fs/9p/cache.h b/fs/9p/cache.h
index a94192b..46fc228 100644
--- a/fs/9p/cache.h
+++ b/fs/9p/cache.h
@@ -131,6 +131,12 @@ static inline void v9fs_vcookie_set_qid(struct inode *inode,
 	spin_unlock(&vcookie->lock);
 }
 
+static inline void v9fs_fscache_wait_on_page_write(struct inode *inode,
+						   struct page *page)
+{
+	return __v9fs_fscache_wait_on_page_write(inode, page);
+}
+
 #else /* CONFIG_9P_FSCACHE */
 
 static inline int v9fs_cache_register(void)
@@ -172,5 +178,11 @@ static inline void v9fs_vcookie_set_qid(struct inode *inode,
 					struct p9_qid *qid)
 {}
 
+static inline void v9fs_fscache_wait_on_page_write(struct inode *inode,
+						   struct page *page)
+{
+	return;
+}
+
 #endif /* CONFIG_9P_FSCACHE */
 #endif /* _9P_CACHE_H */
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index b7f2a8e..005024c 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -151,6 +151,7 @@ static void v9fs_invalidate_page(struct page *page, unsigned long offset)
 
 static int v9fs_launder_page(struct page *page)
 {
+	v9fs_fscache_wait_on_page_write(inode, page);
 	return 0;
 }
 
-- 
1.7.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH -V1 5/7] fs/9p: Add read write helper function
  2011-01-29 19:26 [RFC PATCH -V1 0/7] Buffered write and writeable mmap support for 9P Aneesh Kumar K.V
                   ` (3 preceding siblings ...)
  2011-01-29 19:26 ` [RFC PATCH -V1 4/7] fs/9p: [fscache] wait for page write " Aneesh Kumar K.V
@ 2011-01-29 19:26 ` Aneesh Kumar K.V
  2011-01-29 19:26 ` [RFC PATCH -V1 6/7] fs/9p: Add fid to inode in cached mode Aneesh Kumar K.V
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Aneesh Kumar K.V @ 2011-01-29 19:26 UTC (permalink / raw)
  To: v9fs-developer; +Cc: linux-fsdevel, linux-kernel, Aneesh Kumar K.V

We add read write helper function here which will
be used later by the mmap patch

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 fs/9p/v9fs_vfs.h |    4 ++-
 fs/9p/vfs_file.c |  100 ++++++++++++++++++++++++++++++++---------------------
 2 files changed, 63 insertions(+), 41 deletions(-)

diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index e4d5540..276ad44 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -64,8 +64,10 @@ void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat);
 int v9fs_uflags2omode(int uflags, int extended);
 
 ssize_t v9fs_file_readn(struct file *, char *, char __user *, u32, u64);
+ssize_t v9fs_fid_readn(struct p9_fid *, char *, char __user *, u32, u64);
 void v9fs_blank_wstat(struct p9_wstat *wstat);
 int v9fs_vfs_setattr_dotl(struct dentry *, struct iattr *);
 int v9fs_file_fsync_dotl(struct file *filp, int datasync);
-
+ssize_t v9fs_file_write_internal(struct inode *, struct p9_fid *, char *,
+				 size_t, loff_t *, int);
 #define P9_LOCK_TIMEOUT (30*HZ)
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index ce1eae4..ecdd512 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -323,25 +323,22 @@ out_err:
 }
 
 /**
- * v9fs_file_readn - read from a file
- * @filp: file pointer to read
+ * v9fs_fid_readn - read from a fid
+ * @fid: fid to read
  * @data: data buffer to read data into
  * @udata: user data buffer to read data into
  * @count: size of buffer
  * @offset: offset at which to read data
  *
  */
-
 ssize_t
-v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count,
+v9fs_fid_readn(struct p9_fid *fid, char *data, char __user *udata, u32 count,
 	       u64 offset)
 {
 	int n, total, size;
-	struct p9_fid *fid = filp->private_data;
 
 	P9_DPRINTK(P9_DEBUG_VFS, "fid %d offset %llu count %d\n", fid->fid,
-					(long long unsigned) offset, count);
-
+		   (long long unsigned) offset, count);
 	n = 0;
 	total = 0;
 	size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ;
@@ -367,6 +364,22 @@ v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count,
 }
 
 /**
+ * v9fs_file_readn - read from a file
+ * @filp: file pointer to read
+ * @data: data buffer to read data into
+ * @udata: user data buffer to read data into
+ * @count: size of buffer
+ * @offset: offset at which to read data
+ *
+ */
+ssize_t
+v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count,
+	       u64 offset)
+{
+	return v9fs_fid_readn(filp->private_data, data, udata, count, offset);
+}
+
+/**
  * v9fs_file_read - read from a file
  * @filp: file pointer to read
  * @udata: user data buffer to read data into
@@ -398,45 +411,20 @@ v9fs_file_read(struct file *filp, char __user *udata, size_t count,
 	return ret;
 }
 
-/**
- * v9fs_file_write - write to a file
- * @filp: file pointer to write
- * @data: data buffer to write data from
- * @count: size of buffer
- * @offset: offset at which to write data
- *
- */
-
-static ssize_t
-v9fs_file_write(struct file *filp, const char __user * data,
-		size_t count, loff_t * offset)
+ssize_t
+v9fs_file_write_internal(struct inode *inode, struct p9_fid *fid, char *data,
+			 size_t count, loff_t *offset, int invalidate)
 {
-	ssize_t retval;
-	size_t total = 0;
 	int n;
-	struct p9_fid *fid;
+	size_t total = 0;
 	struct p9_client *clnt;
-	struct inode *inode = filp->f_path.dentry->d_inode;
 	loff_t origin = *offset;
 	unsigned long pg_start, pg_end;
 
 	P9_DPRINTK(P9_DEBUG_VFS, "data %p count %d offset %x\n", data,
 		(int)count, (int)*offset);
 
-	fid = filp->private_data;
 	clnt = fid->clnt;
-
-	retval = generic_write_checks(filp, &origin, &count, 0);
-	if (retval)
-		goto out;
-
-	retval = -EINVAL;
-	if ((ssize_t) count < 0)
-		goto out;
-	retval = 0;
-	if (!count)
-		goto out;
-
 	do {
 		n = p9_client_write(fid, NULL, data+total, origin+total, count);
 		if (n <= 0)
@@ -445,7 +433,7 @@ v9fs_file_write(struct file *filp, const char __user * data,
 		total += n;
 	} while (count > 0);
 
-	if (total > 0) {
+	if (invalidate && total > 0) {
 		pg_start = origin >> PAGE_CACHE_SHIFT;
 		pg_end = (origin + total - 1) >> PAGE_CACHE_SHIFT;
 		if (inode->i_mapping && inode->i_mapping->nrpages)
@@ -457,9 +445,41 @@ v9fs_file_write(struct file *filp, const char __user * data,
 	}
 
 	if (n < 0)
-		retval = n;
-	else
-		retval = total;
+		return n;
+
+	return total;
+}
+
+/**
+ * v9fs_file_write - write to a file
+ * @filp: file pointer to write
+ * @data: data buffer to write data from
+ * @count: size of buffer
+ * @offset: offset at which to write data
+ *
+ */
+static ssize_t
+v9fs_file_write(struct file *filp, const char __user * data,
+		size_t count, loff_t *offset)
+{
+	ssize_t retval = 0;
+	loff_t origin = *offset;
+
+
+	retval = generic_write_checks(filp, &origin, &count, 0);
+	if (retval)
+		goto out;
+
+	retval = -EINVAL;
+	if ((ssize_t) count < 0)
+		goto out;
+	retval = 0;
+	if (!count)
+		goto out;
+
+	return v9fs_file_write_internal(filp->f_path.dentry->d_inode,
+					filp->private_data,
+					(char *)data, count, offset, 1);
 out:
 	return retval;
 }
-- 
1.7.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH -V1 6/7] fs/9p: Add fid to inode in cached mode
  2011-01-29 19:26 [RFC PATCH -V1 0/7] Buffered write and writeable mmap support for 9P Aneesh Kumar K.V
                   ` (4 preceding siblings ...)
  2011-01-29 19:26 ` [RFC PATCH -V1 5/7] fs/9p: Add read write helper function Aneesh Kumar K.V
@ 2011-01-29 19:26 ` Aneesh Kumar K.V
  2011-01-29 19:26 ` [RFC PATCH -V1 7/7] fs/9p: Add buffered write support for v9fs. We can now support writeable mmaps Aneesh Kumar K.V
  2011-01-31  9:38 ` [RFC PATCH -V1 0/7] Buffered write and writeable mmap support for 9P Miklos Szeredi
  7 siblings, 0 replies; 10+ messages in thread
From: Aneesh Kumar K.V @ 2011-01-29 19:26 UTC (permalink / raw)
  To: v9fs-developer; +Cc: linux-fsdevel, linux-kernel, Aneesh Kumar K.V

The fid attached to inode will be opened O_RDWR mode and is used
for dirty page writeback only.

FIXME!!: Should we make the fid owned by uid = 0

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 fs/9p/vfs_file.c       |   31 +++++++++++++++++++++++++++++++
 fs/9p/vfs_inode.c      |   34 +++++++++++++++++++++++++++++++++-
 fs/9p/vfs_inode_dotl.c |   30 ++++++++++++++++++++++++++++--
 3 files changed, 92 insertions(+), 3 deletions(-)

diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index ecdd512..0f62b26 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -86,11 +86,42 @@ int v9fs_file_open(struct inode *inode, struct file *file)
 	}
 
 	file->private_data = fid;
+	/*
+	 * In cached mode we need to attach a fid to inode. The fid
+	 * attached to inode will only be used to write back the
+	 * dirty pages. We always request for the open fid in read-write
+	 * mode so that a partial page write which result in page
+	 * read can work.
+	 */
+	if (v9ses->cache && !inode->i_private) {
+		/*
+		 * clone a fid and add it to inode->i_private
+		 * we do it during open time instead of
+		 * page dirty time via write_begin/page_mkwrite
+		 * because we want write after unlink usecase
+		 * to work.
+		 */
+		fid = v9fs_fid_clone(file->f_path.dentry);
+		if (IS_ERR(fid)) {
+			err = PTR_ERR(fid);
+			goto out_error;
+		}
+		err = p9_client_open(fid, O_RDWR);
+		if (err < 0) {
+			p9_client_clunk(fid);
+			goto out_error;
+		}
+		inode->i_private = (void *) fid;
+	}
 #ifdef CONFIG_9P_FSCACHE
 	if (v9ses->cache)
 		v9fs_cache_inode_set_cookie(inode, file);
 #endif
 	return 0;
+out_error:
+	p9_client_clunk(file->private_data);
+	file->private_data = 0;
+	return err;
 }
 
 /**
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index b6b939b..908fa08 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -416,6 +416,11 @@ void v9fs_evict_inode(struct inode *inode)
 #ifdef CONFIG_9P_FSCACHE
 	v9fs_cache_inode_put_cookie(inode);
 #endif
+	/* clunk the fid stashed in inode->i_private */
+	if (inode->i_private) {
+		p9_client_clunk((struct p9_fid *)inode->i_private);
+		inode->i_private = 0;
+	}
 }
 
 struct inode *
@@ -577,7 +582,7 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
 	u32 perm;
 	int flags;
 	struct v9fs_session_info *v9ses;
-	struct p9_fid *fid;
+	struct p9_fid *fid, *inode_fid;
 	struct file *filp;
 
 	err = 0;
@@ -600,6 +605,33 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
 
 	/* if we are opening a file, assign the open fid to the file */
 	if (nd && nd->flags & LOOKUP_OPEN) {
+		/*
+		 * In cached mode we need to attach a fid to inode. The fid
+		 * attached to inode will only be used to write back the
+		 * dirty pages. We always request for the open fid in read-write
+		 * mode so that a partial page write which result in page
+		 * read can work.
+		 */
+		if (v9ses->cache && !dentry->d_inode->i_private) {
+			/*
+			 * clone a fid and add it to inode->i_private
+			 * we do it during open time instead of
+			 * page dirty time via write_begin/page_mkwrite
+			 * because we want write after unlink usecase
+			 * to work.
+			 */
+			inode_fid = v9fs_fid_clone(dentry);
+			if (IS_ERR(inode_fid)) {
+				err = PTR_ERR(inode_fid);
+				goto error;
+			}
+			err = p9_client_open(inode_fid, O_RDWR);
+			if (err < 0) {
+				p9_client_clunk(inode_fid);
+				goto error;
+			}
+			dentry->d_inode->i_private = (void *) inode_fid;
+		}
 		filp = lookup_instantiate_filp(nd, dentry, generic_file_open);
 		if (IS_ERR(filp)) {
 			err = PTR_ERR(filp);
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index 265f583..d5aa986 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -142,7 +142,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
 	mode_t mode;
 	struct v9fs_session_info *v9ses;
 	struct p9_fid *fid = NULL;
-	struct p9_fid *dfid, *ofid;
+	struct p9_fid *dfid, *ofid, *inode_fid;
 	struct file *filp;
 	struct p9_qid qid;
 	struct inode *inode;
@@ -218,7 +218,33 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
 
 	/* Now set the ACL based on the default value */
 	v9fs_set_create_acl(dentry, dacl, pacl);
-
+	/*
+	 * In cached mode we need to attach a fid to inode. The fid
+	 * attached to inode will only be used to write back the
+	 * dirty pages. We always request for the open fid in read-write
+	 * mode so that a partial page write which result in page
+	 * read can work.
+	 */
+	if (v9ses->cache && !inode->i_private) {
+		/*
+		 * clone a fid and add it to inode->i_private
+		 * we do it during open time instead of
+		 * page dirty time via write_begin/page_mkwrite
+		 * because we want write after unlink usecase
+		 * to work.
+		 */
+		inode_fid = v9fs_fid_clone(dentry);
+		if (IS_ERR(inode_fid)) {
+			err = PTR_ERR(inode_fid);
+			goto error;
+		}
+		err = p9_client_open(inode_fid, O_RDWR);
+		if (err < 0) {
+			p9_client_clunk(inode_fid);
+			goto error;
+		}
+		inode->i_private = (void *) inode_fid;
+	}
 	/* Since we are opening a file, assign the open fid to the file */
 	filp = lookup_instantiate_filp(nd, dentry, generic_file_open);
 	if (IS_ERR(filp)) {
-- 
1.7.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH -V1 7/7] fs/9p: Add buffered write support for v9fs. We can now support writeable mmaps.
  2011-01-29 19:26 [RFC PATCH -V1 0/7] Buffered write and writeable mmap support for 9P Aneesh Kumar K.V
                   ` (5 preceding siblings ...)
  2011-01-29 19:26 ` [RFC PATCH -V1 6/7] fs/9p: Add fid to inode in cached mode Aneesh Kumar K.V
@ 2011-01-29 19:26 ` Aneesh Kumar K.V
  2011-01-31  9:38 ` [RFC PATCH -V1 0/7] Buffered write and writeable mmap support for 9P Miklos Szeredi
  7 siblings, 0 replies; 10+ messages in thread
From: Aneesh Kumar K.V @ 2011-01-29 19:26 UTC (permalink / raw)
  To: v9fs-developer; +Cc: linux-fsdevel, linux-kernel, Aneesh Kumar K.V

Based on the original patch from Badari Pulavarty <pbadari@us.ibm.com>

TODO: O_DIRECT
      synfc
      fsync

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 fs/9p/vfs_addr.c |  182 +++++++++++++++++++++++++++++++++++++++++++++++++-----
 fs/9p/vfs_file.c |   54 +++++++++++++++-
 2 files changed, 217 insertions(+), 19 deletions(-)

diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index 005024c..792c68a 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -39,16 +39,16 @@
 #include "v9fs.h"
 #include "v9fs_vfs.h"
 #include "cache.h"
+#include "fid.h"
 
 /**
- * v9fs_vfs_readpage - read an entire page in from 9P
+ * v9fs_fid_readpage - read an entire page in from 9P
  *
- * @filp: file being read
+ * @fid: fid being read
  * @page: structure to page
  *
  */
-
-static int v9fs_vfs_readpage(struct file *filp, struct page *page)
+static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page)
 {
 	int retval;
 	loff_t offset;
@@ -67,7 +67,7 @@ static int v9fs_vfs_readpage(struct file *filp, struct page *page)
 	buffer = kmap(page);
 	offset = page_offset(page);
 
-	retval = v9fs_file_readn(filp, buffer, NULL, PAGE_CACHE_SIZE, offset);
+	retval = v9fs_fid_readn(fid, buffer, NULL, PAGE_CACHE_SIZE, offset);
 	if (retval < 0) {
 		v9fs_uncache_page(inode, page);
 		goto done;
@@ -87,6 +87,19 @@ done:
 }
 
 /**
+ * v9fs_vfs_readpage - read an entire page in from 9P
+ *
+ * @filp: file being read
+ * @page: structure to page
+ *
+ */
+
+static int v9fs_vfs_readpage(struct file *filp, struct page *page)
+{
+	return v9fs_fid_readpage(filp->private_data, page);
+}
+
+/**
  * v9fs_vfs_readpages - read a set of pages from 9P
  *
  * @filp: file being read
@@ -124,7 +137,6 @@ static int v9fs_release_page(struct page *page, gfp_t gfp)
 {
 	if (PagePrivate(page))
 		return 0;
-
 	return v9fs_fscache_release_page(page, gfp);
 }
 
@@ -137,21 +149,86 @@ static int v9fs_release_page(struct page *page, gfp_t gfp)
 
 static void v9fs_invalidate_page(struct page *page, unsigned long offset)
 {
+	/*
+	 * If called with zero offset, we should release
+	 * the private state assocated with the page
+	 */
 	if (offset == 0)
 		v9fs_fscache_invalidate_page(page);
 }
 
+static int v9fs_vfs_writepage_locked(struct page *page)
+{
+	char *buffer;
+	int retval, len;
+	loff_t offset, size;
+	mm_segment_t old_fs;
+	struct inode *inode = page->mapping->host;
+
+	size = i_size_read(inode);
+	if (page->index == size >> PAGE_CACHE_SHIFT)
+		len = size & ~PAGE_CACHE_MASK;
+	else
+		len = PAGE_CACHE_SIZE;
+
+	set_page_writeback(page);
+
+	buffer = kmap(page);
+	offset = page_offset(page);
+
+	old_fs = get_fs();
+	set_fs(get_ds());
+	/* We should have i_private always set */
+	BUG_ON(!inode->i_private);
+
+	retval = v9fs_file_write_internal(inode,
+					  (struct p9_fid *)inode->i_private,
+					  buffer, len, &offset, 0);
+	if (retval > 0)
+		retval = 0;
+
+	set_fs(old_fs);
+	kunmap(page);
+	end_page_writeback(page);
+	return retval;
+}
+
+static int v9fs_vfs_writepage(struct page *page, struct writeback_control *wbc)
+{
+	int retval;
+
+	retval = v9fs_vfs_writepage_locked(page);
+	if (retval < 0) {
+		if (retval == -EAGAIN) {
+			redirty_page_for_writepage(wbc, page);
+			retval = 0;
+		} else {
+			SetPageError(page);
+			mapping_set_error(page->mapping, retval);
+		}
+	} else
+		retval = 0;
+
+	unlock_page(page);
+	return retval;
+}
+
 /**
  * v9fs_launder_page - Writeback a dirty page
- * Since the writes go directly to the server, we simply return a 0
- * here to indicate success.
- *
  * Returns 0 on success.
  */
 
 static int v9fs_launder_page(struct page *page)
 {
+	int retval;
+	struct inode *inode = page->mapping->host;
+
 	v9fs_fscache_wait_on_page_write(inode, page);
+	if (clear_page_dirty_for_io(page)) {
+		retval = v9fs_vfs_writepage_locked(page);
+		if (retval)
+			return retval;
+	}
 	return 0;
 }
 
@@ -177,6 +254,11 @@ static int v9fs_launder_page(struct page *page)
 ssize_t v9fs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
 		loff_t pos, unsigned long nr_segs)
 {
+	/*
+	 * FIXME
+	 * Now that we do caching with cache mode enabled, We need
+	 * to support direct IO
+	 */
 	P9_DPRINTK(P9_DEBUG_VFS, "v9fs_direct_IO: v9fs_direct_IO (%s) "
 			"off/no(%lld/%lu) EINVAL\n",
 			iocb->ki_filp->f_path.dentry->d_name.name,
@@ -184,11 +266,81 @@ ssize_t v9fs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
 
 	return -EINVAL;
 }
+
+static int v9fs_write_begin(struct file *filp, struct address_space *mapping,
+			    loff_t pos, unsigned len, unsigned flags,
+			    struct page **pagep, void **fsdata)
+{
+	int retval = 0;
+	struct page *page;
+	pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+	struct inode *inode = mapping->host;
+
+start:
+	page = grab_cache_page_write_begin(mapping, index, flags);
+	if (!page) {
+		retval = -ENOMEM;
+		goto out;
+	}
+	BUG_ON(!inode->i_private);
+	if (PageUptodate(page))
+		goto out;
+
+	if (len == PAGE_CACHE_SIZE)
+		goto out;
+
+	retval = v9fs_fid_readpage(inode->i_private, page);
+	page_cache_release(page);
+	if (!retval)
+		goto start;
+out:
+	*pagep = page;
+	return retval;
+}
+
+static int v9fs_write_end(struct file *filp, struct address_space *mapping,
+			  loff_t pos, unsigned len, unsigned copied,
+			  struct page *page, void *fsdata)
+{
+	loff_t last_pos = pos + copied;
+	struct inode *inode = page->mapping->host;
+
+	if (unlikely(copied < len)) {
+		/*
+		 * zero out the rest of the area
+		 */
+		unsigned from = pos & (PAGE_CACHE_SIZE - 1);
+
+		zero_user(page, from + copied, len - copied);
+		flush_dcache_page(page);
+	}
+
+	if (!PageUptodate(page))
+		SetPageUptodate(page);
+	/*
+	 * No need to use i_size_read() here, the i_size
+	 * cannot change under us because we hold the i_mutex.
+	 */
+	if (last_pos > inode->i_size)
+		i_size_write(inode, last_pos);
+
+	set_page_dirty(page);
+	unlock_page(page);
+	page_cache_release(page);
+
+	return copied;
+}
+
+
 const struct address_space_operations v9fs_addr_operations = {
-      .readpage = v9fs_vfs_readpage,
-      .readpages = v9fs_vfs_readpages,
-      .releasepage = v9fs_release_page,
-      .invalidatepage = v9fs_invalidate_page,
-      .launder_page = v9fs_launder_page,
-      .direct_IO = v9fs_direct_IO,
+	.readpage = v9fs_vfs_readpage,
+	.readpages = v9fs_vfs_readpages,
+	.set_page_dirty = __set_page_dirty_nobuffers,
+	.writepage = v9fs_vfs_writepage,
+	.write_begin = v9fs_write_begin,
+	.write_end = v9fs_write_end,
+	.releasepage = v9fs_release_page,
+	.invalidatepage = v9fs_invalidate_page,
+	.launder_page = v9fs_launder_page,
+	.direct_IO = v9fs_direct_IO,
 };
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 0f62b26..6e38947 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -44,6 +44,8 @@
 #include "fid.h"
 #include "cache.h"
 
+static const struct vm_operations_struct v9fs_file_vm_ops;
+
 /**
  * v9fs_file_open - open a file (or directory)
  * @inode: inode to be opened
@@ -515,6 +517,7 @@ out:
 	return retval;
 }
 
+
 static int v9fs_file_fsync(struct file *filp, int datasync)
 {
 	struct p9_fid *fid;
@@ -544,28 +547,71 @@ int v9fs_file_fsync_dotl(struct file *filp, int datasync)
 	return retval;
 }
 
+static int
+v9fs_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	int retval;
+
+	retval = generic_file_mmap(file, vma);
+	if (!retval)
+		vma->vm_ops = &v9fs_file_vm_ops;
+
+	return retval;
+}
+
+static int
+v9fs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	struct page *page = vmf->page;
+	struct file *filp = vma->vm_file;
+	struct inode *inode = filp->f_path.dentry->d_inode;
+
+
+	P9_DPRINTK(P9_DEBUG_VFS, "page %p fid %lx\n",
+		   page, (unsigned long)filp->private_data);
+
+	/* make sure the cache has finished storing the page */
+	v9fs_fscache_wait_on_page_write(inode, page);
+	BUG_ON(!inode->i_private);
+	lock_page(page);
+	if (page->mapping != inode->i_mapping)
+		goto out_unlock;
+
+	return VM_FAULT_LOCKED;
+out_unlock:
+	unlock_page(page);
+	return VM_FAULT_NOPAGE;
+}
+
+static const struct vm_operations_struct v9fs_file_vm_ops = {
+	.fault = filemap_fault,
+	.page_mkwrite = v9fs_vm_page_mkwrite,
+};
+
 const struct file_operations v9fs_cached_file_operations = {
 	.llseek = generic_file_llseek,
 	.read = do_sync_read,
+	.write = do_sync_write,
 	.aio_read = generic_file_aio_read,
-	.write = v9fs_file_write,
+	.aio_write = generic_file_aio_write,
 	.open = v9fs_file_open,
 	.release = v9fs_dir_release,
 	.lock = v9fs_file_lock,
-	.mmap = generic_file_readonly_mmap,
+	.mmap = v9fs_file_mmap,
 	.fsync = v9fs_file_fsync,
 };
 
 const struct file_operations v9fs_cached_file_operations_dotl = {
 	.llseek = generic_file_llseek,
 	.read = do_sync_read,
+	.write = do_sync_write,
 	.aio_read = generic_file_aio_read,
-	.write = v9fs_file_write,
+	.aio_write = generic_file_aio_write,
 	.open = v9fs_file_open,
 	.release = v9fs_dir_release,
 	.lock = v9fs_file_lock_dotl,
 	.flock = v9fs_file_flock_dotl,
-	.mmap = generic_file_readonly_mmap,
+	.mmap = v9fs_file_mmap,
 	.fsync = v9fs_file_fsync_dotl,
 };
 
-- 
1.7.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH -V1 0/7] Buffered write and writeable mmap support for 9P
  2011-01-29 19:26 [RFC PATCH -V1 0/7] Buffered write and writeable mmap support for 9P Aneesh Kumar K.V
                   ` (6 preceding siblings ...)
  2011-01-29 19:26 ` [RFC PATCH -V1 7/7] fs/9p: Add buffered write support for v9fs. We can now support writeable mmaps Aneesh Kumar K.V
@ 2011-01-31  9:38 ` Miklos Szeredi
  2011-01-31 18:41   ` Aneesh Kumar K. V
  7 siblings, 1 reply; 10+ messages in thread
From: Miklos Szeredi @ 2011-01-31  9:38 UTC (permalink / raw)
  To: Aneesh Kumar K.V; +Cc: v9fs-developer, linux-fsdevel, linux-kernel

On Sun, 30 Jan 2011, Aneesh Kumar K.V wrote:
> The patch series implement buffered write and writeable mmap for 9P

P9 is supposed to work with servers on the local machine, right?

In that case you need to think about various deadlock scenarios.  An
example: the P9 server needs a large order allocation while serving
the buffered write request.  That may trigger the page reclaim and go
into synchronous writeback, possibly waiting on the exact page which
the P9 server is just trying to finish writing out.

This is not easy to deal with, see commit 3be5a52b for the fuse
solution.  I'm not saying it's the only way, there may be a better
one.

Thanks,
Miklos

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH -V1 0/7] Buffered write and writeable mmap support for 9P
  2011-01-31  9:38 ` [RFC PATCH -V1 0/7] Buffered write and writeable mmap support for 9P Miklos Szeredi
@ 2011-01-31 18:41   ` Aneesh Kumar K. V
  0 siblings, 0 replies; 10+ messages in thread
From: Aneesh Kumar K. V @ 2011-01-31 18:41 UTC (permalink / raw)
  To: Miklos Szeredi; +Cc: v9fs-developer, linux-fsdevel, linux-kernel

On Mon, 31 Jan 2011 10:38:10 +0100, Miklos Szeredi <miklos@szeredi.hu> wrote:
> On Sun, 30 Jan 2011, Aneesh Kumar K.V wrote:
> > The patch series implement buffered write and writeable mmap for 9P
> 
> P9 is supposed to work with servers on the local machine, right?

Yes

> 
> In that case you need to think about various deadlock scenarios.  An
> example: the P9 server needs a large order allocation while serving
> the buffered write request.  That may trigger the page reclaim and go
> into synchronous writeback, possibly waiting on the exact page which
> the P9 server is just trying to finish writing out.
> 
> This is not easy to deal with, see commit 3be5a52b for the fuse
> solution.  I'm not saying it's the only way, there may be a better
> one.
> 

Thanks for the commit info. I will look at the details and see how best
we can solve this in 9P

-aneesh

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2011-01-31 18:41 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-29 19:26 [RFC PATCH -V1 0/7] Buffered write and writeable mmap support for 9P Aneesh Kumar K.V
2011-01-29 19:26 ` [RFC PATCH -V1 1/7] fs/9p: set the cached file_operations struct during inode init Aneesh Kumar K.V
2011-01-29 19:26 ` [RFC PATCH -V1 2/7] fs/9p: set fs cache cookie in create path also Aneesh Kumar K.V
2011-01-29 19:26 ` [RFC PATCH -V1 3/7] fs/9p: increment inode->i_count in cached mode Aneesh Kumar K.V
2011-01-29 19:26 ` [RFC PATCH -V1 4/7] fs/9p: [fscache] wait for page write " Aneesh Kumar K.V
2011-01-29 19:26 ` [RFC PATCH -V1 5/7] fs/9p: Add read write helper function Aneesh Kumar K.V
2011-01-29 19:26 ` [RFC PATCH -V1 6/7] fs/9p: Add fid to inode in cached mode Aneesh Kumar K.V
2011-01-29 19:26 ` [RFC PATCH -V1 7/7] fs/9p: Add buffered write support for v9fs. We can now support writeable mmaps Aneesh Kumar K.V
2011-01-31  9:38 ` [RFC PATCH -V1 0/7] Buffered write and writeable mmap support for 9P Miklos Szeredi
2011-01-31 18:41   ` Aneesh Kumar K. V

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