dm-log-userspace-base.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819
  1. /*
  2. * Copyright (C) 2006-2009 Red Hat, Inc.
  3. *
  4. * This file is released under the LGPL.
  5. */
  6. #include <linux/bio.h>
  7. #include <linux/slab.h>
  8. #include <linux/dm-dirty-log.h>
  9. #include <linux/device-mapper.h>
  10. #include <linux/dm-log-userspace.h>
  11. #include <linux/module.h>
  12. #include "dm-log-userspace-transfer.h"
  13. #define DM_LOG_USERSPACE_VSN "1.1.0"
  14. struct flush_entry {
  15. int type;
  16. region_t region;
  17. struct list_head list;
  18. };
  19. /*
  20. * This limit on the number of mark and clear request is, to a degree,
  21. * arbitrary. However, there is some basis for the choice in the limits
  22. * imposed on the size of data payload by dm-log-userspace-transfer.c:
  23. * dm_consult_userspace().
  24. */
  25. #define MAX_FLUSH_GROUP_COUNT 32
  26. struct log_c {
  27. struct dm_target *ti;
  28. struct dm_dev *log_dev;
  29. uint32_t region_size;
  30. region_t region_count;
  31. uint64_t luid;
  32. char uuid[DM_UUID_LEN];
  33. char *usr_argv_str;
  34. uint32_t usr_argc;
  35. /*
  36. * in_sync_hint gets set when doing is_remote_recovering. It
  37. * represents the first region that needs recovery. IOW, the
  38. * first zero bit of sync_bits. This can be useful for to limit
  39. * traffic for calls like is_remote_recovering and get_resync_work,
  40. * but be take care in its use for anything else.
  41. */
  42. uint64_t in_sync_hint;
  43. /*
  44. * Mark and clear requests are held until a flush is issued
  45. * so that we can group, and thereby limit, the amount of
  46. * network traffic between kernel and userspace. The 'flush_lock'
  47. * is used to protect these lists.
  48. */
  49. spinlock_t flush_lock;
  50. struct list_head mark_list;
  51. struct list_head clear_list;
  52. };
  53. static mempool_t *flush_entry_pool;
  54. static void *flush_entry_alloc(gfp_t gfp_mask, void *pool_data)
  55. {
  56. return kmalloc(sizeof(struct flush_entry), gfp_mask);
  57. }
  58. static void flush_entry_free(void *element, void *pool_data)
  59. {
  60. kfree(element);
  61. }
  62. static int userspace_do_request(struct log_c *lc, const char *uuid,
  63. int request_type, char *data, size_t data_size,
  64. char *rdata, size_t *rdata_size)
  65. {
  66. int r;
  67. /*
  68. * If the server isn't there, -ESRCH is returned,
  69. * and we must keep trying until the server is
  70. * restored.
  71. */
  72. retry:
  73. r = dm_consult_userspace(uuid, lc->luid, request_type, data,
  74. data_size, rdata, rdata_size);
  75. if (r != -ESRCH)
  76. return r;
  77. DMERR(" Userspace log server not found.");
  78. while (1) {
  79. set_current_state(TASK_INTERRUPTIBLE);
  80. schedule_timeout(2*HZ);
  81. DMWARN("Attempting to contact userspace log server...");
  82. r = dm_consult_userspace(uuid, lc->luid, DM_ULOG_CTR,
  83. lc->usr_argv_str,
  84. strlen(lc->usr_argv_str) + 1,
  85. NULL, NULL);
  86. if (!r)
  87. break;
  88. }
  89. DMINFO("Reconnected to userspace log server... DM_ULOG_CTR complete");
  90. r = dm_consult_userspace(uuid, lc->luid, DM_ULOG_RESUME, NULL,
  91. 0, NULL, NULL);
  92. if (!r)
  93. goto retry;
  94. DMERR("Error trying to resume userspace log: %d", r);
  95. return -ESRCH;
  96. }
  97. static int build_constructor_string(struct dm_target *ti,
  98. unsigned argc, char **argv,
  99. char **ctr_str)
  100. {
  101. int i, str_size;
  102. char *str = NULL;
  103. *ctr_str = NULL;
  104. for (i = 0, str_size = 0; i < argc; i++)
  105. str_size += strlen(argv[i]) + 1; /* +1 for space between args */
  106. str_size += 20; /* Max number of chars in a printed u64 number */
  107. str = kzalloc(str_size, GFP_KERNEL);
  108. if (!str) {
  109. DMWARN("Unable to allocate memory for constructor string");
  110. return -ENOMEM;
  111. }
  112. str_size = sprintf(str, "%llu", (unsigned long long)ti->len);
  113. for (i = 0; i < argc; i++)
  114. str_size += sprintf(str + str_size, " %s", argv[i]);
  115. *ctr_str = str;
  116. return str_size;
  117. }
  118. /*
  119. * userspace_ctr
  120. *
  121. * argv contains:
  122. * <UUID> <other args>
  123. * Where 'other args' is the userspace implementation specific log
  124. * arguments. An example might be:
  125. * <UUID> clustered-disk <arg count> <log dev> <region_size> [[no]sync]
  126. *
  127. * So, this module will strip off the <UUID> for identification purposes
  128. * when communicating with userspace about a log; but will pass on everything
  129. * else.
  130. */
  131. static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
  132. unsigned argc, char **argv)
  133. {
  134. int r = 0;
  135. int str_size;
  136. char *ctr_str = NULL;
  137. struct log_c *lc = NULL;
  138. uint64_t rdata;
  139. size_t rdata_size = sizeof(rdata);
  140. char *devices_rdata = NULL;
  141. size_t devices_rdata_size = DM_NAME_LEN;
  142. if (argc < 3) {
  143. DMWARN("Too few arguments to userspace dirty log");
  144. return -EINVAL;
  145. }
  146. lc = kzalloc(sizeof(*lc), GFP_KERNEL);
  147. if (!lc) {
  148. DMWARN("Unable to allocate userspace log context.");
  149. return -ENOMEM;
  150. }
  151. /* The ptr value is sufficient for local unique id */
  152. lc->luid = (unsigned long)lc;
  153. lc->ti = ti;
  154. if (strlen(argv[0]) > (DM_UUID_LEN - 1)) {
  155. DMWARN("UUID argument too long.");
  156. kfree(lc);
  157. return -EINVAL;
  158. }
  159. strncpy(lc->uuid, argv[0], DM_UUID_LEN);
  160. spin_lock_init(&lc->flush_lock);
  161. INIT_LIST_HEAD(&lc->mark_list);
  162. INIT_LIST_HEAD(&lc->clear_list);
  163. str_size = build_constructor_string(ti, argc - 1, argv + 1, &ctr_str);
  164. if (str_size < 0) {
  165. kfree(lc);
  166. return str_size;
  167. }
  168. devices_rdata = kzalloc(devices_rdata_size, GFP_KERNEL);
  169. if (!devices_rdata) {
  170. DMERR("Failed to allocate memory for device information");
  171. r = -ENOMEM;
  172. goto out;
  173. }
  174. /*
  175. * Send table string and get back any opened device.
  176. */
  177. r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_CTR,
  178. ctr_str, str_size,
  179. devices_rdata, &devices_rdata_size);
  180. if (r < 0) {
  181. if (r == -ESRCH)
  182. DMERR("Userspace log server not found");
  183. else
  184. DMERR("Userspace log server failed to create log");
  185. goto out;
  186. }
  187. /* Since the region size does not change, get it now */
  188. rdata_size = sizeof(rdata);
  189. r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_GET_REGION_SIZE,
  190. NULL, 0, (char *)&rdata, &rdata_size);
  191. if (r) {
  192. DMERR("Failed to get region size of dirty log");
  193. goto out;
  194. }
  195. lc->region_size = (uint32_t)rdata;
  196. lc->region_count = dm_sector_div_up(ti->len, lc->region_size);
  197. if (devices_rdata_size) {
  198. if (devices_rdata[devices_rdata_size - 1] != '\0') {
  199. DMERR("DM_ULOG_CTR device return string not properly terminated");
  200. r = -EINVAL;
  201. goto out;
  202. }
  203. r = dm_get_device(ti, devices_rdata,
  204. dm_table_get_mode(ti->table), &lc->log_dev);
  205. if (r)
  206. DMERR("Failed to register %s with device-mapper",
  207. devices_rdata);
  208. }
  209. out:
  210. kfree(devices_rdata);
  211. if (r) {
  212. kfree(lc);
  213. kfree(ctr_str);
  214. } else {
  215. lc->usr_argv_str = ctr_str;
  216. lc->usr_argc = argc;
  217. log->context = lc;
  218. }
  219. return r;
  220. }
  221. static void userspace_dtr(struct dm_dirty_log *log)
  222. {
  223. struct log_c *lc = log->context;
  224. (void) dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_DTR,
  225. NULL, 0,
  226. NULL, NULL);
  227. if (lc->log_dev)
  228. dm_put_device(lc->ti, lc->log_dev);
  229. kfree(lc->usr_argv_str);
  230. kfree(lc);
  231. return;
  232. }
  233. static int userspace_presuspend(struct dm_dirty_log *log)
  234. {
  235. int r;
  236. struct log_c *lc = log->context;
  237. r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_PRESUSPEND,
  238. NULL, 0,
  239. NULL, NULL);
  240. return r;
  241. }
  242. static int userspace_postsuspend(struct dm_dirty_log *log)
  243. {
  244. int r;
  245. struct log_c *lc = log->context;
  246. r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_POSTSUSPEND,
  247. NULL, 0,
  248. NULL, NULL);
  249. return r;
  250. }
  251. static int userspace_resume(struct dm_dirty_log *log)
  252. {
  253. int r;
  254. struct log_c *lc = log->context;
  255. lc->in_sync_hint = 0;
  256. r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_RESUME,
  257. NULL, 0,
  258. NULL, NULL);
  259. return r;
  260. }
  261. static uint32_t userspace_get_region_size(struct dm_dirty_log *log)
  262. {
  263. struct log_c *lc = log->context;
  264. return lc->region_size;
  265. }
  266. /*
  267. * userspace_is_clean
  268. *
  269. * Check whether a region is clean. If there is any sort of
  270. * failure when consulting the server, we return not clean.
  271. *
  272. * Returns: 1 if clean, 0 otherwise
  273. */
  274. static int userspace_is_clean(struct dm_dirty_log *log, region_t region)
  275. {
  276. int r;
  277. uint64_t region64 = (uint64_t)region;
  278. int64_t is_clean;
  279. size_t rdata_size;
  280. struct log_c *lc = log->context;
  281. rdata_size = sizeof(is_clean);
  282. r = userspace_do_request(lc, lc->uuid, DM_ULOG_IS_CLEAN,
  283. (char *)&region64, sizeof(region64),
  284. (char *)&is_clean, &rdata_size);
  285. return (r) ? 0 : (int)is_clean;
  286. }
  287. /*
  288. * userspace_in_sync
  289. *
  290. * Check if the region is in-sync. If there is any sort
  291. * of failure when consulting the server, we assume that
  292. * the region is not in sync.
  293. *
  294. * If 'can_block' is set, return immediately
  295. *
  296. * Returns: 1 if in-sync, 0 if not-in-sync, -EWOULDBLOCK
  297. */
  298. static int userspace_in_sync(struct dm_dirty_log *log, region_t region,
  299. int can_block)
  300. {
  301. int r;
  302. uint64_t region64 = region;
  303. int64_t in_sync;
  304. size_t rdata_size;
  305. struct log_c *lc = log->context;
  306. /*
  307. * We can never respond directly - even if in_sync_hint is
  308. * set. This is because another machine could see a device
  309. * failure and mark the region out-of-sync. If we don't go
  310. * to userspace to ask, we might think the region is in-sync
  311. * and allow a read to pick up data that is stale. (This is
  312. * very unlikely if a device actually fails; but it is very
  313. * likely if a connection to one device from one machine fails.)
  314. *
  315. * There still might be a problem if the mirror caches the region
  316. * state as in-sync... but then this call would not be made. So,
  317. * that is a mirror problem.
  318. */
  319. if (!can_block)
  320. return -EWOULDBLOCK;
  321. rdata_size = sizeof(in_sync);
  322. r = userspace_do_request(lc, lc->uuid, DM_ULOG_IN_SYNC,
  323. (char *)&region64, sizeof(region64),
  324. (char *)&in_sync, &rdata_size);
  325. return (r) ? 0 : (int)in_sync;
  326. }
  327. static int flush_one_by_one(struct log_c *lc, struct list_head *flush_list)
  328. {
  329. int r = 0;
  330. struct flush_entry *fe;
  331. list_for_each_entry(fe, flush_list, list) {
  332. r = userspace_do_request(lc, lc->uuid, fe->type,
  333. (char *)&fe->region,
  334. sizeof(fe->region),
  335. NULL, NULL);
  336. if (r)
  337. break;
  338. }
  339. return r;
  340. }
  341. static int flush_by_group(struct log_c *lc, struct list_head *flush_list)
  342. {
  343. int r = 0;
  344. int count;
  345. uint32_t type = 0;
  346. struct flush_entry *fe, *tmp_fe;
  347. LIST_HEAD(tmp_list);
  348. uint64_t group[MAX_FLUSH_GROUP_COUNT];
  349. /*
  350. * Group process the requests
  351. */
  352. while (!list_empty(flush_list)) {
  353. count = 0;
  354. list_for_each_entry_safe(fe, tmp_fe, flush_list, list) {
  355. group[count] = fe->region;
  356. count++;
  357. list_move(&fe->list, &tmp_list);
  358. type = fe->type;
  359. if (count >= MAX_FLUSH_GROUP_COUNT)
  360. break;
  361. }
  362. r = userspace_do_request(lc, lc->uuid, type,
  363. (char *)(group),
  364. count * sizeof(uint64_t),
  365. NULL, NULL);
  366. if (r) {
  367. /* Group send failed. Attempt one-by-one. */
  368. list_splice_init(&tmp_list, flush_list);
  369. r = flush_one_by_one(lc, flush_list);
  370. break;
  371. }
  372. }
  373. /*
  374. * Must collect flush_entrys that were successfully processed
  375. * as a group so that they will be free'd by the caller.
  376. */
  377. list_splice_init(&tmp_list, flush_list);
  378. return r;
  379. }
  380. /*
  381. * userspace_flush
  382. *
  383. * This function is ok to block.
  384. * The flush happens in two stages. First, it sends all
  385. * clear/mark requests that are on the list. Then it
  386. * tells the server to commit them. This gives the
  387. * server a chance to optimise the commit, instead of
  388. * doing it for every request.
  389. *
  390. * Additionally, we could implement another thread that
  391. * sends the requests up to the server - reducing the
  392. * load on flush. Then the flush would have less in
  393. * the list and be responsible for the finishing commit.
  394. *
  395. * Returns: 0 on success, < 0 on failure
  396. */
  397. static int userspace_flush(struct dm_dirty_log *log)
  398. {
  399. int r = 0;
  400. unsigned long flags;
  401. struct log_c *lc = log->context;
  402. LIST_HEAD(mark_list);
  403. LIST_HEAD(clear_list);
  404. struct flush_entry *fe, *tmp_fe;
  405. spin_lock_irqsave(&lc->flush_lock, flags);
  406. list_splice_init(&lc->mark_list, &mark_list);
  407. list_splice_init(&lc->clear_list, &clear_list);
  408. spin_unlock_irqrestore(&lc->flush_lock, flags);
  409. if (list_empty(&mark_list) && list_empty(&clear_list))
  410. return 0;
  411. r = flush_by_group(lc, &mark_list);
  412. if (r)
  413. goto fail;
  414. r = flush_by_group(lc, &clear_list);
  415. if (r)
  416. goto fail;
  417. r = userspace_do_request(lc, lc->uuid, DM_ULOG_FLUSH,
  418. NULL, 0, NULL, NULL);
  419. fail:
  420. /*
  421. * We can safely remove these entries, even if failure.
  422. * Calling code will receive an error and will know that
  423. * the log facility has failed.
  424. */
  425. list_for_each_entry_safe(fe, tmp_fe, &mark_list, list) {
  426. list_del(&fe->list);
  427. mempool_free(fe, flush_entry_pool);
  428. }
  429. list_for_each_entry_safe(fe, tmp_fe, &clear_list, list) {
  430. list_del(&fe->list);
  431. mempool_free(fe, flush_entry_pool);
  432. }
  433. if (r)
  434. dm_table_event(lc->ti->table);
  435. return r;
  436. }
  437. /*
  438. * userspace_mark_region
  439. *
  440. * This function should avoid blocking unless absolutely required.
  441. * (Memory allocation is valid for blocking.)
  442. */
  443. static void userspace_mark_region(struct dm_dirty_log *log, region_t region)
  444. {
  445. unsigned long flags;
  446. struct log_c *lc = log->context;
  447. struct flush_entry *fe;
  448. /* Wait for an allocation, but _never_ fail */
  449. fe = mempool_alloc(flush_entry_pool, GFP_NOIO);
  450. BUG_ON(!fe);
  451. spin_lock_irqsave(&lc->flush_lock, flags);
  452. fe->type = DM_ULOG_MARK_REGION;
  453. fe->region = region;
  454. list_add(&fe->list, &lc->mark_list);
  455. spin_unlock_irqrestore(&lc->flush_lock, flags);
  456. return;
  457. }
  458. /*
  459. * userspace_clear_region
  460. *
  461. * This function must not block.
  462. * So, the alloc can't block. In the worst case, it is ok to
  463. * fail. It would simply mean we can't clear the region.
  464. * Does nothing to current sync context, but does mean
  465. * the region will be re-sync'ed on a reload of the mirror
  466. * even though it is in-sync.
  467. */
  468. static void userspace_clear_region(struct dm_dirty_log *log, region_t region)
  469. {
  470. unsigned long flags;
  471. struct log_c *lc = log->context;
  472. struct flush_entry *fe;
  473. /*
  474. * If we fail to allocate, we skip the clearing of
  475. * the region. This doesn't hurt us in any way, except
  476. * to cause the region to be resync'ed when the
  477. * device is activated next time.
  478. */
  479. fe = mempool_alloc(flush_entry_pool, GFP_ATOMIC);
  480. if (!fe) {
  481. DMERR("Failed to allocate memory to clear region.");
  482. return;
  483. }
  484. spin_lock_irqsave(&lc->flush_lock, flags);
  485. fe->type = DM_ULOG_CLEAR_REGION;
  486. fe->region = region;
  487. list_add(&fe->list, &lc->clear_list);
  488. spin_unlock_irqrestore(&lc->flush_lock, flags);
  489. return;
  490. }
  491. /*
  492. * userspace_get_resync_work
  493. *
  494. * Get a region that needs recovery. It is valid to return
  495. * an error for this function.
  496. *
  497. * Returns: 1 if region filled, 0 if no work, <0 on error
  498. */
  499. static int userspace_get_resync_work(struct dm_dirty_log *log, region_t *region)
  500. {
  501. int r;
  502. size_t rdata_size;
  503. struct log_c *lc = log->context;
  504. struct {
  505. int64_t i; /* 64-bit for mix arch compatibility */
  506. region_t r;
  507. } pkg;
  508. if (lc->in_sync_hint >= lc->region_count)
  509. return 0;
  510. rdata_size = sizeof(pkg);
  511. r = userspace_do_request(lc, lc->uuid, DM_ULOG_GET_RESYNC_WORK,
  512. NULL, 0,
  513. (char *)&pkg, &rdata_size);
  514. *region = pkg.r;
  515. return (r) ? r : (int)pkg.i;
  516. }
  517. /*
  518. * userspace_set_region_sync
  519. *
  520. * Set the sync status of a given region. This function
  521. * must not fail.
  522. */
  523. static void userspace_set_region_sync(struct dm_dirty_log *log,
  524. region_t region, int in_sync)
  525. {
  526. int r;
  527. struct log_c *lc = log->context;
  528. struct {
  529. region_t r;
  530. int64_t i;
  531. } pkg;
  532. pkg.r = region;
  533. pkg.i = (int64_t)in_sync;
  534. r = userspace_do_request(lc, lc->uuid, DM_ULOG_SET_REGION_SYNC,
  535. (char *)&pkg, sizeof(pkg),
  536. NULL, NULL);
  537. /*
  538. * It would be nice to be able to report failures.
  539. * However, it is easy emough to detect and resolve.
  540. */
  541. return;
  542. }
  543. /*
  544. * userspace_get_sync_count
  545. *
  546. * If there is any sort of failure when consulting the server,
  547. * we assume that the sync count is zero.
  548. *
  549. * Returns: sync count on success, 0 on failure
  550. */
  551. static region_t userspace_get_sync_count(struct dm_dirty_log *log)
  552. {
  553. int r;
  554. size_t rdata_size;
  555. uint64_t sync_count;
  556. struct log_c *lc = log->context;
  557. rdata_size = sizeof(sync_count);
  558. r = userspace_do_request(lc, lc->uuid, DM_ULOG_GET_SYNC_COUNT,
  559. NULL, 0,
  560. (char *)&sync_count, &rdata_size);
  561. if (r)
  562. return 0;
  563. if (sync_count >= lc->region_count)
  564. lc->in_sync_hint = lc->region_count;
  565. return (region_t)sync_count;
  566. }
  567. /*
  568. * userspace_status
  569. *
  570. * Returns: amount of space consumed
  571. */
  572. static int userspace_status(struct dm_dirty_log *log, status_type_t status_type,
  573. char *result, unsigned maxlen)
  574. {
  575. int r = 0;
  576. char *table_args;
  577. size_t sz = (size_t)maxlen;
  578. struct log_c *lc = log->context;
  579. switch (status_type) {
  580. case STATUSTYPE_INFO:
  581. r = userspace_do_request(lc, lc->uuid, DM_ULOG_STATUS_INFO,
  582. NULL, 0,
  583. result, &sz);
  584. if (r) {
  585. sz = 0;
  586. DMEMIT("%s 1 COM_FAILURE", log->type->name);
  587. }
  588. break;
  589. case STATUSTYPE_TABLE:
  590. sz = 0;
  591. table_args = strchr(lc->usr_argv_str, ' ');
  592. BUG_ON(!table_args); /* There will always be a ' ' */
  593. table_args++;
  594. DMEMIT("%s %u %s %s ", log->type->name, lc->usr_argc,
  595. lc->uuid, table_args);
  596. break;
  597. }
  598. return (r) ? 0 : (int)sz;
  599. }
  600. /*
  601. * userspace_is_remote_recovering
  602. *
  603. * Returns: 1 if region recovering, 0 otherwise
  604. */
  605. static int userspace_is_remote_recovering(struct dm_dirty_log *log,
  606. region_t region)
  607. {
  608. int r;
  609. uint64_t region64 = region;
  610. struct log_c *lc = log->context;
  611. static unsigned long long limit;
  612. struct {
  613. int64_t is_recovering;
  614. uint64_t in_sync_hint;
  615. } pkg;
  616. size_t rdata_size = sizeof(pkg);
  617. /*
  618. * Once the mirror has been reported to be in-sync,
  619. * it will never again ask for recovery work. So,
  620. * we can safely say there is not a remote machine
  621. * recovering if the device is in-sync. (in_sync_hint
  622. * must be reset at resume time.)
  623. */
  624. if (region < lc->in_sync_hint)
  625. return 0;
  626. else if (jiffies < limit)
  627. return 1;
  628. limit = jiffies + (HZ / 4);
  629. r = userspace_do_request(lc, lc->uuid, DM_ULOG_IS_REMOTE_RECOVERING,
  630. (char *)&region64, sizeof(region64),
  631. (char *)&pkg, &rdata_size);
  632. if (r)
  633. return 1;
  634. lc->in_sync_hint = pkg.in_sync_hint;
  635. return (int)pkg.is_recovering;
  636. }
  637. static struct dm_dirty_log_type _userspace_type = {
  638. .name = "userspace",
  639. .module = THIS_MODULE,
  640. .ctr = userspace_ctr,
  641. .dtr = userspace_dtr,
  642. .presuspend = userspace_presuspend,
  643. .postsuspend = userspace_postsuspend,
  644. .resume = userspace_resume,
  645. .get_region_size = userspace_get_region_size,
  646. .is_clean = userspace_is_clean,
  647. .in_sync = userspace_in_sync,
  648. .flush = userspace_flush,
  649. .mark_region = userspace_mark_region,
  650. .clear_region = userspace_clear_region,
  651. .get_resync_work = userspace_get_resync_work,
  652. .set_region_sync = userspace_set_region_sync,
  653. .get_sync_count = userspace_get_sync_count,
  654. .status = userspace_status,
  655. .is_remote_recovering = userspace_is_remote_recovering,
  656. };
  657. static int __init userspace_dirty_log_init(void)
  658. {
  659. int r = 0;
  660. flush_entry_pool = mempool_create(100, flush_entry_alloc,
  661. flush_entry_free, NULL);
  662. if (!flush_entry_pool) {
  663. DMWARN("Unable to create flush_entry_pool: No memory.");
  664. return -ENOMEM;
  665. }
  666. r = dm_ulog_tfr_init();
  667. if (r) {
  668. DMWARN("Unable to initialize userspace log communications");
  669. mempool_destroy(flush_entry_pool);
  670. return r;
  671. }
  672. r = dm_dirty_log_type_register(&_userspace_type);
  673. if (r) {
  674. DMWARN("Couldn't register userspace dirty log type");
  675. dm_ulog_tfr_exit();
  676. mempool_destroy(flush_entry_pool);
  677. return r;
  678. }
  679. DMINFO("version " DM_LOG_USERSPACE_VSN " loaded");
  680. return 0;
  681. }
  682. static void __exit userspace_dirty_log_exit(void)
  683. {
  684. dm_dirty_log_type_unregister(&_userspace_type);
  685. dm_ulog_tfr_exit();
  686. mempool_destroy(flush_entry_pool);
  687. DMINFO("version " DM_LOG_USERSPACE_VSN " unloaded");
  688. return;
  689. }
  690. module_init(userspace_dirty_log_init);
  691. module_exit(userspace_dirty_log_exit);
  692. MODULE_DESCRIPTION(DM_NAME " userspace dirty log link");
  693. MODULE_AUTHOR("Jonathan Brassow <dm-devel@redhat.com>");
  694. MODULE_LICENSE("GPL");