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;
|
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(
|
static void replay_cache_write(
|
||||||
IN nfs41_cb_session *session,
|
IN nfs41_cb_session *session,
|
||||||
IN OPTIONAL struct cb_compound_args *args,
|
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;
|
break;
|
||||||
case OP_CB_NOTIFY_DEVICEID:
|
case OP_CB_NOTIFY_DEVICEID:
|
||||||
dprintf(1, "OP_CB_NOTIFY_DEVICEID\n");
|
dprintf(1, "OP_CB_NOTIFY_DEVICEID\n");
|
||||||
res->status = NFS4ERR_NOTSUPP;
|
res->status = NFS4_OK;
|
||||||
break;
|
break;
|
||||||
case OP_CB_ILLEGAL:
|
case OP_CB_ILLEGAL:
|
||||||
dprintf(1, "OP_CB_ILLEGAL\n");
|
dprintf(1, "OP_CB_ILLEGAL\n");
|
||||||
|
|
@ -573,4 +588,4 @@ int nfs41_handle_callback(void *rpc_clnt, void *cb, struct cb_compound_res **rep
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,8 @@
|
||||||
|
|
||||||
|
|
||||||
/* common types */
|
/* common types */
|
||||||
|
bool_t xdr_bitmap4(XDR *xdr, bitmap4 *bitmap);
|
||||||
|
|
||||||
static bool_t common_stateid(XDR *xdr, stateid4 *stateid)
|
static bool_t common_stateid(XDR *xdr, stateid4 *stateid)
|
||||||
{
|
{
|
||||||
return xdr_u_int32_t(xdr, &stateid->seqid)
|
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);
|
&& 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 */
|
/* OP_CB_LAYOUTRECALL */
|
||||||
static bool_t op_cb_layoutrecall_file(XDR *xdr, struct cb_recall_file *args)
|
static bool_t op_cb_layoutrecall_file(XDR *xdr, struct cb_recall_file *args)
|
||||||
{
|
{
|
||||||
|
|
@ -409,12 +417,86 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OP_CB_NOTIFY_DEVICEID */
|
/* 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;
|
bool_t result;
|
||||||
|
|
||||||
result = xdr_u_int32_t(xdr, &res->target_highest_slotid);
|
result = xdr_u_int32_t(xdr, (uint32_t*)&change->layouttype);
|
||||||
if (!result) { CBX_ERR("notify_deviceid.target_highest_slotid"); goto out; }
|
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:
|
out:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -194,8 +194,26 @@ struct cb_notify_lock_res {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* OP_CB_NOTIFY_DEVICEID */
|
/* 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 {
|
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 {
|
struct cb_notify_deviceid_res {
|
||||||
|
|
@ -211,6 +229,7 @@ union cb_op_args {
|
||||||
struct cb_recall_slot_args recall_slot;
|
struct cb_recall_slot_args recall_slot;
|
||||||
struct cb_sequence_args sequence;
|
struct cb_sequence_args sequence;
|
||||||
struct cb_recall_args recall;
|
struct cb_recall_args recall;
|
||||||
|
struct cb_notify_deviceid_args notify_deviceid;
|
||||||
};
|
};
|
||||||
struct cb_argop {
|
struct cb_argop {
|
||||||
enum_t opnum;
|
enum_t opnum;
|
||||||
|
|
@ -234,6 +253,7 @@ union cb_op_res {
|
||||||
struct cb_recall_slot_res recall_slot;
|
struct cb_recall_slot_res recall_slot;
|
||||||
struct cb_sequence_res sequence;
|
struct cb_sequence_res sequence;
|
||||||
struct cb_recall_res recall;
|
struct cb_recall_res recall;
|
||||||
|
struct cb_notify_deviceid_res notify_deviceid;
|
||||||
};
|
};
|
||||||
struct cb_resop {
|
struct cb_resop {
|
||||||
enum_t opnum;
|
enum_t opnum;
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ static __inline int unexpected_op(uint32_t op, uint32_t expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* typedef uint32_t bitmap4<> */
|
/* typedef uint32_t bitmap4<> */
|
||||||
static bool_t xdr_bitmap4(
|
bool_t xdr_bitmap4(
|
||||||
XDR *xdr,
|
XDR *xdr,
|
||||||
bitmap4 *bitmap)
|
bitmap4 *bitmap)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -317,6 +317,12 @@ enum pnfs_status pnfs_file_device_get(
|
||||||
void pnfs_file_device_put(
|
void pnfs_file_device_put(
|
||||||
IN pnfs_file_device *device);
|
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(
|
enum pnfs_status pnfs_data_server_client(
|
||||||
IN struct __nfs41_root *root,
|
IN struct __nfs41_root *root,
|
||||||
IN pnfs_data_server *server,
|
IN pnfs_data_server *server,
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "nfs41_ops.h"
|
#include "nfs41_ops.h"
|
||||||
|
#include "nfs41_callback.h"
|
||||||
#include "daemon_debug.h"
|
#include "daemon_debug.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -420,3 +421,44 @@ enum pnfs_status pnfs_file_device_io_unit(
|
||||||
io->length = pattern->offset_end - offset;
|
io->length = pattern->offset_end - offset;
|
||||||
return status;
|
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