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:
parent
c570ba2383
commit
98dc722ccc
6 changed files with 172 additions and 7 deletions
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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, ¬ify->mask)
|
||||
&& xdr_bytes(xdr, ¬ify->list, ¬ify->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(¬ify_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(¬ify_xdr, change);
|
||||
if (!result) { CBX_ERR("notify_deviceid.change"); goto out; }
|
||||
break;
|
||||
case NOTIFY_DEVICEID4_DELETE:
|
||||
result = cb_notify_deviceid_delete(¬ify_xdr, change);
|
||||
if (!result) { CBX_ERR("notify_deviceid.delete"); goto out; }
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue