devorangefs-req.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. /*
  2. * (C) 2001 Clemson University and The University of Chicago
  3. *
  4. * Changes by Acxiom Corporation to add protocol version to kernel
  5. * communication, Copyright Acxiom Corporation, 2005.
  6. *
  7. * See COPYING in top-level directory.
  8. */
  9. #include "protocol.h"
  10. #include "orangefs-kernel.h"
  11. #include "orangefs-dev-proto.h"
  12. #include "orangefs-bufmap.h"
  13. #include "orangefs-debugfs.h"
  14. #include <linux/debugfs.h>
  15. #include <linux/slab.h>
  16. /* this file implements the /dev/pvfs2-req device node */
  17. uint32_t orangefs_userspace_version;
  18. static int open_access_count;
  19. static DEFINE_MUTEX(devreq_mutex);
  20. #define DUMP_DEVICE_ERROR() \
  21. do { \
  22. gossip_err("*****************************************************\n");\
  23. gossip_err("ORANGEFS Device Error: You cannot open the device file "); \
  24. gossip_err("\n/dev/%s more than once. Please make sure that\nthere " \
  25. "are no ", ORANGEFS_REQDEVICE_NAME); \
  26. gossip_err("instances of a program using this device\ncurrently " \
  27. "running. (You must verify this!)\n"); \
  28. gossip_err("For example, you can use the lsof program as follows:\n");\
  29. gossip_err("'lsof | grep %s' (run this as root)\n", \
  30. ORANGEFS_REQDEVICE_NAME); \
  31. gossip_err(" open_access_count = %d\n", open_access_count); \
  32. gossip_err("*****************************************************\n");\
  33. } while (0)
  34. static int hash_func(__u64 tag, int table_size)
  35. {
  36. return do_div(tag, (unsigned int)table_size);
  37. }
  38. static void orangefs_devreq_add_op(struct orangefs_kernel_op_s *op)
  39. {
  40. int index = hash_func(op->tag, hash_table_size);
  41. list_add_tail(&op->list, &orangefs_htable_ops_in_progress[index]);
  42. }
  43. /*
  44. * find the op with this tag and remove it from the in progress
  45. * hash table.
  46. */
  47. static struct orangefs_kernel_op_s *orangefs_devreq_remove_op(__u64 tag)
  48. {
  49. struct orangefs_kernel_op_s *op, *next;
  50. int index;
  51. index = hash_func(tag, hash_table_size);
  52. spin_lock(&orangefs_htable_ops_in_progress_lock);
  53. list_for_each_entry_safe(op,
  54. next,
  55. &orangefs_htable_ops_in_progress[index],
  56. list) {
  57. if (op->tag == tag && !op_state_purged(op) &&
  58. !op_state_given_up(op)) {
  59. list_del_init(&op->list);
  60. spin_unlock(&orangefs_htable_ops_in_progress_lock);
  61. return op;
  62. }
  63. }
  64. spin_unlock(&orangefs_htable_ops_in_progress_lock);
  65. return NULL;
  66. }
  67. /* Returns whether any FS are still pending remounted */
  68. static int mark_all_pending_mounts(void)
  69. {
  70. int unmounted = 1;
  71. struct orangefs_sb_info_s *orangefs_sb = NULL;
  72. spin_lock(&orangefs_superblocks_lock);
  73. list_for_each_entry(orangefs_sb, &orangefs_superblocks, list) {
  74. /* All of these file system require a remount */
  75. orangefs_sb->mount_pending = 1;
  76. unmounted = 0;
  77. }
  78. spin_unlock(&orangefs_superblocks_lock);
  79. return unmounted;
  80. }
  81. /*
  82. * Determine if a given file system needs to be remounted or not
  83. * Returns -1 on error
  84. * 0 if already mounted
  85. * 1 if needs remount
  86. */
  87. static int fs_mount_pending(__s32 fsid)
  88. {
  89. int mount_pending = -1;
  90. struct orangefs_sb_info_s *orangefs_sb = NULL;
  91. spin_lock(&orangefs_superblocks_lock);
  92. list_for_each_entry(orangefs_sb, &orangefs_superblocks, list) {
  93. if (orangefs_sb->fs_id == fsid) {
  94. mount_pending = orangefs_sb->mount_pending;
  95. break;
  96. }
  97. }
  98. spin_unlock(&orangefs_superblocks_lock);
  99. return mount_pending;
  100. }
  101. static int orangefs_devreq_open(struct inode *inode, struct file *file)
  102. {
  103. int ret = -EINVAL;
  104. /* in order to ensure that the filesystem driver sees correct UIDs */
  105. if (file->f_cred->user_ns != &init_user_ns) {
  106. gossip_err("%s: device cannot be opened outside init_user_ns\n",
  107. __func__);
  108. goto out;
  109. }
  110. if (!(file->f_flags & O_NONBLOCK)) {
  111. gossip_err("%s: device cannot be opened in blocking mode\n",
  112. __func__);
  113. goto out;
  114. }
  115. ret = -EACCES;
  116. gossip_debug(GOSSIP_DEV_DEBUG, "client-core: opening device\n");
  117. mutex_lock(&devreq_mutex);
  118. if (open_access_count == 0) {
  119. open_access_count = 1;
  120. ret = 0;
  121. } else {
  122. DUMP_DEVICE_ERROR();
  123. }
  124. mutex_unlock(&devreq_mutex);
  125. out:
  126. gossip_debug(GOSSIP_DEV_DEBUG,
  127. "pvfs2-client-core: open device complete (ret = %d)\n",
  128. ret);
  129. return ret;
  130. }
  131. /* Function for read() callers into the device */
  132. static ssize_t orangefs_devreq_read(struct file *file,
  133. char __user *buf,
  134. size_t count, loff_t *offset)
  135. {
  136. struct orangefs_kernel_op_s *op, *temp;
  137. __s32 proto_ver = ORANGEFS_KERNEL_PROTO_VERSION;
  138. static __s32 magic = ORANGEFS_DEVREQ_MAGIC;
  139. struct orangefs_kernel_op_s *cur_op;
  140. unsigned long ret;
  141. /* We do not support blocking IO. */
  142. if (!(file->f_flags & O_NONBLOCK)) {
  143. gossip_err("%s: blocking read from client-core.\n",
  144. __func__);
  145. return -EINVAL;
  146. }
  147. /*
  148. * The client will do an ioctl to find MAX_DEV_REQ_UPSIZE, then
  149. * always read with that size buffer.
  150. */
  151. if (count != MAX_DEV_REQ_UPSIZE) {
  152. gossip_err("orangefs: client-core tried to read wrong size\n");
  153. return -EINVAL;
  154. }
  155. restart:
  156. cur_op = NULL;
  157. /* Get next op (if any) from top of list. */
  158. spin_lock(&orangefs_request_list_lock);
  159. list_for_each_entry_safe(op, temp, &orangefs_request_list, list) {
  160. __s32 fsid;
  161. /* This lock is held past the end of the loop when we break. */
  162. spin_lock(&op->lock);
  163. if (unlikely(op_state_purged(op) || op_state_given_up(op))) {
  164. spin_unlock(&op->lock);
  165. continue;
  166. }
  167. fsid = fsid_of_op(op);
  168. if (fsid != ORANGEFS_FS_ID_NULL) {
  169. int ret;
  170. /* Skip ops whose filesystem needs to be mounted. */
  171. ret = fs_mount_pending(fsid);
  172. if (ret == 1) {
  173. gossip_debug(GOSSIP_DEV_DEBUG,
  174. "%s: mount pending, skipping op tag "
  175. "%llu %s\n",
  176. __func__,
  177. llu(op->tag),
  178. get_opname_string(op));
  179. spin_unlock(&op->lock);
  180. continue;
  181. /*
  182. * Skip ops whose filesystem we don't know about unless
  183. * it is being mounted or unmounted. It is possible for
  184. * a filesystem we don't know about to be unmounted if
  185. * it fails to mount in the kernel after userspace has
  186. * been sent the mount request.
  187. */
  188. /* XXX: is there a better way to detect this? */
  189. } else if (ret == -1 &&
  190. !(op->upcall.type ==
  191. ORANGEFS_VFS_OP_FS_MOUNT ||
  192. op->upcall.type ==
  193. ORANGEFS_VFS_OP_GETATTR ||
  194. op->upcall.type ==
  195. ORANGEFS_VFS_OP_FS_UMOUNT)) {
  196. gossip_debug(GOSSIP_DEV_DEBUG,
  197. "orangefs: skipping op tag %llu %s\n",
  198. llu(op->tag), get_opname_string(op));
  199. gossip_err(
  200. "orangefs: ERROR: fs_mount_pending %d\n",
  201. fsid);
  202. spin_unlock(&op->lock);
  203. continue;
  204. }
  205. }
  206. /*
  207. * Either this op does not pertain to a filesystem, is mounting
  208. * a filesystem, or pertains to a mounted filesystem. Let it
  209. * through.
  210. */
  211. cur_op = op;
  212. break;
  213. }
  214. /*
  215. * At this point we either have a valid op and can continue or have not
  216. * found an op and must ask the client to try again later.
  217. */
  218. if (!cur_op) {
  219. spin_unlock(&orangefs_request_list_lock);
  220. return -EAGAIN;
  221. }
  222. gossip_debug(GOSSIP_DEV_DEBUG, "%s: reading op tag %llu %s\n",
  223. __func__,
  224. llu(cur_op->tag),
  225. get_opname_string(cur_op));
  226. /*
  227. * Such an op should never be on the list in the first place. If so, we
  228. * will abort.
  229. */
  230. if (op_state_in_progress(cur_op) || op_state_serviced(cur_op)) {
  231. gossip_err("orangefs: ERROR: Current op already queued.\n");
  232. list_del_init(&cur_op->list);
  233. spin_unlock(&cur_op->lock);
  234. spin_unlock(&orangefs_request_list_lock);
  235. return -EAGAIN;
  236. }
  237. list_del_init(&cur_op->list);
  238. spin_unlock(&orangefs_request_list_lock);
  239. spin_unlock(&cur_op->lock);
  240. /* Push the upcall out. */
  241. ret = copy_to_user(buf, &proto_ver, sizeof(__s32));
  242. if (ret != 0)
  243. goto error;
  244. ret = copy_to_user(buf+sizeof(__s32), &magic, sizeof(__s32));
  245. if (ret != 0)
  246. goto error;
  247. ret = copy_to_user(buf+2 * sizeof(__s32), &cur_op->tag, sizeof(__u64));
  248. if (ret != 0)
  249. goto error;
  250. ret = copy_to_user(buf+2*sizeof(__s32)+sizeof(__u64), &cur_op->upcall,
  251. sizeof(struct orangefs_upcall_s));
  252. if (ret != 0)
  253. goto error;
  254. spin_lock(&orangefs_htable_ops_in_progress_lock);
  255. spin_lock(&cur_op->lock);
  256. if (unlikely(op_state_given_up(cur_op))) {
  257. spin_unlock(&cur_op->lock);
  258. spin_unlock(&orangefs_htable_ops_in_progress_lock);
  259. complete(&cur_op->waitq);
  260. goto restart;
  261. }
  262. /*
  263. * Set the operation to be in progress and move it between lists since
  264. * it has been sent to the client.
  265. */
  266. set_op_state_inprogress(cur_op);
  267. gossip_debug(GOSSIP_DEV_DEBUG,
  268. "%s: 1 op:%s: op_state:%d: process:%s:\n",
  269. __func__,
  270. get_opname_string(cur_op),
  271. cur_op->op_state,
  272. current->comm);
  273. orangefs_devreq_add_op(cur_op);
  274. spin_unlock(&cur_op->lock);
  275. spin_unlock(&orangefs_htable_ops_in_progress_lock);
  276. /* The client only asks to read one size buffer. */
  277. return MAX_DEV_REQ_UPSIZE;
  278. error:
  279. /*
  280. * We were unable to copy the op data to the client. Put the op back in
  281. * list. If client has crashed, the op will be purged later when the
  282. * device is released.
  283. */
  284. gossip_err("orangefs: Failed to copy data to user space\n");
  285. spin_lock(&orangefs_request_list_lock);
  286. spin_lock(&cur_op->lock);
  287. if (likely(!op_state_given_up(cur_op))) {
  288. set_op_state_waiting(cur_op);
  289. gossip_debug(GOSSIP_DEV_DEBUG,
  290. "%s: 2 op:%s: op_state:%d: process:%s:\n",
  291. __func__,
  292. get_opname_string(cur_op),
  293. cur_op->op_state,
  294. current->comm);
  295. list_add(&cur_op->list, &orangefs_request_list);
  296. spin_unlock(&cur_op->lock);
  297. } else {
  298. spin_unlock(&cur_op->lock);
  299. complete(&cur_op->waitq);
  300. }
  301. spin_unlock(&orangefs_request_list_lock);
  302. return -EFAULT;
  303. }
  304. /*
  305. * Function for writev() callers into the device.
  306. *
  307. * Userspace should have written:
  308. * - __u32 version
  309. * - __u32 magic
  310. * - __u64 tag
  311. * - struct orangefs_downcall_s
  312. * - trailer buffer (in the case of READDIR operations)
  313. */
  314. static ssize_t orangefs_devreq_write_iter(struct kiocb *iocb,
  315. struct iov_iter *iter)
  316. {
  317. ssize_t ret;
  318. struct orangefs_kernel_op_s *op = NULL;
  319. struct {
  320. __u32 version;
  321. __u32 magic;
  322. __u64 tag;
  323. } head;
  324. int total = ret = iov_iter_count(iter);
  325. int n;
  326. int downcall_size = sizeof(struct orangefs_downcall_s);
  327. int head_size = sizeof(head);
  328. gossip_debug(GOSSIP_DEV_DEBUG, "%s: total:%d: ret:%zd:\n",
  329. __func__,
  330. total,
  331. ret);
  332. if (total < MAX_DEV_REQ_DOWNSIZE) {
  333. gossip_err("%s: total:%d: must be at least:%u:\n",
  334. __func__,
  335. total,
  336. (unsigned int) MAX_DEV_REQ_DOWNSIZE);
  337. return -EFAULT;
  338. }
  339. n = copy_from_iter(&head, head_size, iter);
  340. if (n < head_size) {
  341. gossip_err("%s: failed to copy head.\n", __func__);
  342. return -EFAULT;
  343. }
  344. if (head.version < ORANGEFS_MINIMUM_USERSPACE_VERSION) {
  345. gossip_err("%s: userspace claims version"
  346. "%d, minimum version required: %d.\n",
  347. __func__,
  348. head.version,
  349. ORANGEFS_MINIMUM_USERSPACE_VERSION);
  350. return -EPROTO;
  351. }
  352. if (head.magic != ORANGEFS_DEVREQ_MAGIC) {
  353. gossip_err("Error: Device magic number does not match.\n");
  354. return -EPROTO;
  355. }
  356. if (!orangefs_userspace_version) {
  357. orangefs_userspace_version = head.version;
  358. } else if (orangefs_userspace_version != head.version) {
  359. gossip_err("Error: userspace version changes\n");
  360. return -EPROTO;
  361. }
  362. /* remove the op from the in progress hash table */
  363. op = orangefs_devreq_remove_op(head.tag);
  364. if (!op) {
  365. gossip_debug(GOSSIP_DEV_DEBUG,
  366. "%s: No one's waiting for tag %llu\n",
  367. __func__, llu(head.tag));
  368. return ret;
  369. }
  370. n = copy_from_iter(&op->downcall, downcall_size, iter);
  371. if (n != downcall_size) {
  372. gossip_err("%s: failed to copy downcall.\n", __func__);
  373. goto Efault;
  374. }
  375. if (op->downcall.status)
  376. goto wakeup;
  377. /*
  378. * We've successfully peeled off the head and the downcall.
  379. * Something has gone awry if total doesn't equal the
  380. * sum of head_size, downcall_size and trailer_size.
  381. */
  382. if ((head_size + downcall_size + op->downcall.trailer_size) != total) {
  383. gossip_err("%s: funky write, head_size:%d"
  384. ": downcall_size:%d: trailer_size:%lld"
  385. ": total size:%d:\n",
  386. __func__,
  387. head_size,
  388. downcall_size,
  389. op->downcall.trailer_size,
  390. total);
  391. goto Efault;
  392. }
  393. /* Only READDIR operations should have trailers. */
  394. if ((op->downcall.type != ORANGEFS_VFS_OP_READDIR) &&
  395. (op->downcall.trailer_size != 0)) {
  396. gossip_err("%s: %x operation with trailer.",
  397. __func__,
  398. op->downcall.type);
  399. goto Efault;
  400. }
  401. /* READDIR operations should always have trailers. */
  402. if ((op->downcall.type == ORANGEFS_VFS_OP_READDIR) &&
  403. (op->downcall.trailer_size == 0)) {
  404. gossip_err("%s: %x operation with no trailer.",
  405. __func__,
  406. op->downcall.type);
  407. goto Efault;
  408. }
  409. if (op->downcall.type != ORANGEFS_VFS_OP_READDIR)
  410. goto wakeup;
  411. op->downcall.trailer_buf =
  412. vmalloc(op->downcall.trailer_size);
  413. if (op->downcall.trailer_buf == NULL) {
  414. gossip_err("%s: failed trailer vmalloc.\n",
  415. __func__);
  416. goto Enomem;
  417. }
  418. memset(op->downcall.trailer_buf, 0, op->downcall.trailer_size);
  419. n = copy_from_iter(op->downcall.trailer_buf,
  420. op->downcall.trailer_size,
  421. iter);
  422. if (n != op->downcall.trailer_size) {
  423. gossip_err("%s: failed to copy trailer.\n", __func__);
  424. vfree(op->downcall.trailer_buf);
  425. goto Efault;
  426. }
  427. wakeup:
  428. /*
  429. * Return to vfs waitqueue, and back to service_operation
  430. * through wait_for_matching_downcall.
  431. */
  432. spin_lock(&op->lock);
  433. if (unlikely(op_is_cancel(op))) {
  434. spin_unlock(&op->lock);
  435. put_cancel(op);
  436. } else if (unlikely(op_state_given_up(op))) {
  437. spin_unlock(&op->lock);
  438. complete(&op->waitq);
  439. } else {
  440. set_op_state_serviced(op);
  441. gossip_debug(GOSSIP_DEV_DEBUG,
  442. "%s: op:%s: op_state:%d: process:%s:\n",
  443. __func__,
  444. get_opname_string(op),
  445. op->op_state,
  446. current->comm);
  447. spin_unlock(&op->lock);
  448. }
  449. return ret;
  450. Efault:
  451. op->downcall.status = -(ORANGEFS_ERROR_BIT | 9);
  452. ret = -EFAULT;
  453. goto wakeup;
  454. Enomem:
  455. op->downcall.status = -(ORANGEFS_ERROR_BIT | 8);
  456. ret = -ENOMEM;
  457. goto wakeup;
  458. }
  459. /*
  460. * NOTE: gets called when the last reference to this device is dropped.
  461. * Using the open_access_count variable, we enforce a reference count
  462. * on this file so that it can be opened by only one process at a time.
  463. * the devreq_mutex is used to make sure all i/o has completed
  464. * before we call orangefs_bufmap_finalize, and similar such tricky
  465. * situations
  466. */
  467. static int orangefs_devreq_release(struct inode *inode, struct file *file)
  468. {
  469. int unmounted = 0;
  470. gossip_debug(GOSSIP_DEV_DEBUG,
  471. "%s:pvfs2-client-core: exiting, closing device\n",
  472. __func__);
  473. mutex_lock(&devreq_mutex);
  474. orangefs_bufmap_finalize();
  475. open_access_count = -1;
  476. unmounted = mark_all_pending_mounts();
  477. gossip_debug(GOSSIP_DEV_DEBUG, "ORANGEFS Device Close: Filesystem(s) %s\n",
  478. (unmounted ? "UNMOUNTED" : "MOUNTED"));
  479. purge_waiting_ops();
  480. purge_inprogress_ops();
  481. orangefs_bufmap_run_down();
  482. gossip_debug(GOSSIP_DEV_DEBUG,
  483. "pvfs2-client-core: device close complete\n");
  484. open_access_count = 0;
  485. orangefs_userspace_version = 0;
  486. mutex_unlock(&devreq_mutex);
  487. return 0;
  488. }
  489. int is_daemon_in_service(void)
  490. {
  491. int in_service;
  492. /*
  493. * What this function does is checks if client-core is alive
  494. * based on the access count we maintain on the device.
  495. */
  496. mutex_lock(&devreq_mutex);
  497. in_service = open_access_count == 1 ? 0 : -EIO;
  498. mutex_unlock(&devreq_mutex);
  499. return in_service;
  500. }
  501. bool __is_daemon_in_service(void)
  502. {
  503. return open_access_count == 1;
  504. }
  505. static inline long check_ioctl_command(unsigned int command)
  506. {
  507. /* Check for valid ioctl codes */
  508. if (_IOC_TYPE(command) != ORANGEFS_DEV_MAGIC) {
  509. gossip_err("device ioctl magic numbers don't match! Did you rebuild pvfs2-client-core/libpvfs2? [cmd %x, magic %x != %x]\n",
  510. command,
  511. _IOC_TYPE(command),
  512. ORANGEFS_DEV_MAGIC);
  513. return -EINVAL;
  514. }
  515. /* and valid ioctl commands */
  516. if (_IOC_NR(command) >= ORANGEFS_DEV_MAXNR || _IOC_NR(command) <= 0) {
  517. gossip_err("Invalid ioctl command number [%d >= %d]\n",
  518. _IOC_NR(command), ORANGEFS_DEV_MAXNR);
  519. return -ENOIOCTLCMD;
  520. }
  521. return 0;
  522. }
  523. static long dispatch_ioctl_command(unsigned int command, unsigned long arg)
  524. {
  525. static __s32 magic = ORANGEFS_DEVREQ_MAGIC;
  526. static __s32 max_up_size = MAX_DEV_REQ_UPSIZE;
  527. static __s32 max_down_size = MAX_DEV_REQ_DOWNSIZE;
  528. struct ORANGEFS_dev_map_desc user_desc;
  529. int ret = 0;
  530. int upstream_kmod = 1;
  531. struct orangefs_sb_info_s *orangefs_sb;
  532. /* mtmoore: add locking here */
  533. switch (command) {
  534. case ORANGEFS_DEV_GET_MAGIC:
  535. return ((put_user(magic, (__s32 __user *) arg) == -EFAULT) ?
  536. -EIO :
  537. 0);
  538. case ORANGEFS_DEV_GET_MAX_UPSIZE:
  539. return ((put_user(max_up_size,
  540. (__s32 __user *) arg) == -EFAULT) ?
  541. -EIO :
  542. 0);
  543. case ORANGEFS_DEV_GET_MAX_DOWNSIZE:
  544. return ((put_user(max_down_size,
  545. (__s32 __user *) arg) == -EFAULT) ?
  546. -EIO :
  547. 0);
  548. case ORANGEFS_DEV_MAP:
  549. ret = copy_from_user(&user_desc,
  550. (struct ORANGEFS_dev_map_desc __user *)
  551. arg,
  552. sizeof(struct ORANGEFS_dev_map_desc));
  553. /* WTF -EIO and not -EFAULT? */
  554. return ret ? -EIO : orangefs_bufmap_initialize(&user_desc);
  555. case ORANGEFS_DEV_REMOUNT_ALL:
  556. gossip_debug(GOSSIP_DEV_DEBUG,
  557. "%s: got ORANGEFS_DEV_REMOUNT_ALL\n",
  558. __func__);
  559. /*
  560. * remount all mounted orangefs volumes to regain the lost
  561. * dynamic mount tables (if any) -- NOTE: this is done
  562. * without keeping the superblock list locked due to the
  563. * upcall/downcall waiting. also, the request mutex is
  564. * used to ensure that no operations will be serviced until
  565. * all of the remounts are serviced (to avoid ops between
  566. * mounts to fail)
  567. */
  568. ret = mutex_lock_interruptible(&orangefs_request_mutex);
  569. if (ret < 0)
  570. return ret;
  571. gossip_debug(GOSSIP_DEV_DEBUG,
  572. "%s: priority remount in progress\n",
  573. __func__);
  574. spin_lock(&orangefs_superblocks_lock);
  575. list_for_each_entry(orangefs_sb, &orangefs_superblocks, list) {
  576. /*
  577. * We have to drop the spinlock, so entries can be
  578. * removed. They can't be freed, though, so we just
  579. * keep the forward pointers and zero the back ones -
  580. * that way we can get to the rest of the list.
  581. */
  582. if (!orangefs_sb->list.prev)
  583. continue;
  584. gossip_debug(GOSSIP_DEV_DEBUG,
  585. "%s: Remounting SB %p\n",
  586. __func__,
  587. orangefs_sb);
  588. spin_unlock(&orangefs_superblocks_lock);
  589. ret = orangefs_remount(orangefs_sb);
  590. spin_lock(&orangefs_superblocks_lock);
  591. if (ret) {
  592. gossip_debug(GOSSIP_DEV_DEBUG,
  593. "SB %p remount failed\n",
  594. orangefs_sb);
  595. break;
  596. }
  597. }
  598. spin_unlock(&orangefs_superblocks_lock);
  599. gossip_debug(GOSSIP_DEV_DEBUG,
  600. "%s: priority remount complete\n",
  601. __func__);
  602. mutex_unlock(&orangefs_request_mutex);
  603. return ret;
  604. case ORANGEFS_DEV_UPSTREAM:
  605. ret = copy_to_user((void __user *)arg,
  606. &upstream_kmod,
  607. sizeof(upstream_kmod));
  608. if (ret != 0)
  609. return -EIO;
  610. else
  611. return ret;
  612. case ORANGEFS_DEV_CLIENT_MASK:
  613. return orangefs_debugfs_new_client_mask((void __user *)arg);
  614. case ORANGEFS_DEV_CLIENT_STRING:
  615. return orangefs_debugfs_new_client_string((void __user *)arg);
  616. case ORANGEFS_DEV_DEBUG:
  617. return orangefs_debugfs_new_debug((void __user *)arg);
  618. default:
  619. return -ENOIOCTLCMD;
  620. }
  621. return -ENOIOCTLCMD;
  622. }
  623. static long orangefs_devreq_ioctl(struct file *file,
  624. unsigned int command, unsigned long arg)
  625. {
  626. long ret;
  627. /* Check for properly constructed commands */
  628. ret = check_ioctl_command(command);
  629. if (ret < 0)
  630. return (int)ret;
  631. return (int)dispatch_ioctl_command(command, arg);
  632. }
  633. #ifdef CONFIG_COMPAT /* CONFIG_COMPAT is in .config */
  634. /* Compat structure for the ORANGEFS_DEV_MAP ioctl */
  635. struct ORANGEFS_dev_map_desc32 {
  636. compat_uptr_t ptr;
  637. __s32 total_size;
  638. __s32 size;
  639. __s32 count;
  640. };
  641. static unsigned long translate_dev_map26(unsigned long args, long *error)
  642. {
  643. struct ORANGEFS_dev_map_desc32 __user *p32 = (void __user *)args;
  644. /*
  645. * Depending on the architecture, allocate some space on the
  646. * user-call-stack based on our expected layout.
  647. */
  648. struct ORANGEFS_dev_map_desc __user *p =
  649. compat_alloc_user_space(sizeof(*p));
  650. compat_uptr_t addr;
  651. *error = 0;
  652. /* get the ptr from the 32 bit user-space */
  653. if (get_user(addr, &p32->ptr))
  654. goto err;
  655. /* try to put that into a 64-bit layout */
  656. if (put_user(compat_ptr(addr), &p->ptr))
  657. goto err;
  658. /* copy the remaining fields */
  659. if (copy_in_user(&p->total_size, &p32->total_size, sizeof(__s32)))
  660. goto err;
  661. if (copy_in_user(&p->size, &p32->size, sizeof(__s32)))
  662. goto err;
  663. if (copy_in_user(&p->count, &p32->count, sizeof(__s32)))
  664. goto err;
  665. return (unsigned long)p;
  666. err:
  667. *error = -EFAULT;
  668. return 0;
  669. }
  670. /*
  671. * 32 bit user-space apps' ioctl handlers when kernel modules
  672. * is compiled as a 64 bit one
  673. */
  674. static long orangefs_devreq_compat_ioctl(struct file *filp, unsigned int cmd,
  675. unsigned long args)
  676. {
  677. long ret;
  678. unsigned long arg = args;
  679. /* Check for properly constructed commands */
  680. ret = check_ioctl_command(cmd);
  681. if (ret < 0)
  682. return ret;
  683. if (cmd == ORANGEFS_DEV_MAP) {
  684. /*
  685. * convert the arguments to what we expect internally
  686. * in kernel space
  687. */
  688. arg = translate_dev_map26(args, &ret);
  689. if (ret < 0) {
  690. gossip_err("Could not translate dev map\n");
  691. return ret;
  692. }
  693. }
  694. /* no other ioctl requires translation */
  695. return dispatch_ioctl_command(cmd, arg);
  696. }
  697. #endif /* CONFIG_COMPAT is in .config */
  698. /* the assigned character device major number */
  699. static int orangefs_dev_major;
  700. /*
  701. * Initialize orangefs device specific state:
  702. * Must be called at module load time only
  703. */
  704. int orangefs_dev_init(void)
  705. {
  706. /* register orangefs-req device */
  707. orangefs_dev_major = register_chrdev(0,
  708. ORANGEFS_REQDEVICE_NAME,
  709. &orangefs_devreq_file_operations);
  710. if (orangefs_dev_major < 0) {
  711. gossip_debug(GOSSIP_DEV_DEBUG,
  712. "Failed to register /dev/%s (error %d)\n",
  713. ORANGEFS_REQDEVICE_NAME, orangefs_dev_major);
  714. return orangefs_dev_major;
  715. }
  716. gossip_debug(GOSSIP_DEV_DEBUG,
  717. "*** /dev/%s character device registered ***\n",
  718. ORANGEFS_REQDEVICE_NAME);
  719. gossip_debug(GOSSIP_DEV_DEBUG, "'mknod /dev/%s c %d 0'.\n",
  720. ORANGEFS_REQDEVICE_NAME, orangefs_dev_major);
  721. return 0;
  722. }
  723. void orangefs_dev_cleanup(void)
  724. {
  725. unregister_chrdev(orangefs_dev_major, ORANGEFS_REQDEVICE_NAME);
  726. gossip_debug(GOSSIP_DEV_DEBUG,
  727. "*** /dev/%s character device unregistered ***\n",
  728. ORANGEFS_REQDEVICE_NAME);
  729. }
  730. static unsigned int orangefs_devreq_poll(struct file *file,
  731. struct poll_table_struct *poll_table)
  732. {
  733. int poll_revent_mask = 0;
  734. poll_wait(file, &orangefs_request_list_waitq, poll_table);
  735. if (!list_empty(&orangefs_request_list))
  736. poll_revent_mask |= POLL_IN;
  737. return poll_revent_mask;
  738. }
  739. const struct file_operations orangefs_devreq_file_operations = {
  740. .owner = THIS_MODULE,
  741. .read = orangefs_devreq_read,
  742. .write_iter = orangefs_devreq_write_iter,
  743. .open = orangefs_devreq_open,
  744. .release = orangefs_devreq_release,
  745. .unlocked_ioctl = orangefs_devreq_ioctl,
  746. #ifdef CONFIG_COMPAT /* CONFIG_COMPAT is in .config */
  747. .compat_ioctl = orangefs_devreq_compat_ioctl,
  748. #endif
  749. .poll = orangefs_devreq_poll
  750. };