Commit 7f11d8d3 authored by Andy Adamson's avatar Andy Adamson Committed by Trond Myklebust

pnfs: GETDEVICELIST

The block driver uses GETDEVICELIST
Signed-off-by: default avatarAndy Adamson <andros@netapp.com>
[pass struct nfs_server * to getdevicelist]
[get machince creds for getdevicelist]
[fix getdevicelist decode sizing]
Signed-off-by: default avatarBenny Halevy <bhalevy@panasas.com>
Signed-off-by: default avatarBenny Halevy <bhalevy@tonian.com>
Signed-off-by: default avatarJim Rees <rees@umich.edu>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 3557c6c3
......@@ -5834,6 +5834,54 @@ int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp)
return status;
}
/*
* Retrieve the list of Data Server devices from the MDS.
*/
static int _nfs4_getdevicelist(struct nfs_server *server,
const struct nfs_fh *fh,
struct pnfs_devicelist *devlist)
{
struct nfs4_getdevicelist_args args = {
.fh = fh,
.layoutclass = server->pnfs_curr_ld->id,
};
struct nfs4_getdevicelist_res res = {
.devlist = devlist,
};
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETDEVICELIST],
.rpc_argp = &args,
.rpc_resp = &res,
};
int status;
dprintk("--> %s\n", __func__);
status = nfs4_call_sync(server->client, server, &msg, &args.seq_args,
&res.seq_res, 0);
dprintk("<-- %s status=%d\n", __func__, status);
return status;
}
int nfs4_proc_getdevicelist(struct nfs_server *server,
const struct nfs_fh *fh,
struct pnfs_devicelist *devlist)
{
struct nfs4_exception exception = { };
int err;
do {
err = nfs4_handle_exception(server,
_nfs4_getdevicelist(server, fh, devlist),
&exception);
} while (exception.retry);
dprintk("%s: err=%d, num_devs=%u\n", __func__,
err, devlist->num_devs);
return err;
}
EXPORT_SYMBOL_GPL(nfs4_proc_getdevicelist);
static int
_nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev)
{
......
......@@ -314,6 +314,17 @@ static int nfs4_stat_to_errno(int);
XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5)
#define encode_reclaim_complete_maxsz (op_encode_hdr_maxsz + 4)
#define decode_reclaim_complete_maxsz (op_decode_hdr_maxsz + 4)
#define encode_getdevicelist_maxsz (op_encode_hdr_maxsz + 4 + \
encode_verifier_maxsz)
#define decode_getdevicelist_maxsz (op_decode_hdr_maxsz + \
2 /* nfs_cookie4 gdlr_cookie */ + \
decode_verifier_maxsz \
/* verifier4 gdlr_verifier */ + \
1 /* gdlr_deviceid_list count */ + \
XDR_QUADLEN(NFS4_PNFS_GETDEVLIST_MAXNUM * \
NFS4_DEVICEID4_SIZE) \
/* gdlr_deviceid_list */ + \
1 /* bool gdlr_eof */)
#define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + 4 + \
XDR_QUADLEN(NFS4_DEVICEID4_SIZE))
#define decode_getdeviceinfo_maxsz (op_decode_hdr_maxsz + \
......@@ -748,6 +759,14 @@ static int nfs4_stat_to_errno(int);
#define NFS4_dec_reclaim_complete_sz (compound_decode_hdr_maxsz + \
decode_sequence_maxsz + \
decode_reclaim_complete_maxsz)
#define NFS4_enc_getdevicelist_sz (compound_encode_hdr_maxsz + \
encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_getdevicelist_maxsz)
#define NFS4_dec_getdevicelist_sz (compound_decode_hdr_maxsz + \
decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_getdevicelist_maxsz)
#define NFS4_enc_getdeviceinfo_sz (compound_encode_hdr_maxsz + \
encode_sequence_maxsz +\
encode_getdeviceinfo_maxsz)
......@@ -1854,6 +1873,26 @@ static void encode_sequence(struct xdr_stream *xdr,
}
#ifdef CONFIG_NFS_V4_1
static void
encode_getdevicelist(struct xdr_stream *xdr,
const struct nfs4_getdevicelist_args *args,
struct compound_hdr *hdr)
{
__be32 *p;
nfs4_verifier dummy = {
.data = "dummmmmy",
};
p = reserve_space(xdr, 20);
*p++ = cpu_to_be32(OP_GETDEVICELIST);
*p++ = cpu_to_be32(args->layoutclass);
*p++ = cpu_to_be32(NFS4_PNFS_GETDEVLIST_MAXNUM);
xdr_encode_hyper(p, 0ULL); /* cookie */
encode_nfs4_verifier(xdr, &dummy);
hdr->nops++;
hdr->replen += decode_getdevicelist_maxsz;
}
static void
encode_getdeviceinfo(struct xdr_stream *xdr,
const struct nfs4_getdeviceinfo_args *args,
......@@ -2774,6 +2813,24 @@ static void nfs4_xdr_enc_reclaim_complete(struct rpc_rqst *req,
encode_nops(&hdr);
}
/*
* Encode GETDEVICELIST request
*/
static void nfs4_xdr_enc_getdevicelist(struct rpc_rqst *req,
struct xdr_stream *xdr,
struct nfs4_getdevicelist_args *args)
{
struct compound_hdr hdr = {
.minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
encode_compound_hdr(xdr, req, &hdr);
encode_sequence(xdr, &args->seq_args, &hdr);
encode_putfh(xdr, args->fh, &hdr);
encode_getdevicelist(xdr, args, &hdr);
encode_nops(&hdr);
}
/*
* Encode GETDEVICEINFO request
*/
......@@ -5268,6 +5325,53 @@ out_overflow:
}
#if defined(CONFIG_NFS_V4_1)
/*
* TODO: Need to handle case when EOF != true;
*/
static int decode_getdevicelist(struct xdr_stream *xdr,
struct pnfs_devicelist *res)
{
__be32 *p;
int status, i;
struct nfs_writeverf verftemp;
status = decode_op_hdr(xdr, OP_GETDEVICELIST);
if (status)
return status;
p = xdr_inline_decode(xdr, 8 + 8 + 4);
if (unlikely(!p))
goto out_overflow;
/* TODO: Skip cookie for now */
p += 2;
/* Read verifier */
p = xdr_decode_opaque_fixed(p, verftemp.verifier, 8);
res->num_devs = be32_to_cpup(p);
dprintk("%s: num_dev %d\n", __func__, res->num_devs);
if (res->num_devs > NFS4_PNFS_GETDEVLIST_MAXNUM) {
printk(KERN_ERR "%s too many result dev_num %u\n",
__func__, res->num_devs);
return -EIO;
}
p = xdr_inline_decode(xdr,
res->num_devs * NFS4_DEVICEID4_SIZE + 4);
if (unlikely(!p))
goto out_overflow;
for (i = 0; i < res->num_devs; i++)
p = xdr_decode_opaque_fixed(p, res->dev_id[i].data,
NFS4_DEVICEID4_SIZE);
res->eof = be32_to_cpup(p);
return 0;
out_overflow:
print_overflow_msg(__func__, xdr);
return -EIO;
}
static int decode_getdeviceinfo(struct xdr_stream *xdr,
struct pnfs_device *pdev)
......@@ -6541,6 +6645,32 @@ static int nfs4_xdr_dec_reclaim_complete(struct rpc_rqst *rqstp,
return status;
}
/*
* Decode GETDEVICELIST response
*/
static int nfs4_xdr_dec_getdevicelist(struct rpc_rqst *rqstp,
struct xdr_stream *xdr,
struct nfs4_getdevicelist_res *res)
{
struct compound_hdr hdr;
int status;
dprintk("encoding getdevicelist!\n");
status = decode_compound_hdr(xdr, &hdr);
if (status != 0)
goto out;
status = decode_sequence(xdr, &res->seq_res, rqstp);
if (status != 0)
goto out;
status = decode_putfh(xdr);
if (status != 0)
goto out;
status = decode_getdevicelist(xdr, res->devlist);
out:
return status;
}
/*
* Decode GETDEVINFO response
*/
......@@ -6908,6 +7038,7 @@ struct rpc_procinfo nfs4_procedures[] = {
PROC(SECINFO_NO_NAME, enc_secinfo_no_name, dec_secinfo_no_name),
PROC(TEST_STATEID, enc_test_stateid, dec_test_stateid),
PROC(FREE_STATEID, enc_free_stateid, dec_free_stateid),
PROC(GETDEVICELIST, enc_getdevicelist, dec_getdevicelist),
#endif /* CONFIG_NFS_V4_1 */
};
......
......@@ -135,14 +135,26 @@ struct pnfs_device {
unsigned int layout_type;
unsigned int mincount;
struct page **pages;
void *area;
unsigned int pgbase;
unsigned int pglen;
};
#define NFS4_PNFS_GETDEVLIST_MAXNUM 16
struct pnfs_devicelist {
unsigned int eof;
unsigned int num_devs;
struct nfs4_deviceid dev_id[NFS4_PNFS_GETDEVLIST_MAXNUM];
};
extern int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *);
extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *);
/* nfs4proc.c */
extern int nfs4_proc_getdevicelist(struct nfs_server *server,
const struct nfs_fh *fh,
struct pnfs_devicelist *devlist);
extern int nfs4_proc_getdeviceinfo(struct nfs_server *server,
struct pnfs_device *dev);
extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp);
......
......@@ -566,6 +566,7 @@ enum {
NFSPROC4_CLNT_SECINFO_NO_NAME,
NFSPROC4_CLNT_TEST_STATEID,
NFSPROC4_CLNT_FREE_STATEID,
NFSPROC4_CLNT_GETDEVICELIST,
};
/* nfs41 types */
......
......@@ -235,6 +235,17 @@ struct nfs4_layoutget {
gfp_t gfp_flags;
};
struct nfs4_getdevicelist_args {
const struct nfs_fh *fh;
u32 layoutclass;
struct nfs4_sequence_args seq_args;
};
struct nfs4_getdevicelist_res {
struct pnfs_devicelist *devlist;
struct nfs4_sequence_res seq_res;
};
struct nfs4_getdeviceinfo_args {
struct pnfs_device *pdev;
struct nfs4_sequence_args seq_args;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment