2010-05-05 03:07:57

by Fred Isaman

[permalink] [raw]
Subject: [PATCH 0/8]: pnfs_submit: removal of fsdata manipulation

These revert patches in the submit branch in order to remove the fsdata manipulation needed by the block driver, followed immediately by the post-submit "un-reverts".

They apply on top of the 13 patches Andy previously sent.

Fred



2010-05-05 03:07:58

by Fred Isaman

[permalink] [raw]
Subject: [PATCH 1/8] SQUASHME: pnfs_submit: Revert the pnfs_write_end part of "pnfs: commit and pnfs_write_end"

This reverts sections of commit db413b6aad54478ff0a11852b93aade64969f0ca.

pnfs_write_end is not used by the layout driver.

Signed-off-by: Fred Isaman <[email protected]>
---
fs/nfs/file.c | 4 ----
fs/nfs/pnfs.c | 14 --------------
fs/nfs/pnfs.h | 23 -----------------------
include/linux/nfs4_pnfs.h | 3 ---
4 files changed, 0 insertions(+), 44 deletions(-)

diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 47eec55..4398953 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -487,12 +487,8 @@ static int nfs_write_end(struct file *file, struct address_space *mapping,
zero_user_segment(page, pglen, PAGE_CACHE_SIZE);
}

- status = pnfs_write_end(file, page, pos, len, copied, fsdata);
- if (status)
- goto out;
status = nfs_updatepage(file, page, offset, copied, fsdata);

- out:
unlock_page(page);
page_cache_release(page);
pnfs_write_end_cleanup(fsdata);
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index c76b791..46fe088 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1965,20 +1965,6 @@ out:
return status;
}

-/* Return 0 on succes, negative on failure */
-/* CAREFUL - what happens if copied < len??? */
-int _pnfs_write_end(struct inode *inode, struct page *page,
- loff_t pos, unsigned len,
- unsigned copied, struct pnfs_fsdata *fsdata)
-{
- struct nfs_server *nfss = NFS_SERVER(inode);
- int status;
-
- status = nfss->pnfs_curr_ld->ld_io_ops->write_end(inode, page,
- pos, len, copied, fsdata);
- return status;
-}
-
/* Given an nfs request, determine if it should be flushed before proceeding.
* It should default to returning False, returning True only if there is a
* specific reason to flush.
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 7dc3ecc..1c94984 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -76,9 +76,6 @@ void pnfs_destroy_layout(struct nfs_inode *);
int _pnfs_write_begin(struct inode *inode, struct page *page,
loff_t pos, unsigned len,
struct pnfs_fsdata **fsdata);
-int _pnfs_write_end(struct inode *inode, struct page *page,
- loff_t pos, unsigned len,
- unsigned copied, struct pnfs_fsdata *fsdata);
int _pnfs_do_flush(struct inode *inode, struct nfs_page *req,
struct pnfs_fsdata *fsdata);
void _pnfs_modify_new_write_request(struct nfs_page *req,
@@ -200,19 +197,6 @@ static inline int pnfs_do_flush(struct nfs_page *req, void *fsdata)
return 0;
}

-static inline int pnfs_write_end(struct file *filp, struct page *page,
- loff_t pos, unsigned len, unsigned copied,
- void *fsdata)
-{
- struct inode *inode = filp->f_dentry->d_inode;
- struct nfs_server *nfss = NFS_SERVER(inode);
-
- if (PNFS_EXISTS_LDIO_OP(nfss, write_end))
- return _pnfs_write_end(inode, page, pos, len, copied, fsdata);
- else
- return 0;
-}
-
static inline void pnfs_write_end_cleanup(void *fsdata)
{
pnfs_free_fsdata(fsdata);
@@ -312,13 +296,6 @@ static inline int pnfs_write_begin(struct file *filp, struct page *page,
return 0;
}

-static inline int pnfs_write_end(struct file *filp, struct page *page,
- loff_t pos, unsigned len, unsigned copied,
- void *fsdata)
-{
- return 0;
-}
-
static inline void pnfs_write_end_cleanup(void *fsdata)
{
}
diff --git a/include/linux/nfs4_pnfs.h b/include/linux/nfs4_pnfs.h
index 3caac60..e01a065 100644
--- a/include/linux/nfs4_pnfs.h
+++ b/include/linux/nfs4_pnfs.h
@@ -142,9 +142,6 @@ struct layoutdriver_io_operations {
int (*write_begin) (struct pnfs_layout_segment *lseg, struct page *page,
loff_t pos, unsigned count,
struct pnfs_fsdata *fsdata);
- int (*write_end)(struct inode *inode, struct page *page, loff_t pos,
- unsigned count, unsigned copied,
- struct pnfs_fsdata *fsdata);
void (*new_request)(struct pnfs_layout_segment *lseg,
struct nfs_page *req, loff_t pos, unsigned count,
struct pnfs_fsdata *fsdata);
--
1.6.6.1


2010-05-05 03:07:58

by Fred Isaman

[permalink] [raw]
Subject: [PATCH 3/8] SQUASHME: pnfs_submit: Revert "pnfs: propagate fsdata into nfs_create_request"

This reverts commit 4c33e93770316cfa71e2c39965e344a0cc068c65.

fsdata is not used by the file layout
---
fs/nfs/file.c | 4 ++--
fs/nfs/pagelist.c | 2 +-
fs/nfs/read.c | 4 ++--
fs/nfs/write.c | 20 +++++++++-----------
include/linux/nfs_fs.h | 3 +--
include/linux/nfs_page.h | 3 +--
6 files changed, 16 insertions(+), 20 deletions(-)

diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 4398953..38bc81f 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -487,7 +487,7 @@ static int nfs_write_end(struct file *file, struct address_space *mapping,
zero_user_segment(page, pglen, PAGE_CACHE_SIZE);
}

- status = nfs_updatepage(file, page, offset, copied, fsdata);
+ status = nfs_updatepage(file, page, offset, copied);

unlock_page(page);
page_cache_release(page);
@@ -608,7 +608,7 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
if (ret != 0)
goto out_unlock;

- ret = nfs_updatepage(filp, page, 0, pagelen, NULL);
+ ret = nfs_updatepage(filp, page, 0, pagelen);
out_unlock:
if (!ret)
return VM_FAULT_LOCKED;
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 3584b6a..bfc9da7 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -56,7 +56,7 @@ nfs_page_free(struct nfs_page *p)
struct nfs_page *
nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
struct page *page,
- unsigned int offset, unsigned int count, void *fsdata)
+ unsigned int offset, unsigned int count)
{
struct nfs_page *req;

diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index fd8bac7..d2cf82e 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -125,7 +125,7 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
len = nfs_page_length(page);
if (len == 0)
return nfs_return_empty_page(page);
- new = nfs_create_request(ctx, inode, page, 0, len, NULL);
+ new = nfs_create_request(ctx, inode, page, 0, len);
if (IS_ERR(new)) {
unlock_page(page);
return PTR_ERR(new);
@@ -606,7 +606,7 @@ readpage_async_filler(void *data, struct page *page)
if (len == 0)
return nfs_return_empty_page(page);

- new = nfs_create_request(desc->ctx, inode, page, 0, len, NULL);
+ new = nfs_create_request(desc->ctx, inode, page, 0, len);
if (IS_ERR(new))
goto out_error;

diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 38e542a..9aa9dae 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -570,8 +570,7 @@ static inline int nfs_scan_commit(struct inode *inode, struct list_head *dst, pg
static struct nfs_page *nfs_try_to_update_request(struct inode *inode,
struct page *page,
unsigned int offset,
- unsigned int bytes,
- void *fsdata)
+ unsigned int bytes)
{
struct nfs_page *req;
unsigned int rqend;
@@ -598,7 +597,7 @@ static struct nfs_page *nfs_try_to_update_request(struct inode *inode,
*/
if (offset > rqend
|| end < req->wb_offset
- || pnfs_do_flush(req, fsdata))
+ || pnfs_do_flush(req, NULL))
goto out_flushme;

if (nfs_set_page_tag_locked(req))
@@ -646,17 +645,16 @@ out_err:
* already called nfs_flush_incompatible() if necessary.
*/
static struct nfs_page * nfs_setup_write_request(struct nfs_open_context* ctx,
- struct page *page, unsigned int offset, unsigned int bytes,
- void *fsdata)
+ struct page *page, unsigned int offset, unsigned int bytes)
{
struct inode *inode = page->mapping->host;
struct nfs_page *req;
int error;

- req = nfs_try_to_update_request(inode, page, offset, bytes, fsdata);
+ req = nfs_try_to_update_request(inode, page, offset, bytes);
if (req != NULL)
goto out;
- req = nfs_create_request(ctx, inode, page, offset, bytes, fsdata);
+ req = nfs_create_request(ctx, inode, page, offset, bytes);
if (IS_ERR(req))
goto out;
error = nfs_inode_add_request(inode, req);
@@ -669,11 +667,11 @@ out:
}

static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page,
- unsigned int offset, unsigned int count, void *fsdata)
+ unsigned int offset, unsigned int count)
{
struct nfs_page *req;

- req = nfs_setup_write_request(ctx, page, offset, count, fsdata);
+ req = nfs_setup_write_request(ctx, page, offset, count);
if (IS_ERR(req))
return PTR_ERR(req);
nfs_mark_request_dirty(req);
@@ -730,7 +728,7 @@ static int nfs_write_pageuptodate(struct page *page, struct inode *inode)
* things with a page scheduled for an RPC call (e.g. invalidate it).
*/
int nfs_updatepage(struct file *file, struct page *page,
- unsigned int offset, unsigned int count, void *fsdata)
+ unsigned int offset, unsigned int count)
{
struct nfs_open_context *ctx = nfs_file_open_context(file);
struct inode *inode = page->mapping->host;
@@ -755,7 +753,7 @@ int nfs_updatepage(struct file *file, struct page *page,
offset = 0;
}

- status = nfs_writepage_setup(ctx, page, offset, count, fsdata);
+ status = nfs_writepage_setup(ctx, page, offset, count);
if (status < 0)
nfs_set_pageerror(page);

diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 68b3b5c..98a8dc0 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -504,8 +504,7 @@ extern int nfs_congestion_kb;
extern int nfs_writepage(struct page *page, struct writeback_control *wbc);
extern int nfs_writepages(struct address_space *, struct writeback_control *);
extern int nfs_flush_incompatible(struct file *file, struct page *page);
-extern int nfs_updatepage(struct file *, struct page *, unsigned int,
- unsigned int, void *);
+extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int);
extern int nfs_writeback_done(struct rpc_task *, struct nfs_write_data *);

/*
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index 821f871..df93480 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -75,8 +75,7 @@ extern struct nfs_page *nfs_create_request(struct nfs_open_context *ctx,
struct inode *inode,
struct page *page,
unsigned int offset,
- unsigned int count,
- void *fsdata);
+ unsigned int count);
extern void nfs_clear_request(struct nfs_page *req);
extern void nfs_release_request(struct nfs_page *req);

--
1.6.6.1


2010-05-05 03:07:58

by Fred Isaman

[permalink] [raw]
Subject: [PATCH 2/8] SQUASHME: pnfs_submit: Revert "pnfs: pnfs_modify_new_request"

This reverts commit 0b10c9be0ad8e2da1f21dafc5e4526b50710c977.

This is not used by the file layout driver.

Conflicts:

fs/nfs/pnfs.h

Signed-off-by: Fred Isaman <[email protected]>
---
fs/nfs/pagelist.c | 2 --
fs/nfs/pnfs.c | 19 -------------------
fs/nfs/pnfs.h | 15 ---------------
include/linux/nfs4_pnfs.h | 3 ---
4 files changed, 0 insertions(+), 39 deletions(-)

diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 3a1d673..3584b6a 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -20,7 +20,6 @@
#include <linux/nfs_mount.h>

#include "internal.h"
-#include "pnfs.h"

static struct kmem_cache *nfs_page_cachep;

@@ -87,7 +86,6 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
req->wb_bytes = count;
req->wb_context = get_nfs_open_context(ctx);
kref_init(&req->wb_kref);
- pnfs_modify_new_request(req, fsdata);
return req;
}

diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 46fe088..ce6ca4b 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -2245,25 +2245,6 @@ out_unlock:
goto out;
}

-/* Note that fsdata != NULL */
-void _pnfs_modify_new_write_request(struct nfs_page *req,
- struct pnfs_fsdata *fsdata)
-{
- struct inode *inode = req->wb_page->mapping->host;
- struct pnfs_layout_segment *lseg = NULL;
- loff_t pos;
- unsigned count;
-
- pos = ((loff_t)req->wb_index << PAGE_CACHE_SHIFT) + req->wb_offset;
- count = req->wb_bytes;
- lseg = pnfs_find_get_lseg(inode, pos, count, IOMODE_RW);
- if (lseg) {
- if (fsdata->ok_to_use_pnfs)
- set_bit(PG_USE_PNFS, &req->wb_flags);
- put_lseg(lseg);
- }
-}
-
void pnfs_free_fsdata(struct pnfs_fsdata *fsdata)
{
if (fsdata) {
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 1c94984..8d37dfb 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -78,8 +78,6 @@ int _pnfs_write_begin(struct inode *inode, struct page *page,
struct pnfs_fsdata **fsdata);
int _pnfs_do_flush(struct inode *inode, struct nfs_page *req,
struct pnfs_fsdata *fsdata);
-void _pnfs_modify_new_write_request(struct nfs_page *req,
- struct pnfs_fsdata *fsdata);
void _pnfs_direct_init_io(struct inode *inode, struct nfs_open_context *ctx,
size_t count, loff_t loff, int iswrite,
size_t *rwsize, size_t *remaining);
@@ -207,14 +205,6 @@ static inline void pnfs_redirty_request(struct nfs_page *req)
clear_bit(PG_USE_PNFS, &req->wb_flags);
}

-static inline void pnfs_modify_new_request(struct nfs_page *req,
- void *fsdata)
-{
- if (fsdata)
- _pnfs_modify_new_write_request(req, fsdata);
- /* Should we do something (like set PG_USE_PNFS) if !fsdata ? */
-}
-
static inline int pnfs_return_layout(struct inode *ino,
struct nfs4_pnfs_layout_segment *lseg,
const nfs4_stateid *stateid, /* optional */
@@ -304,11 +294,6 @@ static inline void pnfs_redirty_request(struct nfs_page *req)
{
}

-static inline void pnfs_modify_new_request(struct nfs_page *req,
- void *fsdata)
-{
-}
-
static inline int pnfs_get_write_status(struct nfs_write_data *data)
{
return 0;
diff --git a/include/linux/nfs4_pnfs.h b/include/linux/nfs4_pnfs.h
index e01a065..1ba0590 100644
--- a/include/linux/nfs4_pnfs.h
+++ b/include/linux/nfs4_pnfs.h
@@ -142,9 +142,6 @@ struct layoutdriver_io_operations {
int (*write_begin) (struct pnfs_layout_segment *lseg, struct page *page,
loff_t pos, unsigned count,
struct pnfs_fsdata *fsdata);
- void (*new_request)(struct pnfs_layout_segment *lseg,
- struct nfs_page *req, loff_t pos, unsigned count,
- struct pnfs_fsdata *fsdata);

/* Consistency ops */
/* 2 problems:
--
1.6.6.1


2010-05-05 03:07:59

by Fred Isaman

[permalink] [raw]
Subject: [PATCH 5/8] pnfs_post_submit: Restore "pnfs: pnfs_do_flush"

From: Fred Isaman <[email protected]>

pnfs: pnfs_do_flush

Adds a hook into the "check if request needs flushed" routines.
This will be needed to allow driver the ability to prevent comingling
of layout driver handled requests and fallback nfs requests.

Signed-off-by: Fred Isaman <[email protected]>
[pnfs: prevent offset overflow in _pnfs_do_flush]
[pnfs: pnfs_has_layout take_ref parameter should be bool]
[pnfs: clean up put_unlock_current_layout's interface]
[pnfs: introduce lseg valid bit]
Signed-off-by: Benny Halevy <[email protected]>

Signed-off-by: Fred Isaman <[email protected]>
---
fs/nfs/file.c | 14 ++++++-
fs/nfs/pnfs.c | 95 +++++++++++++++++++++++++++++++++++++++++++++
fs/nfs/pnfs.h | 58 +++++++++++++++++++++++++++
fs/nfs/write.c | 6 ++-
include/linux/nfs4_pnfs.h | 12 ++++++
5 files changed, 181 insertions(+), 4 deletions(-)

diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 3ec9abb..38bc81f 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -433,8 +433,7 @@ start:

ret = nfs_flush_incompatible(file, page);
if (ret) {
- unlock_page(page);
- page_cache_release(page);
+ goto out_err;
} else if (!once_thru &&
nfs_want_read_modify_write(file, page, pos, len)) {
once_thru = 1;
@@ -442,8 +441,18 @@ start:
page_cache_release(page);
if (!ret)
goto start;
+ } else {
+ ret = pnfs_write_begin(file, page, pos, len, fsdata);
+ if (ret)
+ goto out_err;
}
return ret;
+
+ out_err:
+ unlock_page(page);
+ page_cache_release(page);
+ *pagep = NULL;
+ return ret;
}

static int nfs_write_end(struct file *file, struct address_space *mapping,
@@ -482,6 +491,7 @@ static int nfs_write_end(struct file *file, struct address_space *mapping,

unlock_page(page);
page_cache_release(page);
+ pnfs_write_end_cleanup(fsdata);

if (status < 0)
return status;
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 7289593..ce6ca4b 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1009,6 +1009,30 @@ pnfs_has_layout(struct pnfs_layout_type *lo,
return ret;
}

+static struct pnfs_layout_segment *
+pnfs_find_get_lseg(struct inode *inode,
+ loff_t pos,
+ size_t count,
+ enum pnfs_iomode iomode)
+{
+ struct nfs_inode *nfsi = NFS_I(inode);
+ struct pnfs_layout_segment *lseg;
+ struct pnfs_layout_type *lo;
+ struct nfs4_pnfs_layout_segment range;
+
+ dprintk("%s:Begin\n", __func__);
+ lo = get_lock_current_layout(nfsi);
+ if (!lo)
+ return NULL;
+ range.iomode = iomode;
+ range.offset = pos;
+ range.length = count;
+ lseg = pnfs_has_layout(lo, &range, true, true);
+ put_unlock_current_layout(lo);
+ dprintk("%s:Return lseg %p", __func__, lseg);
+ return lseg;
+}
+
/* Called with spin lock held */
void drain_layoutreturns(struct pnfs_layout_type *lo)
{
@@ -1898,6 +1922,69 @@ _pnfs_try_to_read_data(struct nfs_read_data *data,
}
}

+/*
+ * This gives the layout driver an opportunity to read in page "around"
+ * the data to be written. It returns 0 on success, otherwise an error code
+ * which will either be passed up to user, or ignored if
+ * some previous part of write succeeded.
+ * Note the range [pos, pos+len-1] is entirely within the page.
+ */
+int _pnfs_write_begin(struct inode *inode, struct page *page,
+ loff_t pos, unsigned len, struct pnfs_fsdata **fsdata)
+{
+ struct pnfs_layout_segment *lseg;
+ int status = 0;
+
+ dprintk("--> %s: pos=%llu len=%u\n",
+ __func__, (unsigned long long)pos, len);
+ status = pnfs_update_layout(inode,
+ NULL,
+ len,
+ pos,
+ IOMODE_RW,
+ &lseg);
+ if (status)
+ goto out;
+ *fsdata = kzalloc(sizeof(struct pnfs_fsdata), GFP_KERNEL);
+ if (!*fsdata) {
+ status = -ENOMEM;
+ goto out_put;
+ }
+ status = NFS_SERVER(inode)->pnfs_curr_ld->ld_io_ops->write_begin(
+ lseg, page, pos, len, *fsdata);
+ if (!status) {
+ (*fsdata)->lseg = lseg;
+ goto out;
+ }
+ kfree(*fsdata);
+ *fsdata = NULL;
+out_put:
+ put_lseg(lseg);
+out:
+ dprintk("<-- %s: status=%d\n", __func__, status);
+ return status;
+}
+
+/* Given an nfs request, determine if it should be flushed before proceeding.
+ * It should default to returning False, returning True only if there is a
+ * specific reason to flush.
+ */
+int _pnfs_do_flush(struct inode *inode, struct nfs_page *req,
+ struct pnfs_fsdata *fsdata)
+{
+ struct nfs_server *nfss = NFS_SERVER(inode);
+ struct pnfs_layout_segment *lseg;
+ loff_t pos = ((loff_t)req->wb_index << PAGE_CACHE_SHIFT) + req->wb_offset;
+ int status = 0;
+
+ lseg = pnfs_find_get_lseg(inode, pos, req->wb_bytes, IOMODE_RW);
+ /* Note that lseg==NULL may be useful info for do_flush */
+ status = nfss->pnfs_curr_ld->ld_policy_ops->do_flush(lseg, req,
+ fsdata);
+ put_lseg(lseg);
+ return status;
+}
+
enum pnfs_try_status
_pnfs_try_to_write_data(struct nfs_write_data *data,
const struct rpc_call_ops *call_ops, int how)
@@ -2158,6 +2245,14 @@ out_unlock:
goto out;
}

+void pnfs_free_fsdata(struct pnfs_fsdata *fsdata)
+{
+ if (fsdata) {
+ put_lseg(fsdata->lseg);
+ kfree(fsdata);
+ }
+}
+
/* Callback operations for layout drivers.
*/
struct pnfs_client_operations pnfs_ops = {
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 2d8cf4f..8d37dfb 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -64,6 +64,7 @@ enum pnfs_try_status _pnfs_try_to_commit(struct nfs_write_data *,
void pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *, struct nfs_open_context *, struct list_head *, size_t *);
void pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *, size_t *wsize);
void pnfs_update_layout_commit(struct inode *, struct list_head *, pgoff_t, unsigned int);
+void pnfs_free_fsdata(struct pnfs_fsdata *fsdata);
ssize_t pnfs_file_write(struct file *, const char __user *, size_t, loff_t *);
void pnfs_get_layout_done(struct nfs4_pnfs_layoutget *, int rpc_status);
int pnfs_layout_process(struct nfs4_pnfs_layoutget *lgp);
@@ -72,6 +73,11 @@ void pnfs_layout_release(struct pnfs_layout_type *, atomic_t *,
void pnfs_set_layout_stateid(struct pnfs_layout_type *lo,
const nfs4_stateid *stateid);
void pnfs_destroy_layout(struct nfs_inode *);
+int _pnfs_write_begin(struct inode *inode, struct page *page,
+ loff_t pos, unsigned len,
+ struct pnfs_fsdata **fsdata);
+int _pnfs_do_flush(struct inode *inode, struct nfs_page *req,
+ struct pnfs_fsdata *fsdata);
void _pnfs_direct_init_io(struct inode *inode, struct nfs_open_context *ctx,
size_t count, loff_t loff, int iswrite,
size_t *rwsize, size_t *remaining);
@@ -157,6 +163,43 @@ pnfs_try_to_commit(struct nfs_write_data *data,
return ret;
}

+static inline int pnfs_write_begin(struct file *filp, struct page *page,
+ loff_t pos, unsigned len, void **fsdata)
+{
+ struct inode *inode = filp->f_dentry->d_inode;
+ struct nfs_server *nfss = NFS_SERVER(inode);
+ int status = 0;
+
+ *fsdata = NULL;
+ if (PNFS_EXISTS_LDIO_OP(nfss, write_begin))
+ status = _pnfs_write_begin(inode, page, pos, len,
+ (struct pnfs_fsdata **) fsdata);
+ return status;
+}
+
+/* req may not be locked, so we have to be prepared for req->wb_page being
+ * set to NULL at any time.
+ */
+static inline int pnfs_do_flush(struct nfs_page *req, void *fsdata)
+{
+ struct page *page = req->wb_page;
+ struct inode *inode;
+
+ if (!page)
+ return 1;
+ inode = page->mapping->host;
+
+ if (PNFS_EXISTS_LDPOLICY_OP(NFS_SERVER(inode), do_flush))
+ return _pnfs_do_flush(inode, req, fsdata);
+ else
+ return 0;
+}
+
+static inline void pnfs_write_end_cleanup(void *fsdata)
+{
+ pnfs_free_fsdata(fsdata);
+}
+
static inline void pnfs_redirty_request(struct nfs_page *req)
{
clear_bit(PG_USE_PNFS, &req->wb_flags);
@@ -232,6 +275,21 @@ pnfs_try_to_commit(struct nfs_write_data *data,
return PNFS_NOT_ATTEMPTED;
}

+static inline int pnfs_do_flush(struct nfs_page *req, void *fsdata)
+{
+ return 0;
+}
+
+static inline int pnfs_write_begin(struct file *filp, struct page *page,
+ loff_t pos, unsigned len, void **fsdata)
+{
+ return 0;
+}
+
+static inline void pnfs_write_end_cleanup(void *fsdata)
+{
+}
+
static inline void pnfs_redirty_request(struct nfs_page *req)
{
}
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index c97a3ab..9aa9dae 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -596,7 +596,8 @@ static struct nfs_page *nfs_try_to_update_request(struct inode *inode,
* have flushed out requests having wrong owners.
*/
if (offset > rqend
- || end < req->wb_offset)
+ || end < req->wb_offset
+ || pnfs_do_flush(req, NULL))
goto out_flushme;

if (nfs_set_page_tag_locked(req))
@@ -699,7 +700,8 @@ int nfs_flush_incompatible(struct file *file, struct page *page)
req = nfs_page_find_request(page);
if (req == NULL)
return 0;
- do_flush = req->wb_page != page || req->wb_context != ctx;
+ do_flush = req->wb_page != page || req->wb_context != ctx ||
+ pnfs_do_flush(req, NULL);
nfs_release_request(req);
if (!do_flush)
return 0;
diff --git a/include/linux/nfs4_pnfs.h b/include/linux/nfs4_pnfs.h
index d4da067..1ba0590 100644
--- a/include/linux/nfs4_pnfs.h
+++ b/include/linux/nfs4_pnfs.h
@@ -37,6 +37,11 @@ struct pnfs_mount_type {
void *mountid;
};

+struct pnfs_fsdata {
+ int ok_to_use_pnfs;
+ struct pnfs_layout_segment *lseg;
+};
+
#if defined(CONFIG_NFS_V4_1)

static inline struct nfs_inode *
@@ -134,6 +139,9 @@ struct layoutdriver_io_operations {
struct page **pages, unsigned int pgbase,
unsigned nr_pages, loff_t offset, size_t count,
int sync, struct nfs_write_data *nfs_data);
+ int (*write_begin) (struct pnfs_layout_segment *lseg, struct page *page,
+ loff_t pos, unsigned count,
+ struct pnfs_fsdata *fsdata);

/* Consistency ops */
/* 2 problems:
@@ -196,6 +204,10 @@ struct layoutdriver_policy_operations {
/* test for nfs page cache coalescing */
int (*pg_test)(struct nfs_pageio_descriptor *, struct nfs_page *, struct nfs_page *);

+ /* Test for pre-write request flushing */
+ int (*do_flush)(struct pnfs_layout_segment *lseg, struct nfs_page *req,
+ struct pnfs_fsdata *fsdata);
+
/* Retreive the block size of the file system. If gather_across_stripes == 1,
* then the file system will gather requests into the block size.
* TODO: Where will the layout driver get this info? It is hard coded in PVFS2.
--
1.6.6.1


2010-05-05 03:07:58

by Fred Isaman

[permalink] [raw]
Subject: [PATCH 4/8] SQUASHME: pnfs_submit: Revert "pnfs: pnfs_do_flush"

This reverts commit f61a5fb1508434b904f9382ba9488d1be4e6ac79.

pnfs_write_begin, fsdata handling, and pnfs_do_flush are not used by
the layout driver.

Conflicts:

fs/nfs/pnfs.c
fs/nfs/pnfs.h

Signed-off-by: Fred Isaman <[email protected]>
---
fs/nfs/file.c | 14 +------
fs/nfs/pnfs.c | 95 ---------------------------------------------
fs/nfs/pnfs.h | 58 ---------------------------
fs/nfs/write.c | 6 +--
include/linux/nfs4_pnfs.h | 12 ------
5 files changed, 4 insertions(+), 181 deletions(-)

diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 38bc81f..3ec9abb 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -433,7 +433,8 @@ start:

ret = nfs_flush_incompatible(file, page);
if (ret) {
- goto out_err;
+ unlock_page(page);
+ page_cache_release(page);
} else if (!once_thru &&
nfs_want_read_modify_write(file, page, pos, len)) {
once_thru = 1;
@@ -441,18 +442,8 @@ start:
page_cache_release(page);
if (!ret)
goto start;
- } else {
- ret = pnfs_write_begin(file, page, pos, len, fsdata);
- if (ret)
- goto out_err;
}
return ret;
-
- out_err:
- unlock_page(page);
- page_cache_release(page);
- *pagep = NULL;
- return ret;
}

static int nfs_write_end(struct file *file, struct address_space *mapping,
@@ -491,7 +482,6 @@ static int nfs_write_end(struct file *file, struct address_space *mapping,

unlock_page(page);
page_cache_release(page);
- pnfs_write_end_cleanup(fsdata);

if (status < 0)
return status;
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index ce6ca4b..7289593 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1009,30 +1009,6 @@ pnfs_has_layout(struct pnfs_layout_type *lo,
return ret;
}

-static struct pnfs_layout_segment *
-pnfs_find_get_lseg(struct inode *inode,
- loff_t pos,
- size_t count,
- enum pnfs_iomode iomode)
-{
- struct nfs_inode *nfsi = NFS_I(inode);
- struct pnfs_layout_segment *lseg;
- struct pnfs_layout_type *lo;
- struct nfs4_pnfs_layout_segment range;
-
- dprintk("%s:Begin\n", __func__);
- lo = get_lock_current_layout(nfsi);
- if (!lo)
- return NULL;
- range.iomode = iomode;
- range.offset = pos;
- range.length = count;
- lseg = pnfs_has_layout(lo, &range, true, true);
- put_unlock_current_layout(lo);
- dprintk("%s:Return lseg %p", __func__, lseg);
- return lseg;
-}
-
/* Called with spin lock held */
void drain_layoutreturns(struct pnfs_layout_type *lo)
{
@@ -1922,69 +1898,6 @@ _pnfs_try_to_read_data(struct nfs_read_data *data,
}
}

-/*
- * This gives the layout driver an opportunity to read in page "around"
- * the data to be written. It returns 0 on success, otherwise an error code
- * which will either be passed up to user, or ignored if
- * some previous part of write succeeded.
- * Note the range [pos, pos+len-1] is entirely within the page.
- */
-int _pnfs_write_begin(struct inode *inode, struct page *page,
- loff_t pos, unsigned len, struct pnfs_fsdata **fsdata)
-{
- struct pnfs_layout_segment *lseg;
- int status = 0;
-
- dprintk("--> %s: pos=%llu len=%u\n",
- __func__, (unsigned long long)pos, len);
- status = pnfs_update_layout(inode,
- NULL,
- len,
- pos,
- IOMODE_RW,
- &lseg);
- if (status)
- goto out;
- *fsdata = kzalloc(sizeof(struct pnfs_fsdata), GFP_KERNEL);
- if (!*fsdata) {
- status = -ENOMEM;
- goto out_put;
- }
- status = NFS_SERVER(inode)->pnfs_curr_ld->ld_io_ops->write_begin(
- lseg, page, pos, len, *fsdata);
- if (!status) {
- (*fsdata)->lseg = lseg;
- goto out;
- }
- kfree(*fsdata);
- *fsdata = NULL;
-out_put:
- put_lseg(lseg);
-out:
- dprintk("<-- %s: status=%d\n", __func__, status);
- return status;
-}
-
-/* Given an nfs request, determine if it should be flushed before proceeding.
- * It should default to returning False, returning True only if there is a
- * specific reason to flush.
- */
-int _pnfs_do_flush(struct inode *inode, struct nfs_page *req,
- struct pnfs_fsdata *fsdata)
-{
- struct nfs_server *nfss = NFS_SERVER(inode);
- struct pnfs_layout_segment *lseg;
- loff_t pos = ((loff_t)req->wb_index << PAGE_CACHE_SHIFT) + req->wb_offset;
- int status = 0;
-
- lseg = pnfs_find_get_lseg(inode, pos, req->wb_bytes, IOMODE_RW);
- /* Note that lseg==NULL may be useful info for do_flush */
- status = nfss->pnfs_curr_ld->ld_policy_ops->do_flush(lseg, req,
- fsdata);
- put_lseg(lseg);
- return status;
-}
-
enum pnfs_try_status
_pnfs_try_to_write_data(struct nfs_write_data *data,
const struct rpc_call_ops *call_ops, int how)
@@ -2245,14 +2158,6 @@ out_unlock:
goto out;
}

-void pnfs_free_fsdata(struct pnfs_fsdata *fsdata)
-{
- if (fsdata) {
- put_lseg(fsdata->lseg);
- kfree(fsdata);
- }
-}
-
/* Callback operations for layout drivers.
*/
struct pnfs_client_operations pnfs_ops = {
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 8d37dfb..2d8cf4f 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -64,7 +64,6 @@ enum pnfs_try_status _pnfs_try_to_commit(struct nfs_write_data *,
void pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *, struct nfs_open_context *, struct list_head *, size_t *);
void pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *, size_t *wsize);
void pnfs_update_layout_commit(struct inode *, struct list_head *, pgoff_t, unsigned int);
-void pnfs_free_fsdata(struct pnfs_fsdata *fsdata);
ssize_t pnfs_file_write(struct file *, const char __user *, size_t, loff_t *);
void pnfs_get_layout_done(struct nfs4_pnfs_layoutget *, int rpc_status);
int pnfs_layout_process(struct nfs4_pnfs_layoutget *lgp);
@@ -73,11 +72,6 @@ void pnfs_layout_release(struct pnfs_layout_type *, atomic_t *,
void pnfs_set_layout_stateid(struct pnfs_layout_type *lo,
const nfs4_stateid *stateid);
void pnfs_destroy_layout(struct nfs_inode *);
-int _pnfs_write_begin(struct inode *inode, struct page *page,
- loff_t pos, unsigned len,
- struct pnfs_fsdata **fsdata);
-int _pnfs_do_flush(struct inode *inode, struct nfs_page *req,
- struct pnfs_fsdata *fsdata);
void _pnfs_direct_init_io(struct inode *inode, struct nfs_open_context *ctx,
size_t count, loff_t loff, int iswrite,
size_t *rwsize, size_t *remaining);
@@ -163,43 +157,6 @@ pnfs_try_to_commit(struct nfs_write_data *data,
return ret;
}

-static inline int pnfs_write_begin(struct file *filp, struct page *page,
- loff_t pos, unsigned len, void **fsdata)
-{
- struct inode *inode = filp->f_dentry->d_inode;
- struct nfs_server *nfss = NFS_SERVER(inode);
- int status = 0;
-
- *fsdata = NULL;
- if (PNFS_EXISTS_LDIO_OP(nfss, write_begin))
- status = _pnfs_write_begin(inode, page, pos, len,
- (struct pnfs_fsdata **) fsdata);
- return status;
-}
-
-/* req may not be locked, so we have to be prepared for req->wb_page being
- * set to NULL at any time.
- */
-static inline int pnfs_do_flush(struct nfs_page *req, void *fsdata)
-{
- struct page *page = req->wb_page;
- struct inode *inode;
-
- if (!page)
- return 1;
- inode = page->mapping->host;
-
- if (PNFS_EXISTS_LDPOLICY_OP(NFS_SERVER(inode), do_flush))
- return _pnfs_do_flush(inode, req, fsdata);
- else
- return 0;
-}
-
-static inline void pnfs_write_end_cleanup(void *fsdata)
-{
- pnfs_free_fsdata(fsdata);
-}
-
static inline void pnfs_redirty_request(struct nfs_page *req)
{
clear_bit(PG_USE_PNFS, &req->wb_flags);
@@ -275,21 +232,6 @@ pnfs_try_to_commit(struct nfs_write_data *data,
return PNFS_NOT_ATTEMPTED;
}

-static inline int pnfs_do_flush(struct nfs_page *req, void *fsdata)
-{
- return 0;
-}
-
-static inline int pnfs_write_begin(struct file *filp, struct page *page,
- loff_t pos, unsigned len, void **fsdata)
-{
- return 0;
-}
-
-static inline void pnfs_write_end_cleanup(void *fsdata)
-{
-}
-
static inline void pnfs_redirty_request(struct nfs_page *req)
{
}
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 9aa9dae..c97a3ab 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -596,8 +596,7 @@ static struct nfs_page *nfs_try_to_update_request(struct inode *inode,
* have flushed out requests having wrong owners.
*/
if (offset > rqend
- || end < req->wb_offset
- || pnfs_do_flush(req, NULL))
+ || end < req->wb_offset)
goto out_flushme;

if (nfs_set_page_tag_locked(req))
@@ -700,8 +699,7 @@ int nfs_flush_incompatible(struct file *file, struct page *page)
req = nfs_page_find_request(page);
if (req == NULL)
return 0;
- do_flush = req->wb_page != page || req->wb_context != ctx ||
- pnfs_do_flush(req, NULL);
+ do_flush = req->wb_page != page || req->wb_context != ctx;
nfs_release_request(req);
if (!do_flush)
return 0;
diff --git a/include/linux/nfs4_pnfs.h b/include/linux/nfs4_pnfs.h
index 1ba0590..d4da067 100644
--- a/include/linux/nfs4_pnfs.h
+++ b/include/linux/nfs4_pnfs.h
@@ -37,11 +37,6 @@ struct pnfs_mount_type {
void *mountid;
};

-struct pnfs_fsdata {
- int ok_to_use_pnfs;
- struct pnfs_layout_segment *lseg;
-};
-
#if defined(CONFIG_NFS_V4_1)

static inline struct nfs_inode *
@@ -139,9 +134,6 @@ struct layoutdriver_io_operations {
struct page **pages, unsigned int pgbase,
unsigned nr_pages, loff_t offset, size_t count,
int sync, struct nfs_write_data *nfs_data);
- int (*write_begin) (struct pnfs_layout_segment *lseg, struct page *page,
- loff_t pos, unsigned count,
- struct pnfs_fsdata *fsdata);

/* Consistency ops */
/* 2 problems:
@@ -204,10 +196,6 @@ struct layoutdriver_policy_operations {
/* test for nfs page cache coalescing */
int (*pg_test)(struct nfs_pageio_descriptor *, struct nfs_page *, struct nfs_page *);

- /* Test for pre-write request flushing */
- int (*do_flush)(struct pnfs_layout_segment *lseg, struct nfs_page *req,
- struct pnfs_fsdata *fsdata);
-
/* Retreive the block size of the file system. If gather_across_stripes == 1,
* then the file system will gather requests into the block size.
* TODO: Where will the layout driver get this info? It is hard coded in PVFS2.
--
1.6.6.1


2010-05-05 03:07:59

by Fred Isaman

[permalink] [raw]
Subject: [PATCH 6/8] pnfs_post_submit: Restore "pnfs: propagate fsdata into nfs_create_request"

From: Fred Isaman <[email protected]>

pnfs: propagate fsdata into nfs_create_request

Now that layout drivers can pass information into nfs_write_end via
fsdata, the natural place to use that data is in nfs_create_request.
So propagate fsdata into nfs_create_request.

Signed-off-by: Fred Isaman <[email protected]>
Signed-off-by: Benny Halevy <[email protected]>

Pass NULL fsdata to nfs_updatepage from nfs_vm_page_mkwrite
as this path does not go through write_{begin,end}

Signed-off-by: Benny Halevy <[email protected]>
Signed-off-by: Fred Isaman <[email protected]>
---
fs/nfs/file.c | 4 ++--
fs/nfs/pagelist.c | 2 +-
fs/nfs/read.c | 4 ++--
fs/nfs/write.c | 20 +++++++++++---------
include/linux/nfs_fs.h | 3 ++-
include/linux/nfs_page.h | 3 ++-
6 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 38bc81f..4398953 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -487,7 +487,7 @@ static int nfs_write_end(struct file *file, struct address_space *mapping,
zero_user_segment(page, pglen, PAGE_CACHE_SIZE);
}

- status = nfs_updatepage(file, page, offset, copied);
+ status = nfs_updatepage(file, page, offset, copied, fsdata);

unlock_page(page);
page_cache_release(page);
@@ -608,7 +608,7 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
if (ret != 0)
goto out_unlock;

- ret = nfs_updatepage(filp, page, 0, pagelen);
+ ret = nfs_updatepage(filp, page, 0, pagelen, NULL);
out_unlock:
if (!ret)
return VM_FAULT_LOCKED;
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index bfc9da7..3584b6a 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -56,7 +56,7 @@ nfs_page_free(struct nfs_page *p)
struct nfs_page *
nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
struct page *page,
- unsigned int offset, unsigned int count)
+ unsigned int offset, unsigned int count, void *fsdata)
{
struct nfs_page *req;

diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index d2cf82e..fd8bac7 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -125,7 +125,7 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
len = nfs_page_length(page);
if (len == 0)
return nfs_return_empty_page(page);
- new = nfs_create_request(ctx, inode, page, 0, len);
+ new = nfs_create_request(ctx, inode, page, 0, len, NULL);
if (IS_ERR(new)) {
unlock_page(page);
return PTR_ERR(new);
@@ -606,7 +606,7 @@ readpage_async_filler(void *data, struct page *page)
if (len == 0)
return nfs_return_empty_page(page);

- new = nfs_create_request(desc->ctx, inode, page, 0, len);
+ new = nfs_create_request(desc->ctx, inode, page, 0, len, NULL);
if (IS_ERR(new))
goto out_error;

diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 9aa9dae..38e542a 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -570,7 +570,8 @@ static inline int nfs_scan_commit(struct inode *inode, struct list_head *dst, pg
static struct nfs_page *nfs_try_to_update_request(struct inode *inode,
struct page *page,
unsigned int offset,
- unsigned int bytes)
+ unsigned int bytes,
+ void *fsdata)
{
struct nfs_page *req;
unsigned int rqend;
@@ -597,7 +598,7 @@ static struct nfs_page *nfs_try_to_update_request(struct inode *inode,
*/
if (offset > rqend
|| end < req->wb_offset
- || pnfs_do_flush(req, NULL))
+ || pnfs_do_flush(req, fsdata))
goto out_flushme;

if (nfs_set_page_tag_locked(req))
@@ -645,16 +646,17 @@ out_err:
* already called nfs_flush_incompatible() if necessary.
*/
static struct nfs_page * nfs_setup_write_request(struct nfs_open_context* ctx,
- struct page *page, unsigned int offset, unsigned int bytes)
+ struct page *page, unsigned int offset, unsigned int bytes,
+ void *fsdata)
{
struct inode *inode = page->mapping->host;
struct nfs_page *req;
int error;

- req = nfs_try_to_update_request(inode, page, offset, bytes);
+ req = nfs_try_to_update_request(inode, page, offset, bytes, fsdata);
if (req != NULL)
goto out;
- req = nfs_create_request(ctx, inode, page, offset, bytes);
+ req = nfs_create_request(ctx, inode, page, offset, bytes, fsdata);
if (IS_ERR(req))
goto out;
error = nfs_inode_add_request(inode, req);
@@ -667,11 +669,11 @@ out:
}

static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page,
- unsigned int offset, unsigned int count)
+ unsigned int offset, unsigned int count, void *fsdata)
{
struct nfs_page *req;

- req = nfs_setup_write_request(ctx, page, offset, count);
+ req = nfs_setup_write_request(ctx, page, offset, count, fsdata);
if (IS_ERR(req))
return PTR_ERR(req);
nfs_mark_request_dirty(req);
@@ -728,7 +730,7 @@ static int nfs_write_pageuptodate(struct page *page, struct inode *inode)
* things with a page scheduled for an RPC call (e.g. invalidate it).
*/
int nfs_updatepage(struct file *file, struct page *page,
- unsigned int offset, unsigned int count)
+ unsigned int offset, unsigned int count, void *fsdata)
{
struct nfs_open_context *ctx = nfs_file_open_context(file);
struct inode *inode = page->mapping->host;
@@ -753,7 +755,7 @@ int nfs_updatepage(struct file *file, struct page *page,
offset = 0;
}

- status = nfs_writepage_setup(ctx, page, offset, count);
+ status = nfs_writepage_setup(ctx, page, offset, count, fsdata);
if (status < 0)
nfs_set_pageerror(page);

diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 98a8dc0..68b3b5c 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -504,7 +504,8 @@ extern int nfs_congestion_kb;
extern int nfs_writepage(struct page *page, struct writeback_control *wbc);
extern int nfs_writepages(struct address_space *, struct writeback_control *);
extern int nfs_flush_incompatible(struct file *file, struct page *page);
-extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int);
+extern int nfs_updatepage(struct file *, struct page *, unsigned int,
+ unsigned int, void *);
extern int nfs_writeback_done(struct rpc_task *, struct nfs_write_data *);

/*
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index df93480..821f871 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -75,7 +75,8 @@ extern struct nfs_page *nfs_create_request(struct nfs_open_context *ctx,
struct inode *inode,
struct page *page,
unsigned int offset,
- unsigned int count);
+ unsigned int count,
+ void *fsdata);
extern void nfs_clear_request(struct nfs_page *req);
extern void nfs_release_request(struct nfs_page *req);

--
1.6.6.1


2010-05-05 03:07:59

by Fred Isaman

[permalink] [raw]
Subject: [PATCH 7/8] pnfs_post_submit: Restore "pnfs: pnfs_modify_new_request"

From: Fred Isaman <[email protected]>

pnfs: pnfs_modify_new_request

Add hook into nfs_page initialization to allow for setting of
PG_USE_PNFS.

[pnfs: pass lseg from write_begin to write_end]
Signed-off-by: Fred Isaman <[email protected]>
Signed-off-by: Benny Halevy <[email protected]>

Signed-off-by: Fred Isaman <[email protected]>
---
fs/nfs/pagelist.c | 2 ++
fs/nfs/pnfs.c | 19 +++++++++++++++++++
fs/nfs/pnfs.h | 15 +++++++++++++++
include/linux/nfs4_pnfs.h | 3 +++
4 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 3584b6a..3a1d673 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -20,6 +20,7 @@
#include <linux/nfs_mount.h>

#include "internal.h"
+#include "pnfs.h"

static struct kmem_cache *nfs_page_cachep;

@@ -86,6 +87,7 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
req->wb_bytes = count;
req->wb_context = get_nfs_open_context(ctx);
kref_init(&req->wb_kref);
+ pnfs_modify_new_request(req, fsdata);
return req;
}

diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index ce6ca4b..46fe088 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -2245,6 +2245,25 @@ out_unlock:
goto out;
}

+/* Note that fsdata != NULL */
+void _pnfs_modify_new_write_request(struct nfs_page *req,
+ struct pnfs_fsdata *fsdata)
+{
+ struct inode *inode = req->wb_page->mapping->host;
+ struct pnfs_layout_segment *lseg = NULL;
+ loff_t pos;
+ unsigned count;
+
+ pos = ((loff_t)req->wb_index << PAGE_CACHE_SHIFT) + req->wb_offset;
+ count = req->wb_bytes;
+ lseg = pnfs_find_get_lseg(inode, pos, count, IOMODE_RW);
+ if (lseg) {
+ if (fsdata->ok_to_use_pnfs)
+ set_bit(PG_USE_PNFS, &req->wb_flags);
+ put_lseg(lseg);
+ }
+}
+
void pnfs_free_fsdata(struct pnfs_fsdata *fsdata)
{
if (fsdata) {
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 8d37dfb..1c94984 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -78,6 +78,8 @@ int _pnfs_write_begin(struct inode *inode, struct page *page,
struct pnfs_fsdata **fsdata);
int _pnfs_do_flush(struct inode *inode, struct nfs_page *req,
struct pnfs_fsdata *fsdata);
+void _pnfs_modify_new_write_request(struct nfs_page *req,
+ struct pnfs_fsdata *fsdata);
void _pnfs_direct_init_io(struct inode *inode, struct nfs_open_context *ctx,
size_t count, loff_t loff, int iswrite,
size_t *rwsize, size_t *remaining);
@@ -205,6 +207,14 @@ static inline void pnfs_redirty_request(struct nfs_page *req)
clear_bit(PG_USE_PNFS, &req->wb_flags);
}

+static inline void pnfs_modify_new_request(struct nfs_page *req,
+ void *fsdata)
+{
+ if (fsdata)
+ _pnfs_modify_new_write_request(req, fsdata);
+ /* Should we do something (like set PG_USE_PNFS) if !fsdata ? */
+}
+
static inline int pnfs_return_layout(struct inode *ino,
struct nfs4_pnfs_layout_segment *lseg,
const nfs4_stateid *stateid, /* optional */
@@ -294,6 +304,11 @@ static inline void pnfs_redirty_request(struct nfs_page *req)
{
}

+static inline void pnfs_modify_new_request(struct nfs_page *req,
+ void *fsdata)
+{
+}
+
static inline int pnfs_get_write_status(struct nfs_write_data *data)
{
return 0;
diff --git a/include/linux/nfs4_pnfs.h b/include/linux/nfs4_pnfs.h
index 1ba0590..e01a065 100644
--- a/include/linux/nfs4_pnfs.h
+++ b/include/linux/nfs4_pnfs.h
@@ -142,6 +142,9 @@ struct layoutdriver_io_operations {
int (*write_begin) (struct pnfs_layout_segment *lseg, struct page *page,
loff_t pos, unsigned count,
struct pnfs_fsdata *fsdata);
+ void (*new_request)(struct pnfs_layout_segment *lseg,
+ struct nfs_page *req, loff_t pos, unsigned count,
+ struct pnfs_fsdata *fsdata);

/* Consistency ops */
/* 2 problems:
--
1.6.6.1


2010-05-05 03:07:59

by Fred Isaman

[permalink] [raw]
Subject: [PATCH 8/8] pnfs_post_submit: Revert the pnfs_write_end part of "pnfs: commit and pnfs_write_end"

From: Fred Isaman <[email protected]>

pnfs: commit and pnfs_write_end

Add hooks in the nfs_write_end path, giving a driver the potential for
post-copy manipulation of the page.

[pnfs: pass lseg from write_begin to write_end]
Signed-off-by: Fred Isaman <[email protected]>
Signed-off-by: Benny Halevy <[email protected]>
[pnfs: fix pnfs_commit update_layout range]
Whole file semantics are different for COMMIT (0,0) and layouts
(0,NFS4_MAX_UINT64).
Reported-by: Alexandros Batsakis <[email protected]>
Signed-off-by: Andy Adamson <[email protected]>
Signed-off-by: Benny Halevy <[email protected]>

Signed-off-by: Fred Isaman <[email protected]>
---
fs/nfs/file.c | 4 ++++
fs/nfs/pnfs.c | 14 ++++++++++++++
fs/nfs/pnfs.h | 23 +++++++++++++++++++++++
include/linux/nfs4_pnfs.h | 3 +++
4 files changed, 44 insertions(+), 0 deletions(-)

diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 4398953..47eec55 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -487,8 +487,12 @@ static int nfs_write_end(struct file *file, struct address_space *mapping,
zero_user_segment(page, pglen, PAGE_CACHE_SIZE);
}

+ status = pnfs_write_end(file, page, pos, len, copied, fsdata);
+ if (status)
+ goto out;
status = nfs_updatepage(file, page, offset, copied, fsdata);

+ out:
unlock_page(page);
page_cache_release(page);
pnfs_write_end_cleanup(fsdata);
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 46fe088..c76b791 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1965,6 +1965,20 @@ out:
return status;
}

+/* Return 0 on succes, negative on failure */
+/* CAREFUL - what happens if copied < len??? */
+int _pnfs_write_end(struct inode *inode, struct page *page,
+ loff_t pos, unsigned len,
+ unsigned copied, struct pnfs_fsdata *fsdata)
+{
+ struct nfs_server *nfss = NFS_SERVER(inode);
+ int status;
+
+ status = nfss->pnfs_curr_ld->ld_io_ops->write_end(inode, page,
+ pos, len, copied, fsdata);
+ return status;
+}
+
/* Given an nfs request, determine if it should be flushed before proceeding.
* It should default to returning False, returning True only if there is a
* specific reason to flush.
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 1c94984..7dc3ecc 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -76,6 +76,9 @@ void pnfs_destroy_layout(struct nfs_inode *);
int _pnfs_write_begin(struct inode *inode, struct page *page,
loff_t pos, unsigned len,
struct pnfs_fsdata **fsdata);
+int _pnfs_write_end(struct inode *inode, struct page *page,
+ loff_t pos, unsigned len,
+ unsigned copied, struct pnfs_fsdata *fsdata);
int _pnfs_do_flush(struct inode *inode, struct nfs_page *req,
struct pnfs_fsdata *fsdata);
void _pnfs_modify_new_write_request(struct nfs_page *req,
@@ -197,6 +200,19 @@ static inline int pnfs_do_flush(struct nfs_page *req, void *fsdata)
return 0;
}

+static inline int pnfs_write_end(struct file *filp, struct page *page,
+ loff_t pos, unsigned len, unsigned copied,
+ void *fsdata)
+{
+ struct inode *inode = filp->f_dentry->d_inode;
+ struct nfs_server *nfss = NFS_SERVER(inode);
+
+ if (PNFS_EXISTS_LDIO_OP(nfss, write_end))
+ return _pnfs_write_end(inode, page, pos, len, copied, fsdata);
+ else
+ return 0;
+}
+
static inline void pnfs_write_end_cleanup(void *fsdata)
{
pnfs_free_fsdata(fsdata);
@@ -296,6 +312,13 @@ static inline int pnfs_write_begin(struct file *filp, struct page *page,
return 0;
}

+static inline int pnfs_write_end(struct file *filp, struct page *page,
+ loff_t pos, unsigned len, unsigned copied,
+ void *fsdata)
+{
+ return 0;
+}
+
static inline void pnfs_write_end_cleanup(void *fsdata)
{
}
diff --git a/include/linux/nfs4_pnfs.h b/include/linux/nfs4_pnfs.h
index e01a065..3caac60 100644
--- a/include/linux/nfs4_pnfs.h
+++ b/include/linux/nfs4_pnfs.h
@@ -142,6 +142,9 @@ struct layoutdriver_io_operations {
int (*write_begin) (struct pnfs_layout_segment *lseg, struct page *page,
loff_t pos, unsigned count,
struct pnfs_fsdata *fsdata);
+ int (*write_end)(struct inode *inode, struct page *page, loff_t pos,
+ unsigned count, unsigned copied,
+ struct pnfs_fsdata *fsdata);
void (*new_request)(struct pnfs_layout_segment *lseg,
struct nfs_page *req, loff_t pos, unsigned count,
struct pnfs_fsdata *fsdata);
--
1.6.6.1


2010-05-06 19:46:04

by Benny Halevy

[permalink] [raw]
Subject: Re: [PATCH 0/8]: pnfs_submit: removal of fsdata manipulation

On May. 03, 2010, 4:00 +0300, Fred Isaman <[email protected]> wrote:
> These revert patches in the submit branch in order to remove the fsdata manipulation needed by the block driver, followed immediately by the post-submit "un-reverts".
>
> They apply on top of the 13 patches Andy previously sent.

patches 1-4 committed to pnfs-submit
5-8 to pnfs

Thanks!

Benny

>
> Fred
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html