pnfs for 2.6.40
Subsystems (3)
v6 cover pnfs for 2.6.40
Hi,
This is a cleaned up version of the v5 patchset I sent earlier. It's also based over v2.6.39 and push togit://linux-nfs.org/~bhalevy/linux-pnfs.git pnfs-submit at tag pnfs-for-2.6.40-v6-2011-05-23
Changes in v6: (Benny)
* squashed all SQUASHMEs
* reverted "SQUASHME: initialize data->task on the non-rpc io done success paths"
* reverted "per mount layout driver private data"
* reverted "pnfs: set/unset layoutdriver"
* applied (in reverse) "SQUASHME: pnfs-obj: Important fallout from the last rebase"
Changes in v5: (Benny)
* use struct nfs_client to qualify deviceid
* make device cache global
* use be32 res in nfs4_callback_devicenotify
* use gfp_flags
* xdr_init_decode_pages
* fix layout stateid used for layoutreturn args
* commit message for layoutret_on_setattr
* use global deviceid cache for pnfs-obj
- revert per-mount hook and related {.un}set_layoutdriver methods
* use layout driver in global device cache
changes in v4: (Boaz)
* See the long SQUASHME patchset I sent yesterday for all the changes.
titled: [PATCHSET 00/13] SQUASHME pnfs-obj: Lots of changes addressing
comments by Trond and Benny
* I have united all 3 raid-engine read/write patches to a single patch
* I've united the two error-reporting and error-encoding into one patch
* Some checkpatch love
* small cleanups here and there.
(I'll send a diff as reply to this mail)
changes in v3: (Benny)
* removed direct i/o patch
* align layoutget requests on page boundaries
* fix lseg ordering
* cleanup pnfs_insert_lseg
* pnfs: clean up pnfs_find_lseg lseg arg
* remove unnecessary FIXME
changes in v2:
* fix CB_NOTIFY_DEVICEID
* call pnfs_return_layout right before pnfs_destroy_layout
* remove assert_spin_locked from pnfs_clear_lseg_list
* remove wait parameter from the layoutreturn path.
* remove return_type field from nfs4_layoutreturn_args
* remove range from nfs4_layoutreturn_args
* no need to send layoutcommit from _pnfs_return_layout
* don't wait on sync layoutreturn
* get rid of PNFS_USE_RPC_CODE
* get rid of __nfs4_write_done_cb
* get rid of ds_[rw]size
* rename pnfs_{read,write}_done -> pnfs_ld_{read,write}_done
* reorganize and reorder the pnfs-obj patchset to expose dependencies and separate api changes
* some cleaning up of the pnfs-obj patches
* add xdr space reservation for pnfs-obj opaque layoutreturn and layoutcommit payloads
List of patches:
generic:
[PATCH v6 01/26] NFSv4.1: use struct nfs_client to qualify deviceid [PATCH v6 02/26] pnfs: resolve header dependency in pnfs.h [PATCH v6 03/26] NFSv4.1: make deviceid cache global [PATCH v6 04/26] NFSv4.1: purge deviceid cache on nfs_free_client [PATCH v6 05/26] pnfs: CB_NOTIFY_DEVICEID
[PATCH v6 06/26] SUNRPC: introduce xdr_init_decode_pages [PATCH v6 07/26] pnfs: Use byte-range for layoutget [PATCH v6 08/26] pnfs: align layoutget requests on page boundaries [PATCH v6 09/26] pnfs: Use byte-range for cb_layoutrecall [PATCH v6 10/26] pnfs: client stats
Basic ld driver and some std definitions:
[PATCH v6 11/26] pnfs-obj: objlayoutdriver module skeleton [PATCH v6 12/26] pnfs-obj: pnfs_osd XDR definitions [PATCH v6 13/26] pnfs-obj: pnfs_osd XDR client implementation
layoutget:
[PATCH v6 14/26] pnfs-obj: decode layout, alloc/free lseg
getdeviceinfo:
[PATCH v6 15/26] pnfs-obj: objio_osd device information retrieval and caching
[PATCH v6 16/26] NFSv4.1: use layout driver in global device cache
read/write:
[PATCH v6 17/26] pnfs: alloc and free layout_hdr layoutdriver methods [PATCH v6 18/26] pnfs-obj: define per-inode private structure [PATCH v6 19/26] pnfs: support for non-rpc layout drivers [PATCH v6 20/26] pnfs-obj: osd raid engine read/write implementation
layoutreturn:
[PATCH v6 21/26] pnfs: layoutreturn
[PATCH v6 22/26] pnfs: layoutret_on_setattr
[PATCH v6 23/26] pnfs: encode_layoutreturn
[PATCH v6 24/26] pnfs-obj: report errors and .encode_layoutreturn Implementation.
layoutcommit:
[PATCH v6 25/26] pnfs: encode_layoutcommit
[PATCH v6 26/26] pnfs-obj: objlayout_encode_layoutcommit implementation
PATCH v6 1/26 NFSv4.1: use struct nfs_client to qualify deviceid
deviceids are unique per server, per layout type. Therefore, in the global cache in the files layout driver deviceids from different servers may clash so we need to qualify them with a struct nfs_client that represents the nfs server that returned the deviceid.
Introduced in 2.6.39 commit ea8eecdd "NFSv4.1 move deviceid cache to filelayout driver"
--- fs/nfs/nfs4filelayout.c | 2 +- fs/nfs/nfs4filelayout.h | 3 ++- fs/nfs/nfs4filelayoutdev.c | 9 ++++----- 3 files changed, 7 insertions(+), 7 deletions(-)
fs/nfs/nfs4filelayout.c +1 -1
@@ -440,7 +440,7 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo, }/* find and reference the deviceid */ - dsaddr =nfs4_fl_find_get_deviceid (id); + dsaddr =nfs4_fl_find_get_deviceid (NFS_SERVER (lo->plh_inode)->nfs_client, id);if (dsaddr ==NULL ) { dsaddr =get_device_info (lo->plh_inode, id, gfp_flags);if (dsaddr ==NULL )
fs/nfs/nfs4filelayout.h +2 -1
@@ -60,6 +60,7 @@ struct nfs4_pnfs_ds {struct nfs4_file_layout_dsaddr {struct hlist_node node; +struct nfs_client *nfs_client;struct nfs4_deviceid deviceid;atomic_t ref;unsigned long flags;
@@ -101,7 +102,7 @@ u32 nfs4_fl_calc_ds_index(struct pnfs_layout_segment *lseg, u32 j);struct nfs4_pnfs_ds *nfs4_fl_prepare_ds (struct pnfs_layout_segment *lseg,u32 ds_idx);extern struct nfs4_file_layout_dsaddr * -nfs4_fl_find_get_deviceid (struct nfs4_deviceid *dev_id); +nfs4_fl_find_get_deviceid (struct nfs_client *,struct nfs4_deviceid *dev_id);extern void nfs4_fl_put_deviceid (struct nfs4_file_layout_dsaddr *dsaddr);struct nfs4_file_layout_dsaddr *get_device_info (struct inode *inode,struct nfs4_deviceid *dev_id,gfp_t gfp_flags);
fs/nfs/nfs4filelayoutdev.c +4 -5
@@ -431,7 +431,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags) dsaddr->stripe_indices = stripe_indices; stripe_indices =NULL ; dsaddr->ds_num = num; - + dsaddr->nfs_client =NFS_SERVER (ino)->nfs_client;memcpy (&dsaddr->deviceid, &pdev->dev_id,sizeof (pdev->dev_id));for (i =0 ; i < dsaddr->ds_num; i++) {
@@ -516,7 +516,7 @@ decode_and_add_device(struct inode *inode, struct pnfs_device *dev, gfp_t gfp_fl }spin_lock (&filelayout_deviceid_lock); - d =nfs4_fl_find_get_deviceid (&new->deviceid); + d =nfs4_fl_find_get_deviceid (new->nfs_client, &new->deviceid);if (d) {spin_unlock (&filelayout_deviceid_lock);nfs4_fl_free_deviceid (new);
@@ -610,16 +610,15 @@ nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) }struct nfs4_file_layout_dsaddr * -nfs4_fl_find_get_deviceid (struct nfs4_deviceid *id) +nfs4_fl_find_get_deviceid (struct nfs_client *clp,struct nfs4_deviceid *id) {struct nfs4_file_layout_dsaddr *d;struct hlist_node *n;long hash =nfs4_fl_deviceid_hash (id); -rcu_read_lock ();hlist_for_each_entry_rcu (d, n, &filelayout_deviceid_cache[hash], node) { -if (!memcmp (&d->deviceid, id,sizeof (*id))) { +if (d->nfs_client == clp && !memcmp (&d->deviceid, id,sizeof (*id))) {if (!atomic_inc_not_zero (&d->ref)) goto fail;rcu_read_unlock ();
Signature · 1 line
1.7.3.4
Re: [PATCH v6 01/26] NFSv4.1: use struct nfs_client to qualify deviceid
Quoted 8 lines · Benny Halevy
deviceids are unique per server, per layout type. Therefore, in the global cache in the files layout driver deviceids from different servers may clash so we need to qualify them with a struct
nfs_clientthat represents the nfs server that returned the deviceid.Introduced in 2.6.39 commit
ea8eecdd"NFSv4.1 move deviceid cache to filelayout driver"
Note this is required for stable 2.6.39
Benny
Quoted 83 lines
Signed-off-by Benny Halevy <[email protected]>--- fs/nfs/nfs4filelayout.c | 2 +- fs/nfs/nfs4filelayout.h | 3 ++- fs/nfs/nfs4filelayoutdev.c | 9 ++++----- 3 files changed, 7 insertions(+), 7 deletions(-)fs/nfs/nfs4filelayout.c +1
-1@@ -440,7 +440,7 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo, }/* find and reference the deviceid */ - dsaddr =nfs4_fl_find_get_deviceid (id); + dsaddr =nfs4_fl_find_get_deviceid (NFS_SERVER (lo->plh_inode)->nfs_client, id);if (dsaddr ==NULL ) { dsaddr =get_device_info (lo->plh_inode, id, gfp_flags);if (dsaddr ==NULL )fs/nfs/nfs4filelayout.h +2
-1@@ -60,6 +60,7 @@ struct nfs4_pnfs_ds {struct nfs4_file_layout_dsaddr {struct hlist_node node; +struct nfs_client *nfs_client;struct nfs4_deviceid deviceid;atomic_t ref;unsigned long flags;@@ -101,7 +102,7 @@ u32 nfs4_fl_calc_ds_index(struct pnfs_layout_segment *lseg, u32 j);struct nfs4_pnfs_ds *nfs4_fl_prepare_ds (struct pnfs_layout_segment *lseg,u32 ds_idx);extern struct nfs4_file_layout_dsaddr * -nfs4_fl_find_get_deviceid (struct nfs4_deviceid *dev_id); +nfs4_fl_find_get_deviceid (struct nfs_client *,struct nfs4_deviceid *dev_id);extern void nfs4_fl_put_deviceid (struct nfs4_file_layout_dsaddr *dsaddr);struct nfs4_file_layout_dsaddr *get_device_info (struct inode *inode,struct nfs4_deviceid *dev_id,gfp_t gfp_flags);fs/nfs/nfs4filelayoutdev.c +4
-5@@ -431,7 +431,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags) dsaddr->stripe_indices = stripe_indices; stripe_indices =NULL ; dsaddr->ds_num = num; - + dsaddr->nfs_client =NFS_SERVER (ino)->nfs_client;memcpy (&dsaddr->deviceid, &pdev->dev_id,sizeof (pdev->dev_id));for (i =0 ; i < dsaddr->ds_num; i++) {@@ -516,7 +516,7 @@ decode_and_add_device(struct inode *inode, struct pnfs_device *dev, gfp_t gfp_fl }spin_lock (&filelayout_deviceid_lock); - d =nfs4_fl_find_get_deviceid (&new->deviceid); + d =nfs4_fl_find_get_deviceid (new->nfs_client, &new->deviceid);if (d) {spin_unlock (&filelayout_deviceid_lock);nfs4_fl_free_deviceid (new);@@ -610,16 +610,15 @@ nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) }struct nfs4_file_layout_dsaddr * -nfs4_fl_find_get_deviceid (struct nfs4_deviceid *id) +nfs4_fl_find_get_deviceid (struct nfs_client *clp,struct nfs4_deviceid *id) {struct nfs4_file_layout_dsaddr *d;struct hlist_node *n;long hash =nfs4_fl_deviceid_hash (id); -rcu_read_lock ();hlist_for_each_entry_rcu (d, n, &filelayout_deviceid_cache[hash], node) { -if (!memcmp (&d->deviceid, id,sizeof (*id))) { +if (d->nfs_client == clp && !memcmp (&d->deviceid, id,sizeof (*id))) {if (!atomic_inc_not_zero (&d->ref)) goto fail;rcu_read_unlock ();
PATCH v6 2/26 pnfs: resolve header dependency in pnfs.h
In reply to Benny HalevySome definitions in the header file depend on nfs_fs.h so pnfs.h can't be included independently.
--- fs/nfs/pnfs.h | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
fs/nfs/pnfs.h +1 -0
@@ -30,6 +30,7 @@#ifndef FS_NFS_PNFS_H #define FS_NFS_PNFS_H +#include <linux/nfs_fs.h> #include <linux/nfs_page.h> enum {
Signature · 1 line
1.7.3.4
PATCH v6 3/26 NFSv4.1: make deviceid cache global
In reply to Benny HalevyMove deviceid cache from the pnfs files layout driver to the generic layer in preparation for the objects layout driver.
--- fs/nfs/Makefile | 2 +- fs/nfs/nfs4filelayout.c | 10 ++- fs/nfs/nfs4filelayout.h | 8 +-- fs/nfs/nfs4filelayoutdev.c | 104 ++++------------------------- fs/nfs/pnfs.h | 17 +++++ fs/nfs/pnfs_dev.c | 156 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 194 insertions(+), 103 deletions(-) create mode 100644 fs/nfs/pnfs_dev.c
fs/nfs/Makefile +1 -1
@@ -15,7 +15,7 @@ nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \ delegation.o idmap.o \ callback.o callback_xdr.o callback_proc.o \ nfs4namespace.o -nfs-$(CONFIG_NFS_V4_1) += pnfs.o +nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o nfs-$(CONFIG_SYSCTL) += sysctl.o nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
fs/nfs/nfs4filelayout.c +6 -4
@@ -421,6 +421,7 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo, struct nfs4_deviceid *id, gfp_t gfp_flags) { +struct nfs4_deviceid_node *d;struct nfs4_file_layout_dsaddr *dsaddr;int status = -EINVAL ;struct nfs_server *nfss =NFS_SERVER (lo->plh_inode);
@@ -440,12 +441,13 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo, }/* find and reference the deviceid */ - dsaddr =nfs4_fl_find_get_deviceid (NFS_SERVER (lo->plh_inode)->nfs_client, id); -if (dsaddr ==NULL ) { + d =nfs4_find_get_deviceid (NFS_SERVER (lo->plh_inode)->nfs_client, id); +if (d ==NULL ) { dsaddr =get_device_info (lo->plh_inode, id, gfp_flags);if (dsaddr ==NULL ) goto out; - } + }else + dsaddr = container_of(d, struct nfs4_file_layout_dsaddr, id_node); fl->dsaddr = dsaddr; if (fl->first_stripe_index < 0 ||
@@ -535,7 +537,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,memcpy (id, p,sizeof (*id)); p +=XDR_QUADLEN (NFS4_DEVICEID4_SIZE ); -print_deviceid (id); +nfs4_print_deviceid (id); nfl_util =be32_to_cpup (p++);if (nfl_util &NFL4_UFLG_COMMIT_THRU_MDS )
fs/nfs/nfs4filelayout.h +1 -7
@@ -59,10 +59,7 @@ struct nfs4_pnfs_ds {#define NFS4_DEVICE_ID_NEG_ENTRY 0x00000001struct nfs4_file_layout_dsaddr { -struct hlist_node node; -struct nfs_client *nfs_client; -struct nfs4_deviceid deviceid; -atomic_t ref; +struct nfs4_deviceid_node id_node;unsigned long flags;u32 stripe_count;u8 *stripe_indices;
@@ -96,13 +93,10 @@ extern struct nfs_fh * nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j);extern void print_ds (struct nfs4_pnfs_ds *ds); -extern void print_deviceid (struct nfs4_deviceid *dev_id);u32 nfs4_fl_calc_j_index (struct pnfs_layout_segment *lseg,loff_t offset);u32 nfs4_fl_calc_ds_index (struct pnfs_layout_segment *lseg,u32 j);struct nfs4_pnfs_ds *nfs4_fl_prepare_ds (struct pnfs_layout_segment *lseg,u32 ds_idx); -extern struct nfs4_file_layout_dsaddr * -nfs4_fl_find_get_deviceid (struct nfs_client *,struct nfs4_deviceid *dev_id);extern void nfs4_fl_put_deviceid (struct nfs4_file_layout_dsaddr *dsaddr);struct nfs4_file_layout_dsaddr *get_device_info (struct inode *inode,struct nfs4_deviceid *dev_id,gfp_t gfp_flags);
fs/nfs/nfs4filelayoutdev.c +13 -91
162 lines not on this page · raw message
fs/nfs/pnfs.h +17 -0
@@ -157,6 +157,23 @@ bool pnfs_roc_drain(struct inode *ino, u32 *barrier);void pnfs_set_layoutcommit (struct nfs_write_data *wdata);int pnfs_layoutcommit_inode (struct inode *inode,bool sync); +/* pnfs_dev.c */ +struct nfs4_deviceid_node { +struct hlist_node node; +const struct nfs_client *nfs_client; +struct nfs4_deviceid deviceid; +atomic_t ref; +}; + +void nfs4_print_deviceid (const struct nfs4_deviceid *dev_id); +struct nfs4_deviceid_node *nfs4_find_get_deviceid (const struct nfs_client *,const struct nfs4_deviceid *); +struct nfs4_deviceid_node *nfs4_unhash_put_deviceid (const struct nfs_client *,const struct nfs4_deviceid *); +void nfs4_init_deviceid_node (struct nfs4_deviceid_node *, +const struct nfs_client *, +const struct nfs4_deviceid *); +struct nfs4_deviceid_node *nfs4_insert_deviceid_node (struct nfs4_deviceid_node *); +bool nfs4_put_deviceid_node (struct nfs4_deviceid_node *); +static inline int lo_fail_bit (u32 iomode) { return iomode == IOMODE_RW ?
fs/nfs/pnfs_dev.c new file +156 -0
156 lines not on this page · raw message
Signature · 1 line
1.7.3.4
PATCH v6 4/26 NFSv4.1: purge deviceid cache on nfs_free_client
In reply to Benny HalevyUse the pnfs_layoutdriver_type both as a qualifier for the deviceid, distinguishing deviceid from different layout types on the server, and for freeing the layout-driver allocated structure containing the nfs4_deviceid_node.
--- fs/nfs/client.c | 2 + fs/nfs/nfs4filelayout.c | 7 +++++ fs/nfs/nfs4filelayout.h | 1 + fs/nfs/nfs4filelayoutdev.c | 9 ++++--- fs/nfs/pnfs.h | 11 +++++++++ fs/nfs/pnfs_dev.c | 53 +++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 76 insertions(+), 7 deletions(-)
fs/nfs/client.c +2 -0
@@ -290,6 +290,8 @@ static void nfs_free_client(struct nfs_client *clp)if (clp->cl_machine_cred !=NULL )put_rpccred (clp->cl_machine_cred); +nfs4_deviceid_purge_client (clp); +kfree (clp->cl_hostname);kfree (clp);
fs/nfs/nfs4filelayout.c +7 -0
@@ -862,6 +862,12 @@ filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages,return -ENOMEM ; } +static void +filelayout_free_deveiceid_node (struct nfs4_deviceid_node *d) +{ +nfs4_fl_free_deviceid (container_of(d ,struct nfs4_file_layout_dsaddr ,id_node )); +} +static struct pnfs_layoutdriver_type filelayout_type = { .id =LAYOUT_NFSV4_1_FILES , .name ="LAYOUT_NFSV4_1_FILES" ,
@@ -874,6 +880,7 @@ static struct pnfs_layoutdriver_type filelayout_type = { .commit_pagelist = filelayout_commit_pagelist, .read_pagelist = filelayout_read_pagelist, .write_pagelist = filelayout_write_pagelist, + .free_deviceid_node = filelayout_free_deveiceid_node, };static int __init nfs4filelayout_init (void )
fs/nfs/nfs4filelayout.h +1 -0
@@ -98,6 +98,7 @@ u32 nfs4_fl_calc_ds_index(struct pnfs_layout_segment *lseg, u32 j);struct nfs4_pnfs_ds *nfs4_fl_prepare_ds (struct pnfs_layout_segment *lseg,u32 ds_idx);extern void nfs4_fl_put_deviceid (struct nfs4_file_layout_dsaddr *dsaddr); +extern void nfs4_fl_free_deviceid (struct nfs4_file_layout_dsaddr *dsaddr);struct nfs4_file_layout_dsaddr *get_device_info (struct inode *inode,struct nfs4_deviceid *dev_id,gfp_t gfp_flags);
fs/nfs/nfs4filelayoutdev.c +5 -4
@@ -156,7 +156,7 @@ destroy_ds(struct nfs4_pnfs_ds *ds)kfree (ds); } -static void +void nfs4_fl_free_deviceid (struct nfs4_file_layout_dsaddr *dsaddr) {struct nfs4_pnfs_ds *ds;
@@ -386,7 +386,9 @@ decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags) dsaddr->stripe_indices = stripe_indices; stripe_indices =NULL ; dsaddr->ds_num = num; -nfs4_init_deviceid_node (&dsaddr->id_node,NFS_SERVER (ino)->nfs_client, +nfs4_init_deviceid_node (&dsaddr->id_node, +NFS_SERVER (ino)->pnfs_curr_ld, +NFS_SERVER (ino)->nfs_client, &pdev->dev_id);for (i =0 ; i < dsaddr->ds_num; i++) {
@@ -548,8 +550,7 @@ out_free:void nfs4_fl_put_deviceid (struct nfs4_file_layout_dsaddr *dsaddr) { -if (nfs4_put_deviceid_node (&dsaddr->id_node)) -nfs4_fl_free_deviceid (dsaddr); +nfs4_put_deviceid_node (&dsaddr->id_node); }/*
fs/nfs/pnfs.h +11 -0
@@ -65,6 +65,8 @@ enum { NFS_LAYOUT_DESTROYED, /* no new use of layout allowed */ }; +struct nfs4_deviceid_node ; +/* Per-layout driver specific registration structure */ struct pnfs_layoutdriver_type {struct list_head pnfs_tblid;
@@ -90,6 +92,8 @@ struct pnfs_layoutdriver_type {*/ enum pnfs_try_status (*read_pagelist) (struct nfs_read_data *nfs_data);enum pnfs_try_status (*write_pagelist) (struct nfs_write_data *nfs_data,int how); + +void (*free_deviceid_node) (struct nfs4_deviceid_node *); };struct pnfs_layout_hdr {
@@ -160,6 +164,7 @@ int pnfs_layoutcommit_inode(struct inode *inode, bool sync);/* pnfs_dev.c */ struct nfs4_deviceid_node {struct hlist_node node; +const struct pnfs_layoutdriver_type *ld;const struct nfs_client *nfs_client;struct nfs4_deviceid deviceid;atomic_t ref;
@@ -169,10 +174,12 @@ void nfs4_print_deviceid(const struct nfs4_deviceid *dev_id);struct nfs4_deviceid_node *nfs4_find_get_deviceid (const struct nfs_client *,const struct nfs4_deviceid *);struct nfs4_deviceid_node *nfs4_unhash_put_deviceid (const struct nfs_client *,const struct nfs4_deviceid *);void nfs4_init_deviceid_node (struct nfs4_deviceid_node *, +const struct pnfs_layoutdriver_type *,const struct nfs_client *,const struct nfs4_deviceid *);struct nfs4_deviceid_node *nfs4_insert_deviceid_node (struct nfs4_deviceid_node *);bool nfs4_put_deviceid_node (struct nfs4_deviceid_node *); +void nfs4_deviceid_purge_client (const struct nfs_client *);static inline int lo_fail_bit (u32 iomode) {
@@ -349,6 +356,10 @@ static inline int pnfs_layoutcommit_inode(struct inode *inode, bool sync) {return 0 ; } + +static inline void nfs4_deviceid_purge_client (struct nfs_client *) +{ +}#endif /* CONFIG_NFS_V4_1 */ #endif /* FS_NFS_PNFS_H */
fs/nfs/pnfs_dev.c +50 -3
82 lines not on this page · raw message
Signature · 1 line
1.7.3.4
Re: [PATCH v6 04/26] NFSv4.1: purge deviceid cache on nfs_free_client
Quoted 233 lines · Benny Halevy
Use the
pnfs_layoutdriver_typeboth as a qualifier for the deviceid, distinguishing deviceid from different layout types on the server, and for freeing the layout-driver allocated structure containing thenfs4_deviceid_node.Signed-off-by Benny Halevy <[email protected]>--- fs/nfs/client.c | 2 + fs/nfs/nfs4filelayout.c | 7 +++++ fs/nfs/nfs4filelayout.h | 1 + fs/nfs/nfs4filelayoutdev.c | 9 ++++--- fs/nfs/pnfs.h | 11 +++++++++ fs/nfs/pnfs_dev.c | 53 +++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 76 insertions(+), 7 deletions(-)fs/nfs/client.c +2
-0@@ -290,6 +290,8 @@ static void nfs_free_client(struct nfs_client *clp)if (clp->cl_machine_cred !=NULL )put_rpccred (clp->cl_machine_cred); +nfs4_deviceid_purge_client (clp); +kfree (clp->cl_hostname);kfree (clp);fs/nfs/nfs4filelayout.c +7
-0@@ -862,6 +862,12 @@ filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages,return -ENOMEM ; } +static void +filelayout_free_deveiceid_node (struct nfs4_deviceid_node *d) +{ +nfs4_fl_free_deviceid (container_of(d ,struct nfs4_file_layout_dsaddr ,id_node )); +} +static struct pnfs_layoutdriver_type filelayout_type = { .id =LAYOUT_NFSV4_1_FILES , .name ="LAYOUT_NFSV4_1_FILES" ,@@ -874,6 +880,7 @@ static struct pnfs_layoutdriver_type filelayout_type = { .commit_pagelist = filelayout_commit_pagelist, .read_pagelist = filelayout_read_pagelist, .write_pagelist = filelayout_write_pagelist, + .free_deviceid_node = filelayout_free_deveiceid_node, };static int __init nfs4filelayout_init (void )fs/nfs/nfs4filelayout.h +1
-0@@ -98,6 +98,7 @@ u32 nfs4_fl_calc_ds_index(struct pnfs_layout_segment *lseg, u32 j);struct nfs4_pnfs_ds *nfs4_fl_prepare_ds (struct pnfs_layout_segment *lseg,u32 ds_idx);extern void nfs4_fl_put_deviceid (struct nfs4_file_layout_dsaddr *dsaddr); +extern void nfs4_fl_free_deviceid (struct nfs4_file_layout_dsaddr *dsaddr);struct nfs4_file_layout_dsaddr *get_device_info (struct inode *inode,struct nfs4_deviceid *dev_id,gfp_t gfp_flags);fs/nfs/nfs4filelayoutdev.c +5
-4@@ -156,7 +156,7 @@ destroy_ds(struct nfs4_pnfs_ds *ds)kfree (ds); } -static void +void nfs4_fl_free_deviceid (struct nfs4_file_layout_dsaddr *dsaddr) {struct nfs4_pnfs_ds *ds;@@ -386,7 +386,9 @@ decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags) dsaddr->stripe_indices = stripe_indices; stripe_indices =NULL ; dsaddr->ds_num = num; -nfs4_init_deviceid_node (&dsaddr->id_node,NFS_SERVER (ino)->nfs_client, +nfs4_init_deviceid_node (&dsaddr->id_node, +NFS_SERVER (ino)->pnfs_curr_ld, +NFS_SERVER (ino)->nfs_client, &pdev->dev_id);for (i =0 ; i < dsaddr->ds_num; i++) {@@ -548,8 +550,7 @@ out_free:void nfs4_fl_put_deviceid (struct nfs4_file_layout_dsaddr *dsaddr) { -if (nfs4_put_deviceid_node (&dsaddr->id_node)) -nfs4_fl_free_deviceid (dsaddr); +nfs4_put_deviceid_node (&dsaddr->id_node); }/* fs/nfs/pnfs.h +11
-0@@ -65,6 +65,8 @@ enum { NFS_LAYOUT_DESTROYED, /* no new use of layout allowed */ }; +struct nfs4_deviceid_node ; +/* Per-layout driver specific registration structure */ struct pnfs_layoutdriver_type {struct list_head pnfs_tblid;@@ -90,6 +92,8 @@ struct pnfs_layoutdriver_type {*/ enum pnfs_try_status (*read_pagelist) (struct nfs_read_data *nfs_data);enum pnfs_try_status (*write_pagelist) (struct nfs_write_data *nfs_data,int how); + +void (*free_deviceid_node) (struct nfs4_deviceid_node *); };struct pnfs_layout_hdr {@@ -160,6 +164,7 @@ int pnfs_layoutcommit_inode(struct inode *inode, bool sync);/* pnfs_dev.c */ struct nfs4_deviceid_node {struct hlist_node node; +const struct pnfs_layoutdriver_type *ld;const struct nfs_client *nfs_client;struct nfs4_deviceid deviceid;atomic_t ref;@@ -169,10 +174,12 @@ void nfs4_print_deviceid(const struct nfs4_deviceid *dev_id);struct nfs4_deviceid_node *nfs4_find_get_deviceid (const struct nfs_client *,const struct nfs4_deviceid *);struct nfs4_deviceid_node *nfs4_unhash_put_deviceid (const struct nfs_client *,const struct nfs4_deviceid *);void nfs4_init_deviceid_node (struct nfs4_deviceid_node *, +const struct pnfs_layoutdriver_type *,const struct nfs_client *,const struct nfs4_deviceid *);struct nfs4_deviceid_node *nfs4_insert_deviceid_node (struct nfs4_deviceid_node *);bool nfs4_put_deviceid_node (struct nfs4_deviceid_node *); +void nfs4_deviceid_purge_client (const struct nfs_client *);static inline int lo_fail_bit (u32 iomode) {@@ -349,6 +356,10 @@ static inline int pnfs_layoutcommit_inode(struct inode *inode, bool sync) {return 0 ; } + +static inline void nfs4_deviceid_purge_client (struct nfs_client *) +{ +}#endif /* CONFIG_NFS_V4_1 */ #endif /* FS_NFS_PNFS_H */ fs/nfs/pnfs_dev.c +40
-3@@ -96,11 +96,15 @@ EXPORT_SYMBOL_GPL(nfs4_find_get_deviceid);void nfs4_init_deviceid_node (struct nfs4_deviceid_node *d, +const struct pnfs_layoutdriver_type *ld,const struct nfs_client *nfs_client,const struct nfs4_deviceid *id) { +INIT_HLIST_NODE (&d->node); + d->ld = ld; d->nfs_client = nfs_client; d->deviceid = *id; +atomic_set (&d->ref,1 ); }EXPORT_SYMBOL_GPL (nfs4_init_deviceid_node);@@ -108,7 +112,10 @@ EXPORT_SYMBOL_GPL(nfs4_init_deviceid_node);* Uniquely initialize and insert a deviceid node into cache * * @new new deviceid node -* Note that the caller must set up new->nfs_client and new->deviceid +* Note that the caller must set up the following members: +* new->ld +* new->nfs_client +* new->deviceid * * @ret the inserted node, if none found, otherwise, the found entry. */ @@ -125,8 +132,6 @@ nfs4_insert_deviceid_node(struct nfs4_deviceid_node *new)return d; } -INIT_HLIST_NODE (&new->node); -atomic_set (&new->ref,1 ); hash =nfs4_deviceid_hash (&new->deviceid);hlist_add_head_rcu (&new->node, &nfs4_deviceid_cache[hash]);spin_unlock (&nfs4_deviceid_lock);@@ -151,6 +156,48 @@ nfs4_put_deviceid_node(struct nfs4_deviceid_node *d)hlist_del_init_rcu (&d->node);spin_unlock (&nfs4_deviceid_lock);synchronize_rcu (); +if (d->ld->free_deviceid_node) + d->ld->free_deviceid_node (d);return true; }EXPORT_SYMBOL_GPL (nfs4_put_deviceid_node); + +static void +_deviceid_purge_client (const struct nfs_client *clp,long hash) +{ +struct nfs4_deviceid_node *d; +struct hlist_node *n, *next; +HLIST_HEAD (tmp); + +rcu_read_lock (); +hlist_for_each_entry_rcu (d, n, &nfs4_deviceid_cache[hash], node) +if (d->nfs_client == clp &&atomic_read (&d->ref)) { +hlist_del_init_rcu (&d->node); +hlist_add_head (&d->node, &tmp); + } +rcu_read_unlock (); + +if (hlist_empty (&tmp)) +return ; + +synchronize_rcu (); +hlist_for_each_entry_safe (d, n, next, &tmp, node) +if (!atomic_dec_and_test (&d->ref)) { +if (d->ld->free_deviceid_node) + d->ld->free_deviceid_node (d); +else +kfree (d); + } +} + +void
fs/nfs/pnfs_dev.c nfs4_put_deviceid_node(struct nfs4_deviceid_node *d) · line 203
Quoted 10 lines
fs/nfs/pnfs_dev.c +10
-0+nfs4_deviceid_purge_client(const struct nfs_client *clp) +{ +long h; + +spin_lock (&nfs4_deviceid_lock); +for (h =0 ; h <NFS4_DEVICE_ID_HASH_SIZE ; h++) +_deviceid_purge_client (clp, h); +spin_unlock (&nfs4_deviceid_lock); +} +EXPORT_SYMBOL_GPL (nfs4_deviceid_purge_client);
no need for EXPORT
Benny
PATCH v6 5/26 pnfs: CB_NOTIFY_DEVICEID
In reply to Benny HalevyFrom: Marc Eshel <[email protected]>
Note: This functionlaity is incomplete as all layout segments referring to the 'to be removed device id' need to be reaped, and all in flight I/O drained.
--- fs/nfs/callback.h | 17 ++++++++ fs/nfs/callback_proc.c | 47 +++++++++++++++++++++++ fs/nfs/callback_xdr.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++- fs/nfs/pnfs.h | 1 + fs/nfs/pnfs_dev.c | 98 +++++++++++++++++++++++++++++++++++++++++------- 5 files changed, 244 insertions(+), 15 deletions(-)
fs/nfs/callback.h +17 -0
@@ -167,6 +167,23 @@ extern unsigned nfs4_callback_layoutrecall(extern void nfs4_check_drain_bc_complete (struct nfs4_session *ses);extern void nfs4_cb_take_slot (struct nfs_client *clp); + +struct cb_devicenotifyitem { +uint32_t cbd_notify_type; +uint32_t cbd_layout_type; +struct nfs4_deviceid cbd_dev_id; +uint32_t cbd_immediate; +}; + +struct cb_devicenotifyargs { +int ndevs; +struct cb_devicenotifyitem *devs; +}; + +extern __be32 nfs4_callback_devicenotify ( +struct cb_devicenotifyargs *args, +void *dummy,struct cb_process_state *cps); +#endif /* CONFIG_NFS_V4_1 */ extern int check_gss_callback_principal (struct nfs_client *,struct svc_rqst *); extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args,
fs/nfs/callback_proc.c +47 -0
53 lines not on this page · raw message
fs/nfs/callback_xdr.c +95 -1
123 lines not on this page · raw message
fs/nfs/pnfs.h +1 -0
@@ -173,6 +173,7 @@ struct nfs4_deviceid_node {void nfs4_print_deviceid (const struct nfs4_deviceid *dev_id);struct nfs4_deviceid_node *nfs4_find_get_deviceid (const struct nfs_client *,const struct nfs4_deviceid *);struct nfs4_deviceid_node *nfs4_unhash_put_deviceid (const struct nfs_client *,const struct nfs4_deviceid *); +void nfs4_delete_deviceid (const struct nfs_client *,const struct nfs4_deviceid *); void nfs4_init_deviceid_node(struct nfs4_deviceid_node *, const struct pnfs_layoutdriver_type *, const struct nfs_client *,
fs/nfs/pnfs_dev.c +84 -14
129 lines not on this page · raw message
Signature · 1 line
1.7.3.4
PATCH v6 6/26 SUNRPC: introduce xdr_init_decode_pages
In reply to Benny HalevyInitialize xdr_stream and xdr_buf using an array of page pointers and length of buffer.
--- fs/nfs/dir.c | 9 ++------- fs/nfs/nfs4filelayout.c | 9 ++------- fs/nfs/nfs4filelayoutdev.c | 9 ++------- include/linux/sunrpc/xdr.h | 2 ++ net/sunrpc/xdr.c | 19 +++++++++++++++++++ 5 files changed, 27 insertions(+), 21 deletions(-)
fs/nfs/dir.c +2 -7
@@ -512,12 +512,7 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en struct page **xdr_pages, struct page *page, unsigned int buflen) { struct xdr_stream stream; -struct xdr_buf buf = { - .pages = xdr_pages, - .page_len = buflen, - .buflen = buflen, - .len = buflen, - }; +struct xdr_buf buf;struct page *scratch;struct nfs_cache_array *array;unsigned int count =0 ;
@@ -527,7 +522,7 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *enif (scratch ==NULL )return -ENOMEM ; -xdr_init_decode (&stream, &buf,NULL ); +xdr_init_decode_pages (&stream, &buf, xdr_pages, buflen);xdr_set_scratch_buffer (&stream,page_address (scratch),PAGE_SIZE ); do {
fs/nfs/nfs4filelayout.c +2 -7
@@ -509,12 +509,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, gfp_t gfp_flags) {struct xdr_stream stream; -struct xdr_buf buf = { - .pages = lgr->layoutp->pages, - .page_len = lgr->layoutp->len, - .buflen = lgr->layoutp->len, - .len = lgr->layoutp->len, - }; +struct xdr_buf buf;struct page *scratch;__be32 *p;uint32_t nfl_util;
@@ -526,7 +521,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,if (!scratch)return -ENOMEM ; -xdr_init_decode (&stream, &buf,NULL ); +xdr_init_decode_pages (&stream, &buf, lgr->layoutp->pages, lgr->layoutp->len);xdr_set_scratch_buffer (&stream,page_address (scratch),PAGE_SIZE );/* 20 = ufl_util (4), first_stripe_index (4), pattern_offset (8),
fs/nfs/nfs4filelayoutdev.c +2 -7
@@ -308,12 +308,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags)u8 max_stripe_index;struct nfs4_file_layout_dsaddr *dsaddr =NULL ;struct xdr_stream stream; -struct xdr_buf buf = { - .pages = pdev->pages, - .page_len = pdev->pglen, - .buflen = pdev->pglen, - .len = pdev->pglen, - }; +struct xdr_buf buf;struct page *scratch;/* set up xdr stream */
@@ -321,7 +316,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags)if (!scratch) goto out_err; -xdr_init_decode (&stream, &buf,NULL ); +xdr_init_decode_pages (&stream, &buf, pdev->pages, pdev->pglen);xdr_set_scratch_buffer (&stream,page_address (scratch),PAGE_SIZE );/* Get the stripe count (number of stripe index) */
include/linux/sunrpc/xdr.h +2 -0
@@ -216,6 +216,8 @@ extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes);extern void xdr_write_pages (struct xdr_stream *xdr,struct page **pages,unsigned int base,unsigned int len);extern void xdr_init_decode (struct xdr_stream *xdr,struct xdr_buf *buf,__be32 *p); +extern void xdr_init_decode_pages (struct xdr_stream *xdr,struct xdr_buf *buf, +struct page **pages,unsigned int len);extern void xdr_set_scratch_buffer (struct xdr_stream *xdr,void *buf,size_t buflen);extern __be32 *xdr_inline_decode (struct xdr_stream *xdr,size_t nbytes);extern void xdr_read_pages (struct xdr_stream *xdr,unsigned int len);
net/sunrpc/xdr.c +19 -0
@@ -638,6 +638,25 @@ void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p) }EXPORT_SYMBOL_GPL (xdr_init_decode); +/** +* xdr_init_decode - Initialize an xdr_stream for decoding data. +* @xdr: pointer to xdr_stream struct +* @buf: pointer to XDR buffer from which to decode data +* @pages: list of pages to decode into +* @len: length in bytes of buffer in pages +*/ +void xdr_init_decode_pages (struct xdr_stream *xdr,struct xdr_buf *buf, +struct page **pages,unsigned int len) +{ +memset (buf,0 ,sizeof (*buf)); + buf->pages = pages; + buf->page_len = len; + buf->buflen = len; + buf->len = len; +xdr_init_decode (xdr, buf,NULL ); +} +EXPORT_SYMBOL_GPL (xdr_init_decode_pages); +static __be32 *__xdr_inline_decode (struct xdr_stream *xdr,size_t nbytes) {__be32 *p = xdr->p;
Signature · 1 line
1.7.3.4
PATCH v6 7/26 pnfs: Use byte-range for layoutget
In reply to Benny HalevyAdd offset and count parameters to pnfs_update_layout and use them to get the layout in the pageio path.
Order cache layout segments in the following order:
* offset (ascending)
* length (descending)
* iomode (RW before READ)
Test byte range against the layout segment in use in pnfs_{read,write}_pg_test so not to coalesce pages not using the same layout segment.
--- fs/nfs/pnfs.c | 165 ++++++++++++++++++++++++++++++++++++++++++------------- fs/nfs/pnfs.h | 6 ++- fs/nfs/read.c | 8 ++- fs/nfs/write.c | 8 ++- 4 files changed, 142 insertions(+), 45 deletions(-)
fs/nfs/pnfs.c +126 -39
@@ -261,6 +261,65 @@ put_lseg(struct pnfs_layout_segment *lseg) }EXPORT_SYMBOL_GPL (put_lseg); +static inline u64 +end_offset (u64 start,u64 len) +{ +u64 end; + + end = start + len; +return end >= start ? end :NFS4_MAX_UINT64 ; +} + +/* last octet in a range */ +static inline u64 +last_byte_offset (u64 start,u64 len) +{ +u64 end; + +BUG_ON (!len); + end = start + len; +return end > start ? end -1 :NFS4_MAX_UINT64 ; +} + +/* +* is l2 fully contained in l1? +* start1 end1 +* [----------------------------------) +* start2 end2 +* [----------------) +*/ +static inline int +lo_seg_contained (struct pnfs_layout_range *l1, +struct pnfs_layout_range *l2) +{ +u64 start1 = l1->offset; +u64 end1 =end_offset (start1, l1->length); +u64 start2 = l2->offset; +u64 end2 =end_offset (start2, l2->length); + +return (start1 <= start2) && (end1 >= end2); +} + +/* +* is l1 and l2 intersecting? +* start1 end1 +* [----------------------------------) +* start2 end2 +* [----------------) +*/ +static inline int +lo_seg_intersecting (struct pnfs_layout_range *l1, +struct pnfs_layout_range *l2) +{ +u64 start1 = l1->offset; +u64 end1 =end_offset (start1, l1->length); +u64 start2 = l2->offset; +u64 end2 =end_offset (start2, l2->length); + +return (end1 ==NFS4_MAX_UINT64 || end1 > start2) && + (end2 ==NFS4_MAX_UINT64 || end2 > start1); +} +static bool should_free_lseg (u32 lseg_iomode,u32 recall_iomode) {
@@ -467,7 +526,7 @@ pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,static struct pnfs_layout_segment *send_layoutget (struct pnfs_layout_hdr *lo,struct nfs_open_context *ctx, -u32 iomode, +struct pnfs_layout_range *range,gfp_t gfp_flags) {struct inode *ino = lo->plh_inode;
@@ -499,11 +558,11 @@ send_layoutget(struct pnfs_layout_hdr *lo, goto out_err_free; } - lgp->args.minlength =NFS4_MAX_UINT64 ; + lgp->args.minlength =PAGE_CACHE_SIZE ; +if (lgp->args.minlength > range->length) + lgp->args.minlength = range->length; lgp->args.maxcount =PNFS_LAYOUT_MAXSIZE ; - lgp->args.range.iomode = iomode; - lgp->args.range.offset =0 ; - lgp->args.range.length =NFS4_MAX_UINT64 ; + lgp->args.range = *range; lgp->args.type = server->pnfs_curr_ld->id; lgp->args.inode = ino; lgp->args.ctx =get_nfs_open_context (ctx);
@@ -518,7 +577,7 @@ send_layoutget(struct pnfs_layout_hdr *lo,nfs4_proc_layoutget (lgp);if (!lseg) {/* remember that LAYOUTGET failed and suspend trying */ -set_bit (lo_fail_bit (iomode), &lo->plh_flags); +set_bit (lo_fail_bit (range->iomode), &lo->plh_flags); }/* free xdr pages */
@@ -625,10 +684,23 @@ bool pnfs_roc_drain(struct inode *ino, u32 *barrier)* are seen first. */ static s64 -cmp_layout (u32 iomode1,u32 iomode2) +cmp_layout (struct pnfs_layout_range *l1, +struct pnfs_layout_range *l2) { +s64 d; + +/* high offset > low offset */ + d = l1->offset - l2->offset; +if (d) +return d; + +/* short length > long length */ + d = l2->length - l1->length; +if (d) +return d; +/* read > read/write */ -return (int )(iomode2 ==IOMODE_READ ) - (int )(iomode1 ==IOMODE_READ ); +return (int )(l1->iomode ==IOMODE_READ ) - (int )(l2->iomode ==IOMODE_READ ); } static void
@@ -636,13 +708,12 @@ pnfs_insert_layout(struct pnfs_layout_hdr *lo, struct pnfs_layout_segment *lseg) {struct pnfs_layout_segment *lp; -int found =0 ;dprintk ("%s:Begin\n" , __func__);assert_spin_locked (&lo->plh_inode->i_lock);list_for_each_entry (lp, &lo->plh_segs, pls_list) { -if (cmp_layout (lp->pls_range.iomode, lseg->pls_range.iomode) >0 ) +if (cmp_layout (&lseg->pls_range, &lp->pls_range) >0 )continue ;list_add_tail (&lseg->pls_list, &lp->pls_list); dprintk("%s: inserted lseg %p "
@@ -652,16 +723,14 @@ pnfs_insert_layout(struct pnfs_layout_hdr *lo, lseg->pls_range.offset, lseg->pls_range.length, lp, lp->pls_range.iomode, lp->pls_range.offset, lp->pls_range.length); - found =1 ; -break ; - } -if (!found) { -list_add_tail (&lseg->pls_list, &lo->plh_segs); -dprintk ("%s: inserted lseg %p " -"iomode %d offset %llu length %llu at tail\n" , - __func__, lseg, lseg->pls_range.iomode, - lseg->pls_range.offset, lseg->pls_range.length); + goto out; } +list_add_tail (&lseg->pls_list, &lo->plh_segs); +dprintk ("%s: inserted lseg %p " +"iomode %d offset %llu length %llu at tail\n" , + __func__, lseg, lseg->pls_range.iomode, + lseg->pls_range.offset, lseg->pls_range.length); +out:get_layout_hdr (lo);dprintk ("%s:Return\n" , __func__);
@@ -721,16 +790,28 @@ pnfs_find_alloc_layout(struct inode *ino, gfp_t gfp_flags)* READ RW true */ static int -is_matching_lseg (struct pnfs_layout_segment *lseg,u32 iomode) +is_matching_lseg (struct pnfs_layout_range *ls_range, +struct pnfs_layout_range *range) { -return (iomode !=IOMODE_RW || lseg->pls_range.iomode ==IOMODE_RW ); +struct pnfs_layout_range range1; + +if ((range->iomode ==IOMODE_RW && + ls_range->iomode !=IOMODE_RW ) || + !lo_seg_intersecting (ls_range, range)) +return 0 ; + +/* range1 covers only the first byte in the range */ + range1 = *range; + range1.length =1 ; +return lo_seg_contained (ls_range, &range1); }/* * lookup range in layout */ static struct pnfs_layout_segment * -pnfs_find_lseg (struct pnfs_layout_hdr *lo,u32 iomode) +pnfs_find_lseg (struct pnfs_layout_hdr *lo, +struct pnfs_layout_range *range) {struct pnfs_layout_segment *lseg, *ret =NULL ;
@@ -739,11 +820,11 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo, u32 iomode)assert_spin_locked (&lo->plh_inode->i_lock);list_for_each_entry (lseg, &lo->plh_segs, pls_list) {if (test_bit (NFS_LSEG_VALID , &lseg->pls_flags) && -is_matching_lseg (lseg, iomode)) { +is_matching_lseg (&lseg->pls_range, range)) { ret =get_lseg (lseg);break ; } -if (cmp_layout (iomode, lseg->pls_range.iomode) >0 ) +if (cmp_layout (range, &lseg->pls_range) >0 )break ; }
@@ -759,9 +840,16 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo, u32 iomode)struct pnfs_layout_segment *pnfs_update_layout (struct inode *ino,struct nfs_open_context *ctx, +loff_t pos, +u64 count,enum pnfs_iomode iomode,gfp_t gfp_flags) { +struct pnfs_layout_range arg = { + .iomode = iomode, + .offset = pos, + .length = count, + };struct nfs_inode *nfsi =NFS_I (ino);struct nfs_client *clp =NFS_SERVER (ino)->nfs_client;struct pnfs_layout_hdr *lo;
@@ -789,7 +877,7 @@ pnfs_update_layout(struct inode *ino, goto out_unlock;/* Check to see if the layout for the given range already exists */ - lseg =pnfs_find_lseg (lo, iomode); + lseg =pnfs_find_lseg (lo, &arg);if (lseg) goto out_unlock;
@@ -811,7 +899,7 @@ pnfs_update_layout(struct inode *ino,spin_unlock (&clp->cl_lock); } - lseg =send_layoutget (lo, ctx, iomode, gfp_flags); + lseg =send_layoutget (lo, ctx, &arg, gfp_flags);if (!lseg && first) {spin_lock (&clp->cl_lock);list_del_init (&lo->plh_layouts);
@@ -838,17 +926,6 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)struct nfs_client *clp =NFS_SERVER (ino)->nfs_client;int status =0 ; -/* Verify we got what we asked for. -* Note that because the xdr parsing only accepts a single -* element array, this can fail even if the server is behaving -* correctly. -*/ -if (lgp->args.range.iomode > res->range.iomode || - res->range.offset !=0 || - res->range.length !=NFS4_MAX_UINT64 ) { - status = -EINVAL ; - goto out; - }/* Inject layout blob into I/O device driver */ lseg =NFS_SERVER (ino)->pnfs_curr_ld->alloc_lseg (lo, res, lgp->gfp_flags);if (!lseg ||IS_ERR (lseg)) {
@@ -903,9 +980,14 @@ static int pnfs_read_pg_test(struct nfs_pageio_descriptor *pgio,/* This is first coelesce call for a series of nfs_pages */ pgio->pg_lseg =pnfs_update_layout (pgio->pg_inode, prev->wb_context, +req_offset (req), + pgio->pg_count,IOMODE_READ ,GFP_KERNEL ); - } + }else if (pgio->pg_lseg && +req_offset (req) >end_offset (pgio->pg_lseg->pls_range.offset, + pgio->pg_lseg->pls_range.length)) +return 0 ;return NFS_SERVER (pgio->pg_inode)->pnfs_curr_ld->pg_test (pgio, prev, req); }
@@ -926,9 +1008,14 @@ static int pnfs_write_pg_test(struct nfs_pageio_descriptor *pgio,/* This is first coelesce call for a series of nfs_pages */ pgio->pg_lseg =pnfs_update_layout (pgio->pg_inode, prev->wb_context, +req_offset (req), + pgio->pg_count,IOMODE_RW ,GFP_NOFS ); - } + }else if (pgio->pg_lseg && +req_offset (req) >end_offset (pgio->pg_lseg->pls_range.offset, + pgio->pg_lseg->pls_range.length)) +return 0 ;return NFS_SERVER (pgio->pg_inode)->pnfs_curr_ld->pg_test (pgio, prev, req); }
fs/nfs/pnfs.h +4 -2
@@ -131,7 +131,8 @@ void get_layout_hdr(struct pnfs_layout_hdr *lo);void put_lseg (struct pnfs_layout_segment *lseg);struct pnfs_layout_segment *pnfs_update_layout (struct inode *ino,struct nfs_open_context *ctx, -enum pnfs_iomode access_type,gfp_t gfp_flags); +loff_t pos,u64 count,enum pnfs_iomode access_type, +gfp_t gfp_flags);void set_pnfs_layoutdriver (struct nfs_server *,u32 id);void unset_pnfs_layoutdriver (struct nfs_server *); enum pnfs_try_status pnfs_try_to_write_data(struct nfs_write_data *,
@@ -271,7 +272,8 @@ static inline void put_lseg(struct pnfs_layout_segment *lseg)static inline struct pnfs_layout_segment *pnfs_update_layout (struct inode *ino,struct nfs_open_context *ctx, -enum pnfs_iomode access_type,gfp_t gfp_flags) +loff_t pos,u64 count,enum pnfs_iomode access_type, +gfp_t gfp_flags) {return NULL ; }
fs/nfs/read.c +6 -2
@@ -288,7 +288,9 @@ static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc)atomic_set (&req->wb_complete, requests);BUG_ON (desc->pg_lseg !=NULL ); - lseg =pnfs_update_layout (desc->pg_inode, req->wb_context,IOMODE_READ ,GFP_KERNEL ); + lseg =pnfs_update_layout (desc->pg_inode, req->wb_context, +req_offset (req), desc->pg_count, +IOMODE_READ ,GFP_KERNEL );ClearPageError (page); offset =0 ; nbytes = desc->pg_count;
@@ -351,7 +353,9 @@ static int nfs_pagein_one(struct nfs_pageio_descriptor *desc) } req =nfs_list_entry (data->pages.next);if ((!lseg) &&list_is_singular (&data->pages)) - lseg =pnfs_update_layout (desc->pg_inode, req->wb_context,IOMODE_READ ,GFP_KERNEL ); + lseg =pnfs_update_layout (desc->pg_inode, req->wb_context, +req_offset (req), desc->pg_count, +IOMODE_READ ,GFP_KERNEL ); ret =nfs_read_rpcsetup (req, data, &nfs_read_full_ops, desc->pg_count,0 , lseg);
fs/nfs/write.c +6 -2
@@ -939,7 +939,9 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc)atomic_set (&req->wb_complete, requests);BUG_ON (desc->pg_lseg); - lseg =pnfs_update_layout (desc->pg_inode, req->wb_context,IOMODE_RW ,GFP_NOFS ); + lseg =pnfs_update_layout (desc->pg_inode, req->wb_context, +req_offset (req), desc->pg_count, +IOMODE_RW ,GFP_NOFS );ClearPageError (page); offset =0 ; nbytes = desc->pg_count;
@@ -1013,7 +1015,9 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc) } req =nfs_list_entry (data->pages.next);if ((!lseg) &&list_is_singular (&data->pages)) - lseg =pnfs_update_layout (desc->pg_inode, req->wb_context,IOMODE_RW ,GFP_NOFS ); + lseg =pnfs_update_layout (desc->pg_inode, req->wb_context, +req_offset (req), desc->pg_count, +IOMODE_RW ,GFP_NOFS );if ((desc->pg_ioflags &FLUSH_COND_STABLE ) && (desc->pg_moreio ||NFS_I (desc->pg_inode)->ncommit))
Signature · 1 line
1.7.3.4
PATCH v6 8/26 pnfs: align layoutget requests on page boundaries
In reply to Benny Halevy--- fs/nfs/pnfs.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-)
fs/nfs/pnfs.c +8 -0
@@ -850,6 +850,7 @@ pnfs_update_layout(struct inode *ino, .offset = pos, .length = count, }; +unsigned pg_offset;struct nfs_inode *nfsi =NFS_I (ino);struct nfs_client *clp =NFS_SERVER (ino)->nfs_client;struct pnfs_layout_hdr *lo;
@@ -899,6 +900,13 @@ pnfs_update_layout(struct inode *ino,spin_unlock (&clp->cl_lock); } + pg_offset = arg.offset & ~PAGE_CACHE_MASK ; +if (pg_offset) { + arg.offset -= pg_offset; + arg.length += pg_offset; + } + arg.length =PAGE_CACHE_ALIGN (arg.length); + lseg =send_layoutget (lo, ctx, &arg, gfp_flags);if (!lseg && first) {spin_lock (&clp->cl_lock);
Signature · 1 line
1.7.3.4
PATCH v6 9/26 pnfs: Use byte-range for cb_layoutrecall
In reply to Benny HalevyUse recalled range to invalidate particular layout segments in the layout cache.
--- fs/nfs/callback_proc.c | 4 ++-- fs/nfs/pnfs.c | 15 +++++++++------ fs/nfs/pnfs.h | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-)
fs/nfs/callback_proc.c +2 -2
@@ -139,7 +139,7 @@ static u32 initiate_file_draining(struct nfs_client *clp,spin_lock (&ino->i_lock);if (test_bit (NFS_LAYOUT_BULK_RECALL , &lo->plh_flags) ||mark_matching_lsegs_invalid (lo, &free_me_list, - args->cbl_range.iomode)) + &args->cbl_range)) rv =NFS4ERR_DELAY ;else rv =NFS4ERR_NOMATCHING_LAYOUT ;
@@ -184,7 +184,7 @@ static u32 initiate_bulk_draining(struct nfs_client *clp, ino = lo->plh_inode;spin_lock (&ino->i_lock);set_bit (NFS_LAYOUT_BULK_RECALL , &lo->plh_flags); -if (mark_matching_lsegs_invalid (lo, &free_me_list, range.iomode)) +if (mark_matching_lsegs_invalid (lo, &free_me_list, &range)) rv =NFS4ERR_DELAY ;list_del_init (&lo->plh_bulk_recall);spin_unlock (&ino->i_lock);
fs/nfs/pnfs.c +9 -6
@@ -321,10 +321,12 @@ lo_seg_intersecting(struct pnfs_layout_range *l1, }static bool -should_free_lseg (u32 lseg_iomode,u32 recall_iomode) +should_free_lseg (struct pnfs_layout_range *lseg_range, +struct pnfs_layout_range *recall_range) { -return (recall_iomode ==IOMODE_ANY || - lseg_iomode == recall_iomode); +return (recall_range->iomode ==IOMODE_ANY || + lseg_range->iomode == recall_range->iomode) && +lo_seg_intersecting (lseg_range, recall_range); }/* Returns 1 if lseg is removed from list, 0 otherwise */
@@ -355,7 +357,7 @@ static int mark_lseg_invalid(struct pnfs_layout_segment *lseg,int mark_matching_lsegs_invalid (struct pnfs_layout_hdr *lo,struct list_head *tmp_list, -u32 iomode) +struct pnfs_layout_range *recall_range) {struct pnfs_layout_segment *lseg, *next;int invalid =0 , removed =0 ;
@@ -368,7 +370,8 @@ mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo,return 0 ; }list_for_each_entry_safe (lseg, next, &lo->plh_segs, pls_list) -if (should_free_lseg (lseg->pls_range.iomode, iomode)) { +if (!recall_range || +should_free_lseg (&lseg->pls_range, recall_range)) { dprintk("%s: freeing lseg %p iomode %d " "offset %llu length %llu\n", __func__, lseg, lseg->pls_range.iomode, lseg->pls_range.offset,
@@ -417,7 +420,7 @@ pnfs_destroy_layout(struct nfs_inode *nfsi) lo = nfsi->layout;if (lo) { lo->plh_block_lgets++;/* permanently block new LAYOUTGETs */ -mark_matching_lsegs_invalid (lo, &tmp_list,IOMODE_ANY ); +mark_matching_lsegs_invalid (lo, &tmp_list,NULL ); }spin_unlock (&nfsi->vfs_inode.i_lock);pnfs_free_lseg_list (&tmp_list);
fs/nfs/pnfs.h +1 -1
@@ -154,7 +154,7 @@ int pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct nfs4_state *open_state);int mark_matching_lsegs_invalid (struct pnfs_layout_hdr *lo,struct list_head *tmp_list, -u32 iomode); +struct pnfs_layout_range *recall_range);bool pnfs_roc (struct inode *ino);void pnfs_roc_release (struct inode *ino);void pnfs_roc_set_barrier (struct inode *ino,u32 barrier);
Signature · 1 line
1.7.3.4
PATCH v6 10/26 pnfs: client stats
In reply to Benny HalevyFrom: J. Bruce Fields <[email protected]>
A pNFS client auto-negotiates a lot of features (minorversion level, pNFS layout type, etc.). This is convenient, but makes certain kinds of failures hard for a user to detect.
For example, if the client falls back on 4.0, or falls back to MDS IO because the user didn't connect to the right iscsi disks before mounting, the only symptoms may be reduced performance, which may not be noticed till long after the actual failure, and may be difficult for a user to diagnose.
However, such "failures" may also be perfectly normal in some cases, so we don't want to spam the system logs with them.
One approach would be to put some more information into /proc/self/mountstats.
There is a build error when CONFIG_NFS_V4 is set but CONFIG_NFS_V4_1 is *not* set. show_sessions() prototype was unbalanced between the two cases.
--- fs/nfs/super.c | 25 +++++++++++++++++++++++++ 1 files changed, 25 insertions(+), 0 deletions(-)
fs/nfs/super.c +25 -0
@@ -63,6 +63,7 @@#include "iostat.h" #include "internal.h" #include "fscache.h" +#include "pnfs.h" #define NFSDBG_FACILITY NFSDBG_VFS
@@ -732,6 +733,28 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)return 0 ; } +#ifdef CONFIG_NFS_V4_1 +void show_sessions (struct seq_file *m,struct nfs_server *server) +{ +if (nfs4_has_session (server->nfs_client)) +seq_printf (m,",sessions" ); +} +#else +void show_sessions (struct seq_file *m,struct nfs_server *server) {} +#endif + +#ifdef CONFIG_NFS_V4_1 +void show_pnfs (struct seq_file *m,struct nfs_server *server) +{ +seq_printf (m,",pnfs=" ); +if (server->pnfs_curr_ld) +seq_printf (m,"%s" , server->pnfs_curr_ld->name); +else +seq_printf (m,"not configured" ); +} +#else /* CONFIG_NFS_V4_1 */ +void show_pnfs (struct seq_file *m,struct nfs_server *server) {} +#endif /* CONFIG_NFS_V4_1 */ static int nfs_show_devname (struct seq_file *m,struct vfsmount *mnt) {
@@ -792,6 +815,8 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)seq_printf (m,"bm0=0x%x" , nfss->attr_bitmask[0 ]);seq_printf (m,",bm1=0x%x" , nfss->attr_bitmask[1 ]);seq_printf (m,",acl=0x%x" , nfss->acl_bitmask); +show_sessions (m, nfss); + show_pnfs(m, nfss); }#endif
Signature · 1 line
1.7.3.4
PATCH v6 11/26 pnfs-obj: objlayoutdriver module skeleton
In reply to Benny Halevy* Define the PNFS_OBJLAYOUT Kconfig option in the nfs master Kconfig file.
* Add the objlayout driver to the Kernel's Kbuild system.
* Add the fs/nfs/objlayout/Kbuild file for building the objlayoutdriver.ko driver
* Define fs/nfs/objlayout/objio_osd.c, register the driver on module initialization and unregister on exit.
--- fs/nfs/Kconfig | 10 +++++ fs/nfs/Makefile | 2 + fs/nfs/objlayout/Kbuild | 5 +++ fs/nfs/objlayout/objio_osd.c | 76 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 0 deletions(-) create mode 100644 fs/nfs/objlayout/Kbuild create mode 100644 fs/nfs/objlayout/objio_osd.c
fs/nfs/Kconfig +10 -0
@@ -87,6 +87,16 @@ config NFS_V4_1 config PNFS_FILE_LAYOUT tristate +config PNFS_OBJLAYOUT + tristate "Provide support for the pNFS Objects Layout Driver for NFSv4.1 pNFS (EXPERIMENTAL)" + depends on NFS_FS && NFS_V4_1 && SCSI_OSD_ULD + help + Say M here if you want your pNFS client to support the Objects Layout Driver. + Requires the SCSI osd initiator library (SCSI_OSD_INITIATOR) and + upper level driver (SCSI_OSD_ULD). + + If unsure, say N. + config ROOT_NFS bool "Root file system on NFS" depends on NFS_FS=y && IP_PNP
fs/nfs/Makefile +2 -0
@@ -21,3 +21,5 @@ nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o + +obj-$(CONFIG_PNFS_OBJLAYOUT) += objlayout/
fs/nfs/objlayout/Kbuild new file +5 -0
@@ -0,0 +1,5 @@ +# +# Makefile for the pNFS Objects Layout Driver kernel module +# +objlayoutdriver-y := objio_osd.o +obj-$(CONFIG_PNFS_OBJLAYOUT) += objlayoutdriver.o
fs/nfs/objlayout/objio_osd.c new file +76 -0
76 lines not on this page · raw message
Signature · 1 line
1.7.3.4
PATCH v6 12/26 pnfs-obj: pnfs_osd XDR definitions
In reply to Benny Halevy* Add the pnfs_osd_xdr.h header
* defintions the pnfs_osd_layout structure including all it's sub-types and constants.
* Declare the pnfs_osd_xdr_encode/decode_layout API + all needed inline helpers.
* Define the pnfs_osd_deviceaddr structure and all its subtypes and constants.
* Declare API for encoding/decoding of a pnfs_osd_deviceaddr to/from XDR stream.
* Define the pnfs_osd_ioerr structure, its substructures and constants.
* Declare API for encoding/decoding of a pnfs_osd_ioerr to/from XDR stream.
* Define the pnfs_osd_layoutupdate structure and its substructures.
* Declare API for encoding/decoding of a pnfs_osd_layoutupdate to/from XDR stream.
--- include/linux/pnfs_osd_xdr.h | 350 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 350 insertions(+), 0 deletions(-) create mode 100644 include/linux/pnfs_osd_xdr.h
include/linux/pnfs_osd_xdr.h new file +350 -0
@@ -0,0 +1,350 @@ +/* +* pNFS-osd on-the-wire data structures +* +* Copyright (C) 2007 Panasas Inc. [year of first publication] +* All rights reserved. +* +* Benny Halevy <[email protected]> +* Boaz Harrosh <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 +* See the file COPYING included with this distribution for more details. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* 3. Neither the name of the Panasas company nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef __PNFS_OSD_XDR_H__ +#define __PNFS_OSD_XDR_H__ + +#include <linux/nfs_fs.h> +#include <linux/nfs_page.h> +#include <scsi/osd_protocol.h> + +#define PNFS_OSD_OSDNAME_MAXSIZE 256 + +/* +* draft-ietf-nfsv4-minorversion-22 +* draft-ietf-nfsv4-pnfs-obj-12 +*/ + +/* Layout Structure */ + +enum pnfs_osd_raid_algorithm4 { +PNFS_OSD_RAID_0 =1 , +PNFS_OSD_RAID_4 =2 , +PNFS_OSD_RAID_5 =3 , +PNFS_OSD_RAID_PQ =4 /* Reed-Solomon P+Q */ +}; + +/* struct pnfs_osd_data_map4 { +* uint32_t odm_num_comps; +* length4 odm_stripe_unit; +* uint32_t odm_group_width; +* uint32_t odm_group_depth; +* uint32_t odm_mirror_cnt; +* pnfs_osd_raid_algorithm4 odm_raid_algorithm; +* }; +*/ +struct pnfs_osd_data_map { +u32 odm_num_comps; +u64 odm_stripe_unit; +u32 odm_group_width; +u32 odm_group_depth; +u32 odm_mirror_cnt; +u32 odm_raid_algorithm; +}; + +/* struct pnfs_osd_objid4 { +* deviceid4 oid_device_id; +* uint64_t oid_partition_id; +* uint64_t oid_object_id; +* }; +*/ +struct pnfs_osd_objid { +struct nfs4_deviceid oid_device_id; +u64 oid_partition_id; +u64 oid_object_id; +}; + +/* For printout. I use: +* kprint("dev(%llx:%llx)", _DEVID_LO(pointer), _DEVID_HI(pointer)); +* BE style +*/ +#define _DEVID_LO (oid_device_id) \ + (unsigned long long)be64_to_cpup((__be64 *)(oid_device_id)->data) + +#define _DEVID_HI (oid_device_id) \ + (unsigned long long)be64_to_cpup(((__be64 *)(oid_device_id)->data) + 1) + +static inline int +pnfs_osd_objid_xdr_sz (void ) +{ +return (NFS4_DEVICEID4_SIZE /4 ) +2 +2 ; +} + +enum pnfs_osd_version { +PNFS_OSD_MISSING =0 , +PNFS_OSD_VERSION_1 =1 , +PNFS_OSD_VERSION_2 =2 +}; + +struct pnfs_osd_opaque_cred { +u32 cred_len; +void *cred; +}; + +enum pnfs_osd_cap_key_sec { +PNFS_OSD_CAP_KEY_SEC_NONE =0 , +PNFS_OSD_CAP_KEY_SEC_SSV =1 , +}; + +/* struct pnfs_osd_object_cred4 { +* pnfs_osd_objid4 oc_object_id; +* pnfs_osd_version4 oc_osd_version; +* pnfs_osd_cap_key_sec4 oc_cap_key_sec; +* opaque oc_capability_key<>; +* opaque oc_capability<>; +* }; +*/ +struct pnfs_osd_object_cred { +struct pnfs_osd_objid oc_object_id; +u32 oc_osd_version; +u32 oc_cap_key_sec; +struct pnfs_osd_opaque_cred oc_cap_key; +struct pnfs_osd_opaque_cred oc_cap; +}; + +/* struct pnfs_osd_layout4 { +* pnfs_osd_data_map4 olo_map; +* uint32_t olo_comps_index; +* pnfs_osd_object_cred4 olo_components<>; +* }; +*/ +struct pnfs_osd_layout { +struct pnfs_osd_data_map olo_map; +u32 olo_comps_index; +u32 olo_num_comps; +struct pnfs_osd_object_cred *olo_comps; +}; + +/* Device Address */ +enum pnfs_osd_targetid_type { +OBJ_TARGET_ANON =1 , +OBJ_TARGET_SCSI_NAME =2 , +OBJ_TARGET_SCSI_DEVICE_ID =3 , +}; + +/* union pnfs_osd_targetid4 switch (pnfs_osd_targetid_type4 oti_type) { +* case OBJ_TARGET_SCSI_NAME: +* string oti_scsi_name<>; +* +* case OBJ_TARGET_SCSI_DEVICE_ID: +* opaque oti_scsi_device_id<>; +* +* default: +* void; +* }; +* +* union pnfs_osd_targetaddr4 switch (bool ota_available) { +* case TRUE: +* netaddr4 ota_netaddr; +* case FALSE: +* void; +* }; +* +* struct pnfs_osd_deviceaddr4 { +* pnfs_osd_targetid4 oda_targetid; +* pnfs_osd_targetaddr4 oda_targetaddr; +* uint64_t oda_lun; +* opaque oda_systemid<>; +* pnfs_osd_object_cred4 oda_root_obj_cred; +* opaque oda_osdname<>; +* }; +*/ +struct pnfs_osd_targetid { +u32 oti_type; +struct nfs4_string oti_scsi_device_id; +}; + +enum {PNFS_OSD_TARGETID_MAX =1 +PNFS_OSD_OSDNAME_MAXSIZE /4 }; + +/* struct netaddr4 { +* // see struct rpcb in RFC1833 +* string r_netid<>; // network id +* string r_addr<>; // universal address +* }; +*/ +struct pnfs_osd_net_addr { +struct nfs4_string r_netid; +struct nfs4_string r_addr; +}; + +struct pnfs_osd_targetaddr { +u32 ota_available; +struct pnfs_osd_net_addr ota_netaddr; +}; + +enum { +NETWORK_ID_MAX =16 /4 , +UNIVERSAL_ADDRESS_MAX =64 /4 , +PNFS_OSD_TARGETADDR_MAX =3 +NETWORK_ID_MAX +UNIVERSAL_ADDRESS_MAX , +}; + +struct pnfs_osd_deviceaddr { +struct pnfs_osd_targetid oda_targetid; +struct pnfs_osd_targetaddr oda_targetaddr; +u8 oda_lun[8 ]; +struct nfs4_string oda_systemid; +struct pnfs_osd_object_cred oda_root_obj_cred; +struct nfs4_string oda_osdname; +}; + +enum { +ODA_OSDNAME_MAX =PNFS_OSD_OSDNAME_MAXSIZE /4 , +PNFS_OSD_DEVICEADDR_MAX = +PNFS_OSD_TARGETID_MAX +PNFS_OSD_TARGETADDR_MAX + +2 /*oda_lun*/ + +1 +OSD_SYSTEMID_LEN + +1 +ODA_OSDNAME_MAX , +}; + +/* LAYOUTCOMMIT: layoutupdate */ + +/* union pnfs_osd_deltaspaceused4 switch (bool dsu_valid) { +* case TRUE: +* int64_t dsu_delta; +* case FALSE: +* void; +* }; +* +* struct pnfs_osd_layoutupdate4 { +* pnfs_osd_deltaspaceused4 olu_delta_space_used; +* bool olu_ioerr_flag; +* }; +*/ +struct pnfs_osd_layoutupdate { +u32 dsu_valid; +s64 dsu_delta; +u32 olu_ioerr_flag; +}; + +/* LAYOUTRETURN: I/O Rrror Report */ + +enum pnfs_osd_errno { +PNFS_OSD_ERR_EIO =1 , +PNFS_OSD_ERR_NOT_FOUND =2 , +PNFS_OSD_ERR_NO_SPACE =3 , +PNFS_OSD_ERR_BAD_CRED =4 , +PNFS_OSD_ERR_NO_ACCESS =5 , +PNFS_OSD_ERR_UNREACHABLE =6 , +PNFS_OSD_ERR_RESOURCE =7 +}; + +/* struct pnfs_osd_ioerr4 { +* pnfs_osd_objid4 oer_component; +* length4 oer_comp_offset; +* length4 oer_comp_length; +* bool oer_iswrite; +* pnfs_osd_errno4 oer_errno; +* }; +*/ +struct pnfs_osd_ioerr { +struct pnfs_osd_objid oer_component; +u64 oer_comp_offset; +u64 oer_comp_length; +u32 oer_iswrite; +u32 oer_errno; +}; + +/* OSD XDR API */ +/* Layout helpers */ +/* Layout decoding is done in two parts: +* 1. First Call pnfs_osd_xdr_decode_layout_map to read in only the header part +* of the layout. @iter members need not be initialized. +* Returned: +* @layout members are set. (@layout->olo_comps set to NULL). +* +* Zero on success, or negative error if passed xdr is broken. +* +* 2. 2nd Call pnfs_osd_xdr_decode_layout_comp() in a loop until it returns +* false, to decode the next component. +* Returned: +* true if there is more to decode or false if we are done or error. +* +* Example: +* struct pnfs_osd_xdr_decode_layout_iter iter; +* struct pnfs_osd_layout layout; +* struct pnfs_osd_object_cred comp; +* int status; +* +* status = pnfs_osd_xdr_decode_layout_map(&layout, &iter, xdr); +* if (unlikely(status)) +* goto err; +* while(pnfs_osd_xdr_decode_layout_comp(&comp, &iter, xdr, &status)) { +* // All of @comp strings point to inside the xdr_buffer +* // or scrach buffer. Copy them out to user memory eg. +* copy_single_comp(dest_comp++, &comp); +* } +* if (unlikely(status)) +* goto err; +*/ + +struct pnfs_osd_xdr_decode_layout_iter { +unsigned total_comps; +unsigned decoded_comps; +}; + +extern int pnfs_osd_xdr_decode_layout_map (struct pnfs_osd_layout *layout, +struct pnfs_osd_xdr_decode_layout_iter *iter,struct xdr_stream *xdr); + +extern bool pnfs_osd_xdr_decode_layout_comp (struct pnfs_osd_object_cred *comp, +struct pnfs_osd_xdr_decode_layout_iter *iter,struct xdr_stream *xdr, +int *err); + +/* Device Info helpers */ + +/* Note: All strings inside @deviceaddr point to space inside @p. +* @p should stay valid while @deviceaddr is in use. +*/ +extern void pnfs_osd_xdr_decode_deviceaddr ( +struct pnfs_osd_deviceaddr *deviceaddr,__be32 *p); + +/* layoutupdate (layout_commit) xdr helpers */ +extern int +pnfs_osd_xdr_encode_layoutupdate (struct xdr_stream *xdr, +struct pnfs_osd_layoutupdate *lou); +extern __be32 * +pnfs_osd_xdr_decode_layoutupdate (struct pnfs_osd_layoutupdate *lou,__be32 *p); + +/* osd_ioerror encoding/decoding (layout_return) */ +/* Client */ +extern __be32 *pnfs_osd_xdr_ioerr_reserve_space (struct xdr_stream *xdr); +extern void pnfs_osd_xdr_encode_ioerr (__be32 *p,struct pnfs_osd_ioerr *ioerr); +/* Server*/ +extern __be32 * +pnfs_osd_xdr_decode_ioerr (struct pnfs_osd_ioerr *ioerr,__be32 *p); + +#endif /* __PNFS_OSD_XDR_H__ */
Signature · 1 line
1.7.3.4
PATCH v6 13/26 pnfs-obj: pnfs_osd XDR client implementation
In reply to Benny HalevyFrom: Boaz Harrosh <[email protected]>
* Add the fs/nfs/objlayout/pnfs_osd_xdr_cli.c file, which will include the XDR encode/decode implementations for the pNFS client objlayout driver.
--- fs/nfs/objlayout/Kbuild | 2 +- fs/nfs/objlayout/pnfs_osd_xdr_cli.c | 412 +++++++++++++++++++++++++++++++++++ 2 files changed, 413 insertions(+), 1 deletions(-) create mode 100644 fs/nfs/objlayout/pnfs_osd_xdr_cli.c
fs/nfs/objlayout/Kbuild +1 -1
@@ -1,5 +1,5 @@ # # Makefile for the pNFS Objects Layout Driver kernel module # -objlayoutdriver-y := objio_osd.o +objlayoutdriver-y := objio_osd.o pnfs_osd_xdr_cli.o obj-$(CONFIG_PNFS_OBJLAYOUT) += objlayoutdriver.o
fs/nfs/objlayout/pnfs_osd_xdr_cli.c new file +412 -0
412 lines not on this page · raw message
Signature · 1 line
1.7.3.4
PATCH 1/1 SQUASHME: pnf-obj xdr_cli: Wrong type in comments
--- fs/nfs/objlayout/pnfs_osd_xdr_cli.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
fs/nfs/objlayout/pnfs_osd_xdr_cli.c +2 -2
@@ -47,7 +47,7 @@/* * struct pnfs_osd_objid { -* struct pnfs_deviceid oid_device_id; +* struct nfs4_deviceid oid_device_id; * u64 oid_partition_id; * u64 oid_object_id; * }; // xdr size 32 bytes
@@ -366,7 +366,7 @@ pnfs_osd_xdr_encode_layoutupdate(struct xdr_stream *xdr,/* * struct pnfs_osd_objid { -* struct pnfs_deviceid oid_device_id; +* struct nfs4_deviceid oid_device_id; * u64 oid_partition_id; * u64 oid_object_id; * }; // xdr size 32 bytes
Signature · 1 line
1.7.2.3
PATCH v6 14/26 pnfs-obj: decode layout, alloc/free lseg
In reply to Benny HalevyFrom: Boaz Harrosh <[email protected]>
objlayout_alloc_lseg prepares an xdr_stream and calls the raid engins objio_alloc_lseg() to allocate a private pnfs_layout_segment.
objio_osd.c::objio_alloc_lseg() uses passed xdr_stream to decode and store the layout_segment information in an objio_segment struct, using the pnfs_osd_xdr.h API for the actual parsing the layout xdr.
objlayout_free_lseg calls objio_free_lseg() to free the allocated space.
--- fs/nfs/objlayout/Kbuild | 2 +- fs/nfs/objlayout/objio_osd.c | 169 +++++++++++++++++++++++++++++++++++++++++- fs/nfs/objlayout/objlayout.c | 104 ++++++++++++++++++++++++++ fs/nfs/objlayout/objlayout.h | 67 +++++++++++++++++ 4 files changed, 340 insertions(+), 2 deletions(-) create mode 100644 fs/nfs/objlayout/objlayout.c create mode 100644 fs/nfs/objlayout/objlayout.h
fs/nfs/objlayout/Kbuild +1 -1
@@ -1,5 +1,5 @@ # # Makefile for the pNFS Objects Layout Driver kernel module # -objlayoutdriver-y := objio_osd.o pnfs_osd_xdr_cli.o +objlayoutdriver-y := objio_osd.o pnfs_osd_xdr_cli.o objlayout.o obj-$(CONFIG_PNFS_OBJLAYOUT) += objlayoutdriver.o
fs/nfs/objlayout/objio_osd.c +168 -1
179 lines not on this page · raw message
fs/nfs/objlayout/objlayout.c new file +104 -0
104 lines not on this page · raw message
fs/nfs/objlayout/objlayout.h new file +67 -0
67 lines not on this page · raw message
Signature · 1 line
1.7.3.4
PATCH 1/1 SQUASHME: objio read/write patch: Bugs fixes
Wrong allocation and pointering in lseg_alloc.
Cap BIO size it one page (This hunk goes into the read/write patch)
--- fs/nfs/objlayout/objio_osd.c | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-)
fs/nfs/objlayout/objio_osd.c +8 -4
@@ -147,7 +147,7 @@ struct objio_segment {unsigned comps_index;unsigned num_comps;/* variable length */ -struct osd_dev *ods[1 ]; +struct osd_dev *ods[]; }; static inline struct objio_segment *
@@ -331,7 +331,6 @@ extern int objio_alloc_lseg(struct pnfs_layout_segment **outp,struct pnfs_osd_layout layout;struct pnfs_osd_object_cred *cur_comp, src_comp;struct caps_buffers *caps_p; -int err; err =pnfs_osd_xdr_decode_layout_map (&layout, &iter, xdr);
@@ -342,14 +341,16 @@ extern int objio_alloc_lseg(struct pnfs_layout_segment **outp,if (unlikely (err))return err; - objio_seg =kzalloc (sizeof (*objio_seg) + + objio_seg =kzalloc (sizeof (*objio_seg) + +sizeof (objio_seg->ods[0 ]) * layout.olo_num_comps +sizeof (*objio_seg->comps) * layout.olo_num_comps +sizeof (struct caps_buffers ) * layout.olo_num_comps,GFP_KERNEL );if (!objio_seg)return -ENOMEM ; - cur_comp = objio_seg->comps = (void *)(objio_seg +1 ); + objio_seg->comps = (void *)(objio_seg->ods + layout.olo_num_comps); + cur_comp = objio_seg->comps; caps_p = (void *)(cur_comp + layout.olo_num_comps);while (pnfs_osd_xdr_decode_layout_comp (&src_comp, &iter, xdr, &err)) {copy_single_comp (cur_comp++, &src_comp, caps_p++);
@@ -606,6 +607,9 @@ static int _add_stripe_unit(struct objio_state *ios, unsigned *cur_pg,unsigned bio_size = (ios->ol_state.nr_pages + pages_in_stripe) / stripes; +if (BIO_MAX_PAGES_KMALLOC < bio_size) + bio_size =BIO_MAX_PAGES_KMALLOC ; + per_dev->bio =bio_kmalloc (GFP_KERNEL , bio_size);if (unlikely (!per_dev->bio)) {dprintk ("Faild to allocate BIO size=%u\n" , bio_size);
Signature · 1 line
1.7.2.3
Re: [PATCH] SQUASHME: objio read/write patch: Bugs fixes
Quoted 32 lines · Boaz Harrosh
Wrong allocation and pointering in
lseg_alloc.Cap BIO size it one page (This hunk goes into the read/write patch)
Signed-off-by Boaz Harrosh <[email protected]>--- fs/nfs/objlayout/objio_osd.c | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-)fs/nfs/objlayout/objio_osd.c +1
-2@@ -147,7 +147,7 @@ struct objio_segment {unsigned comps_index;unsigned num_comps;/* variable length */ -struct osd_dev *ods[1 ]; +struct osd_dev *ods[]; }; static inline struct objio_segment *@@ -331,7 +331,6 @@ extern int objio_alloc_lseg(struct pnfs_layout_segment **outp,struct pnfs_osd_layout layout;struct pnfs_osd_object_cred *cur_comp, src_comp;struct caps_buffers *caps_p; -int err; err =pnfs_osd_xdr_decode_layout_map (&layout, &iter, xdr);
fs/nfs/objlayout/objio_osd.c extern int objio_alloc_lseg(struct pnfs_layout_segment **outp, · line 348
Quoted 9 lines
fs/nfs/objlayout/objio_osd.c +2
-1@@ -342,14 +341,16 @@ extern int objio_alloc_lseg(struct pnfs_layout_segment **outp,if (unlikely (err))return err; - objio_seg =kzalloc (sizeof (*objio_seg) + + objio_seg =kzalloc (sizeof (*objio_seg) + +sizeof (objio_seg->ods[0 ]) * layout.olo_num_comps +sizeof (*objio_seg->comps) * layout.olo_num_comps +sizeof (struct caps_buffers ) * layout.olo_num_comps,GFP_KERNEL );
This hunk doesn't apply cleanly, as in the latest version we pass gfp_flags, not GFP_KERNEL.
Quoted 10 lines
fs/nfs/objlayout/objio_osd.c +2
-1if (!objio_seg)return -ENOMEM ; - cur_comp = objio_seg->comps = (void *)(objio_seg +1 ); + objio_seg->comps = (void *)(objio_seg->ods + layout.olo_num_comps); + cur_comp = objio_seg->comps; caps_p = (void *)(cur_comp + layout.olo_num_comps);while (pnfs_osd_xdr_decode_layout_comp (&src_comp, &iter, xdr, &err)) {copy_single_comp (cur_comp++, &src_comp, caps_p++);
fs/nfs/objlayout/objio_osd.c static int _add_stripe_unit(struct objio_state *ios, unsigned *cur_pg, · line 613
Quoted 7 lines
fs/nfs/objlayout/objio_osd.c +3
-0@@ -606,6 +607,9 @@ static int _add_stripe_unit(struct objio_state *ios, unsigned *cur_pg,unsigned bio_size = (ios->ol_state.nr_pages + pages_in_stripe) / stripes; +if (BIO_MAX_PAGES_KMALLOC < bio_size) + bio_size =BIO_MAX_PAGES_KMALLOC ; + per_dev->bio =bio_kmalloc (GFP_KERNEL , bio_size);
ditto
I'll fix that in my tree...
Benny
Quoted 2 lines
fs/nfs/objlayout/objio_osd.c +0
-0if (unlikely (!per_dev->bio)) {dprintk ("Faild to allocate BIO size=%u\n" , bio_size);
Re: [PATCH] SQUASHME: objio read/write patch: Bugs fixes
Quoted 7 lines · Benny Halevy
This hunk doesn't apply cleanly, as in the latest version we pass
gfp_flags, notGFP_KERNEL.Quoted 3 lines
fs/nfs/objlayout/objio_osd.c +0
-0if (!objio_seg)return -ENOMEM ;
Please don't do anything. I'm just now sending a clean SQUASHME set
Please talk to me
Boaz]
Re: [PATCH] SQUASHME: objio read/write patch: Bugs fixes
Quoted 9 lines · Boaz Harrosh
Quoted 7 lines · Benny Halevy
This hunk doesn't apply cleanly, as in the latest version we pass
gfp_flags, notGFP_KERNEL.Quoted 3 lines
fs/nfs/objlayout/objio_osd.c +0
-0if (!objio_seg)return -ENOMEM ;
Quoted 6 lines
Please don't do anything. I'm just now sending a clean SQUASHME set
Please talk to me
Boaz]
OK. I'm waiting for a plumber to arrive in a few minutes so I'll call you later today...
Benny
Re: [PATCH] SQUASHME: objio read/write patch: Bugs fixes
Quoted 13 lines · Benny Halevy
Quoted 12 lines · Boaz Harrosh
Quoted 7 lines · Benny Halevy
This hunk doesn't apply cleanly, as in the latest version we pass
gfp_flags, notGFP_KERNEL.Quoted 3 lines
fs/nfs/objlayout/objio_osd.c +0
-0if (!objio_seg)return -ENOMEM ;Please don't do anything. I'm just now sending a clean SQUASHME set
Quoted 9 lines
Quoted 3 lines
Please talk to me
Boaz]
OK. I'm waiting for a plumber to arrive in a few minutes so I'll call you later today...
Benny
Thanks Benny.
I've now re-sent all the fixes in the right order and properly
separated, to be able to cleanly squash on the V6 patchset from you.
Please see my mail:
[PATCHES 00/12] Mostly a Resend of ALL Bug fixes and SQUASHMEs - pnfs-submit 2.6.40 V7
and the thread that follows, also the proposed patch reorder.
Tell me if you also need the cleaned squashed set. It is no problem.
Boaz
PATCH v6 15/26 pnfs-obj: objio_osd device information retrieval and caching
In reply to Benny HalevyFrom: Boaz Harrosh <[email protected]>
When a new layout is received in objio_alloc_lseg all device_ids referenced are retrieved. The device information is queried for from MDS and then the osd_device is looked-up from the osd-initiator library. The devices are cached in a per-mount-point list, for later use. At unmount all devices are "put" back to the library.
objlayout_get_deviceinfo(), objlayout_put_deviceinfo() middleware API for retrieving device information given a device_id.
TODO: The device cache can get big. Cap its size. Keep an LRU and start
to return devices which were not used, when list gets to big, or when new entries allocation fail.
--- fs/nfs/objlayout/objio_osd.c | 148 +++++++++++++++++++++++++++++++++++++++++- fs/nfs/objlayout/objlayout.c | 68 +++++++++++++++++++ fs/nfs/objlayout/objlayout.h | 8 ++ 3 files changed, 223 insertions(+), 1 deletions(-)
fs/nfs/objlayout/objio_osd.c +147 -1
@@ -46,6 +46,58 @@#define _LLU (x) ((unsigned long long)x) +struct objio_dev_ent { +struct nfs4_deviceid_node id_node; +struct osd_dev *od; +}; + +static void +objio_free_deviceid_node (struct nfs4_deviceid_node *d) +{ + struct objio_dev_ent *de = container_of(d, struct objio_dev_ent, id_node); + +osduld_put_device (de->od); +kfree (de); +} + +static struct objio_dev_ent *_dev_list_find (const struct nfs_client *clp, +const struct nfs4_deviceid *d_id) +{ +struct nfs4_deviceid_node *d; + + d =nfs4_find_get_deviceid (clp, d_id); +if (!d) +return NULL ; + return container_of(d, struct objio_dev_ent, id_node); +} + +static int _dev_list_add (const struct nfs_server *nfss, +const struct nfs4_deviceid *d_id,struct osd_dev *od, +gfp_t gfp_flags) +{ +struct nfs4_deviceid_node *d; +struct objio_dev_ent *de =kzalloc (sizeof (*de), gfp_flags); +struct objio_dev_ent *n; + +if (!de) +return -ENOMEM ; + +nfs4_init_deviceid_node (&de->id_node, + nfss->pnfs_curr_ld, + nfss->nfs_client, + d_id); + de->od = od; + + d =nfs4_insert_deviceid_node (&de->id_node); + n = container_of(d, struct objio_dev_ent, id_node); +if (n != de) { +BUG_ON (n->od != od); +objio_free_deviceid_node (&de->id_node); + } + +return 0 ; +} +struct caps_buffers {u8 caps_key[OSD_CRYPTO_KEYID_SIZE ];u8 creds[OSD_CAP_LEN ];
@@ -65,7 +117,7 @@ struct objio_segment {unsigned comps_index;unsigned num_comps;/* variable length */ -struct osd_dev *ods[1 ]; +struct objio_dev_ent *ods[1 ]; }; static inline struct objio_segment *
@@ -74,6 +126,89 @@ OBJIO_LSEG(struct pnfs_layout_segment *lseg) return container_of(lseg, struct objio_segment, lseg); } +/* Send and wait for a get_device_info of devices in the layout, +then look them up with the osd_initiator library */ +static struct objio_dev_ent *_device_lookup (struct pnfs_layout_hdr *pnfslay, +struct objio_segment *objio_seg,unsigned comp, +gfp_t gfp_flags) +{ +struct pnfs_osd_deviceaddr *deviceaddr; +struct nfs4_deviceid *d_id; +struct objio_dev_ent *ode; +struct osd_dev *od; +struct osd_dev_info odi; +int err; + + d_id = &objio_seg->comps[comp].oc_object_id.oid_device_id; + + ode =_dev_list_find (NFS_SERVER (pnfslay->plh_inode)->nfs_client, d_id); +if (ode) +return ode; + + err =objlayout_get_deviceinfo (pnfslay, d_id, &deviceaddr, gfp_flags); +if (unlikely (err)) { +dprintk ("%s: objlayout_get_deviceinfo dev(%llx:%llx) =>%d\n" , + __func__,_DEVID_LO (d_id),_DEVID_HI (d_id), err); +return ERR_PTR (err); + } + + odi.systemid_len = deviceaddr->oda_systemid.len; +if (odi.systemid_len >sizeof (odi.systemid)) { + err = -EINVAL ; + goto out; + }else if (odi.systemid_len) +memcpy (odi.systemid, deviceaddr->oda_systemid.data, + odi.systemid_len); + odi.osdname_len = deviceaddr->oda_osdname.len; + odi.osdname = (u8 *)deviceaddr->oda_osdname.data; + +if (!odi.osdname_len && !odi.systemid_len) { +dprintk ("%s: !odi.osdname_len && !odi.systemid_len\n" , + __func__); + err = -ENODEV ; + goto out; + } + + od =osduld_info_lookup (&odi); +if (unlikely (IS_ERR (od))) { + err =PTR_ERR (od); +dprintk ("%s: osduld_info_lookup => %d\n" , __func__, err); + goto out; + } + +_dev_list_add (NFS_SERVER (pnfslay->plh_inode), d_id, od, gfp_flags); + +out: +dprintk ("%s: return=%d\n" , __func__, err); +objlayout_put_deviceinfo (deviceaddr); +return err ?ERR_PTR (err) : od; +} + +static int objio_devices_lookup (struct pnfs_layout_hdr *pnfslay, +struct objio_segment *objio_seg, +gfp_t gfp_flags) +{ +unsigned i; +int err; + +/* lookup all devices */ +for (i =0 ; i < objio_seg->num_comps; i++) { +struct objio_dev_ent *ode; + + ode =_device_lookup (pnfslay, objio_seg, i, gfp_flags); +if (unlikely (IS_ERR (ode))) { + err =PTR_ERR (ode); + goto out; + } + objio_seg->ods[i] = ode; + } + err =0 ; + +out: +dprintk ("%s: return=%d\n" , __func__, err); +return err; +} +static int _verify_data_map (struct pnfs_osd_layout *layout) {struct pnfs_osd_data_map *data_map = &layout->olo_map;
@@ -170,6 +305,9 @@ extern int objio_alloc_lseg(struct pnfs_layout_segment **outp, objio_seg->num_comps = layout.olo_num_comps; objio_seg->comps_index = layout.olo_comps_index; + err =objio_devices_lookup (pnfslay, objio_seg, gfp_flags); +if (err) + goto err; objio_seg->mirrors_p1 = layout.olo_map.odm_mirror_cnt +1 ; objio_seg->stripe_unit = layout.olo_map.odm_stripe_unit;
@@ -198,8 +336,14 @@ err:void objio_free_lseg (struct pnfs_layout_segment *lseg) { +int i;struct objio_segment *objio_seg =OBJIO_LSEG (lseg); +for (i =0 ; i < objio_seg->num_comps; i++) { +if (!objio_seg->ods[i]) +break ; +nfs4_put_deviceid_node (&objio_seg->ods[i]->id_node); + }kfree (objio_seg); }
@@ -210,6 +354,8 @@ static struct pnfs_layoutdriver_type objlayout_type = { .alloc_lseg = objlayout_alloc_lseg, .free_lseg = objlayout_free_lseg, + + .free_deviceid_node = objio_free_deviceid_node, };MODULE_DESCRIPTION ("pNFS Layout Driver for OSD2 objects" );
fs/nfs/objlayout/objlayout.c +68 -0
71 lines not on this page · raw message
fs/nfs/objlayout/objlayout.h +8 -0
@@ -56,6 +56,14 @@ extern int objio_alloc_lseg(struct pnfs_layout_segment **outp,extern void objio_free_lseg (struct pnfs_layout_segment *lseg);/* +* callback API +*/ +extern int objlayout_get_deviceinfo (struct pnfs_layout_hdr *pnfslay, +struct nfs4_deviceid *d_id,struct pnfs_osd_deviceaddr **deviceaddr, +gfp_t gfp_flags); +extern void objlayout_put_deviceinfo (struct pnfs_osd_deviceaddr *deviceaddr); + +/* * exported generic objects function vectors */ extern struct pnfs_layout_segment *objlayout_alloc_lseg(
Signature · 1 line
1.7.3.4
PATCH v6 16/26 NFSv4.1: use layout driver in global device cache
In reply to Benny Halevypnfs deviceids are unique per server, per layout type. struct nfs_client is currently used to distinguish deviceids from different nfs servers, yet these may clash between different layout types on the same server. Therefore, use the layout driver associated with each deviceid at insertion time to look it up, unhash, or delete it.
--- fs/nfs/callback_proc.c | 2 +- fs/nfs/nfs4filelayout.c | 3 ++- fs/nfs/objlayout/objio_osd.c | 6 +++--- fs/nfs/pnfs.h | 6 +++--- fs/nfs/pnfs_dev.c | 28 +++++++++++++++++----------- 5 files changed, 26 insertions(+), 19 deletions(-)
fs/nfs/callback_proc.c +1 -1
@@ -278,7 +278,7 @@ __be32 nfs4_callback_devicenotify(struct cb_devicenotifyargs *args,if (dev->cbd_notify_type ==NOTIFY_DEVICEID4_CHANGE )dprintk ("%s: NOTIFY_DEVICEID4_CHANGE not supported, " "deleting instead\n" , __func__); -nfs4_delete_deviceid (clp, &dev->cbd_dev_id); +nfs4_delete_deviceid (server->pnfs_curr_ld, clp, &dev->cbd_dev_id); } out:
fs/nfs/nfs4filelayout.c +2 -1
@@ -441,7 +441,8 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo, }/* find and reference the deviceid */ - d =nfs4_find_get_deviceid (NFS_SERVER (lo->plh_inode)->nfs_client, id); + d =nfs4_find_get_deviceid (NFS_SERVER (lo->plh_inode)->pnfs_curr_ld, +NFS_SERVER (lo->plh_inode)->nfs_client, id);if (d ==NULL ) { dsaddr =get_device_info (lo->plh_inode, id, gfp_flags);if (dsaddr ==NULL )
fs/nfs/objlayout/objio_osd.c +3 -3
@@ -60,12 +60,12 @@ objio_free_deviceid_node(struct nfs4_deviceid_node *d)kfree (de); } -static struct objio_dev_ent *_dev_list_find (const struct nfs_client *clp, +static struct objio_dev_ent *_dev_list_find (const struct nfs_server *nfss,const struct nfs4_deviceid *d_id) {struct nfs4_deviceid_node *d; - d =nfs4_find_get_deviceid (clp, d_id); + d =nfs4_find_get_deviceid (nfss->pnfs_curr_ld, nfss->nfs_client, d_id);if (!d)return NULL ; return container_of(d, struct objio_dev_ent, id_node);
@@ -141,7 +141,7 @@ static struct objio_dev_ent *_device_lookup(struct pnfs_layout_hdr *pnfslay, d_id = &objio_seg->comps[comp].oc_object_id.oid_device_id; - ode =_dev_list_find (NFS_SERVER (pnfslay->plh_inode)->nfs_client, d_id); + ode =_dev_list_find (NFS_SERVER (pnfslay->plh_inode), d_id);if (ode)return ode;
fs/nfs/pnfs.h +3 -3
@@ -172,9 +172,9 @@ struct nfs4_deviceid_node { };void nfs4_print_deviceid (const struct nfs4_deviceid *dev_id); -struct nfs4_deviceid_node *nfs4_find_get_deviceid (const struct nfs_client *,const struct nfs4_deviceid *); -struct nfs4_deviceid_node *nfs4_unhash_put_deviceid (const struct nfs_client *,const struct nfs4_deviceid *); -void nfs4_delete_deviceid (const struct nfs_client *,const struct nfs4_deviceid *); +struct nfs4_deviceid_node *nfs4_find_get_deviceid (const struct pnfs_layoutdriver_type *,const struct nfs_client *,const struct nfs4_deviceid *); +struct nfs4_deviceid_node *nfs4_unhash_put_deviceid (const struct pnfs_layoutdriver_type *,const struct nfs_client *,const struct nfs4_deviceid *); +void nfs4_delete_deviceid (const struct pnfs_layoutdriver_type *,const struct nfs_client *,const struct nfs4_deviceid *); void nfs4_init_deviceid_node(struct nfs4_deviceid_node *, const struct pnfs_layoutdriver_type *, const struct nfs_client *,
fs/nfs/pnfs_dev.c +17 -11
@@ -67,14 +67,16 @@ nfs4_deviceid_hash(const struct nfs4_deviceid *id) }static struct nfs4_deviceid_node * -_lookup_deviceid (const struct nfs_client *clp,const struct nfs4_deviceid *id, +_lookup_deviceid (const struct pnfs_layoutdriver_type *ld, +const struct nfs_client *clp,const struct nfs4_deviceid *id,long hash) {struct nfs4_deviceid_node *d;struct hlist_node *n;hlist_for_each_entry_rcu (d, n, &nfs4_deviceid_cache[hash], node) -if (d->nfs_client == clp && !memcmp (&d->deviceid, id,sizeof (*id))) { +if (d->ld == ld && d->nfs_client == clp && + !memcmp (&d->deviceid, id,sizeof (*id))) {if (atomic_read (&d->ref))return d;else
@@ -90,13 +92,14 @@ _lookup_deviceid(const struct nfs_client *clp, const struct nfs4_deviceid *id,* @id deviceid to look up */ struct nfs4_deviceid_node * -_find_get_deviceid (const struct nfs_client *clp,const struct nfs4_deviceid *id, +_find_get_deviceid (const struct pnfs_layoutdriver_type *ld, +const struct nfs_client *clp,const struct nfs4_deviceid *id,long hash) {struct nfs4_deviceid_node *d;rcu_read_lock (); - d =_lookup_deviceid (clp, id, hash); + d =_lookup_deviceid (ld, clp, id, hash);if (!atomic_inc_not_zero (&d->ref)) d =NULL ;rcu_read_unlock ();
@@ -104,9 +107,10 @@ _find_get_deviceid(const struct nfs_client *clp, const struct nfs4_deviceid *id, }struct nfs4_deviceid_node * -nfs4_find_get_deviceid (const struct nfs_client *clp,const struct nfs4_deviceid *id) +nfs4_find_get_deviceid (const struct pnfs_layoutdriver_type *ld, +const struct nfs_client *clp,const struct nfs4_deviceid *id) { -return _find_get_deviceid (clp, id,nfs4_deviceid_hash (id)); +return _find_get_deviceid (ld, clp, id,nfs4_deviceid_hash (id)); }EXPORT_SYMBOL_GPL (nfs4_find_get_deviceid);
@@ -119,13 +123,14 @@ EXPORT_SYMBOL_GPL(nfs4_find_get_deviceid);* @ret the unhashed node, if found and dereferenced to zero, NULL otherwise. */ struct nfs4_deviceid_node * -nfs4_unhash_put_deviceid (const struct nfs_client *clp,const struct nfs4_deviceid *id) +nfs4_unhash_put_deviceid (const struct pnfs_layoutdriver_type *ld, +const struct nfs_client *clp,const struct nfs4_deviceid *id) {struct nfs4_deviceid_node *d;spin_lock (&nfs4_deviceid_lock);rcu_read_lock (); - d =_lookup_deviceid (clp, id,nfs4_deviceid_hash (id)); + d =_lookup_deviceid (ld, clp, id,nfs4_deviceid_hash (id));rcu_read_unlock ();if (!d) {spin_unlock (&nfs4_deviceid_lock);
@@ -150,11 +155,12 @@ EXPORT_SYMBOL_GPL(nfs4_unhash_put_deviceid);* @id deviceid to delete */ void -nfs4_delete_deviceid (const struct nfs_client *clp,const struct nfs4_deviceid *id) +nfs4_delete_deviceid (const struct pnfs_layoutdriver_type *ld, +const struct nfs_client *clp,const struct nfs4_deviceid *id) {struct nfs4_deviceid_node *d; - d =nfs4_unhash_put_deviceid (clp, id); + d =nfs4_unhash_put_deviceid (ld, clp, id);if (!d)return ;if (d->ld->free_deviceid_node)
@@ -197,7 +203,7 @@ nfs4_insert_deviceid_node(struct nfs4_deviceid_node *new)spin_lock (&nfs4_deviceid_lock); hash =nfs4_deviceid_hash (&new->deviceid); - d =_find_get_deviceid (new->nfs_client, &new->deviceid, hash); + d =_find_get_deviceid (new->ld, new->nfs_client, &new->deviceid, hash);if (d) {spin_unlock (&nfs4_deviceid_lock);return d;
Signature · 1 line
1.7.3.4
PATCH v6 17/26 pnfs: alloc and free layout_hdr layoutdriver methods
In reply to Benny Halevy--- fs/nfs/pnfs.c | 21 ++++++++++++++++++--- fs/nfs/pnfs.h | 4 ++++ 2 files changed, 22 insertions(+), 3 deletions(-)
fs/nfs/pnfs.c +18 -3
@@ -177,13 +177,28 @@ get_layout_hdr(struct pnfs_layout_hdr *lo)atomic_inc (&lo->plh_refcount); } +static struct pnfs_layout_hdr * +pnfs_alloc_layout_hdr (struct inode *ino,gfp_t gfp_flags) +{ +struct pnfs_layoutdriver_type *ld =NFS_SERVER (ino)->pnfs_curr_ld; +return ld->alloc_layout_hdr ? ld->alloc_layout_hdr (ino, gfp_flags) : +kzalloc (sizeof (struct pnfs_layout_hdr ), gfp_flags); +} + +static void +pnfs_free_layout_hdr (struct pnfs_layout_hdr *lo) +{ +struct pnfs_layoutdriver_type *ld =NFS_SERVER (lo->plh_inode)->pnfs_curr_ld; +return ld->alloc_layout_hdr ? ld->free_layout_hdr (lo) :kfree (lo); +} +static void destroy_layout_hdr (struct pnfs_layout_hdr *lo) {dprintk ("%s: freeing layout cache %p\n" , __func__, lo);BUG_ON (!list_empty (&lo->plh_layouts));NFS_I (lo->plh_inode)->layout =NULL ; -kfree (lo); +pnfs_free_layout_hdr (lo); } static void
@@ -744,7 +759,7 @@ alloc_init_layout_hdr(struct inode *ino, gfp_t gfp_flags) {struct pnfs_layout_hdr *lo; - lo =kzalloc (sizeof (struct pnfs_layout_hdr ), gfp_flags); + lo =pnfs_alloc_layout_hdr (ino, gfp_flags);if (!lo)return NULL ;atomic_set (&lo->plh_refcount,1 );
@@ -777,7 +792,7 @@ pnfs_find_alloc_layout(struct inode *ino, gfp_t gfp_flags)if (likely (nfsi->layout ==NULL ))/* Won the race? */ nfsi->layout = new;else -kfree (new); +pnfs_free_layout_hdr (new);return nfsi->layout; }
fs/nfs/pnfs.h +4 -0
@@ -73,6 +73,10 @@ struct pnfs_layoutdriver_type {const u32 id;const char *name;struct module *owner; + +struct pnfs_layout_hdr * (*alloc_layout_hdr) (struct inode *inode,gfp_t gfp_flags); +void (*free_layout_hdr) (struct pnfs_layout_hdr *); +struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_hdr *layoutid,struct nfs4_layoutget_res *lgr,gfp_t gfp_flags);void (*free_lseg) (struct pnfs_layout_segment *lseg);
Signature · 1 line
1.7.3.4
PATCH v6 18/26 pnfs-obj: define per-inode private structure
In reply to Benny Halevyallocate and deallocate per-inode private pnfs_layout_hdr in preparation for I/O implementation.
--- fs/nfs/objlayout/objio_osd.c | 3 +++ fs/nfs/objlayout/objlayout.c | 26 ++++++++++++++++++++++++++ fs/nfs/objlayout/objlayout.h | 17 +++++++++++++++++ 3 files changed, 46 insertions(+), 0 deletions(-)
fs/nfs/objlayout/objio_osd.c +3 -0
@@ -352,6 +352,9 @@ static struct pnfs_layoutdriver_type objlayout_type = { .id = LAYOUT_OSD2_OBJECTS, .name = "LAYOUT_OSD2_OBJECTS", + .alloc_layout_hdr = objlayout_alloc_layout_hdr, + .free_layout_hdr = objlayout_free_layout_hdr, + .alloc_lseg = objlayout_alloc_lseg, .free_lseg = objlayout_free_lseg,
fs/nfs/objlayout/objlayout.c +26 -0
@@ -42,6 +42,32 @@#define NFSDBG_FACILITY NFSDBG_PNFS_LD/* +* Create a objlayout layout structure for the given inode and return it. +*/ +struct pnfs_layout_hdr * +objlayout_alloc_layout_hdr (struct inode *inode,gfp_t gfp_flags) +{ +struct objlayout *objlay; + + objlay =kzalloc (sizeof (struct objlayout ), gfp_flags); +dprintk ("%s: Return %p\n" , __func__, objlay); +return &objlay->pnfs_layout; +} + +/* +* Free an objlayout layout structure +*/ +void +objlayout_free_layout_hdr (struct pnfs_layout_hdr *lo) +{ +struct objlayout *objlay =OBJLAYOUT (lo); + +dprintk ("%s: objlay %p\n" , __func__, objlay); + +kfree (objlay); +} + +/* * Unmarshall layout and store it in pnfslay. */ struct pnfs_layout_segment *
fs/nfs/objlayout/objlayout.h +17 -0
@@ -46,6 +46,19 @@#include "../pnfs.h" /* +* per-inode layout +*/ +struct objlayout { +struct pnfs_layout_hdr pnfs_layout; +}; + +static inline struct objlayout * +OBJLAYOUT (struct pnfs_layout_hdr *lo) +{ + return container_of(lo, struct objlayout, pnfs_layout); +} + +/* * Raid engine I/O API */ extern int objio_alloc_lseg(struct pnfs_layout_segment **outp,
@@ -66,6 +79,10 @@ extern void objlayout_put_deviceinfo(struct pnfs_osd_deviceaddr *deviceaddr);/* * exported generic objects function vectors */ + +extern struct pnfs_layout_hdr *objlayout_alloc_layout_hdr (struct inode *,gfp_t gfp_flags); +extern void objlayout_free_layout_hdr (struct pnfs_layout_hdr *); + extern struct pnfs_layout_segment *objlayout_alloc_lseg( struct pnfs_layout_hdr *, struct nfs4_layoutget_res *,
Signature · 1 line
1.7.3.4
PATCH v6 19/26 pnfs: support for non-rpc layout drivers
In reply to Benny HalevyNon-rpc layout driver such as for objects and blocks implement their own I/O path and error handling logic. Therefore bypass NFS-based error handling for these layout drivers.
--- fs/nfs/internal.h | 1 + fs/nfs/nfs4proc.c | 13 +++++++++-- fs/nfs/pnfs.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++- fs/nfs/pnfs.h | 2 + include/linux/nfs_xdr.h | 2 + 5 files changed, 66 insertions(+), 4 deletions(-)
fs/nfs/internal.h +1 -0
@@ -310,6 +310,7 @@ extern int nfs_migrate_page(struct address_space *,#endif /* nfs4proc.c */ +extern void __nfs4_read_done_cb (struct nfs_read_data *);extern void nfs4_reset_read (struct rpc_task *task,struct nfs_read_data *data); extern int nfs4_init_client(struct nfs_client *clp, const struct rpc_timeout *timeparms,
fs/nfs/nfs4proc.c +10 -3
@@ -3175,6 +3175,11 @@ static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,return err; } +void __nfs4_read_done_cb (struct nfs_read_data *data) +{ +nfs_invalidate_atime (data->inode); +} +static int nfs4_read_done_cb (struct rpc_task *task,struct nfs_read_data *data) {struct nfs_server *server =NFS_SERVER (data->inode);
@@ -3184,7 +3189,7 @@ static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_read_data *data)return -EAGAIN ; } -nfs_invalidate_atime (data->inode); +__nfs4_read_done_cb (data);if (task->tk_status >0 )renew_lease (server, data->timestamp);return 0 ;
@@ -3198,7 +3203,8 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)if (!nfs4_sequence_done (task, &data->res.seq_res))return -EAGAIN ; -return data->read_done_cb (task, data); +return data->read_done_cb ? data->read_done_cb (task, data) : +nfs4_read_done_cb (task, data); }static void nfs4_proc_read_setup (struct nfs_read_data *data,struct rpc_message *msg)
@@ -3243,7 +3249,8 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) {if (!nfs4_sequence_done (task, &data->res.seq_res))return -EAGAIN ; -return data->write_done_cb (task, data); +return data->write_done_cb ? data->write_done_cb (task, data) : +nfs4_write_done_cb (task, data); }/* Reset the the nfs_write_data to send the write to the MDS. */
fs/nfs/pnfs.c +51 -1
70 lines not on this page · raw message
fs/nfs/pnfs.h +2 -0
@@ -165,6 +165,8 @@ void pnfs_roc_set_barrier(struct inode *ino, u32 barrier);bool pnfs_roc_drain (struct inode *ino,u32 *barrier);void pnfs_set_layoutcommit (struct nfs_write_data *wdata);int pnfs_layoutcommit_inode (struct inode *inode,bool sync); +int pnfs_ld_write_done (struct nfs_write_data *); +int pnfs_ld_read_done (struct nfs_read_data *);/* pnfs_dev.c */ struct nfs4_deviceid_node {
include/linux/nfs_xdr.h +2 -0
@@ -1087,6 +1087,7 @@ struct nfs_read_data {const struct rpc_call_ops *mds_ops;int (*read_done_cb) (struct rpc_task *task,struct nfs_read_data *data);__u64 mds_offset; +int pnfs_error;struct page *page_array[NFS_PAGEVEC_SIZE ]; };
@@ -1112,6 +1113,7 @@ struct nfs_write_data {unsigned long timestamp;/* For lease renewal */ #endif __u64 mds_offset;/* Filelayout dense stripe */ +int pnfs_error;struct page *page_array[NFS_PAGEVEC_SIZE ]; };
Signature · 1 line
1.7.3.4
Re: [PATCH v6 19/26] pnfs: support for non-rpc layout drivers
Quoted 99 lines · Benny Halevy
Non-rpc layout driver such as for objects and blocks implement their own I/O path and error handling logic. Therefore bypass NFS-based error handling for these layout drivers.
[fix lseg ref-count bugs, and null de-refs]Signed-off-by Boaz Harrosh <[email protected]>[get rid of PNFS_USE_RPC_CODE][get rid of __nfs4_write_done_cb][revert useless change in nfs4_write_done_cb]Signed-off-by Benny Halevy <[email protected]>--- fs/nfs/internal.h | 1 + fs/nfs/nfs4proc.c | 13 +++++++++-- fs/nfs/pnfs.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++- fs/nfs/pnfs.h | 2 + include/linux/nfs_xdr.h | 2 + 5 files changed, 66 insertions(+), 4 deletions(-)fs/nfs/internal.h +1
-0@@ -310,6 +310,7 @@ extern int nfs_migrate_page(struct address_space *,#endif /* nfs4proc.c */ +extern void __nfs4_read_done_cb (struct nfs_read_data *);extern void nfs4_reset_read (struct rpc_task *task,struct nfs_read_data *data); extern int nfs4_init_client(struct nfs_client *clp, const struct rpc_timeout *timeparms,fs/nfs/nfs4proc.c +10
-3@@ -3175,6 +3175,11 @@ static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,return err; } +void __nfs4_read_done_cb (struct nfs_read_data *data) +{ +nfs_invalidate_atime (data->inode); +} +static int nfs4_read_done_cb (struct rpc_task *task,struct nfs_read_data *data) {struct nfs_server *server =NFS_SERVER (data->inode);@@ -3184,7 +3189,7 @@ static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_read_data *data)return -EAGAIN ; } -nfs_invalidate_atime (data->inode); +__nfs4_read_done_cb (data);if (task->tk_status >0 )renew_lease (server, data->timestamp);return 0 ;@@ -3198,7 +3203,8 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)if (!nfs4_sequence_done (task, &data->res.seq_res))return -EAGAIN ; -return data->read_done_cb (task, data); +return data->read_done_cb ? data->read_done_cb (task, data) : +nfs4_read_done_cb (task, data); }static void nfs4_proc_read_setup (struct nfs_read_data *data,struct rpc_message *msg)@@ -3243,7 +3249,8 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) {if (!nfs4_sequence_done (task, &data->res.seq_res))return -EAGAIN ; -return data->write_done_cb (task, data); +return data->write_done_cb ? data->write_done_cb (task, data) : +nfs4_write_done_cb (task, data); }/* Reset the the nfs_write_data to send the write to the MDS. */ fs/nfs/pnfs.c +8
-1@@ -243,7 +243,7 @@ put_lseg_common(struct pnfs_layout_segment *lseg) {struct inode *inode = lseg->pls_layout->plh_inode; -BUG_ON (test_bit (NFS_LSEG_VALID , &lseg->pls_flags)); +WARN_ON (test_bit (NFS_LSEG_VALID , &lseg->pls_flags));list_del_init (&lseg->pls_list);if (list_empty (&lseg->pls_layout->plh_segs)) {set_bit (NFS_LAYOUT_DESTROYED , &lseg->pls_layout->plh_flags);@@ -1054,6 +1054,31 @@ pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode) pgio->pg_test = (ld && ld->pg_test) ? pnfs_write_pg_test :NULL ; } +/* +* Called by non rpc-based layout drivers +*/ +int +pnfs_ld_write_done (struct nfs_write_data *data) +{ +int status;
fs/nfs/pnfs.c pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode) · line 1073
Quoted 10 lines
fs/nfs/pnfs.c +10
-0+ +if (!data->pnfs_error) { +pnfs_set_layoutcommit (data); + data->mds_ops->rpc_call_done (&data->task, data); + data->mds_ops->rpc_release (data); +return 0 ; + } + +put_lseg (data->lseg); + data->lseg =NULL ;
These puts are not good as well. I tested. Do you want a SQUASHME or a replacement patch?
Quoted 21 lines
fs/nfs/pnfs.c +14
-0+dprintk ("%s: pnfs_error=%d, retry via MDS\n" , __func__, + data->pnfs_error); + status =nfs_initiate_write (data,NFS_CLIENT (data->inode), + data->mds_ops,NFS_FILE_SYNC ); +return status ? : -EAGAIN ; +} +EXPORT_SYMBOL_GPL (pnfs_ld_write_done); +enum pnfs_try_status pnfs_try_to_write_data (struct nfs_write_data *wdata,const struct rpc_call_ops *call_ops,int how)@@ -1079,6 +1104,31 @@ pnfs_try_to_write_data(struct nfs_write_data *wdata, }/* +* Called by non rpc-based layout drivers +*/ +int +pnfs_ld_read_done (struct nfs_read_data *data) +{ +int status;
fs/nfs/pnfs.c pnfs_try_to_write_data(struct nfs_write_data *wdata, · line 1122
Quoted 10 lines
fs/nfs/pnfs.c +10
-0+ +if (!data->pnfs_error) { +__nfs4_read_done_cb (data); + data->mds_ops->rpc_call_done (&data->task, data); + data->mds_ops->rpc_release (data); +return 0 ; + } + +put_lseg (data->lseg); + data->lseg =NULL ;
Here to
Boaz
Quoted 45 lines
fs/nfs/pnfs.c +9
-0+dprintk ("%s: pnfs_error=%d, retry via MDS\n" , __func__, + data->pnfs_error); + status =nfs_initiate_read (data,NFS_CLIENT (data->inode), + data->mds_ops); +return status ? : -EAGAIN ; +} +EXPORT_SYMBOL_GPL (pnfs_ld_read_done); + +/* * Call the appropriate parallel I/O subsystem read function. */ enum pnfs_try_status fs/nfs/pnfs.h +2
-0@@ -165,6 +165,8 @@ void pnfs_roc_set_barrier(struct inode *ino, u32 barrier);bool pnfs_roc_drain (struct inode *ino,u32 *barrier);void pnfs_set_layoutcommit (struct nfs_write_data *wdata);int pnfs_layoutcommit_inode (struct inode *inode,bool sync); +int pnfs_ld_write_done (struct nfs_write_data *); +int pnfs_ld_read_done (struct nfs_read_data *);/* pnfs_dev.c */ struct nfs4_deviceid_node {include/linux/nfs_xdr.h +2
-0@@ -1087,6 +1087,7 @@ struct nfs_read_data {const struct rpc_call_ops *mds_ops;int (*read_done_cb) (struct rpc_task *task,struct nfs_read_data *data);__u64 mds_offset; +int pnfs_error;struct page *page_array[NFS_PAGEVEC_SIZE ]; };@@ -1112,6 +1113,7 @@ struct nfs_write_data {unsigned long timestamp;/* For lease renewal */ #endif __u64 mds_offset;/* Filelayout dense stripe */ +int pnfs_error;struct page *page_array[NFS_PAGEVEC_SIZE ]; };
Re: [PATCH v6 19/26] pnfs: support for non-rpc layout drivers
Quoted 105 lines · Boaz Harrosh
Quoted 104 lines · Benny Halevy
Non-rpc layout driver such as for objects and blocks implement their own I/O path and error handling logic. Therefore bypass NFS-based error handling for these layout drivers.
[fix lseg ref-count bugs, and null de-refs]Signed-off-by Boaz Harrosh <[email protected]>[get rid of PNFS_USE_RPC_CODE][get rid of __nfs4_write_done_cb][revert useless change in nfs4_write_done_cb]Signed-off-by Benny Halevy <[email protected]>--- fs/nfs/internal.h | 1 + fs/nfs/nfs4proc.c | 13 +++++++++-- fs/nfs/pnfs.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++- fs/nfs/pnfs.h | 2 + include/linux/nfs_xdr.h | 2 + 5 files changed, 66 insertions(+), 4 deletions(-)fs/nfs/internal.h +1
-0@@ -310,6 +310,7 @@ extern int nfs_migrate_page(struct address_space *,#endif /* nfs4proc.c */ +extern void __nfs4_read_done_cb (struct nfs_read_data *);extern void nfs4_reset_read (struct rpc_task *task,struct nfs_read_data *data); extern int nfs4_init_client(struct nfs_client *clp, const struct rpc_timeout *timeparms,fs/nfs/nfs4proc.c +10
-3@@ -3175,6 +3175,11 @@ static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,return err; } +void __nfs4_read_done_cb (struct nfs_read_data *data) +{ +nfs_invalidate_atime (data->inode); +} +static int nfs4_read_done_cb (struct rpc_task *task,struct nfs_read_data *data) {struct nfs_server *server =NFS_SERVER (data->inode);@@ -3184,7 +3189,7 @@ static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_read_data *data)return -EAGAIN ; } -nfs_invalidate_atime (data->inode); +__nfs4_read_done_cb (data);if (task->tk_status >0 )renew_lease (server, data->timestamp);return 0 ;@@ -3198,7 +3203,8 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)if (!nfs4_sequence_done (task, &data->res.seq_res))return -EAGAIN ; -return data->read_done_cb (task, data); +return data->read_done_cb ? data->read_done_cb (task, data) : +nfs4_read_done_cb (task, data); }static void nfs4_proc_read_setup (struct nfs_read_data *data,struct rpc_message *msg)@@ -3243,7 +3249,8 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) {if (!nfs4_sequence_done (task, &data->res.seq_res))return -EAGAIN ; -return data->write_done_cb (task, data); +return data->write_done_cb ? data->write_done_cb (task, data) : +nfs4_write_done_cb (task, data); }/* Reset the the nfs_write_data to send the write to the MDS. */ fs/nfs/pnfs.c +13
-1@@ -243,7 +243,7 @@ put_lseg_common(struct pnfs_layout_segment *lseg) {struct inode *inode = lseg->pls_layout->plh_inode; -BUG_ON (test_bit (NFS_LSEG_VALID , &lseg->pls_flags)); +WARN_ON (test_bit (NFS_LSEG_VALID , &lseg->pls_flags));list_del_init (&lseg->pls_list);if (list_empty (&lseg->pls_layout->plh_segs)) {set_bit (NFS_LAYOUT_DESTROYED , &lseg->pls_layout->plh_flags);@@ -1054,6 +1054,31 @@ pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode) pgio->pg_test = (ld && ld->pg_test) ? pnfs_write_pg_test :NULL ; } +/* +* Called by non rpc-based layout drivers +*/ +int +pnfs_ld_write_done (struct nfs_write_data *data) +{ +int status; + +if (!data->pnfs_error) { +pnfs_set_layoutcommit (data); + data->mds_ops->rpc_call_done (&data->task, data); + data->mds_ops->rpc_release (data);
Quoted 10 lines
fs/nfs/pnfs.c pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode) · line 1073
Quoted 5 lines
fs/nfs/pnfs.c +5
-0+return 0 ; + } + +put_lseg (data->lseg); + data->lseg =NULL ;These puts are not good as well. I tested. Do you want a SQUASHME or a replacement patch?
SQUASHME will be great.
Benny
Quoted 81 lines
Quoted 21 lines
fs/nfs/pnfs.c +14
-0+dprintk ("%s: pnfs_error=%d, retry via MDS\n" , __func__, + data->pnfs_error); + status =nfs_initiate_write (data,NFS_CLIENT (data->inode), + data->mds_ops,NFS_FILE_SYNC ); +return status ? : -EAGAIN ; +} +EXPORT_SYMBOL_GPL (pnfs_ld_write_done); +enum pnfs_try_status pnfs_try_to_write_data (struct nfs_write_data *wdata,const struct rpc_call_ops *call_ops,int how)@@ -1079,6 +1104,31 @@ pnfs_try_to_write_data(struct nfs_write_data *wdata, }/* +* Called by non rpc-based layout drivers +*/ +int +pnfs_ld_read_done (struct nfs_read_data *data) +{ +int status;fs/nfs/pnfs.c pnfs_try_to_write_data(struct nfs_write_data *wdata, · line 1122
Quoted 10 lines
fs/nfs/pnfs.c +10
-0+ +if (!data->pnfs_error) { +__nfs4_read_done_cb (data); + data->mds_ops->rpc_call_done (&data->task, data); + data->mds_ops->rpc_release (data); +return 0 ; + } + +put_lseg (data->lseg); + data->lseg =NULL ;Here to
Boaz
Quoted 45 lines
fs/nfs/pnfs.c +9
-0+dprintk ("%s: pnfs_error=%d, retry via MDS\n" , __func__, + data->pnfs_error); + status =nfs_initiate_read (data,NFS_CLIENT (data->inode), + data->mds_ops); +return status ? : -EAGAIN ; +} +EXPORT_SYMBOL_GPL (pnfs_ld_read_done); + +/* * Call the appropriate parallel I/O subsystem read function. */ enum pnfs_try_status fs/nfs/pnfs.h +2
-0@@ -165,6 +165,8 @@ void pnfs_roc_set_barrier(struct inode *ino, u32 barrier);bool pnfs_roc_drain (struct inode *ino,u32 *barrier);void pnfs_set_layoutcommit (struct nfs_write_data *wdata);int pnfs_layoutcommit_inode (struct inode *inode,bool sync); +int pnfs_ld_write_done (struct nfs_write_data *); +int pnfs_ld_read_done (struct nfs_read_data *);/* pnfs_dev.c */ struct nfs4_deviceid_node {include/linux/nfs_xdr.h +2
-0@@ -1087,6 +1087,7 @@ struct nfs_read_data {const struct rpc_call_ops *mds_ops;int (*read_done_cb) (struct rpc_task *task,struct nfs_read_data *data);__u64 mds_offset; +int pnfs_error;struct page *page_array[NFS_PAGEVEC_SIZE ]; };@@ -1112,6 +1113,7 @@ struct nfs_write_data {unsigned long timestamp;/* For lease renewal */ #endif __u64 mds_offset;/* Filelayout dense stripe */ +int pnfs_error;struct page *page_array[NFS_PAGEVEC_SIZE ]; };
PATCH 1/1 SQUASHME: into pnfs: pnfs: support for non-rpc layout drivers: de-ref not needed
the de-ref in pnfs_ld_read/write_done in the error case is not needed. I only tested the write path but I suspect it is all symetric
--- fs/nfs/pnfs.c | 4 ---- 1 files changed, 0 insertions(+), 4 deletions(-)
fs/nfs/pnfs.c +0 -4
@@ -1130,8 +1130,6 @@ pnfs_ld_write_done(struct nfs_write_data *data)return 0 ; } -put_lseg (data->lseg); - data->lseg =NULL ;dprintk ("%s: pnfs_error=%d, retry via MDS\n" , __func__, data->pnfs_error); status = nfs_initiate_write(data, NFS_CLIENT(data->inode),
@@ -1179,8 +1177,6 @@ pnfs_ld_read_done(struct nfs_read_data *data)return 0 ; } -put_lseg (data->lseg); - data->lseg =NULL ;dprintk ("%s: pnfs_error=%d, retry via MDS\n" , __func__, data->pnfs_error); status = nfs_initiate_read(data, NFS_CLIENT(data->inode),
Signature · 1 line
1.7.2.3
PATCH v6 20/26 pnfs-obj: osd raid engine read/write implementation
In reply to Benny HalevyFrom: Boaz Harrosh <[email protected]>
With the use of the in-kernel osd library. Implement read/write of data from/to osd-objects according to information specified in the objects-layout.
Support for stripping over mirrors with a received stripe_unit. There are however a few constrains which are not supported:
1. Stripe Unit must be a multiple of PAGE_SIZE
2. stripe length (stripe_unit * number_of_stripes) can not be bigger then 32bit.
Also support raid-groups and partial-layout. Partial-layout is when not all the groups are received on the line, addressing only a partial range of the file.
TODO:
Only raid0! raid 4/5/6 support will come at later stage
A none supported layout will send IO through the MDS
--- fs/nfs/objlayout/objio_osd.c | 603 ++++++++++++++++++++++++++++++++++++++++++ fs/nfs/objlayout/objlayout.c | 254 ++++++++++++++++++ fs/nfs/objlayout/objlayout.h | 42 +++ 3 files changed, 899 insertions(+), 0 deletions(-)
fs/nfs/objlayout/objio_osd.c +603 -0
@@ -46,6 +46,10 @@#define _LLU (x) ((unsigned long long)x) +enum {BIO_MAX_PAGES_KMALLOC = + (PAGE_SIZE -sizeof (struct bio )) /sizeof (struct bio_vec ), +}; +struct objio_dev_ent {struct nfs4_deviceid_node id_node;struct osd_dev *od;
@@ -126,6 +130,31 @@ OBJIO_LSEG(struct pnfs_layout_segment *lseg) return container_of(lseg, struct objio_segment, lseg); } +struct objio_state ; +typedef ssize_t (*objio_done_fn )(struct objio_state *ios); + +struct objio_state { +/* Generic layer */ +struct objlayout_io_state ol_state; + +struct objio_segment *layout; + +struct kref kref; +objio_done_fn done; +void *private; + +unsigned long length; +unsigned numdevs;/* Actually used devs in this IO */ +/* A per-device variable array of size numdevs */ +struct _objio_per_comp { +struct bio *bio; +struct osd_request *or; +unsigned long length; +u64 offset; +unsigned dev; + } per_dev[]; +}; +/* Send and wait for a get_device_info of devices in the layout, then look them up with the osd_initiator library */ static struct objio_dev_ent *_device_lookup(struct pnfs_layout_hdr *pnfslay,
@@ -347,6 +376,576 @@ void objio_free_lseg(struct pnfs_layout_segment *lseg)kfree (objio_seg); } +int objio_alloc_io_state (struct pnfs_layout_segment *lseg, +struct objlayout_io_state **outp, +gfp_t gfp_flags) +{ +struct objio_segment *objio_seg =OBJIO_LSEG (lseg); +struct objio_state *ios; +const unsigned first_size =sizeof (*ios) + + objio_seg->num_comps *sizeof (ios->per_dev[0 ]); + +dprintk ("%s: num_comps=%d\n" , __func__, objio_seg->num_comps); + ios =kzalloc (first_size, gfp_flags); +if (unlikely (!ios)) +return -ENOMEM ; + + ios->layout = objio_seg; + + *outp = &ios->ol_state; +return 0 ; +} + +void objio_free_io_state (struct objlayout_io_state *ol_state) +{ + struct objio_state *ios = container_of(ol_state, struct objio_state, + ol_state); + +kfree (ios); +} + +static void _clear_bio (struct bio *bio) +{ +struct bio_vec *bv; +unsigned i; + +__bio_for_each_segment (bv, bio, i,0 ) { +unsigned this_count = bv->bv_len; + +if (likely (PAGE_SIZE == this_count)) +clear_highpage (bv->bv_page); +else +zero_user (bv->bv_page, bv->bv_offset, this_count); + } +} + +static int _io_check (struct objio_state *ios,bool is_write) +{ +enum osd_err_priority oep =OSD_ERR_PRI_NO_ERROR ; +int lin_ret =0 ; +int i; + +for (i =0 ; i < ios->numdevs; i++) { +struct osd_sense_info osi; +struct osd_request *or = ios->per_dev[i].or; +unsigned dev; +int ret; + +if (!or) +continue ; + + ret =osd_req_decode_sense (or, &osi); +if (likely (!ret)) +continue ; + +if (OSD_ERR_PRI_CLEAR_PAGES == osi.osd_err_pri) { +/* start read offset passed endof file */ +BUG_ON (is_write); +_clear_bio (ios->per_dev[i].bio); +dprintk ("%s: start read offset passed end of file " +"offset=0x%llx, length=0x%lx\n" , __func__, +_LLU (ios->per_dev[i].offset), + ios->per_dev[i].length); + +continue ;/* we recovered */ + } + dev = ios->per_dev[i].dev; + +if (osi.osd_err_pri >= oep) { + oep = osi.osd_err_pri; + lin_ret = ret; + } + } + +return lin_ret; +} + +/* +* Common IO state helpers. +*/ +static void _io_free (struct objio_state *ios) +{ +unsigned i; + +for (i =0 ; i < ios->numdevs; i++) { +struct _objio_per_comp *per_dev = &ios->per_dev[i]; + +if (per_dev->or) { +osd_end_request (per_dev->or); + per_dev->or =NULL ; + } + +if (per_dev->bio) { +bio_put (per_dev->bio); + per_dev->bio =NULL ; + } + } +} + +struct osd_dev *_io_od (struct objio_state *ios,unsigned dev) +{ +unsigned min_dev = ios->layout->comps_index; +unsigned max_dev = min_dev + ios->layout->num_comps; + +BUG_ON (dev < min_dev || max_dev <= dev); +return ios->layout->ods[dev - min_dev]->od; +} + +struct _striping_info { +u64 obj_offset; +u64 group_length; +unsigned dev; +unsigned unit_off; +}; + +static void _calc_stripe_info (struct objio_state *ios,u64 file_offset, +struct _striping_info *si) +{ +u32 stripe_unit = ios->layout->stripe_unit; +u32 group_width = ios->layout->group_width; +u64 group_depth = ios->layout->group_depth; +u32 U = stripe_unit * group_width; + +u64 T =U * group_depth; +u64 S =T * ios->layout->group_count; +u64 M =div64_u64 (file_offset,S ); + +/* +G = (L - (M * S)) / T +H = (L - (M * S)) % T +*/ +u64 LmodU = file_offset -M *S ; +u32 G =div64_u64 (LmodU,T ); +u64 H = LmodU -G *T ; + +u32 N =div_u64 (H ,U ); + +div_u64_rem (file_offset, stripe_unit, &si->unit_off); + si->obj_offset = si->unit_off + (N * stripe_unit) + + (M * group_depth * stripe_unit); + +/* "H - (N * U)" is just "H % U" so it's bound to u32 */ + si->dev = (u32)(H - (N *U )) / stripe_unit +G * group_width; + si->dev *= ios->layout->mirrors_p1; + + si->group_length =T -H ; +} + +static int _add_stripe_unit (struct objio_state *ios,unsigned *cur_pg, +unsigned pgbase,struct _objio_per_comp *per_dev,int cur_len, +gfp_t gfp_flags) +{ +unsigned pg = *cur_pg; +struct request_queue *q = +osd_request_queue (_io_od (ios, per_dev->dev)); + + per_dev->length += cur_len; + +if (per_dev->bio ==NULL ) { +unsigned stripes = ios->layout->num_comps / + ios->layout->mirrors_p1; +unsigned pages_in_stripe = stripes * + (ios->layout->stripe_unit /PAGE_SIZE ); +unsigned bio_size = (ios->ol_state.nr_pages + pages_in_stripe) / + stripes; + + per_dev->bio =bio_kmalloc (gfp_flags, bio_size); +if (unlikely (!per_dev->bio)) { +dprintk ("Faild to allocate BIO size=%u\n" , bio_size); +return -ENOMEM ; + } + } + +while (cur_len >0 ) { +unsigned pglen =min_t (unsigned,PAGE_SIZE - pgbase, cur_len); +unsigned added_len; + +BUG_ON (ios->ol_state.nr_pages <= pg); + cur_len -= pglen; + + added_len =bio_add_pc_page (q, per_dev->bio, + ios->ol_state.pages[pg], pglen, pgbase); +if (unlikely (pglen != added_len)) +return -ENOMEM ; + pgbase =0 ; + ++pg; + } +BUG_ON (cur_len); + + *cur_pg = pg; +return 0 ; +} + +static int _prepare_one_group (struct objio_state *ios,u64 length, +struct _striping_info *si,unsigned *last_pg, +gfp_t gfp_flags) +{ +unsigned stripe_unit = ios->layout->stripe_unit; +unsigned mirrors_p1 = ios->layout->mirrors_p1; +unsigned devs_in_group = ios->layout->group_width * mirrors_p1; +unsigned dev = si->dev; +unsigned first_dev = dev - (dev % devs_in_group); +unsigned max_comp = ios->numdevs ? ios->numdevs - mirrors_p1 :0 ; +unsigned cur_pg = *last_pg; +int ret =0 ; + +while (length) { +struct _objio_per_comp *per_dev = &ios->per_dev[dev]; +unsigned cur_len, page_off =0 ; + +if (!per_dev->length) { + per_dev->dev = dev; +if (dev < si->dev) { + per_dev->offset = si->obj_offset + stripe_unit - + si->unit_off; + cur_len = stripe_unit; + }else if (dev == si->dev) { + per_dev->offset = si->obj_offset; + cur_len = stripe_unit - si->unit_off; + page_off = si->unit_off & ~PAGE_MASK ; +BUG_ON (page_off && + (page_off != ios->ol_state.pgbase)); + }else {/* dev > si->dev */ + per_dev->offset = si->obj_offset - si->unit_off; + cur_len = stripe_unit; + } + +if (max_comp < dev) + max_comp = dev; + }else { + cur_len = stripe_unit; + } +if (cur_len >= length) + cur_len = length; + + ret =_add_stripe_unit (ios, &cur_pg, page_off , per_dev, + cur_len, gfp_flags); +if (unlikely (ret)) + goto out; + + dev += mirrors_p1; + dev = (dev % devs_in_group) + first_dev; + + length -= cur_len; + ios->length += cur_len; + } +out: + ios->numdevs = max_comp + mirrors_p1; + *last_pg = cur_pg; +return ret; +} + +static int _io_rw_pagelist (struct objio_state *ios,gfp_t gfp_flags) +{ +u64 length = ios->ol_state.count; +u64 offset = ios->ol_state.offset; +struct _striping_info si; +unsigned last_pg =0 ; +int ret =0 ; + +while (length) { +_calc_stripe_info (ios, offset, &si); + +if (length < si.group_length) + si.group_length = length; + + ret =_prepare_one_group (ios, si.group_length, &si, &last_pg, gfp_flags); +if (unlikely (ret)) + goto out; + + offset += si.group_length; + length -= si.group_length; + } + +out: +if (!ios->length) +return ret; + +return 0 ; +} + +static ssize_t _sync_done (struct objio_state *ios) +{ +struct completion *waiting = ios->private; + +complete (waiting); +return 0 ; +} + +static void _last_io (struct kref *kref) +{ + struct objio_state *ios = container_of(kref, struct objio_state, kref); + + ios->done (ios); +} + +static void _done_io (struct osd_request *or,void *p) +{ +struct objio_state *ios = p; + +kref_put (&ios->kref, _last_io); +} + +static ssize_t _io_exec (struct objio_state *ios) +{ +DECLARE_COMPLETION_ONSTACK (wait); +ssize_t status =0 ;/* sync status */ +unsigned i; +objio_done_fn saved_done_fn = ios->done; +bool sync = ios->ol_state.sync; + +if (sync) { + ios->done = _sync_done; + ios->private = &wait; + } + +kref_init (&ios->kref); + +for (i =0 ; i < ios->numdevs; i++) { +struct osd_request *or = ios->per_dev[i].or; + +if (!or) +continue ; + +kref_get (&ios->kref); +osd_execute_request_async (or, _done_io, ios); + } + +kref_put (&ios->kref, _last_io); + +if (sync) { +wait_for_completion (&wait); + status =saved_done_fn (ios); + } + +return status; +} + +/* +* read +*/ +static ssize_t _read_done (struct objio_state *ios) +{ +ssize_t status; +int ret =_io_check (ios, false); + +_io_free (ios); + +if (likely (!ret)) + status = ios->length; +else + status = ret; + +objlayout_read_done (&ios->ol_state, status, ios->ol_state.sync); +return status; +} + +static int _read_mirrors (struct objio_state *ios,unsigned cur_comp) +{ +struct osd_request *or =NULL ; +struct _objio_per_comp *per_dev = &ios->per_dev[cur_comp]; +unsigned dev = per_dev->dev; +struct pnfs_osd_object_cred *cred = + &ios->layout->comps[dev]; +struct osd_obj_id obj = { + .partition = cred->oc_object_id.oid_partition_id, + .id = cred->oc_object_id.oid_object_id, + }; +int ret; + + or =osd_start_request (_io_od (ios, dev),GFP_KERNEL ); +if (unlikely (!or)) { + ret = -ENOMEM ; + goto err; + } + per_dev->or = or; + +osd_req_read (or, &obj, per_dev->offset, per_dev->bio, per_dev->length); + + ret =osd_finalize_request (or,0 , cred->oc_cap.cred,NULL ); +if (ret) { +dprintk ("%s: Faild to osd_finalize_request() => %d\n" , + __func__, ret); + goto err; + } + +dprintk ("%s:[%d] dev=%d obj=0x%llx start=0x%llx length=0x%lx\n" , + __func__, cur_comp, dev, obj.id,_LLU (per_dev->offset), + per_dev->length); + +err: +return ret; +} + +static ssize_t _read_exec (struct objio_state *ios) +{ +unsigned i; +int ret; + +for (i =0 ; i < ios->numdevs; i += ios->layout->mirrors_p1) { +if (!ios->per_dev[i].length) +continue ; + ret =_read_mirrors (ios, i); +if (unlikely (ret)) + goto err; + } + + ios->done = _read_done; +return _io_exec (ios);/* In sync mode exec returns the io status */ + +err: +_io_free (ios); +return ret; +} + +ssize_t objio_read_pagelist (struct objlayout_io_state *ol_state) +{ + struct objio_state *ios = container_of(ol_state, struct objio_state, + ol_state); +int ret; + + ret =_io_rw_pagelist (ios,GFP_KERNEL ); +if (unlikely (ret)) +return ret; + +return _read_exec (ios); +} + +/* +* write +*/ +static ssize_t _write_done (struct objio_state *ios) +{ +ssize_t status; +int ret =_io_check (ios, true); + +_io_free (ios); + +if (likely (!ret)) { +/* FIXME: should be based on the OSD's persistence model +* See OSD2r05 Section 4.13 Data persistence model */ + ios->ol_state.committed =NFS_FILE_SYNC ; + status = ios->length; + }else { + status = ret; + } + +objlayout_write_done (&ios->ol_state, status, ios->ol_state.sync); +return status; +} + +static int _write_mirrors (struct objio_state *ios,unsigned cur_comp) +{ +struct _objio_per_comp *master_dev = &ios->per_dev[cur_comp]; +unsigned dev = ios->per_dev[cur_comp].dev; +unsigned last_comp = cur_comp + ios->layout->mirrors_p1; +int ret; + +for (; cur_comp < last_comp; ++cur_comp, ++dev) { +struct osd_request *or =NULL ; +struct pnfs_osd_object_cred *cred = + &ios->layout->comps[dev]; +struct osd_obj_id obj = { + .partition = cred->oc_object_id.oid_partition_id, + .id = cred->oc_object_id.oid_object_id, + }; +struct _objio_per_comp *per_dev = &ios->per_dev[cur_comp]; +struct bio *bio; + + or =osd_start_request (_io_od (ios, dev),GFP_NOFS ); +if (unlikely (!or)) { + ret = -ENOMEM ; + goto err; + } + per_dev->or = or; + +if (per_dev != master_dev) { + bio =bio_kmalloc (GFP_NOFS , + master_dev->bio->bi_max_vecs); +if (unlikely (!bio)) { +dprintk ("Faild to allocate BIO size=%u\n" , + master_dev->bio->bi_max_vecs); + ret = -ENOMEM ; + goto err; + } + +__bio_clone (bio, master_dev->bio); + bio->bi_bdev =NULL ; + bio->bi_next =NULL ; + per_dev->bio = bio; + per_dev->dev = dev; + per_dev->length = master_dev->length; + per_dev->offset = master_dev->offset; + }else { + bio = master_dev->bio; + bio->bi_rw |=REQ_WRITE ; + } + +osd_req_write (or, &obj, per_dev->offset, bio, per_dev->length); + + ret =osd_finalize_request (or,0 , cred->oc_cap.cred,NULL ); +if (ret) { +dprintk ("%s: Faild to osd_finalize_request() => %d\n" , + __func__, ret); + goto err; + } + +dprintk ("%s:[%d] dev=%d obj=0x%llx start=0x%llx length=0x%lx\n" , + __func__, cur_comp, dev, obj.id,_LLU (per_dev->offset), + per_dev->length); + } + +err: +return ret; +} + +static ssize_t _write_exec (struct objio_state *ios) +{ +unsigned i; +int ret; + +for (i =0 ; i < ios->numdevs; i += ios->layout->mirrors_p1) { +if (!ios->per_dev[i].length) +continue ; + ret =_write_mirrors (ios, i); +if (unlikely (ret)) + goto err; + } + + ios->done = _write_done; +return _io_exec (ios);/* In sync mode exec returns the io->status */ + +err: +_io_free (ios); +return ret; +} + +ssize_t objio_write_pagelist (struct objlayout_io_state *ol_state,bool stable) +{ + struct objio_state *ios = container_of(ol_state, struct objio_state, + ol_state); +int ret; + +/* TODO: ios->stable = stable; */ + ret =_io_rw_pagelist (ios,GFP_NOFS ); +if (unlikely (ret)) +return ret; + +return _write_exec (ios); +} + +/* +* objlayout_pg_test(). Called by nfs_can_coalesce_requests() +* +* return 1 : coalesce page +* return 0 : don't coalesce page +*/ +int +objlayout_pg_test (struct nfs_pageio_descriptor *pgio,struct nfs_page *prev, +struct nfs_page *req) +{ +return 1 ; +}static struct pnfs_layoutdriver_type objlayout_type = { .id =LAYOUT_OSD2_OBJECTS ,
@@ -358,6 +957,10 @@ static struct pnfs_layoutdriver_type objlayout_type = { .alloc_lseg = objlayout_alloc_lseg, .free_lseg = objlayout_free_lseg, + .read_pagelist = objlayout_read_pagelist, + .write_pagelist = objlayout_write_pagelist, + .pg_test = objlayout_pg_test, + .free_deviceid_node = objio_free_deviceid_node, };
fs/nfs/objlayout/objlayout.c +254 -0
260 lines not on this page · raw message
fs/nfs/objlayout/objlayout.h +42 -0
61 lines not on this page · raw message
Signature · 1 line
1.7.3.4
Re: [PATCH v6 20/26] pnfs-obj: osd raid engine read/write implementation
Benny hi!
I've implemented and tested the new schema we talked about with max IO sizes and pg_test. (Just for debugging I removed the check for bsize in the pnfs case). It works grate.
If you have anything send it so I can test it. Meanwhile you can SQUASH this one as well, it will not hurt. (Sent as reply to this mail)
I have couple more nit patches, that remove or move some prints if that's OK? I'll send them as reply to the patches they go into. Do you want to send one more clean round (V8). before linux-next?
Boaz
PATCH 1/1 SQUASHME: pnfs-obj: pg_test check for max_io_size
This should be squashed into:
pnfs-obj: osd raid engine read/write implementation
Implement pg_test vector to test for max IO sizes. We calculate a max_io_size member only once, and cache it in lseg so to not do so on every page insert.
--- fs/nfs/objlayout/objio_osd.c | 14 +++++++++++++- 1 files changed, 13 insertions(+), 1 deletions(-)
fs/nfs/objlayout/objio_osd.c +13 -1
@@ -129,6 +129,8 @@ struct objio_segment {u64 group_depth;unsigned group_count; +unsigned max_io_size; +unsigned comps_index;unsigned num_comps;/* variable length */
@@ -366,6 +368,11 @@ extern int objio_alloc_lseg(struct pnfs_layout_segment **outp, objio_seg->group_count =1 ; } +/* Cache this calculation it will hit for every page */ + objio_seg->max_io_size = (BIO_MAX_PAGES_KMALLOC *PAGE_SIZE - + objio_seg->stripe_unit) * + objio_seg->group_width; + *outp = &objio_seg->lseg;return 0 ;
@@ -1000,7 +1007,12 @@ int objlayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, struct nfs_page *req) { - return 1; + struct objio_segment *layout = OBJIO_LSEG(pgio->pg_lseg); + +if ((pgio->pg_count + req->wb_bytes) > layout->max_io_size) +return 0 ; +else +return 1 ; } static struct pnfs_layoutdriver_type objlayout_type = {
Signature · 1 line
1.7.2.3
Re: [PATCH] SQUASHME: pnfs-obj: pg_test check for max_io_size
Quoted 7 lines · Boaz Harrosh
This should be squashed into:
pnfs-obj: osd raid engine read/write implementationImplement
pg_testvector to test for max IO sizes. We calculate amax_io_sizemember only once, and cache it in lseg so to not do so on every page insert.
Looks good (except one minor nit, see inline below). I prefer to commit it as a separate patch rather than squash it if ok with you.
Benny
Quoted 32 lines
Signed-off-by Boaz Harrosh <[email protected]>--- fs/nfs/objlayout/objio_osd.c | 14 +++++++++++++- 1 files changed, 13 insertions(+), 1 deletions(-)fs/nfs/objlayout/objio_osd.c +7
-0@@ -129,6 +129,8 @@ struct objio_segment {u64 group_depth;unsigned group_count; +unsigned max_io_size; +unsigned comps_index;unsigned num_comps;/* variable length */ @@ -366,6 +368,11 @@ extern int objio_alloc_lseg(struct pnfs_layout_segment **outp, objio_seg->group_count =1 ; } +/* Cache this calculation it will hit for every page */ + objio_seg->max_io_size = (BIO_MAX_PAGES_KMALLOC *PAGE_SIZE - + objio_seg->stripe_unit) * + objio_seg->group_width; + *outp = &objio_seg->lseg;return 0 ;
fs/nfs/objlayout/objio_osd.c int · line 1015
Quoted 10 lines
fs/nfs/objlayout/objio_osd.c +6
-1@@ -1000,7 +1007,12 @@ int objlayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, struct nfs_page *req) { - return 1; + struct objio_segment *layout = OBJIO_LSEG(pgio->pg_lseg); + +if ((pgio->pg_count + req->wb_bytes) > layout->max_io_size) +return 0 ; +else +return 1 ;
why not simply do this?
return (pgio->pg_count + req->wb_bytes) <= layout->max_io_size;
Benny
Quoted 3 lines
fs/nfs/objlayout/objio_osd.c +0
-0}static struct pnfs_layoutdriver_type objlayout_type = {
PATCH v6 21/26 pnfs: layoutreturn
In reply to Benny HalevyNFSv4.1 LAYOUTRETURN implementation
Currently, does not support layout-type payload encoding.
--- fs/nfs/inode.c | 3 +- fs/nfs/nfs4proc.c | 82 ++++++++++++++++++++++++++++++++++ fs/nfs/nfs4xdr.c | 111 ++++++++++++++++++++++++++++++++++++++++++++--- fs/nfs/pnfs.c | 46 +++++++++++++++++++ fs/nfs/pnfs.h | 18 ++++++++ include/linux/nfs4.h | 1 + include/linux/nfs_xdr.h | 22 +++++++++ 7 files changed, 276 insertions(+), 7 deletions(-)
fs/nfs/inode.c +2 -1
@@ -1424,9 +1424,10 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)*/ void nfs4_evict_inode (struct inode *inode) { -pnfs_destroy_layout (NFS_I (inode));truncate_inode_pages (&inode->i_data,0 );end_writeback (inode); +pnfs_return_layout (inode); +pnfs_destroy_layout (NFS_I (inode));/* If we are holding a delegation, return it! */ nfs_inode_return_delegation_noreclaim (inode);/* First call standard NFS clear_inode() code */
fs/nfs/nfs4proc.c +82 -0
88 lines not on this page · raw message
fs/nfs/nfs4xdr.c +105 -6
159 lines not on this page · raw message
fs/nfs/pnfs.c +46 -0
52 lines not on this page · raw message
fs/nfs/pnfs.h +18 -0
@@ -129,6 +129,7 @@ extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *);extern int nfs4_proc_getdeviceinfo (struct nfs_server *server,struct pnfs_device *dev);extern int nfs4_proc_layoutget (struct nfs4_layoutget *lgp); +extern int nfs4_proc_layoutreturn (struct nfs4_layoutreturn *lrp);/* pnfs.c */ void get_layout_hdr (struct pnfs_layout_hdr *lo);
@@ -165,6 +166,7 @@ void pnfs_roc_set_barrier(struct inode *ino, u32 barrier);bool pnfs_roc_drain (struct inode *ino,u32 *barrier);void pnfs_set_layoutcommit (struct nfs_write_data *wdata);int pnfs_layoutcommit_inode (struct inode *inode,bool sync); +int _pnfs_return_layout (struct inode *);int pnfs_ld_write_done (struct nfs_write_data *);int pnfs_ld_read_done (struct nfs_read_data *);
@@ -256,6 +258,17 @@ static inline void pnfs_clear_request_commit(struct nfs_page *req) put_lseg(req->wb_commit_lseg); } +static inline int pnfs_return_layout (struct inode *ino) +{ +struct nfs_inode *nfsi =NFS_I (ino); +struct nfs_server *nfss =NFS_SERVER (ino); + +if (pnfs_enabled_sb (nfss) && nfsi->layout) +return _pnfs_return_layout (ino); + +return 0 ; +} +#else /* CONFIG_NFS_V4_1 */ static inline void pnfs_destroy_all_layouts (struct nfs_client *clp)
@@ -298,6 +311,11 @@ pnfs_try_to_write_data(struct nfs_write_data *data,return PNFS_NOT_ATTEMPTED ; } +static inline int pnfs_return_layout (struct inode *ino) +{ +return 0 ; +} +static inline bool pnfs_roc (struct inode *ino) {
include/linux/nfs4.h +1 -0
@@ -562,6 +562,7 @@ enum {NFSPROC4_CLNT_LAYOUTGET ,NFSPROC4_CLNT_GETDEVICEINFO ,NFSPROC4_CLNT_LAYOUTCOMMIT , + NFSPROC4_CLNT_LAYOUTRETURN, };/* nfs41 types */
include/linux/nfs_xdr.h +22 -0
@@ -269,6 +269,28 @@ struct nfs4_layoutcommit_data {struct nfs4_layoutcommit_res res; }; +struct nfs4_layoutreturn_args { +__u32 reclaim; +__u32 layout_type; +struct inode *inode; +nfs4_stateid stateid; +struct nfs4_sequence_args seq_args; +}; + +struct nfs4_layoutreturn_res { +struct nfs4_sequence_res seq_res; +u32 lrs_present; +nfs4_stateid stateid; +}; + +struct nfs4_layoutreturn { +struct nfs4_layoutreturn_args args; +struct nfs4_layoutreturn_res res; +struct rpc_cred *cred; +struct nfs_client *clp; +int rpc_status; +}; +/* * Arguments to the open call. */
Signature · 1 line
1.7.3.4
PATCH 1/1 SQUASHME: pnfs: Fix NULL dereference in the -ENOMEM path
In _pnfs_return_layout:
lrp pointer is checked for NULL after it was already accessed.
The rational here is that in _pnfs_return_layout we want to de-ref and release the layout regardless of if we sent the return or not (forgetfull). An eventual recall can return -ENOMATCHING instead of -EDELAY.
So to keep the reasoning above, copy the stateid twice.
Benny if it is OK to not release the layout on -ENOMEM then the check could just be moved above the spin_lock(), and the put_layout_hdr removed.
--- fs/nfs/pnfs.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
fs/nfs/pnfs.c +3 -1
@@ -628,6 +628,7 @@ _pnfs_return_layout(struct inode *ino)struct nfs_inode *nfsi =NFS_I (ino);LIST_HEAD (tmp_list);struct nfs4_layoutreturn *lrp; +nfs4_stateid stateid;int status =0 ;dprintk ("--> %s\n" , __func__);
@@ -642,7 +643,7 @@ _pnfs_return_layout(struct inode *ino)kfree (lrp); goto out; } - lrp->args.stateid = nfsi->layout->plh_stateid; + stateid = nfsi->layout->plh_stateid;/* Reference matched in nfs4_layoutreturn_release */ get_layout_hdr (lo);spin_unlock (&ino->i_lock);
@@ -655,6 +656,7 @@ _pnfs_return_layout(struct inode *ino) status = -ENOMEM ; goto out; } + lrp->args.stateid = stateid; lrp->args.reclaim =0 ; lrp->args.layout_type =NFS_SERVER (ino)->pnfs_curr_ld->id; lrp->args.inode = ino;
Signature · 1 line
1.7.2.3
Re: [PATCH] SQUASHME: pnfs: Fix NULL dereference in the -ENOMEM path
Quoted 33 lines · Boaz Harrosh
In
_pnfs_return_layout:lrp pointer is checked for NULL after it was already accessed.
The rational here is that in
_pnfs_return_layoutwe want to de-ref and release the layout regardless of if we sent the return or not (forgetfull). An eventual recall can return-ENOMATCHINGinstead of-EDELAY.So to keep the reasoning above, copy the stateid twice.
Benny if it is OK to not release the layout on
-ENOMEMthen the check could just be moved above thespin_lock(), and theput_layout_hdrremoved.Signed-off-by Boaz Harrosh <[email protected]>--- fs/nfs/pnfs.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)fs/nfs/pnfs.c +1
-0@@ -628,6 +628,7 @@ _pnfs_return_layout(struct inode *ino)struct nfs_inode *nfsi =NFS_I (ino);LIST_HEAD (tmp_list);struct nfs4_layoutreturn *lrp; +nfs4_stateid stateid;int status =0 ;dprintk ("--> %s\n" , __func__);
fs/nfs/pnfs.c _pnfs_return_layout(struct inode *ino) · line 644
Quoted 2 lines
fs/nfs/pnfs.c +0
-0@@ -642,7 +643,7 @@ _pnfs_return_layout(struct inode *ino)kfree (lrp); goto out;
Rrrr the lrp is leaked here
Quoted 7 lines
fs/nfs/pnfs.c +1
-1} - lrp->args.stateid = nfsi->layout->plh_stateid; + stateid = nfsi->layout->plh_stateid;/* Reference matched in nfs4_layoutreturn_release */ get_layout_hdr (lo);spin_unlock (&ino->i_lock);
fs/nfs/pnfs.c _pnfs_return_layout(struct inode *ino) · line 662
Quoted 7 lines
fs/nfs/pnfs.c +1
-0@@ -655,6 +656,7 @@ _pnfs_return_layout(struct inode *ino) status = -ENOMEM ; goto out; } + lrp->args.stateid = stateid; lrp->args.reclaim =0 ; lrp->args.layout_type =NFS_SERVER (ino)->pnfs_curr_ld->id; lrp->args.inode = ino;
I'll send a second squashme. Ignore that one please Boaz
PATCH v2 1/1 SQUASHME: pnfs: Fix NULL dereference and leak in the -ENOMEM path
In reply to Boaz HarroshIn _pnfs_return_layout:
lrp pointer is checked for NULL after it was already accessed.
The rational here is that in _pnfs_return_layout we want to de-ref and release the layout regardless of if we sent the return or not (forgetfull). An eventual recall can return -ENOMATCHING instead of -EDELAY.
So to keep the reasoning above, copy the stateid twice.
Benny if it is OK to not release the layout on -ENOMEM then the check could just be moved above the spin_lock(), and the put_layout_hdr removed.
Also the error returns would leak the lrp so fix it.
--- fs/nfs/pnfs.c | 14 +++++++++----- 1 files changed, 9 insertions(+), 5 deletions(-)
fs/nfs/pnfs.c +9 -5
@@ -627,13 +627,12 @@ _pnfs_return_layout(struct inode *ino)struct pnfs_layout_hdr *lo =NULL ;struct nfs_inode *nfsi =NFS_I (ino);LIST_HEAD (tmp_list); -struct nfs4_layoutreturn *lrp; +struct nfs4_layoutreturn *lrp =NULL ; +nfs4_stateid stateid;int status =0 ;dprintk ("--> %s\n" , __func__); - lrp =kzalloc (sizeof (*lrp),GFP_KERNEL ); -spin_lock (&ino->i_lock); lo = nfsi->layout;if (!lo || !mark_matching_lsegs_invalid (lo, &tmp_list,NULL )) {
@@ -642,7 +641,7 @@ _pnfs_return_layout(struct inode *ino)kfree (lrp); goto out; } - lrp->args.stateid = nfsi->layout->plh_stateid; + stateid = nfsi->layout->plh_stateid;/* Reference matched in nfs4_layoutreturn_release */ get_layout_hdr (lo);spin_unlock (&ino->i_lock);
@@ -650,11 +649,14 @@ _pnfs_return_layout(struct inode *ino)WARN_ON (test_bit (NFS_INO_LAYOUTCOMMIT , &nfsi->flags)); -if (lrp ==NULL ) { +/* lrp is freed in nfs4_layoutreturn_release */ + lrp =kzalloc (sizeof (*lrp),GFP_KERNEL ); +if (unlikely (!lrp)) {put_layout_hdr (NFS_I (ino)->layout); status = -ENOMEM ; goto out; } + lrp->args.stateid = stateid; lrp->args.reclaim =0 ; lrp->args.layout_type =NFS_SERVER (ino)->pnfs_curr_ld->id; lrp->args.inode = ino;
@@ -662,6 +664,8 @@ _pnfs_return_layout(struct inode *ino) status =nfs4_proc_layoutreturn (lrp); out: +if (unlikely (status)) +kfree (lrp);dprintk ("<-- %s status: %d\n" , __func__, status);return status; }
Signature · 1 line
1.7.2.3
Re: [PATCH V2] SQUASHME: pnfs: Fix NULL dereference and leak in the -ENOMEM path
Quoted 43 lines · Boaz Harrosh
In
_pnfs_return_layout:lrp pointer is checked for NULL after it was already accessed.
The rational here is that in
_pnfs_return_layoutwe want to de-ref and release the layout regardless of if we sent the return or not (forgetfull). An eventual recall can return-ENOMATCHINGinstead of-EDELAY.So to keep the reasoning above, copy the stateid twice.
Benny if it is OK to not release the layout on
-ENOMEMthen the check could just be moved above thespin_lock(), and theput_layout_hdrremoved.Also the error returns would leak the lrp so fix it.
Signed-off-by Boaz Harrosh <[email protected]>--- fs/nfs/pnfs.c | 14 +++++++++----- 1 files changed, 9 insertions(+), 5 deletions(-)fs/nfs/pnfs.c +2
-3@@ -627,13 +627,12 @@ _pnfs_return_layout(struct inode *ino)struct pnfs_layout_hdr *lo =NULL ;struct nfs_inode *nfsi =NFS_I (ino);LIST_HEAD (tmp_list); -struct nfs4_layoutreturn *lrp; +struct nfs4_layoutreturn *lrp =NULL ; +nfs4_stateid stateid;int status =0 ;dprintk ("--> %s\n" , __func__); - lrp =kzalloc (sizeof (*lrp),GFP_KERNEL ); -spin_lock (&ino->i_lock); lo = nfsi->layout;if (!lo || !mark_matching_lsegs_invalid (lo, &tmp_list,NULL )) {
fs/nfs/pnfs.c _pnfs_return_layout(struct inode *ino) · line 641
Quoted 1 line
fs/nfs/pnfs.c +0
-0@@ -642,7 +641,7 @@ _pnfs_return_layout(struct inode *ino)kfree (lrp);
OK Where is my coffee today
there was no leak here. There was a leak if nfs4_proc_layoutreturn() returned error which means _release was not called.
I'll send a 3rd version (Though it's harmless)
Quoted 32 lines
fs/nfs/pnfs.c +7
-2goto out; } - lrp->args.stateid = nfsi->layout->plh_stateid; + stateid = nfsi->layout->plh_stateid;/* Reference matched in nfs4_layoutreturn_release */ get_layout_hdr (lo);spin_unlock (&ino->i_lock);@@ -650,11 +649,14 @@ _pnfs_return_layout(struct inode *ino)WARN_ON (test_bit (NFS_INO_LAYOUTCOMMIT , &nfsi->flags)); -if (lrp ==NULL ) { +/* lrp is freed in nfs4_layoutreturn_release */ + lrp =kzalloc (sizeof (*lrp),GFP_KERNEL ); +if (unlikely (!lrp)) {put_layout_hdr (NFS_I (ino)->layout); status = -ENOMEM ; goto out; } + lrp->args.stateid = stateid; lrp->args.reclaim =0 ; lrp->args.layout_type =NFS_SERVER (ino)->pnfs_curr_ld->id; lrp->args.inode = ino;@@ -662,6 +664,8 @@ _pnfs_return_layout(struct inode *ino) status =nfs4_proc_layoutreturn (lrp); out: +if (unlikely (status)) +kfree (lrp);dprintk ("<-- %s status: %d\n" , __func__, status);return status; }
Re: [PATCH V2] SQUASHME: pnfs: Fix NULL dereference and leak in the -ENOMEM path
Quoted 36 lines · Boaz Harrosh
Quoted 35 lines · Boaz Harrosh
In
_pnfs_return_layout:lrp pointer is checked for NULL after it was already accessed.
The rational here is that in
_pnfs_return_layoutwe want to de-ref and release the layout regardless of if we sent the return or not (forgetfull). An eventual recall can return-ENOMATCHINGinstead of-EDELAY.So to keep the reasoning above, copy the stateid twice.
Benny if it is OK to not release the layout on
-ENOMEMthen the check could just be moved above thespin_lock(), and theput_layout_hdrremoved.Also the error returns would leak the lrp so fix it.
Signed-off-by Boaz Harrosh <[email protected]>--- fs/nfs/pnfs.c | 14 +++++++++----- 1 files changed, 9 insertions(+), 5 deletions(-)fs/nfs/pnfs.c +2
-1@@ -627,13 +627,12 @@ _pnfs_return_layout(struct inode *ino)struct pnfs_layout_hdr *lo =NULL ;struct nfs_inode *nfsi =NFS_I (ino);LIST_HEAD (tmp_list); -struct nfs4_layoutreturn *lrp; +struct nfs4_layoutreturn *lrp =NULL ; +nfs4_stateid stateid;int status =0 ;
Quoted 4 lines
fs/nfs/pnfs.c _pnfs_return_layout(struct inode *ino) · line 636
Quoted 4 lines
fs/nfs/pnfs.c +0
-2dprintk ("--> %s\n" , __func__); - lrp =kzalloc (sizeof (*lrp),GFP_KERNEL ); -
Hmm, the original idea (<blush>not perfectly implemented, as you noticed</blush>) was to do the allocation earlier and to fail with -ENOMEM
before traversing the lseg list, and by that save the extra memcpy of the stateid.
The assumptions were that kzalloc failure is rare, as well as not finding any segment to return, as the layout hdr existence is checked in the wrapper before entering this function ad we're only doing whole file returns at this point.
Quoted 5 lines
fs/nfs/pnfs.c _pnfs_return_layout(struct inode *ino) · line 641
Quoted 5 lines
fs/nfs/pnfs.c +0
-0spin_lock (&ino->i_lock); lo = nfsi->layout;if (!lo || !mark_matching_lsegs_invalid (lo, &tmp_list,NULL )) {@@ -642,7 +641,7 @@ _pnfs_return_layout(struct inode *ino)kfree (lrp);
If lrp is not allocated before this block no point in kfree'ing it on this exit path.
Quoted 7 lines
OK Where is my coffee today
there was no leak here. There was a leak if
nfs4_proc_layoutreturn()returned error which means_releasewas not called.
I'll send a 3rd version (Though it's harmless)
Please just free lrp there, just if rpc_run_task returns an error, otherwise nfs4_layoutreturn_release must be called.
Bottom like is that it always nfs4_proc_layoutreturn's responsibility to free lrp (a.k.a calldata)
Benny
Quoted 33 lines
Quoted 32 lines
fs/nfs/pnfs.c +7
-2goto out; } - lrp->args.stateid = nfsi->layout->plh_stateid; + stateid = nfsi->layout->plh_stateid;/* Reference matched in nfs4_layoutreturn_release */ get_layout_hdr (lo);spin_unlock (&ino->i_lock);@@ -650,11 +649,14 @@ _pnfs_return_layout(struct inode *ino)WARN_ON (test_bit (NFS_INO_LAYOUTCOMMIT , &nfsi->flags)); -if (lrp ==NULL ) { +/* lrp is freed in nfs4_layoutreturn_release */ + lrp =kzalloc (sizeof (*lrp),GFP_KERNEL ); +if (unlikely (!lrp)) {put_layout_hdr (NFS_I (ino)->layout); status = -ENOMEM ; goto out; } + lrp->args.stateid = stateid; lrp->args.reclaim =0 ; lrp->args.layout_type =NFS_SERVER (ino)->pnfs_curr_ld->id; lrp->args.inode = ino;@@ -662,6 +664,8 @@ _pnfs_return_layout(struct inode *ino) status =nfs4_proc_layoutreturn (lrp); out: +if (unlikely (status)) +kfree (lrp);dprintk ("<-- %s status: %d\n" , __func__, status);return status; }
PATCH v3 1/1 SQUASHME: pnfs: Fix NULL dereference and leak in the -ENOMEM path
In reply to Boaz HarroshIn _pnfs_return_layout:
lrp pointer is checked for NULL after it was already accessed.
The rational here is that in _pnfs_return_layout we want to de-ref and release the layout regardless of if we sent the return or not (forgetfull). An eventual recall can return -ENOMATCHING instead of -EDELAY.
So to keep the reasoning above, copy the stateid twice.
Benny if it is OK to not release the layout on -ENOMEM then the check could just be moved above the spin_lock(), and the put_layout_hdr removed.
Also the error returns would leak the lrp so fix it.
--- fs/nfs/pnfs.c | 15 +++++++++------ 1 files changed, 9 insertions(+), 6 deletions(-)
fs/nfs/pnfs.c +9 -6
@@ -627,22 +627,20 @@ _pnfs_return_layout(struct inode *ino)struct pnfs_layout_hdr *lo =NULL ;struct nfs_inode *nfsi =NFS_I (ino);LIST_HEAD (tmp_list); -struct nfs4_layoutreturn *lrp; +struct nfs4_layoutreturn *lrp =NULL ; +nfs4_stateid stateid;int status =0 ;dprintk ("--> %s\n" , __func__); - lrp =kzalloc (sizeof (*lrp),GFP_KERNEL ); -spin_lock (&ino->i_lock); lo = nfsi->layout;if (!lo || !mark_matching_lsegs_invalid (lo, &tmp_list,NULL )) {spin_unlock (&ino->i_lock);dprintk ("%s: no layout segments to return\n" , __func__); -kfree (lrp); goto out; } - lrp->args.stateid = nfsi->layout->plh_stateid; + stateid = nfsi->layout->plh_stateid;/* Reference matched in nfs4_layoutreturn_release */ get_layout_hdr (lo);spin_unlock (&ino->i_lock);
@@ -650,11 +648,14 @@ _pnfs_return_layout(struct inode *ino)WARN_ON (test_bit (NFS_INO_LAYOUTCOMMIT , &nfsi->flags)); -if (lrp ==NULL ) { +/* lrp is freed in nfs4_layoutreturn_release */ + lrp =kzalloc (sizeof (*lrp),GFP_KERNEL ); +if (unlikely (!lrp)) {put_layout_hdr (NFS_I (ino)->layout); status = -ENOMEM ; goto out; } + lrp->args.stateid = stateid; lrp->args.reclaim =0 ; lrp->args.layout_type =NFS_SERVER (ino)->pnfs_curr_ld->id; lrp->args.inode = ino;
@@ -662,6 +663,8 @@ _pnfs_return_layout(struct inode *ino) status =nfs4_proc_layoutreturn (lrp); out: +if (unlikely (status)) +kfree (lrp);dprintk ("<-- %s status: %d\n" , __func__, status);return status; }
Signature · 1 line
1.7.2.3
Re: [PATCH V3] SQUASHME: pnfs: Fix NULL dereference and leak in the -ENOMEM path
Quoted 53 lines · Boaz Harrosh
In
_pnfs_return_layout:lrp pointer is checked for NULL after it was already accessed.
The rational here is that in
_pnfs_return_layoutwe want to de-ref and release the layout regardless of if we sent the return or not (forgetfull). An eventual recall can return-ENOMATCHINGinstead of-EDELAY.So to keep the reasoning above, copy the stateid twice.
Benny if it is OK to not release the layout on
-ENOMEMthen the check could just be moved above thespin_lock(), and theput_layout_hdrremoved.Also the error returns would leak the lrp so fix it.
Signed-off-by Boaz Harrosh <[email protected]>--- fs/nfs/pnfs.c | 15 +++++++++------ 1 files changed, 9 insertions(+), 6 deletions(-)fs/nfs/pnfs.c +3
-5@@ -627,22 +627,20 @@ _pnfs_return_layout(struct inode *ino)struct pnfs_layout_hdr *lo =NULL ;struct nfs_inode *nfsi =NFS_I (ino);LIST_HEAD (tmp_list); -struct nfs4_layoutreturn *lrp; +struct nfs4_layoutreturn *lrp =NULL ; +nfs4_stateid stateid;int status =0 ;dprintk ("--> %s\n" , __func__); - lrp =kzalloc (sizeof (*lrp),GFP_KERNEL ); -spin_lock (&ino->i_lock); lo = nfsi->layout;if (!lo || !mark_matching_lsegs_invalid (lo, &tmp_list,NULL )) {spin_unlock (&ino->i_lock);dprintk ("%s: no layout segments to return\n" , __func__); -kfree (lrp); goto out; } - lrp->args.stateid = nfsi->layout->plh_stateid; + stateid = nfsi->layout->plh_stateid;/* Reference matched in nfs4_layoutreturn_release */ get_layout_hdr (lo);spin_unlock (&ino->i_lock);
fs/nfs/pnfs.c _pnfs_return_layout(struct inode *ino) · line 653
Quoted 4 lines
fs/nfs/pnfs.c +0
-1@@ -650,11 +648,14 @@ _pnfs_return_layout(struct inode *ino)WARN_ON (test_bit (NFS_INO_LAYOUTCOMMIT , &nfsi->flags)); -if (lrp ==NULL ) {
I prefer to simply move this test up before the condition calling mark_matching_lsegs_invalid
Quoted 12 lines
fs/nfs/pnfs.c +4
-0+/* lrp is freed in nfs4_layoutreturn_release */ + lrp =kzalloc (sizeof (*lrp),GFP_KERNEL ); +if (unlikely (!lrp)) {put_layout_hdr (NFS_I (ino)->layout); status = -ENOMEM ; goto out; } + lrp->args.stateid = stateid; lrp->args.reclaim =0 ; lrp->args.layout_type =NFS_SERVER (ino)->pnfs_curr_ld->id; lrp->args.inode = ino;
fs/nfs/pnfs.c _pnfs_return_layout(struct inode *ino) · line 667
Quoted 5 lines
fs/nfs/pnfs.c +2
-0@@ -662,6 +663,8 @@ _pnfs_return_layout(struct inode *ino) status =nfs4_proc_layoutreturn (lrp); out: +if (unlikely (status)) +kfree (lrp);
I wonder where this leak you're seeing is coming from. rpc_release is supposed to be called even on task allocation error, see rpc_new_task.
Benny
Quoted 3 lines
fs/nfs/pnfs.c +0
-0dprintk ("<-- %s status: %d\n" , __func__, status);return status; }
PATCH v6 22/26 pnfs: layoutret_on_setattr
In reply to Benny HalevyWith the objects layout security model, we have object capabilities that are associated with the layout and we anticipate that the server will issue a cb_layoutrecall for any setattr that changes security related attributes (user/group/mode/acl) or truncates the file.
Therefore, the layout is returned before issuing the setattr to avoid the anticipated cb_layoutrecall.
--- fs/nfs/nfs4proc.c | 3 +++ fs/nfs/objlayout/objio_osd.c | 1 + fs/nfs/pnfs.h | 22 ++++++++++++++++++++++ 3 files changed, 26 insertions(+), 0 deletions(-)
fs/nfs/nfs4proc.c +3 -0
@@ -2361,6 +2361,9 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,struct nfs4_state *state =NULL ;int status; +if (pnfs_ld_layoutret_on_setattr (inode)) +pnfs_return_layout (inode); +nfs_fattr_init (fattr);/* Search for an existing open(O_WRITE) file */
fs/nfs/objlayout/objio_osd.c +1 -0
@@ -950,6 +950,7 @@ objlayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,static struct pnfs_layoutdriver_type objlayout_type = { .id =LAYOUT_OSD2_OBJECTS , .name ="LAYOUT_OSD2_OBJECTS" , + .flags =PNFS_LAYOUTRET_ON_SETATTR , .alloc_layout_hdr = objlayout_alloc_layout_hdr, .free_layout_hdr = objlayout_free_layout_hdr,
fs/nfs/pnfs.h +22 -0
@@ -65,6 +65,11 @@ enum { NFS_LAYOUT_DESTROYED, /* no new use of layout allowed */ }; +enum layoutdriver_policy_flags { +/* Should the pNFS client commit and return the layout upon a setattr */ +PNFS_LAYOUTRET_ON_SETATTR =1 <<0 , +}; +struct nfs4_deviceid_node ;/* Per-layout driver specific registration structure */
@@ -73,6 +78,7 @@ struct pnfs_layoutdriver_type {const u32 id;const char *name;struct module *owner; +unsigned flags;struct pnfs_layout_hdr * (*alloc_layout_hdr) (struct inode *inode,gfp_t gfp_flags);void (*free_layout_hdr) (struct pnfs_layout_hdr *);
@@ -258,6 +264,16 @@ static inline void pnfs_clear_request_commit(struct nfs_page *req)put_lseg (req->wb_commit_lseg); } +/* Should the pNFS client commit and return the layout upon a setattr */ +static inline bool +pnfs_ld_layoutret_on_setattr (struct inode *inode) +{ +if (!pnfs_enabled_sb (NFS_SERVER (inode))) +return false; +return NFS_SERVER (inode)->pnfs_curr_ld->flags & +PNFS_LAYOUTRET_ON_SETATTR ; +} +static inline int pnfs_return_layout (struct inode *ino) {struct nfs_inode *nfsi =NFS_I (ino);
@@ -317,6 +333,12 @@ static inline int pnfs_return_layout(struct inode *ino) }static inline bool +pnfs_ld_layoutret_on_setattr (struct inode *inode) +{ +return false; +} + +static inline bool pnfs_roc (struct inode *ino) {return false;
Signature · 1 line
1.7.3.4
PATCH v6 23/26 pnfs: encode_layoutreturn
In reply to Benny HalevyFrom: Andy Adamson <[email protected]>
Add a layout driver method to encode the layout type specific opaque part of layout return in-line in the xdr stream.
Currently the pnfs-objects layout driver uses it to encode i/o error information on LAYOUTRETURN.
--- fs/nfs/nfs4xdr.c | 9 +++++++-- fs/nfs/pnfs.h | 4 ++++ 2 files changed, 11 insertions(+), 2 deletions(-)
fs/nfs/nfs4xdr.c +7 -2
@@ -1920,8 +1920,13 @@ encode_layoutreturn(struct xdr_stream *xdr,spin_lock (&args->inode->i_lock);xdr_encode_opaque_fixed (p, &args->stateid.data,NFS4_STATEID_SIZE );spin_unlock (&args->inode->i_lock); - p =reserve_space (xdr,4 ); - *p =cpu_to_be32 (0 ); +if (NFS_SERVER (args->inode)->pnfs_curr_ld->encode_layoutreturn) { +NFS_SERVER (args->inode)->pnfs_curr_ld->encode_layoutreturn ( +NFS_I (args->inode)->layout, xdr, args); + }else { + p =reserve_space (xdr,4 ); + *p =cpu_to_be32 (0 ); + } hdr->nops++; hdr->replen += decode_layoutreturn_maxsz; }
fs/nfs/pnfs.h +4 -0
@@ -104,6 +104,10 @@ struct pnfs_layoutdriver_type {enum pnfs_try_status (*write_pagelist) (struct nfs_write_data *nfs_data,int how);void (*free_deviceid_node) (struct nfs4_deviceid_node *); + +void (*encode_layoutreturn) (struct pnfs_layout_hdr *layoutid, +struct xdr_stream *xdr, +const struct nfs4_layoutreturn_args *args); };struct pnfs_layout_hdr {
Signature · 1 line
1.7.3.4
PATCH v6 24/26 pnfs-obj: report errors and .encode_layoutreturn Implementation.
In reply to Benny HalevyFrom: Boaz Harrosh <[email protected]>
An io_state pre-allocates an error information structure for each possible osd-device that might error during IO. When IO is done if all was well the io_state is freed. (as today). If the I/O has ended with an error, the io_state is queued on a per-layout err_list. When eventually encode_layoutreturn() is called, each error is properly encoded on the XDR buffer and only then the io_state is removed from err_list and de-allocated.
It is up to the io_engine to fill in the segment that fault and the type of osd_error that occurred. By calling objlayout_io_set_result() for each failing device.
In objio_osd:
* Allocate io-error descriptors space as part of io_state
* Use generic objlayout error reporting at end of io.
--- fs/nfs/objlayout/objio_osd.c | 44 ++++++++- fs/nfs/objlayout/objlayout.c | 232 +++++++++++++++++++++++++++++++++++++++++- fs/nfs/objlayout/objlayout.h | 23 ++++ 3 files changed, 297 insertions(+), 2 deletions(-)
fs/nfs/objlayout/objio_osd.c +43 -1
@@ -384,13 +384,17 @@ int objio_alloc_io_state(struct pnfs_layout_segment *lseg,struct objio_state *ios;const unsigned first_size =sizeof (*ios) + objio_seg->num_comps *sizeof (ios->per_dev[0 ]); +const unsigned sec_size = objio_seg->num_comps * +sizeof (ios->ol_state.ioerrs[0 ]);dprintk ("%s: num_comps=%d\n" , __func__, objio_seg->num_comps); - ios =kzalloc (first_size, gfp_flags); + ios =kzalloc (first_size + sec_size, gfp_flags);if (unlikely (!ios))return -ENOMEM ; ios->layout = objio_seg; + ios->ol_state.ioerrs = ((void *)ios) + first_size; + ios->ol_state.num_comps = objio_seg->num_comps; *outp = &ios->ol_state;return 0 ;
@@ -404,6 +408,36 @@ void objio_free_io_state(struct objlayout_io_state *ol_state)kfree (ios); } +enum pnfs_osd_errno osd_pri_2_pnfs_err (enum osd_err_priority oep) +{ +switch (oep) { +case OSD_ERR_PRI_NO_ERROR : +return (enum pnfs_osd_errno )0 ; + +case OSD_ERR_PRI_CLEAR_PAGES : +BUG_ON (1 ); +return 0 ; + +case OSD_ERR_PRI_RESOURCE : +return PNFS_OSD_ERR_RESOURCE ; +case OSD_ERR_PRI_BAD_CRED : +return PNFS_OSD_ERR_BAD_CRED ; +case OSD_ERR_PRI_NO_ACCESS : +return PNFS_OSD_ERR_NO_ACCESS ; +case OSD_ERR_PRI_UNREACHABLE : +return PNFS_OSD_ERR_UNREACHABLE ; +case OSD_ERR_PRI_NOT_FOUND : +return PNFS_OSD_ERR_NOT_FOUND ; +case OSD_ERR_PRI_NO_SPACE : +return PNFS_OSD_ERR_NO_SPACE ; +default : +WARN_ON (1 ); +/* fallthrough */ +case OSD_ERR_PRI_EIO : +return PNFS_OSD_ERR_EIO ; + } +} +static void _clear_bio (struct bio *bio) {struct bio_vec *bv;
@@ -450,6 +484,12 @@ static int _io_check(struct objio_state *ios, bool is_write)continue ;/* we recovered */ } dev = ios->per_dev[i].dev; +objlayout_io_set_result (&ios->ol_state, dev, + &ios->layout->comps[dev].oc_object_id, +osd_pri_2_pnfs_err (osi.osd_err_pri), + ios->per_dev[i].offset, + ios->per_dev[i].length, + is_write);if (osi.osd_err_pri >= oep) { oep = osi.osd_err_pri;
@@ -963,6 +1003,8 @@ static struct pnfs_layoutdriver_type objlayout_type = { .pg_test = objlayout_pg_test, .free_deviceid_node = objio_free_deviceid_node, + + .encode_layoutreturn = objlayout_encode_layoutreturn, };MODULE_DESCRIPTION ("pNFS Layout Driver for OSD2 objects" );
fs/nfs/objlayout/objlayout.c +231 -1
262 lines not on this page · raw message
fs/nfs/objlayout/objlayout.h +23 -0
@@ -50,6 +50,10 @@*/ struct objlayout {struct pnfs_layout_hdr pnfs_layout; + +/* for layout_return */ +spinlock_t lock; +struct list_head err_list; }; static inline struct objlayout *
@@ -76,6 +80,16 @@ struct objlayout_io_state {int status;/* res */ int eof;/* res */ int committed;/* res */ + +/* Error reporting (layout_return) */ +struct list_head err_list; +unsigned num_comps; +/* Pointer to array of error descriptors of size num_comps. +* It should contain as many entries as devices in the osd_layout +* that participate in the I/O. It is up to the io_engine to allocate +* needed space and set num_comps. +*/ +struct pnfs_osd_ioerr *ioerrs; };/*
@@ -101,6 +115,10 @@ extern ssize_t objio_write_pagelist(struct objlayout_io_state *ol_state,/* * callback API */ +extern void objlayout_io_set_result (struct objlayout_io_state *state, +unsigned index,struct pnfs_osd_objid *pooid, +int osd_error,u64 offset,u64 length,bool is_write); +extern void objlayout_read_done (struct objlayout_io_state *state,ssize_t status,bool sync); extern void objlayout_write_done(struct objlayout_io_state *state,
@@ -131,4 +149,9 @@ extern enum pnfs_try_status objlayout_write_pagelist( struct nfs_write_data *, int how); +extern void objlayout_encode_layoutreturn ( +struct pnfs_layout_hdr *, +struct xdr_stream *, +const struct nfs4_layoutreturn_args *); +#endif /* _OBJLAYOUT_H */
Signature · 1 line
1.7.3.4
PATCH v6 25/26 pnfs: encode_layoutcommit
In reply to Benny HalevyAdd a layout driver method to encode the layout type specific opaque part of layout commit in-line in the xdr stream.
Currently, the pnfs-objects layout driver uses it to encode metadata hints to the MDS and the blocks layout driver to commit provisionally allocated extents to the file.
--- fs/nfs/nfs4xdr.c | 16 +++++++++++++--- fs/nfs/pnfs.h | 4 ++++ 2 files changed, 17 insertions(+), 3 deletions(-)
fs/nfs/nfs4xdr.c +13 -3
@@ -1875,6 +1875,7 @@ encode_layoutget(struct xdr_stream *xdr,static int encode_layoutcommit (struct xdr_stream *xdr, +struct inode *inode,const struct nfs4_layoutcommit_args *args,struct compound_hdr *hdr) {
@@ -1883,7 +1884,7 @@ encode_layoutcommit(struct xdr_stream *xdr,dprintk ("%s: lbw: %llu type: %d\n" , __func__, args->lastbytewritten,NFS_SERVER (args->inode)->pnfs_curr_ld->id); - p =reserve_space (xdr,48 +NFS4_STATEID_SIZE ); + p =reserve_space (xdr,44 +NFS4_STATEID_SIZE ); *p++ =cpu_to_be32 (OP_LAYOUTCOMMIT );/* Only whole file layouts */ p =xdr_encode_hyper (p,0 );/* offset */
@@ -1894,7 +1895,14 @@ encode_layoutcommit(struct xdr_stream *xdr, p =xdr_encode_hyper (p, args->lastbytewritten); *p++ =cpu_to_be32 (0 );/* Never send time_modify_changed */ *p++ =cpu_to_be32 (NFS_SERVER (args->inode)->pnfs_curr_ld->id);/* type */ - *p++ =cpu_to_be32 (0 );/* no file layout payload */ + +if (NFS_SERVER (inode)->pnfs_curr_ld->encode_layoutcommit) +NFS_SERVER (inode)->pnfs_curr_ld->encode_layoutcommit ( +NFS_I (inode)->layout, xdr, args); +else { + p =reserve_space (xdr,4 ); + *p =cpu_to_be32 (0 );/* no layout-type payload */ + } hdr->nops++; hdr->replen += decode_layoutcommit_maxsz;
@@ -2751,6 +2759,8 @@ static void nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req,struct xdr_stream *xdr, struct nfs4_layoutcommit_args *args) { + struct nfs4_layoutcommit_data *data = + container_of(args, struct nfs4_layoutcommit_data, args);struct compound_hdr hdr = { .minorversion =nfs4_xdr_minorversion (&args->seq_args), };
@@ -2758,7 +2768,7 @@ static void nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req,encode_compound_hdr (xdr, req, &hdr);encode_sequence (xdr, &args->seq_args, &hdr);encode_putfh (xdr,NFS_FH (args->inode), &hdr); -encode_layoutcommit (xdr, args, &hdr); +encode_layoutcommit (xdr, data->args.inode, args, &hdr);encode_getfattr (xdr, args->bitmask, &hdr);encode_nops (&hdr); }
fs/nfs/pnfs.h +4 -0
@@ -108,6 +108,10 @@ struct pnfs_layoutdriver_type {void (*encode_layoutreturn) (struct pnfs_layout_hdr *layoutid,struct xdr_stream *xdr,const struct nfs4_layoutreturn_args *args); + +void (*encode_layoutcommit) (struct pnfs_layout_hdr *layoutid, +struct xdr_stream *xdr, +const struct nfs4_layoutcommit_args *args); };struct pnfs_layout_hdr {
Signature · 1 line
1.7.3.4
PATCH v6 26/26 pnfs-obj: objlayout_encode_layoutcommit implementation
In reply to Benny HalevyFrom: Boaz Harrosh <[email protected]>
* Define API for io-engines to report delta_space_used in IOs
* Encode the osd-layout specific information of the layoutcommit XDR buffer.
--- fs/nfs/objlayout/objio_osd.c | 1 + fs/nfs/objlayout/objlayout.c | 30 ++++++++++++++++++++++++++++++ fs/nfs/objlayout/objlayout.h | 30 ++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 0 deletions(-)
fs/nfs/objlayout/objio_osd.c +1 -0
@@ -1004,6 +1004,7 @@ static struct pnfs_layoutdriver_type objlayout_type = { .free_deviceid_node = objio_free_deviceid_node, + .encode_layoutcommit = objlayout_encode_layoutcommit, .encode_layoutreturn = objlayout_encode_layoutreturn, };
fs/nfs/objlayout/objlayout.c +30 -0
@@ -225,6 +225,7 @@ objlayout_iodone(struct objlayout_io_state *state)struct objlayout *objlay =OBJLAYOUT (state->lseg->pls_layout);spin_lock (&objlay->lock); + objlay->delta_space_valid =OBJ_DSU_INVALID ;list_add (&objlay->err_list, &state->err_list);spin_unlock (&objlay->lock); }
@@ -433,6 +434,35 @@ objlayout_write_pagelist(struct nfs_write_data *wdata,return PNFS_ATTEMPTED ; } +void +objlayout_encode_layoutcommit (struct pnfs_layout_hdr *pnfslay, +struct xdr_stream *xdr, +const struct nfs4_layoutcommit_args *args) +{ +struct objlayout *objlay =OBJLAYOUT (pnfslay); +struct pnfs_osd_layoutupdate lou; +__be32 *start; + +dprintk ("%s: Begin\n" , __func__); + +spin_lock (&objlay->lock); + lou.dsu_valid = (objlay->delta_space_valid ==OBJ_DSU_VALID ); + lou.dsu_delta = objlay->delta_space_used; + objlay->delta_space_used =0 ; + objlay->delta_space_valid =OBJ_DSU_INIT ; + lou.olu_ioerr_flag = !list_empty (&objlay->err_list); +spin_unlock (&objlay->lock); + + start =xdr_reserve_space (xdr,4 ); + +BUG_ON (pnfs_osd_xdr_encode_layoutupdate (xdr, &lou)); + + *start =cpu_to_be32 ((xdr->p - start -1 ) *4 ); + +dprintk ("%s: Return delta_space_used %lld err %d\n" , __func__, + lou.dsu_delta, lou.olu_ioerr_flag); +} +static int err_prio (u32 oer_errno) {
fs/nfs/objlayout/objlayout.h +30 -0
@@ -51,6 +51,14 @@struct objlayout {struct pnfs_layout_hdr pnfs_layout; +/* for layout_commit */ +enum osd_delta_space_valid_enum { +OBJ_DSU_INIT =0 , +OBJ_DSU_VALID , +OBJ_DSU_INVALID , + } delta_space_valid; +s64 delta_space_used;/* consumed by write ops */ +/* for layout_return */ spinlock_t lock;struct list_head err_list;
@@ -119,6 +127,23 @@ extern void objlayout_io_set_result(struct objlayout_io_state *state, unsigned index, struct pnfs_osd_objid *pooid, int osd_error, u64 offset, u64 length, bool is_write); +static inline void +objlayout_add_delta_space_used (struct objlayout_io_state *state,s64 space_used) +{ +struct objlayout *objlay =OBJLAYOUT (state->lseg->pls_layout); + +/* If one of the I/Os errored out and the delta_space_used was +* invalid we render the complete report as invalid. Protocol mandate +* the DSU be accurate or not reported. +*/ +spin_lock (&objlay->lock); +if (objlay->delta_space_valid !=OBJ_DSU_INVALID ) { + objlay->delta_space_valid =OBJ_DSU_VALID ; + objlay->delta_space_used += space_used; + } +spin_unlock (&objlay->lock); +} +extern void objlayout_read_done (struct objlayout_io_state *state,ssize_t status,bool sync); extern void objlayout_write_done(struct objlayout_io_state *state,
@@ -149,6 +174,11 @@ extern enum pnfs_try_status objlayout_write_pagelist( struct nfs_write_data *, int how); +extern void objlayout_encode_layoutcommit ( +struct pnfs_layout_hdr *, +struct xdr_stream *, +const struct nfs4_layoutcommit_args *); + extern void objlayout_encode_layoutreturn( struct pnfs_layout_hdr *, struct xdr_stream *,
Signature · 1 line
1.7.3.4
Quoted 7 lines · Benny Halevy
Hi,
This is a cleaned up version of the v5 patchset I sent earlier. It's also based over v2.6.39 and push to
git://linux-nfs.org/~bhalevy/linux-pnfs.gitpnfs-submit at tag pnfs-for-2.6.40-v6-2011-05-23
Quoted 9 lines
Changes in v6: (Benny)
* squashed all SQUASHMEs
* reverted "SQUASHME: initializedata->taskon the non-rpc io done success paths"
* reverted "per mount layout driver private data"
* reverted "pnfs: set/unset layoutdriver"
* applied (in reverse) "SQUASHME: pnfs-obj: Important fallout from the last rebase"
<snip>
Benny I found some more small bugs. Do you want a full replacement patch or a SQUASHME?
Boaz
On 05/23/2011 07:33 PM, Benny Halevy wrote:
Benny Hi
I have a problem that the default wsize is very small 64K and I get small IOs. I found that the governing member right now is NFS_SERVER()->wsize
I did the below hack on My current code, but you took that away from me.
fs/nfs/objlayout/objlayout.c +0 -0
+ server->wsize = ((PAGE_SIZE - sizeof(struct bio)) / sizeof(struct bio_vec))
+ * PAGE_SIZE * 2;
- dprintk("%s: Return data=%p\n", __func__, data);
+ dprintk("%s: Return data=%p wsize=0x%x\n", __func__, data, server->wsize);
return 0;
}
What do you want that we do to replace this. The default 64K is to small. I don't mind that for pnfs it will be ~0 and the pg_test() will test for maxc_size as well. But then we'll also need the current size or the start_index
Boaz
Quoted 22 lines · Boaz Harrosh
On 05/23/2011 07:33 PM, Benny Halevy wrote:
Benny HiI have a problem that the default wsize is very small 64K and I get small IOs. I found that the governing member right now is NFS_SERVER()->wsize
I did the below hack on My current code, but you took that away from me.
fs/nfs/objlayout/objlayout.c +3
-1+ server->wsize = ((PAGE_SIZE -sizeof (struct bio )) /sizeof (struct bio_vec )) + *PAGE_SIZE *2 ; -dprintk ("%s: Return data=%p\n" , __func__, data); +dprintk ("%s: Return data=%p wsize=0x%x\n" , __func__, data, server->wsize);return 0 ; }
Quoted 6 lines
What do you want that we do to replace this. The default 64K is to small. I don't mind that for pnfs it will be ~0 and the
pg_test()will test formaxc_sizeas well. But then we'll also need the current size or thestart_indexBoaz
How about this approach?
git diff --stat -p -M
fs/nfs/pagelist.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
fs/nfs/pagelist.c +0 -0
@@ -293,7 +293,7 @@ static int nfs_pageio_do_add_request(struct
nfs_pageio_descriptor *desc,
if (desc->pg_bsize < PAGE_SIZE)
return 0;
newlen += desc->pg_count;
- if (newlen > desc->pg_bsize)
+ if (newlen > desc->pg_bsize && !desc->pg_test)
return 0;
prev = nfs_list_entry(desc->pg_list.prev); if (!nfs_can_coalesce_requests(prev, req, desc))
A message that is not in the archive (sent off-list or not yet received): 2E1EB2CF9ED1CB4AA966F0EB76EAB443080D6E54@SACMVEXC2-PRD.hq.netapp.com
Quoted 50 lines · Trond
Quoted 8 lines · Benny Halevy
Quoted 7 lines · Boaz Harrosh
On 05/23/2011 07:33 PM, Benny Halevy wrote:
Benny HiI have a problem that the default wsize is very small 64K and I get small IOs. I found that the governing member right now is NFS_SERVER()->wsize
Quoted 8 lines
fs/nfs/objlayout/objlayout.c
Quoted 8 lines
I did the below hack on My current code, but you took that away from me.
fs/nfs/objlayout/objlayout.c +1
-0+ server->wsize = ((PAGE_SIZE - sizeof(struct bio)) /
sizeof(struct bio_vec))Quoted 4 lines
fs/nfs/objlayout/objlayout.c
Quoted 4 lines
fs/nfs/objlayout/objlayout.c +2
-1+ *PAGE_SIZE *2 ; -dprintk ("%s: Return data=%p\n" , __func__, data); + dprintk("%s: Return data=%p wsize=0x%x\n", __func__, data,
server->wsize);Quoted 4 lines
Quoted 4 lines
return 0;}
What do you want that we do to replace this. The default 64K is to
small.
Quoted 22 lines
Quoted 5 lines
I don't mind that for pnfs it will be ~0 and the
pg_test()will test formaxc_sizeas well. But then we'll also need the current size or thestart_indexBoaz
How about this approach?
git diff --stat -p -M
fs/nfs/pagelist.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)fs/nfs/pagelist.c +0
-1@@ -293,7 +293,7 @@ static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc, if (desc->pg_bsize < PAGE_SIZE)return 0 ; newlen += desc->pg_count; -if (newlen > desc->pg_bsize)
Quoted 8 lines
Quoted 4 lines
fs/nfs/pagelist.c +1
-0+if (newlen > desc->pg_bsize && !desc->pg_test)return 0 ; prev =nfs_list_entry (desc->pg_list.prev);if (!nfs_can_coalesce_requests(prev, req, desc))
Alternatively, clean the above up by putting the newlen >
desc->pg_bsizetest into a defaultnfs_generic_test_coalesce()and require ordinary NFS reads and writes to set that as theirdesc->pg_test().
Good idea!
I'll send a RFC patch including the generic pnfs pg_test for the layout drivers.
Fred - I hope you haven't started working on pg_test, have you? Please let me know.
Benny
Quoted 11 lines
Cheers
Trond
--
Trond Myklebust
Linux NFS client maintainerNetApp
[email protected]
www.netapp.com
Quoted 9 lines · Benny Halevy
I'll send a RFC patch including the generic pnfs
pg_testfor the layout drivers.Fred - I hope you haven't started working on
pg_test, have you? Please let me know.Benny
It is all yours.
Fred
Quoted 56 lines · Trond
Quoted 49 lines · Benny Halevy
Quoted 22 lines · Boaz Harrosh
On 05/23/2011 07:33 PM, Benny Halevy wrote:
Benny HiI have a problem that the default wsize is very small 64K and I get small IOs. I found that the governing member right now is NFS_SERVER()->wsize
I did the below hack on My current code, but you took that away from me.
fs/nfs/objlayout/objlayout.c +3
-1+ server->wsize = ((PAGE_SIZE -sizeof (struct bio )) /sizeof (struct bio_vec )) + *PAGE_SIZE *2 ; -dprintk ("%s: Return data=%p\n" , __func__, data); +dprintk ("%s: Return data=%p wsize=0x%x\n" , __func__, data, server->wsize);return 0 ; }Quoted 6 lines
What do you want that we do to replace this. The default 64K is to small. I don't mind that for pnfs it will be ~0 and the
pg_test()will test formaxc_sizeas well. But then we'll also need the current size or thestart_indexBoaz
How about this approach?
git diff --stat -p -M
fs/nfs/pagelist.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)fs/nfs/pagelist.c +1
-1@@ -293,7 +293,7 @@ static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc, if (desc->pg_bsize < PAGE_SIZE)return 0 ; newlen += desc->pg_count; -if (newlen > desc->pg_bsize) +if (newlen > desc->pg_bsize && !desc->pg_test)return 0 ; prev =nfs_list_entry (desc->pg_list.prev);Quoted 1 line
if (!nfs_can_coalesce_requests(prev, req, desc))
Alternatively, clean the above up by putting the newlen >
desc->pg_bsizetest into a defaultnfs_generic_test_coalesce()and require ordinary NFS reads and writes to set that as theirdesc->pg_test().
Quoted 2 lines
Cheers
Trond
This all approach sounds very good to me. But please I have some questions?
In the nfs_pageio_descriptor passed to pg_test() together with the two pages:
Which member means the current byte_size (or page_count?) and what is the meaning of some of these fields
struct nfs_pageio_descriptor {
....
unsigned long pg_bytes_written;
Is this for result after read/write?
size_t pg_count;
Is this the number of pages added up to now? Do we also have the start of the first page?
size_t pg_bsize;
So I understand this is the max allowed pages. Does that mean also the allocated size or Just the negotiated size with the server? (Really bad name if you ask me)
unsigned int pg_base;
Is that the index of the first page? That cannot be, the page->index needs to be 64bit. So what is this then?
...
};
Thanks
Boaz
Quoted 8 lines · Boaz Harrosh
In the
nfs_pageio_descriptorpassed topg_test()together with the two pages:
Which member means the currentbyte_size(orpage_count?) and what is the meaning of some of these fieldsstruct nfs_pageio_descriptor { .... unsigned long pg_bytes_written; Is this for result after read/write?
This is the total number of bytes we successfully called nfs_pageio_doio() for. In other words, it should represent the total number of bytes we put on the wire.
Quoted 3 lines
size_tpg_count;
Is this the number of pages added up to now? Do we also have the start of the first page?
This is the number of bytes we have successfully coalesced into the current i/o.
Quoted 4 lines
size_tpg_bsize;
So I understand this is the max allowed pages. Does that mean also the allocated size or Just the negotiated size with the server? (Really bad name if you ask me)
It means the 'block size'. In ordinary NFS parlance that will be the 'rsize' or the 'wsize'.
Quoted 3 lines
unsigned int pg_base; Is that the index of the first page? That cannot be, the page->index needs to be 64bit. So what is this then?
It is used when dealing with I/O requests that are not page aligned.
If you consider the pages that we are to write out in the current I/O as a single buffer, then the pg_base is the offset of the first byte to write out/read in.
Signature · 6 lines
Trond Myklebust Linux NFS client maintainer NetApp [email protected] www.netapp.com
Quoted 33 lines · Trond Myklebust
Quoted 8 lines · Boaz Harrosh
In the
nfs_pageio_descriptorpassed topg_test()together with the two pages:
Which member means the currentbyte_size(orpage_count?) and what is the meaning of some of these fieldsstruct nfs_pageio_descriptor { .... unsigned long pg_bytes_written; Is this for result after read/write?This is the total number of bytes we successfully called
nfs_pageio_doio()for. In other words, it should represent the total number of bytes we put on the wire.Quoted 3 lines
size_tpg_count;
Is this the number of pages added up to now? Do we also have the start of the first page?This is the number of bytes we have successfully coalesced into the current i/o.
Quoted 4 lines
size_tpg_bsize;
So I understand this is the max allowed pages. Does that mean also the allocated size or Just the negotiated size with the server? (Really bad name if you ask me)It means the 'block size'. In ordinary NFS parlance that will be the 'rsize' or the 'wsize'.
Quoted 3 lines
unsigned int pg_base; Is that the index of the first page? That cannot be, the page->index needs to be 64bit. So what is this then?
Quoted 6 lines
It is used when dealing with I/O requests that are not page aligned.
If you consider the pages that we are to write out in the current I/O as a single buffer, then the
pg_baseis the offset of the first byte to write out/read in.
Thanks Trond, I think I understand and can write the proper implementation for objects->pg_test now. One more question. I need the file offset of the beginning of the write would that then be:
int objlayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
struct nfs_page *req)
}
struct nfs_page *first_pg = list_entry(pgio->pg_list.next, struct nfs_page, wb_list); u64 io_offset = (first_pg->wb_index << PAGE_SHIFT) + first_pg->wb_offset; ... }
Thanks
Boaz
Quoted 4 lines · Boaz Harrosh
Thanks Trond, I think I understand and can write the proper implementation for
objects->pg_testnow. One more question. I need the file offset of the beginning of the write would that then be:
Quoted 8 lines
int objlayout_pg_test(struct
nfs_pageio_descriptor*pgio, structnfs_page*prev,
structnfs_page*req)
}struct nfs_page *first_pg = list_entry(pgio->pg_list.next, struct nfs_page, wb_list); u64 io_offset = (first_pg->wb_index << PAGE_SHIFT) + first_pg->wb_offset; ... }
Yes. That looks correct.
Signature · 6 lines
Trond Myklebust Linux NFS client maintainer NetApp [email protected] www.netapp.com
Quoted 10 lines · Trond Myklebust
Quoted 9 lines · Boaz Harrosh
Thanks Trond, I think I understand and can write the proper implementation for
objects->pg_testnow. One more question. I need the file offset of the beginning of the write would that then be:int objlayout_pg_test(struct
nfs_pageio_descriptor*pgio, structnfs_page*prev,
structnfs_page*req)
}struct nfs_page *first_pg = list_entry(pgio->pg_list.next, struct nfs_page, wb_list);
Quoted 6 lines
Quoted 3 lines
u64 io_offset = (first_pg->wb_index << PAGE_SHIFT) + first_pg->wb_offset; ... }Yes. That looks correct.
Grate the new skim with pg_test looks perfect. We have all we need and it will be really nice with the raid5/6 code. I think I will use a similar system in exofs now.
Thanks
Boaz