pnfs: xdr for CB_NOTIFY_DEVICEID

calls stub function pnfs_file_device_notify() for each deviceid

Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
Casey Bodley 2011-06-16 12:33:39 -04:00 committed by unknown
parent c570ba2383
commit 98dc722ccc
6 changed files with 172 additions and 7 deletions

View file

@ -245,6 +245,21 @@ out:
return res->status;
}
/* OP_CB_NOTIFY_DEVICEID */
static enum_t handle_cb_notify_deviceid(
IN nfs41_rpc_clnt *rpc_clnt,
IN struct cb_notify_deviceid_args *args,
OUT struct cb_notify_deviceid_res *res)
{
uint32_t i;
for (i = 0; i < args->change_count; i++) {
pnfs_file_device_notify(rpc_clnt->client->devices,
&args->change_list[i]);
}
res->status = NFS4_OK;
return res->status;
}
static void replay_cache_write(
IN nfs41_cb_session *session,
IN OPTIONAL struct cb_compound_args *args,
@ -516,7 +531,7 @@ static void handle_cb_compound(nfs41_rpc_clnt *rpc_clnt, cb_req *req, struct cb_
break;
case OP_CB_NOTIFY_DEVICEID:
dprintf(1, "OP_CB_NOTIFY_DEVICEID\n");
res->status = NFS4ERR_NOTSUPP;
res->status = NFS4_OK;
break;
case OP_CB_ILLEGAL:
dprintf(1, "OP_CB_ILLEGAL\n");

View file

@ -31,6 +31,8 @@
/* common types */
bool_t xdr_bitmap4(XDR *xdr, bitmap4 *bitmap);
static bool_t common_stateid(XDR *xdr, stateid4 *stateid)
{
return xdr_u_int32_t(xdr, &stateid->seqid)
@ -50,6 +52,12 @@ static bool_t common_fsid(XDR *xdr, nfs41_fsid *fsid)
&& xdr_u_int64_t(xdr, &fsid->minor);
}
static bool_t common_notify4(XDR *xdr, struct notify4 *notify)
{
return xdr_bitmap4(xdr, &notify->mask)
&& xdr_bytes(xdr, &notify->list, &notify->len, NFS4_OPAQUE_LIMIT);
}
/* OP_CB_LAYOUTRECALL */
static bool_t op_cb_layoutrecall_file(XDR *xdr, struct cb_recall_file *args)
{
@ -409,12 +417,86 @@ out:
}
/* OP_CB_NOTIFY_DEVICEID */
static bool_t op_cb_notify_deviceid_args(XDR *xdr, struct cb_notify_deviceid_args *res)
static bool_t cb_notify_deviceid_change(XDR *xdr, struct notify_deviceid4 *change)
{
bool_t result;
result = xdr_u_int32_t(xdr, &res->target_highest_slotid);
if (!result) { CBX_ERR("notify_deviceid.target_highest_slotid"); goto out; }
result = xdr_u_int32_t(xdr, (uint32_t*)&change->layouttype);
if (!result) { CBX_ERR("notify_deviceid.change.layouttype"); goto out; }
result = xdr_opaque(xdr, (char*)change->deviceid, PNFS_DEVICEID_SIZE);
if (!result) { CBX_ERR("notify_deviceid.change.deviceid"); goto out; }
result = xdr_bool(xdr, &change->immediate);
if (!result) { CBX_ERR("notify_deviceid.change.immediate"); goto out; }
out:
return result;
}
static bool_t cb_notify_deviceid_delete(XDR *xdr, struct notify_deviceid4 *change)
{
bool_t result;
result = xdr_u_int32_t(xdr, (uint32_t*)&change->layouttype);
if (!result) { CBX_ERR("notify_deviceid.delete.layouttype"); goto out; }
result = xdr_opaque(xdr, (char*)change->deviceid, PNFS_DEVICEID_SIZE);
if (!result) { CBX_ERR("notify_deviceid.delete.deviceid"); goto out; }
out:
return result;
}
static bool_t op_cb_notify_deviceid_args(XDR *xdr, struct cb_notify_deviceid_args *args)
{
XDR notify_xdr;
uint32_t i, j, c;
bool_t result;
/* decode the generic notify4 list */
result = xdr_array(xdr, (char**)&args->notify_list,
&args->notify_count, CB_COMPOUND_MAX_OPERATIONS,
sizeof(struct notify4), (xdrproc_t)common_notify4);
if (!result) { CBX_ERR("notify_deviceid.notify_list"); goto out; }
switch (xdr->x_op) {
case XDR_FREE:
free(args->change_list);
case XDR_ENCODE:
return TRUE;
}
/* count the number of device changes */
args->change_count = 0;
for (i = 0; i < args->notify_count; i++)
args->change_count += args->notify_list[i].mask.count;
args->change_list = calloc(args->change_count, sizeof(struct notify_deviceid4));
if (args->change_list == NULL)
return FALSE;
c = 0;
for (i = 0; i < args->notify_count; i++) {
struct notify4 *notify = &args->notify_list[i];
/* decode the device notifications out of the opaque buffer */
xdrmem_create(&notify_xdr, notify->list, notify->len, XDR_DECODE);
for (j = 0; j < notify->mask.count; j++) {
struct notify_deviceid4 *change = &args->change_list[c++];
change->type = notify->mask.arr[j];
switch (change->type) {
case NOTIFY_DEVICEID4_CHANGE:
result = cb_notify_deviceid_change(&notify_xdr, change);
if (!result) { CBX_ERR("notify_deviceid.change"); goto out; }
break;
case NOTIFY_DEVICEID4_DELETE:
result = cb_notify_deviceid_delete(&notify_xdr, change);
if (!result) { CBX_ERR("notify_deviceid.delete"); goto out; }
break;
}
}
}
out:
return result;
}

View file

@ -194,8 +194,26 @@ struct cb_notify_lock_res {
};
/* OP_CB_NOTIFY_DEVICEID */
enum notify_deviceid_type4 {
NOTIFY_DEVICEID4_CHANGE = 1,
NOTIFY_DEVICEID4_DELETE = 2
};
struct notify_deviceid4 {
unsigned char deviceid[16];
enum notify_deviceid_type4 type;
enum pnfs_layout_type layouttype;
bool_t immediate;
};
struct notify4 {
bitmap4 mask;
char *list;
uint32_t len;
};
struct cb_notify_deviceid_args {
uint32_t target_highest_slotid;
struct notify4 *notify_list;
uint32_t notify_count;
struct notify_deviceid4 *change_list;
uint32_t change_count;
};
struct cb_notify_deviceid_res {
@ -211,6 +229,7 @@ union cb_op_args {
struct cb_recall_slot_args recall_slot;
struct cb_sequence_args sequence;
struct cb_recall_args recall;
struct cb_notify_deviceid_args notify_deviceid;
};
struct cb_argop {
enum_t opnum;
@ -234,6 +253,7 @@ union cb_op_res {
struct cb_recall_slot_res recall_slot;
struct cb_sequence_res sequence;
struct cb_recall_res recall;
struct cb_notify_deviceid_res notify_deviceid;
};
struct cb_resop {
enum_t opnum;

View file

@ -47,7 +47,7 @@ static __inline int unexpected_op(uint32_t op, uint32_t expected)
}
/* typedef uint32_t bitmap4<> */
static bool_t xdr_bitmap4(
bool_t xdr_bitmap4(
XDR *xdr,
bitmap4 *bitmap)
{

View file

@ -317,6 +317,12 @@ enum pnfs_status pnfs_file_device_get(
void pnfs_file_device_put(
IN pnfs_file_device *device);
struct notify_deviceid4; /* from nfs41_callback.h */
enum notify_deviceid_type4;
enum pnfs_status pnfs_file_device_notify(
IN struct pnfs_file_device_list *devices,
IN const struct notify_deviceid4 *change);
enum pnfs_status pnfs_data_server_client(
IN struct __nfs41_root *root,
IN pnfs_data_server *server,

View file

@ -26,6 +26,7 @@
#include <stdio.h>
#include "nfs41_ops.h"
#include "nfs41_callback.h"
#include "daemon_debug.h"
@ -420,3 +421,44 @@ enum pnfs_status pnfs_file_device_io_unit(
io->length = pattern->offset_end - offset;
return status;
}
/* CB_NOTIFY_DEVICEID */
enum pnfs_status pnfs_file_device_notify(
IN struct pnfs_file_device_list *devices,
IN const struct notify_deviceid4 *change)
{
struct list_entry *entry;
enum pnfs_status status = PNFSERR_NO_DEVICE;
dprintf(FDLVL, "--> pnfs_file_device_notify(%u, %0llX:%0llX)\n",
change->type, change->deviceid);
if (change->layouttype != PNFS_LAYOUTTYPE_FILE) {
status = PNFSERR_NOT_SUPPORTED;
goto out;
}
EnterCriticalSection(&devices->lock);
entry = list_search(&devices->head, change->deviceid, deviceid_compare);
if (entry) {
dprintf(FDLVL, "found file device %p\n", device_entry(entry));
if (change->type == NOTIFY_DEVICEID4_CHANGE) {
/* if (change->immediate) ... */
dprintf(FDLVL, "CHANGE (%u)\n", change->immediate);
} else if (change->type == NOTIFY_DEVICEID4_DELETE) {
/* This notification MUST NOT be sent if the client
* has a layout that refers to the device ID. */
dprintf(FDLVL, "DELETE\n");
}
status = PNFS_SUCCESS;
}
LeaveCriticalSection(&devices->lock);
out:
dprintf(FDLVL, "<-- pnfs_file_device_notify() returning %s\n",
pnfs_error_string(status));
return status;
}