cmservice.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. /* AFS Cache Manager Service
  2. *
  3. * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
  4. * Written by David Howells (dhowells@redhat.com)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. */
  11. #include <linux/module.h>
  12. #include <linux/init.h>
  13. #include <linux/sched.h>
  14. #include <linux/ip.h>
  15. #include "internal.h"
  16. #include "afs_cm.h"
  17. struct workqueue_struct *afs_cm_workqueue;
  18. static int afs_deliver_cb_init_call_back_state(struct afs_call *,
  19. struct sk_buff *, bool);
  20. static int afs_deliver_cb_probe(struct afs_call *, struct sk_buff *, bool);
  21. static int afs_deliver_cb_callback(struct afs_call *, struct sk_buff *, bool);
  22. static void afs_cm_destructor(struct afs_call *);
  23. /*
  24. * CB.CallBack operation type
  25. */
  26. static const struct afs_call_type afs_SRXCBCallBack = {
  27. .deliver = afs_deliver_cb_callback,
  28. .abort_to_error = afs_abort_to_error,
  29. .destructor = afs_cm_destructor,
  30. };
  31. /*
  32. * CB.InitCallBackState operation type
  33. */
  34. static const struct afs_call_type afs_SRXCBInitCallBackState = {
  35. .deliver = afs_deliver_cb_init_call_back_state,
  36. .abort_to_error = afs_abort_to_error,
  37. .destructor = afs_cm_destructor,
  38. };
  39. /*
  40. * CB.Probe operation type
  41. */
  42. static const struct afs_call_type afs_SRXCBProbe = {
  43. .deliver = afs_deliver_cb_probe,
  44. .abort_to_error = afs_abort_to_error,
  45. .destructor = afs_cm_destructor,
  46. };
  47. /*
  48. * route an incoming cache manager call
  49. * - return T if supported, F if not
  50. */
  51. bool afs_cm_incoming_call(struct afs_call *call)
  52. {
  53. u32 operation_id = ntohl(call->operation_ID);
  54. _enter("{CB.OP %u}", operation_id);
  55. switch (operation_id) {
  56. case CBCallBack:
  57. call->type = &afs_SRXCBCallBack;
  58. return true;
  59. case CBInitCallBackState:
  60. call->type = &afs_SRXCBInitCallBackState;
  61. return true;
  62. case CBProbe:
  63. call->type = &afs_SRXCBProbe;
  64. return true;
  65. default:
  66. return false;
  67. }
  68. }
  69. /*
  70. * clean up a cache manager call
  71. */
  72. static void afs_cm_destructor(struct afs_call *call)
  73. {
  74. _enter("");
  75. afs_put_server(call->server);
  76. call->server = NULL;
  77. kfree(call->buffer);
  78. call->buffer = NULL;
  79. }
  80. /*
  81. * allow the fileserver to see if the cache manager is still alive
  82. */
  83. static void SRXAFSCB_CallBack(struct work_struct *work)
  84. {
  85. struct afs_call *call = container_of(work, struct afs_call, work);
  86. _enter("");
  87. /* be sure to send the reply *before* attempting to spam the AFS server
  88. * with FSFetchStatus requests on the vnodes with broken callbacks lest
  89. * the AFS server get into a vicious cycle of trying to break further
  90. * callbacks because it hadn't received completion of the CBCallBack op
  91. * yet */
  92. afs_send_empty_reply(call);
  93. afs_break_callbacks(call->server, call->count, call->request);
  94. _leave("");
  95. }
  96. /*
  97. * deliver request data to a CB.CallBack call
  98. */
  99. static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
  100. bool last)
  101. {
  102. struct afs_callback *cb;
  103. struct afs_server *server;
  104. struct in_addr addr;
  105. __be32 *bp;
  106. u32 tmp;
  107. int ret, loop;
  108. _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
  109. switch (call->unmarshall) {
  110. case 0:
  111. call->offset = 0;
  112. call->unmarshall++;
  113. /* extract the FID array and its count in two steps */
  114. case 1:
  115. _debug("extract FID count");
  116. ret = afs_extract_data(call, skb, last, &call->tmp, 4);
  117. switch (ret) {
  118. case 0: break;
  119. case -EAGAIN: return 0;
  120. default: return ret;
  121. }
  122. call->count = ntohl(call->tmp);
  123. _debug("FID count: %u", call->count);
  124. if (call->count > AFSCBMAX)
  125. return -EBADMSG;
  126. call->buffer = kmalloc(call->count * 3 * 4, GFP_KERNEL);
  127. if (!call->buffer)
  128. return -ENOMEM;
  129. call->offset = 0;
  130. call->unmarshall++;
  131. case 2:
  132. _debug("extract FID array");
  133. ret = afs_extract_data(call, skb, last, call->buffer,
  134. call->count * 3 * 4);
  135. switch (ret) {
  136. case 0: break;
  137. case -EAGAIN: return 0;
  138. default: return ret;
  139. }
  140. _debug("unmarshall FID array");
  141. call->request = kcalloc(call->count,
  142. sizeof(struct afs_callback),
  143. GFP_KERNEL);
  144. if (!call->request)
  145. return -ENOMEM;
  146. cb = call->request;
  147. bp = call->buffer;
  148. for (loop = call->count; loop > 0; loop--, cb++) {
  149. cb->fid.vid = ntohl(*bp++);
  150. cb->fid.vnode = ntohl(*bp++);
  151. cb->fid.unique = ntohl(*bp++);
  152. cb->type = AFSCM_CB_UNTYPED;
  153. }
  154. call->offset = 0;
  155. call->unmarshall++;
  156. /* extract the callback array and its count in two steps */
  157. case 3:
  158. _debug("extract CB count");
  159. ret = afs_extract_data(call, skb, last, &call->tmp, 4);
  160. switch (ret) {
  161. case 0: break;
  162. case -EAGAIN: return 0;
  163. default: return ret;
  164. }
  165. tmp = ntohl(call->tmp);
  166. _debug("CB count: %u", tmp);
  167. if (tmp != call->count && tmp != 0)
  168. return -EBADMSG;
  169. call->offset = 0;
  170. call->unmarshall++;
  171. if (tmp == 0)
  172. goto empty_cb_array;
  173. case 4:
  174. _debug("extract CB array");
  175. ret = afs_extract_data(call, skb, last, call->request,
  176. call->count * 3 * 4);
  177. switch (ret) {
  178. case 0: break;
  179. case -EAGAIN: return 0;
  180. default: return ret;
  181. }
  182. _debug("unmarshall CB array");
  183. cb = call->request;
  184. bp = call->buffer;
  185. for (loop = call->count; loop > 0; loop--, cb++) {
  186. cb->version = ntohl(*bp++);
  187. cb->expiry = ntohl(*bp++);
  188. cb->type = ntohl(*bp++);
  189. }
  190. empty_cb_array:
  191. call->offset = 0;
  192. call->unmarshall++;
  193. case 5:
  194. _debug("trailer");
  195. if (skb->len != 0)
  196. return -EBADMSG;
  197. break;
  198. }
  199. if (!last)
  200. return 0;
  201. call->state = AFS_CALL_REPLYING;
  202. /* we'll need the file server record as that tells us which set of
  203. * vnodes to operate upon */
  204. memcpy(&addr, &ip_hdr(skb)->saddr, 4);
  205. server = afs_find_server(&addr);
  206. if (!server)
  207. return -ENOTCONN;
  208. call->server = server;
  209. INIT_WORK(&call->work, SRXAFSCB_CallBack);
  210. schedule_work(&call->work);
  211. return 0;
  212. }
  213. /*
  214. * allow the fileserver to request callback state (re-)initialisation
  215. */
  216. static void SRXAFSCB_InitCallBackState(struct work_struct *work)
  217. {
  218. struct afs_call *call = container_of(work, struct afs_call, work);
  219. _enter("{%p}", call->server);
  220. afs_init_callback_state(call->server);
  221. afs_send_empty_reply(call);
  222. _leave("");
  223. }
  224. /*
  225. * deliver request data to a CB.InitCallBackState call
  226. */
  227. static int afs_deliver_cb_init_call_back_state(struct afs_call *call,
  228. struct sk_buff *skb,
  229. bool last)
  230. {
  231. struct afs_server *server;
  232. struct in_addr addr;
  233. _enter(",{%u},%d", skb->len, last);
  234. if (skb->len > 0)
  235. return -EBADMSG;
  236. if (!last)
  237. return 0;
  238. /* no unmarshalling required */
  239. call->state = AFS_CALL_REPLYING;
  240. /* we'll need the file server record as that tells us which set of
  241. * vnodes to operate upon */
  242. memcpy(&addr, &ip_hdr(skb)->saddr, 4);
  243. server = afs_find_server(&addr);
  244. if (!server)
  245. return -ENOTCONN;
  246. call->server = server;
  247. INIT_WORK(&call->work, SRXAFSCB_InitCallBackState);
  248. schedule_work(&call->work);
  249. return 0;
  250. }
  251. /*
  252. * allow the fileserver to see if the cache manager is still alive
  253. */
  254. static void SRXAFSCB_Probe(struct work_struct *work)
  255. {
  256. struct afs_call *call = container_of(work, struct afs_call, work);
  257. _enter("");
  258. afs_send_empty_reply(call);
  259. _leave("");
  260. }
  261. /*
  262. * deliver request data to a CB.Probe call
  263. */
  264. static int afs_deliver_cb_probe(struct afs_call *call, struct sk_buff *skb,
  265. bool last)
  266. {
  267. _enter(",{%u},%d", skb->len, last);
  268. if (skb->len > 0)
  269. return -EBADMSG;
  270. if (!last)
  271. return 0;
  272. /* no unmarshalling required */
  273. call->state = AFS_CALL_REPLYING;
  274. INIT_WORK(&call->work, SRXAFSCB_Probe);
  275. schedule_work(&call->work);
  276. return 0;
  277. }