fsclient.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. /* AFS File Server client stubs
  2. *
  3. * Copyright (C) 2002, 2007 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/init.h>
  12. #include <linux/sched.h>
  13. #include <linux/circ_buf.h>
  14. #include "internal.h"
  15. #include "afs_fs.h"
  16. /*
  17. * decode an AFSFetchStatus block
  18. */
  19. static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
  20. struct afs_vnode *vnode)
  21. {
  22. const __be32 *bp = *_bp;
  23. umode_t mode;
  24. u64 data_version;
  25. u32 changed = 0; /* becomes non-zero if ctime-type changes seen */
  26. #define EXTRACT(DST) \
  27. do { \
  28. u32 x = ntohl(*bp++); \
  29. changed |= DST - x; \
  30. DST = x; \
  31. } while (0)
  32. vnode->status.if_version = ntohl(*bp++);
  33. EXTRACT(vnode->status.type);
  34. vnode->status.nlink = ntohl(*bp++);
  35. EXTRACT(vnode->status.size);
  36. data_version = ntohl(*bp++);
  37. EXTRACT(vnode->status.author);
  38. EXTRACT(vnode->status.owner);
  39. EXTRACT(vnode->status.caller_access); /* call ticket dependent */
  40. EXTRACT(vnode->status.anon_access);
  41. EXTRACT(vnode->status.mode);
  42. vnode->status.parent.vid = vnode->fid.vid;
  43. EXTRACT(vnode->status.parent.vnode);
  44. EXTRACT(vnode->status.parent.unique);
  45. bp++; /* seg size */
  46. vnode->status.mtime_client = ntohl(*bp++);
  47. vnode->status.mtime_server = ntohl(*bp++);
  48. bp++; /* group */
  49. bp++; /* sync counter */
  50. data_version |= (u64) ntohl(*bp++) << 32;
  51. bp++; /* spare2 */
  52. bp++; /* spare3 */
  53. bp++; /* spare4 */
  54. *_bp = bp;
  55. if (changed) {
  56. _debug("vnode changed");
  57. set_bit(AFS_VNODE_CHANGED, &vnode->flags);
  58. vnode->vfs_inode.i_uid = vnode->status.owner;
  59. vnode->vfs_inode.i_size = vnode->status.size;
  60. vnode->vfs_inode.i_version = vnode->fid.unique;
  61. vnode->status.mode &= S_IALLUGO;
  62. mode = vnode->vfs_inode.i_mode;
  63. mode &= ~S_IALLUGO;
  64. mode |= vnode->status.mode;
  65. vnode->vfs_inode.i_mode = mode;
  66. }
  67. _debug("vnode time %lx, %lx",
  68. vnode->status.mtime_client, vnode->status.mtime_server);
  69. vnode->vfs_inode.i_ctime.tv_sec = vnode->status.mtime_server;
  70. vnode->vfs_inode.i_mtime = vnode->vfs_inode.i_ctime;
  71. vnode->vfs_inode.i_atime = vnode->vfs_inode.i_ctime;
  72. if (vnode->status.data_version != data_version) {
  73. _debug("vnode modified %llx", data_version);
  74. vnode->status.data_version = data_version;
  75. set_bit(AFS_VNODE_MODIFIED, &vnode->flags);
  76. set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
  77. }
  78. }
  79. /*
  80. * decode an AFSCallBack block
  81. */
  82. static void xdr_decode_AFSCallBack(const __be32 **_bp, struct afs_vnode *vnode)
  83. {
  84. const __be32 *bp = *_bp;
  85. vnode->cb_version = ntohl(*bp++);
  86. vnode->cb_expiry = ntohl(*bp++);
  87. vnode->cb_type = ntohl(*bp++);
  88. vnode->cb_expires = vnode->cb_expiry + get_seconds();
  89. *_bp = bp;
  90. }
  91. /*
  92. * decode an AFSVolSync block
  93. */
  94. static void xdr_decode_AFSVolSync(const __be32 **_bp,
  95. struct afs_volsync *volsync)
  96. {
  97. const __be32 *bp = *_bp;
  98. volsync->creation = ntohl(*bp++);
  99. bp++; /* spare2 */
  100. bp++; /* spare3 */
  101. bp++; /* spare4 */
  102. bp++; /* spare5 */
  103. bp++; /* spare6 */
  104. *_bp = bp;
  105. }
  106. /*
  107. * deliver reply data to an FS.FetchStatus
  108. */
  109. static int afs_deliver_fs_fetch_status(struct afs_call *call,
  110. struct sk_buff *skb, bool last)
  111. {
  112. const __be32 *bp;
  113. _enter(",,%u", last);
  114. afs_transfer_reply(call, skb);
  115. if (!last)
  116. return 0;
  117. if (call->reply_size != call->reply_max)
  118. return -EBADMSG;
  119. /* unmarshall the reply once we've received all of it */
  120. bp = call->buffer;
  121. xdr_decode_AFSFetchStatus(&bp, call->reply);
  122. xdr_decode_AFSCallBack(&bp, call->reply);
  123. if (call->reply2)
  124. xdr_decode_AFSVolSync(&bp, call->reply2);
  125. _leave(" = 0 [done]");
  126. return 0;
  127. }
  128. /*
  129. * FS.FetchStatus operation type
  130. */
  131. static const struct afs_call_type afs_RXFSFetchStatus = {
  132. .deliver = afs_deliver_fs_fetch_status,
  133. .abort_to_error = afs_abort_to_error,
  134. .destructor = afs_flat_call_destructor,
  135. };
  136. /*
  137. * fetch the status information for a file
  138. */
  139. int afs_fs_fetch_file_status(struct afs_server *server,
  140. struct afs_vnode *vnode,
  141. struct afs_volsync *volsync,
  142. const struct afs_wait_mode *wait_mode)
  143. {
  144. struct afs_call *call;
  145. __be32 *bp;
  146. _enter("");
  147. call = afs_alloc_flat_call(&afs_RXFSFetchStatus, 16, 120);
  148. if (!call)
  149. return -ENOMEM;
  150. call->reply = vnode;
  151. call->reply2 = volsync;
  152. call->service_id = FS_SERVICE;
  153. call->port = htons(AFS_FS_PORT);
  154. /* marshall the parameters */
  155. bp = call->request;
  156. bp[0] = htonl(FSFETCHSTATUS);
  157. bp[1] = htonl(vnode->fid.vid);
  158. bp[2] = htonl(vnode->fid.vnode);
  159. bp[3] = htonl(vnode->fid.unique);
  160. return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
  161. }
  162. /*
  163. * deliver reply data to an FS.FetchData
  164. */
  165. static int afs_deliver_fs_fetch_data(struct afs_call *call,
  166. struct sk_buff *skb, bool last)
  167. {
  168. const __be32 *bp;
  169. struct page *page;
  170. void *buffer;
  171. int ret;
  172. _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
  173. switch (call->unmarshall) {
  174. case 0:
  175. call->offset = 0;
  176. call->unmarshall++;
  177. /* extract the returned data length */
  178. case 1:
  179. _debug("extract data length");
  180. ret = afs_extract_data(call, skb, last, &call->tmp, 4);
  181. switch (ret) {
  182. case 0: break;
  183. case -EAGAIN: return 0;
  184. default: return ret;
  185. }
  186. call->count = ntohl(call->tmp);
  187. _debug("DATA length: %u", call->count);
  188. if (call->count > PAGE_SIZE)
  189. return -EBADMSG;
  190. call->offset = 0;
  191. call->unmarshall++;
  192. if (call->count < PAGE_SIZE) {
  193. buffer = kmap_atomic(call->reply3, KM_USER0);
  194. memset(buffer + PAGE_SIZE - call->count, 0,
  195. call->count);
  196. kunmap_atomic(buffer, KM_USER0);
  197. }
  198. /* extract the returned data */
  199. case 2:
  200. _debug("extract data");
  201. page = call->reply3;
  202. buffer = kmap_atomic(page, KM_USER0);
  203. ret = afs_extract_data(call, skb, last, buffer, call->count);
  204. kunmap_atomic(buffer, KM_USER0);
  205. switch (ret) {
  206. case 0: break;
  207. case -EAGAIN: return 0;
  208. default: return ret;
  209. }
  210. call->offset = 0;
  211. call->unmarshall++;
  212. /* extract the metadata */
  213. case 3:
  214. ret = afs_extract_data(call, skb, last, call->buffer, 120);
  215. switch (ret) {
  216. case 0: break;
  217. case -EAGAIN: return 0;
  218. default: return ret;
  219. }
  220. bp = call->buffer;
  221. xdr_decode_AFSFetchStatus(&bp, call->reply);
  222. xdr_decode_AFSCallBack(&bp, call->reply);
  223. if (call->reply2)
  224. xdr_decode_AFSVolSync(&bp, call->reply2);
  225. call->offset = 0;
  226. call->unmarshall++;
  227. case 4:
  228. _debug("trailer");
  229. if (skb->len != 0)
  230. return -EBADMSG;
  231. break;
  232. }
  233. if (!last)
  234. return 0;
  235. _leave(" = 0 [done]");
  236. return 0;
  237. }
  238. /*
  239. * FS.FetchData operation type
  240. */
  241. static const struct afs_call_type afs_RXFSFetchData = {
  242. .deliver = afs_deliver_fs_fetch_data,
  243. .abort_to_error = afs_abort_to_error,
  244. .destructor = afs_flat_call_destructor,
  245. };
  246. /*
  247. * fetch data from a file
  248. */
  249. int afs_fs_fetch_data(struct afs_server *server,
  250. struct afs_vnode *vnode,
  251. off_t offset, size_t length,
  252. struct page *buffer,
  253. struct afs_volsync *volsync,
  254. const struct afs_wait_mode *wait_mode)
  255. {
  256. struct afs_call *call;
  257. __be32 *bp;
  258. _enter("");
  259. call = afs_alloc_flat_call(&afs_RXFSFetchData, 24, 120);
  260. if (!call)
  261. return -ENOMEM;
  262. call->reply = vnode;
  263. call->reply2 = volsync;
  264. call->reply3 = buffer;
  265. call->service_id = FS_SERVICE;
  266. call->port = htons(AFS_FS_PORT);
  267. /* marshall the parameters */
  268. bp = call->request;
  269. bp[0] = htonl(FSFETCHDATA);
  270. bp[1] = htonl(vnode->fid.vid);
  271. bp[2] = htonl(vnode->fid.vnode);
  272. bp[3] = htonl(vnode->fid.unique);
  273. bp[4] = htonl(offset);
  274. bp[5] = htonl(length);
  275. return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
  276. }
  277. /*
  278. * deliver reply data to an FS.GiveUpCallBacks
  279. */
  280. static int afs_deliver_fs_give_up_callbacks(struct afs_call *call,
  281. struct sk_buff *skb, bool last)
  282. {
  283. _enter(",{%u},%d", skb->len, last);
  284. if (skb->len > 0)
  285. return -EBADMSG; /* shouldn't be any reply data */
  286. return 0;
  287. }
  288. /*
  289. * FS.GiveUpCallBacks operation type
  290. */
  291. static const struct afs_call_type afs_RXFSGiveUpCallBacks = {
  292. .deliver = afs_deliver_fs_give_up_callbacks,
  293. .abort_to_error = afs_abort_to_error,
  294. .destructor = afs_flat_call_destructor,
  295. };
  296. /*
  297. * give up a set of callbacks
  298. * - the callbacks are held in the server->cb_break ring
  299. */
  300. int afs_fs_give_up_callbacks(struct afs_server *server,
  301. const struct afs_wait_mode *wait_mode)
  302. {
  303. struct afs_call *call;
  304. size_t ncallbacks;
  305. __be32 *bp, *tp;
  306. int loop;
  307. ncallbacks = CIRC_CNT(server->cb_break_head, server->cb_break_tail,
  308. ARRAY_SIZE(server->cb_break));
  309. _enter("{%zu},", ncallbacks);
  310. if (ncallbacks == 0)
  311. return 0;
  312. if (ncallbacks > AFSCBMAX)
  313. ncallbacks = AFSCBMAX;
  314. _debug("break %zu callbacks", ncallbacks);
  315. call = afs_alloc_flat_call(&afs_RXFSGiveUpCallBacks,
  316. 12 + ncallbacks * 6 * 4, 0);
  317. if (!call)
  318. return -ENOMEM;
  319. call->service_id = FS_SERVICE;
  320. call->port = htons(AFS_FS_PORT);
  321. /* marshall the parameters */
  322. bp = call->request;
  323. tp = bp + 2 + ncallbacks * 3;
  324. *bp++ = htonl(FSGIVEUPCALLBACKS);
  325. *bp++ = htonl(ncallbacks);
  326. *tp++ = htonl(ncallbacks);
  327. atomic_sub(ncallbacks, &server->cb_break_n);
  328. for (loop = ncallbacks; loop > 0; loop--) {
  329. struct afs_callback *cb =
  330. &server->cb_break[server->cb_break_tail];
  331. *bp++ = htonl(cb->fid.vid);
  332. *bp++ = htonl(cb->fid.vnode);
  333. *bp++ = htonl(cb->fid.unique);
  334. *tp++ = htonl(cb->version);
  335. *tp++ = htonl(cb->expiry);
  336. *tp++ = htonl(cb->type);
  337. smp_mb();
  338. server->cb_break_tail =
  339. (server->cb_break_tail + 1) &
  340. (ARRAY_SIZE(server->cb_break) - 1);
  341. }
  342. ASSERT(ncallbacks > 0);
  343. wake_up_nr(&server->cb_break_waitq, ncallbacks);
  344. return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
  345. }