|
@@ -26,6 +26,7 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *,
|
|
|
struct sk_buff *, bool);
|
|
|
static int afs_deliver_cb_probe(struct afs_call *, struct sk_buff *, bool);
|
|
|
static int afs_deliver_cb_callback(struct afs_call *, struct sk_buff *, bool);
|
|
|
+static int afs_deliver_cb_probe_uuid(struct afs_call *, struct sk_buff *, bool);
|
|
|
static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *,
|
|
|
struct sk_buff *, bool);
|
|
|
static void afs_cm_destructor(struct afs_call *);
|
|
@@ -70,6 +71,16 @@ static const struct afs_call_type afs_SRXCBProbe = {
|
|
|
.destructor = afs_cm_destructor,
|
|
|
};
|
|
|
|
|
|
+/*
|
|
|
+ * CB.ProbeUuid operation type
|
|
|
+ */
|
|
|
+static const struct afs_call_type afs_SRXCBProbeUuid = {
|
|
|
+ .name = "CB.ProbeUuid",
|
|
|
+ .deliver = afs_deliver_cb_probe_uuid,
|
|
|
+ .abort_to_error = afs_abort_to_error,
|
|
|
+ .destructor = afs_cm_destructor,
|
|
|
+};
|
|
|
+
|
|
|
/*
|
|
|
* CB.TellMeAboutYourself operation type
|
|
|
*/
|
|
@@ -392,6 +403,102 @@ static int afs_deliver_cb_probe(struct afs_call *call, struct sk_buff *skb,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * allow the fileserver to quickly find out if the fileserver has been rebooted
|
|
|
+ */
|
|
|
+static void SRXAFSCB_ProbeUuid(struct work_struct *work)
|
|
|
+{
|
|
|
+ struct afs_call *call = container_of(work, struct afs_call, work);
|
|
|
+ struct afs_uuid *r = call->request;
|
|
|
+
|
|
|
+ struct {
|
|
|
+ __be32 match;
|
|
|
+ } reply;
|
|
|
+
|
|
|
+ _enter("");
|
|
|
+
|
|
|
+
|
|
|
+ if (memcmp(r, &afs_uuid, sizeof(afs_uuid)) == 0)
|
|
|
+ reply.match = htonl(0);
|
|
|
+ else
|
|
|
+ reply.match = htonl(1);
|
|
|
+
|
|
|
+ afs_send_simple_reply(call, &reply, sizeof(reply));
|
|
|
+ _leave("");
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * deliver request data to a CB.ProbeUuid call
|
|
|
+ */
|
|
|
+static int afs_deliver_cb_probe_uuid(struct afs_call *call, struct sk_buff *skb,
|
|
|
+ bool last)
|
|
|
+{
|
|
|
+ struct afs_uuid *r;
|
|
|
+ unsigned loop;
|
|
|
+ __be32 *b;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
|
|
|
+
|
|
|
+ if (skb->len > 0)
|
|
|
+ return -EBADMSG;
|
|
|
+ if (!last)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ switch (call->unmarshall) {
|
|
|
+ case 0:
|
|
|
+ call->offset = 0;
|
|
|
+ call->buffer = kmalloc(11 * sizeof(__be32), GFP_KERNEL);
|
|
|
+ if (!call->buffer)
|
|
|
+ return -ENOMEM;
|
|
|
+ call->unmarshall++;
|
|
|
+
|
|
|
+ case 1:
|
|
|
+ _debug("extract UUID");
|
|
|
+ ret = afs_extract_data(call, skb, last, call->buffer,
|
|
|
+ 11 * sizeof(__be32));
|
|
|
+ switch (ret) {
|
|
|
+ case 0: break;
|
|
|
+ case -EAGAIN: return 0;
|
|
|
+ default: return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ _debug("unmarshall UUID");
|
|
|
+ call->request = kmalloc(sizeof(struct afs_uuid), GFP_KERNEL);
|
|
|
+ if (!call->request)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ b = call->buffer;
|
|
|
+ r = call->request;
|
|
|
+ r->time_low = ntohl(b[0]);
|
|
|
+ r->time_mid = ntohl(b[1]);
|
|
|
+ r->time_hi_and_version = ntohl(b[2]);
|
|
|
+ r->clock_seq_hi_and_reserved = ntohl(b[3]);
|
|
|
+ r->clock_seq_low = ntohl(b[4]);
|
|
|
+
|
|
|
+ for (loop = 0; loop < 6; loop++)
|
|
|
+ r->node[loop] = ntohl(b[loop + 5]);
|
|
|
+
|
|
|
+ call->offset = 0;
|
|
|
+ call->unmarshall++;
|
|
|
+
|
|
|
+ case 2:
|
|
|
+ _debug("trailer");
|
|
|
+ if (skb->len != 0)
|
|
|
+ return -EBADMSG;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!last)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ call->state = AFS_CALL_REPLYING;
|
|
|
+
|
|
|
+ INIT_WORK(&call->work, SRXAFSCB_ProbeUuid);
|
|
|
+ schedule_work(&call->work);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* allow the fileserver to ask about the cache manager's capabilities
|
|
|
*/
|