dir.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. /*
  2. * (C) 2001 Clemson University and The University of Chicago
  3. *
  4. * See COPYING in top-level directory.
  5. */
  6. #include "protocol.h"
  7. #include "pvfs2-kernel.h"
  8. #include "pvfs2-bufmap.h"
  9. struct readdir_handle_s {
  10. int buffer_index;
  11. struct pvfs2_readdir_response_s readdir_response;
  12. void *dents_buf;
  13. };
  14. /*
  15. * decode routine needed by kmod to make sense of the shared page for readdirs.
  16. */
  17. static long decode_dirents(char *ptr, struct pvfs2_readdir_response_s *readdir)
  18. {
  19. int i;
  20. struct pvfs2_readdir_response_s *rd =
  21. (struct pvfs2_readdir_response_s *) ptr;
  22. char *buf = ptr;
  23. char **pptr = &buf;
  24. readdir->token = rd->token;
  25. readdir->pvfs_dirent_outcount = rd->pvfs_dirent_outcount;
  26. readdir->dirent_array = kmalloc(readdir->pvfs_dirent_outcount *
  27. sizeof(*readdir->dirent_array),
  28. GFP_KERNEL);
  29. if (readdir->dirent_array == NULL)
  30. return -ENOMEM;
  31. *pptr += offsetof(struct pvfs2_readdir_response_s, dirent_array);
  32. for (i = 0; i < readdir->pvfs_dirent_outcount; i++) {
  33. dec_string(pptr, &readdir->dirent_array[i].d_name,
  34. &readdir->dirent_array[i].d_length);
  35. readdir->dirent_array[i].khandle =
  36. *(struct pvfs2_khandle *) *pptr;
  37. *pptr += 16;
  38. }
  39. return (unsigned long)*pptr - (unsigned long)ptr;
  40. }
  41. static long readdir_handle_ctor(struct readdir_handle_s *rhandle, void *buf,
  42. int buffer_index)
  43. {
  44. long ret;
  45. if (buf == NULL) {
  46. gossip_err
  47. ("Invalid NULL buffer specified in readdir_handle_ctor\n");
  48. return -ENOMEM;
  49. }
  50. if (buffer_index < 0) {
  51. gossip_err
  52. ("Invalid buffer index specified in readdir_handle_ctor\n");
  53. return -EINVAL;
  54. }
  55. rhandle->buffer_index = buffer_index;
  56. rhandle->dents_buf = buf;
  57. ret = decode_dirents(buf, &rhandle->readdir_response);
  58. if (ret < 0) {
  59. gossip_err("Could not decode readdir from buffer %ld\n", ret);
  60. rhandle->buffer_index = -1;
  61. gossip_debug(GOSSIP_DIR_DEBUG, "vfree %p\n", buf);
  62. vfree(buf);
  63. rhandle->dents_buf = NULL;
  64. }
  65. return ret;
  66. }
  67. static void readdir_handle_dtor(struct pvfs2_bufmap *bufmap,
  68. struct readdir_handle_s *rhandle)
  69. {
  70. if (rhandle == NULL)
  71. return;
  72. /* kfree(NULL) is safe */
  73. kfree(rhandle->readdir_response.dirent_array);
  74. rhandle->readdir_response.dirent_array = NULL;
  75. if (rhandle->buffer_index >= 0) {
  76. readdir_index_put(bufmap, rhandle->buffer_index);
  77. rhandle->buffer_index = -1;
  78. }
  79. if (rhandle->dents_buf) {
  80. gossip_debug(GOSSIP_DIR_DEBUG, "vfree %p\n",
  81. rhandle->dents_buf);
  82. vfree(rhandle->dents_buf);
  83. rhandle->dents_buf = NULL;
  84. }
  85. }
  86. /*
  87. * Read directory entries from an instance of an open directory.
  88. *
  89. * \note This routine was converted for the readdir to iterate change
  90. * in "struct file_operations". "converted" mostly amounts to
  91. * changing occurrences of "readdir" and "filldir" in the
  92. * comments to "iterate" and "dir_emit". Also filldir calls
  93. * were changed to dir_emit calls.
  94. *
  95. * \param dir_emit callback function called for each entry read.
  96. *
  97. * \retval <0 on error
  98. * \retval 0 when directory has been completely traversed
  99. * \retval >0 if we don't call dir_emit for all entries
  100. *
  101. * \note If the dir_emit call-back returns non-zero, then iterate should
  102. * assume that it has had enough, and should return as well.
  103. */
  104. static int pvfs2_readdir(struct file *file, struct dir_context *ctx)
  105. {
  106. struct pvfs2_bufmap *bufmap = NULL;
  107. int ret = 0;
  108. int buffer_index;
  109. __u64 *ptoken = file->private_data;
  110. __u64 pos = 0;
  111. ino_t ino = 0;
  112. struct dentry *dentry = file->f_path.dentry;
  113. struct pvfs2_kernel_op_s *new_op = NULL;
  114. struct pvfs2_inode_s *pvfs2_inode = PVFS2_I(dentry->d_inode);
  115. int buffer_full = 0;
  116. struct readdir_handle_s rhandle;
  117. int i = 0;
  118. int len = 0;
  119. ino_t current_ino = 0;
  120. char *current_entry = NULL;
  121. long bytes_decoded;
  122. gossip_ldebug(GOSSIP_DIR_DEBUG,
  123. "%s: ctx->pos:%lld, token = %llu\n",
  124. __func__,
  125. lld(ctx->pos),
  126. llu(*ptoken));
  127. pos = (__u64) ctx->pos;
  128. /* are we done? */
  129. if (pos == PVFS_READDIR_END) {
  130. gossip_debug(GOSSIP_DIR_DEBUG,
  131. "Skipping to termination path\n");
  132. return 0;
  133. }
  134. gossip_debug(GOSSIP_DIR_DEBUG,
  135. "pvfs2_readdir called on %s (pos=%llu)\n",
  136. dentry->d_name.name, llu(pos));
  137. rhandle.buffer_index = -1;
  138. rhandle.dents_buf = NULL;
  139. memset(&rhandle.readdir_response, 0, sizeof(rhandle.readdir_response));
  140. new_op = op_alloc(PVFS2_VFS_OP_READDIR);
  141. if (!new_op)
  142. return -ENOMEM;
  143. new_op->uses_shared_memory = 1;
  144. new_op->upcall.req.readdir.refn = pvfs2_inode->refn;
  145. new_op->upcall.req.readdir.max_dirent_count = MAX_DIRENT_COUNT_READDIR;
  146. gossip_debug(GOSSIP_DIR_DEBUG,
  147. "%s: upcall.req.readdir.refn.khandle: %pU\n",
  148. __func__,
  149. &new_op->upcall.req.readdir.refn.khandle);
  150. /*
  151. * NOTE: the position we send to the readdir upcall is out of
  152. * sync with ctx->pos since:
  153. * 1. pvfs2 doesn't include the "." and ".." entries that are
  154. * added below.
  155. * 2. the introduction of distributed directory logic makes token no
  156. * longer be related to f_pos and pos. Instead an independent
  157. * variable is used inside the function and stored in the
  158. * private_data of the file structure.
  159. */
  160. new_op->upcall.req.readdir.token = *ptoken;
  161. get_new_buffer_index:
  162. ret = readdir_index_get(&bufmap, &buffer_index);
  163. if (ret < 0) {
  164. gossip_lerr("pvfs2_readdir: readdir_index_get() failure (%d)\n",
  165. ret);
  166. goto out_free_op;
  167. }
  168. new_op->upcall.req.readdir.buf_index = buffer_index;
  169. ret = service_operation(new_op,
  170. "pvfs2_readdir",
  171. get_interruptible_flag(dentry->d_inode));
  172. gossip_debug(GOSSIP_DIR_DEBUG,
  173. "Readdir downcall status is %d. ret:%d\n",
  174. new_op->downcall.status,
  175. ret);
  176. if (ret == -EAGAIN && op_state_purged(new_op)) {
  177. /*
  178. * readdir shared memory aread has been wiped due to
  179. * pvfs2-client-core restarting, so we must get a new
  180. * index into the shared memory.
  181. */
  182. gossip_debug(GOSSIP_DIR_DEBUG,
  183. "%s: Getting new buffer_index for retry of readdir..\n",
  184. __func__);
  185. readdir_index_put(bufmap, buffer_index);
  186. goto get_new_buffer_index;
  187. }
  188. if (ret == -EIO && op_state_purged(new_op)) {
  189. gossip_err("%s: Client is down. Aborting readdir call.\n",
  190. __func__);
  191. readdir_index_put(bufmap, buffer_index);
  192. goto out_free_op;
  193. }
  194. if (ret < 0 || new_op->downcall.status != 0) {
  195. gossip_debug(GOSSIP_DIR_DEBUG,
  196. "Readdir request failed. Status:%d\n",
  197. new_op->downcall.status);
  198. readdir_index_put(bufmap, buffer_index);
  199. if (ret >= 0)
  200. ret = new_op->downcall.status;
  201. goto out_free_op;
  202. }
  203. bytes_decoded =
  204. readdir_handle_ctor(&rhandle,
  205. new_op->downcall.trailer_buf,
  206. buffer_index);
  207. if (bytes_decoded < 0) {
  208. gossip_err("pvfs2_readdir: Could not decode trailer buffer into a readdir response %d\n",
  209. ret);
  210. ret = bytes_decoded;
  211. readdir_index_put(bufmap, buffer_index);
  212. goto out_free_op;
  213. }
  214. if (bytes_decoded != new_op->downcall.trailer_size) {
  215. gossip_err("pvfs2_readdir: # bytes decoded (%ld) != trailer size (%ld)\n",
  216. bytes_decoded,
  217. (long)new_op->downcall.trailer_size);
  218. ret = -EINVAL;
  219. goto out_destroy_handle;
  220. }
  221. if (pos == 0) {
  222. ino = get_ino_from_khandle(dentry->d_inode);
  223. gossip_debug(GOSSIP_DIR_DEBUG,
  224. "%s: calling dir_emit of \".\" with pos = %llu\n",
  225. __func__,
  226. llu(pos));
  227. ret = dir_emit(ctx, ".", 1, ino, DT_DIR);
  228. if (ret < 0)
  229. goto out_destroy_handle;
  230. ctx->pos++;
  231. gossip_ldebug(GOSSIP_DIR_DEBUG,
  232. "%s: ctx->pos:%lld\n",
  233. __func__,
  234. lld(ctx->pos));
  235. pos++;
  236. }
  237. if (pos == 1) {
  238. ino = get_parent_ino_from_dentry(dentry);
  239. gossip_debug(GOSSIP_DIR_DEBUG,
  240. "%s: calling dir_emit of \"..\" with pos = %llu\n",
  241. __func__,
  242. llu(pos));
  243. ret = dir_emit(ctx, "..", 2, ino, DT_DIR);
  244. if (ret < 0)
  245. goto out_destroy_handle;
  246. ctx->pos++;
  247. gossip_ldebug(GOSSIP_DIR_DEBUG,
  248. "%s: ctx->pos:%lld\n",
  249. __func__,
  250. lld(ctx->pos));
  251. pos++;
  252. }
  253. for (i = 0; i < rhandle.readdir_response.pvfs_dirent_outcount; i++) {
  254. len = rhandle.readdir_response.dirent_array[i].d_length;
  255. current_entry = rhandle.readdir_response.dirent_array[i].d_name;
  256. current_ino = pvfs2_khandle_to_ino(
  257. &(rhandle.readdir_response.dirent_array[i].khandle));
  258. gossip_debug(GOSSIP_DIR_DEBUG,
  259. "calling dir_emit for %s with len %d, pos %ld\n",
  260. current_entry,
  261. len,
  262. (unsigned long)pos);
  263. ret =
  264. dir_emit(ctx, current_entry, len, current_ino, DT_UNKNOWN);
  265. if (ret < 0) {
  266. gossip_debug(GOSSIP_DIR_DEBUG,
  267. "dir_emit() failed. ret:%d\n",
  268. ret);
  269. if (i < 2) {
  270. gossip_err("dir_emit failed on one of the first two true PVFS directory entries.\n");
  271. gossip_err("Duplicate entries may appear.\n");
  272. }
  273. buffer_full = 1;
  274. break;
  275. }
  276. ctx->pos++;
  277. gossip_ldebug(GOSSIP_DIR_DEBUG,
  278. "%s: ctx->pos:%lld\n",
  279. __func__,
  280. lld(ctx->pos));
  281. pos++;
  282. }
  283. /* this means that all of the dir_emit calls succeeded */
  284. if (i == rhandle.readdir_response.pvfs_dirent_outcount) {
  285. /* update token */
  286. *ptoken = rhandle.readdir_response.token;
  287. } else {
  288. /* this means a dir_emit call failed */
  289. if (rhandle.readdir_response.token == PVFS_READDIR_END) {
  290. /*
  291. * If PVFS hit end of directory, then there
  292. * is no way to do math on the token that it
  293. * returned. Instead we go by ctx->pos but
  294. * back up to account for the artificial .
  295. * and .. entries.
  296. */
  297. ctx->pos -= 3;
  298. } else {
  299. /*
  300. * this means a dir_emit call failed. !!! need to set
  301. * back to previous ctx->pos, no middle value allowed
  302. */
  303. pos -= (i - 1);
  304. ctx->pos -= (i - 1);
  305. }
  306. gossip_debug(GOSSIP_DIR_DEBUG,
  307. "at least one dir_emit call failed. Setting ctx->pos to: %lld\n",
  308. lld(ctx->pos));
  309. }
  310. /*
  311. * Did we hit the end of the directory?
  312. */
  313. if (rhandle.readdir_response.token == PVFS_READDIR_END &&
  314. !buffer_full) {
  315. gossip_debug(GOSSIP_DIR_DEBUG, "End of dir detected; setting ctx->pos to PVFS_READDIR_END.\n");
  316. ctx->pos = PVFS_READDIR_END;
  317. }
  318. gossip_debug(GOSSIP_DIR_DEBUG,
  319. "pos = %llu, token = %llu"
  320. ", ctx->pos should have been %lld\n",
  321. llu(pos),
  322. llu(*ptoken),
  323. lld(ctx->pos));
  324. out_destroy_handle:
  325. readdir_handle_dtor(bufmap, &rhandle);
  326. out_free_op:
  327. op_release(new_op);
  328. gossip_debug(GOSSIP_DIR_DEBUG, "pvfs2_readdir returning %d\n", ret);
  329. return ret;
  330. }
  331. static int pvfs2_dir_open(struct inode *inode, struct file *file)
  332. {
  333. __u64 *ptoken;
  334. file->private_data = kmalloc(sizeof(__u64), GFP_KERNEL);
  335. if (!file->private_data)
  336. return -ENOMEM;
  337. ptoken = file->private_data;
  338. *ptoken = PVFS_READDIR_START;
  339. return 0;
  340. }
  341. static int pvfs2_dir_release(struct inode *inode, struct file *file)
  342. {
  343. pvfs2_flush_inode(inode);
  344. kfree(file->private_data);
  345. return 0;
  346. }
  347. /** PVFS2 implementation of VFS directory operations */
  348. const struct file_operations pvfs2_dir_operations = {
  349. .read = generic_read_dir,
  350. .iterate = pvfs2_readdir,
  351. .open = pvfs2_dir_open,
  352. .release = pvfs2_dir_release,
  353. };