logo

oasis

Own branch of Oasis Linux (upstream: <https://git.sr.ht/~mcf/oasis/>) git clone https://anongit.hacktivis.me/git/oasis.git

0002-Use-a-compact-array-and-free-list-for-requests.patch (8027B)


  1. From 9e0a40fee13134d47980f01c68ec3b10e0d31bc3 Mon Sep 17 00:00:00 2001
  2. From: Michael Forney <mforney@mforney.org>
  3. Date: Sun, 5 Jun 2016 17:25:36 -0700
  4. Subject: [PATCH] Use a compact array and free list for requests
  5. ---
  6. sshfs.c | 126 +++++++++++++++++++++++++++++++++++---------------------
  7. 1 file changed, 80 insertions(+), 46 deletions(-)
  8. diff --git a/sshfs.c b/sshfs.c
  9. index d4d624d..92b893e 100644
  10. --- a/sshfs.c
  11. +++ b/sshfs.c
  12. @@ -171,6 +171,17 @@ struct request {
  13. struct list_head list;
  14. };
  15. +union request_entry {
  16. + struct request *req;
  17. + uintptr_t next;
  18. +};
  19. +
  20. +struct request_table {
  21. + union request_entry *entries;
  22. + int len, cap;
  23. + uint32_t free;
  24. +};
  25. +
  26. struct sshfs_io {
  27. int num_reqs;
  28. pthread_cond_t finished;
  29. @@ -253,7 +264,7 @@ struct sshfs {
  30. int slave;
  31. char *host;
  32. char *base_path;
  33. - GHashTable *reqtab;
  34. + struct request_table reqtab;
  35. pthread_mutex_t lock;
  36. pthread_mutex_t lock_write;
  37. int processing_thread_started;
  38. @@ -1171,12 +1182,6 @@ static int do_write(struct iovec *iov, size_t count)
  39. return 0;
  40. }
  41. -static uint32_t sftp_get_id(void)
  42. -{
  43. - static uint32_t idctr;
  44. - return idctr++;
  45. -}
  46. -
  47. static void buf_to_iov(const struct buffer *buf, struct iovec *iov)
  48. {
  49. iov->iov_base = buf->p;
  50. @@ -1269,6 +1274,43 @@ static void request_free(struct request *req)
  51. g_free(req);
  52. }
  53. +static int request_table_insert(struct request_table *reqtab, struct request *req)
  54. +{
  55. + union request_entry *entries;
  56. + size_t cap;
  57. +
  58. + if (reqtab->free) {
  59. + req->id = reqtab->free;
  60. + reqtab->free = reqtab->entries[req->id-1].next >> 1;
  61. + } else {
  62. + if (reqtab->len == reqtab->cap) {
  63. + cap = reqtab->cap * 2 + 1;
  64. + entries = realloc(reqtab->entries, cap * sizeof(reqtab->entries[0]));
  65. + if (!entries)
  66. + return -1;
  67. + reqtab->cap = cap;
  68. + reqtab->entries = entries;
  69. + }
  70. + req->id = ++reqtab->len;
  71. + }
  72. +
  73. + reqtab->entries[req->id-1].req = req;
  74. + return 0;
  75. +}
  76. +
  77. +static struct request *request_table_lookup(struct request_table *reqtab, uint32_t id)
  78. +{
  79. + if (reqtab->entries[id-1].next & 1)
  80. + return NULL;
  81. + return reqtab->entries[id-1].req;
  82. +}
  83. +
  84. +static void request_table_remove(struct request_table *reqtab, uint32_t id)
  85. +{
  86. + reqtab->entries[id-1].next = (reqtab->free << 1) | 1;
  87. + reqtab->free = id;
  88. +}
  89. +
  90. static void chunk_free(struct read_chunk *chunk)
  91. {
  92. while (!list_empty(&chunk->reqs)) {
  93. @@ -1298,22 +1340,6 @@ static void chunk_put_locked(struct read_chunk *chunk)
  94. pthread_mutex_unlock(&sshfs.lock);
  95. }
  96. -static int clean_req(void *key_, struct request *req, gpointer user_data_)
  97. -{
  98. - (void) key_;
  99. - (void) user_data_;
  100. -
  101. - req->error = -EIO;
  102. - if (req->want_reply)
  103. - sem_post(&req->ready);
  104. - else {
  105. - if (req->end_func)
  106. - req->end_func(req);
  107. - request_free(req);
  108. - }
  109. - return TRUE;
  110. -}
  111. -
  112. static int process_one_request(void)
  113. {
  114. int res;
  115. @@ -1330,8 +1356,7 @@ static int process_one_request(void)
  116. return -1;
  117. pthread_mutex_lock(&sshfs.lock);
  118. - req = (struct request *)
  119. - g_hash_table_lookup(sshfs.reqtab, GUINT_TO_POINTER(id));
  120. + req = request_table_lookup(&sshfs.reqtab, id);
  121. if (req == NULL)
  122. fprintf(stderr, "request %i not found\n", id);
  123. else {
  124. @@ -1343,7 +1368,7 @@ static int process_one_request(void)
  125. sshfs.outstanding_len <= sshfs.max_outstanding_len) {
  126. pthread_cond_broadcast(&sshfs.outstanding_cond);
  127. }
  128. - g_hash_table_remove(sshfs.reqtab, GUINT_TO_POINTER(id));
  129. + request_table_remove(&sshfs.reqtab, id);
  130. }
  131. pthread_mutex_unlock(&sshfs.lock);
  132. if (req != NULL) {
  133. @@ -1404,6 +1429,9 @@ static void close_conn(void)
  134. static void *process_requests(void *data_)
  135. {
  136. + int i;
  137. + struct request *req;
  138. +
  139. (void) data_;
  140. while (1) {
  141. @@ -1414,7 +1442,20 @@ static void *process_requests(void *data_)
  142. pthread_mutex_lock(&sshfs.lock);
  143. sshfs.processing_thread_started = 0;
  144. close_conn();
  145. - g_hash_table_foreach_remove(sshfs.reqtab, (GHRFunc) clean_req, NULL);
  146. + for (i = 0; i < sshfs.reqtab.len; ++i) {
  147. + if (sshfs.reqtab.entries[i].next & 1)
  148. + continue;
  149. + req = sshfs.reqtab.entries[i].req;
  150. + req->error = -EIO;
  151. + if (req->want_reply)
  152. + sem_post(&req->ready);
  153. + else {
  154. + if (req->end_func)
  155. + req->end_func(req);
  156. + request_free(req);
  157. + }
  158. + request_table_remove(&sshfs.reqtab, i + 1);
  159. + }
  160. sshfs.connver ++;
  161. sshfs.outstanding_len = 0;
  162. pthread_cond_broadcast(&sshfs.outstanding_cond);
  163. @@ -1562,7 +1603,6 @@ static int sftp_error_to_errno(uint32_t error)
  164. static void sftp_detect_uid()
  165. {
  166. int flags;
  167. - uint32_t id = sftp_get_id();
  168. uint32_t replid;
  169. uint8_t type;
  170. struct buffer buf;
  171. @@ -1572,7 +1612,7 @@ static void sftp_detect_uid()
  172. buf_init(&buf, 5);
  173. buf_add_string(&buf, ".");
  174. buf_to_iov(&buf, &iov[0]);
  175. - if (sftp_send_iov(SSH_FXP_STAT, id, iov, 1) == -1)
  176. + if (sftp_send_iov(SSH_FXP_STAT, 0, iov, 1) == -1)
  177. goto out;
  178. buf_clear(&buf);
  179. if (sftp_read(&type, &buf) == -1)
  180. @@ -1583,7 +1623,7 @@ static void sftp_detect_uid()
  181. }
  182. if (buf_get_uint32(&buf, &replid) == -1)
  183. goto out;
  184. - if (replid != id) {
  185. + if (replid != 0) {
  186. fprintf(stderr, "bad reply ID\n");
  187. goto out;
  188. }
  189. @@ -1618,7 +1658,6 @@ out:
  190. static int sftp_check_root(const char *base_path)
  191. {
  192. int flags;
  193. - uint32_t id = sftp_get_id();
  194. uint32_t replid;
  195. uint8_t type;
  196. struct buffer buf;
  197. @@ -1630,7 +1669,7 @@ static int sftp_check_root(const char *base_path)
  198. buf_init(&buf, 0);
  199. buf_add_string(&buf, remote_dir);
  200. buf_to_iov(&buf, &iov[0]);
  201. - if (sftp_send_iov(SSH_FXP_LSTAT, id, iov, 1) == -1)
  202. + if (sftp_send_iov(SSH_FXP_LSTAT, 0, iov, 1) == -1)
  203. goto out;
  204. buf_clear(&buf);
  205. if (sftp_read(&type, &buf) == -1)
  206. @@ -1641,7 +1680,7 @@ static int sftp_check_root(const char *base_path)
  207. }
  208. if (buf_get_uint32(&buf, &replid) == -1)
  209. goto out;
  210. - if (replid != id) {
  211. + if (replid != 0) {
  212. fprintf(stderr, "bad reply ID\n");
  213. goto out;
  214. }
  215. @@ -1831,7 +1870,6 @@ static int sftp_request_send(uint8_t type, struct iovec *iov, size_t count,
  216. struct request **reqp)
  217. {
  218. int err;
  219. - uint32_t id;
  220. struct request *req = g_new0(struct request, 1);
  221. req->want_reply = want_reply;
  222. @@ -1842,8 +1880,6 @@ static int sftp_request_send(uint8_t type, struct iovec *iov, size_t count,
  223. pthread_mutex_lock(&sshfs.lock);
  224. if (begin_func)
  225. begin_func(req);
  226. - id = sftp_get_id();
  227. - req->id = id;
  228. err = start_processing_thread();
  229. if (err) {
  230. pthread_mutex_unlock(&sshfs.lock);
  231. @@ -1854,21 +1890,24 @@ static int sftp_request_send(uint8_t type, struct iovec *iov, size_t count,
  232. while (sshfs.outstanding_len > sshfs.max_outstanding_len)
  233. pthread_cond_wait(&sshfs.outstanding_cond, &sshfs.lock);
  234. - g_hash_table_insert(sshfs.reqtab, GUINT_TO_POINTER(id), req);
  235. + if (request_table_insert(&sshfs.reqtab, req) < 0)
  236. + abort();
  237. if (sshfs.debug) {
  238. gettimeofday(&req->start, NULL);
  239. sshfs.num_sent++;
  240. sshfs.bytes_sent += req->len;
  241. }
  242. - DEBUG("[%05i] %s\n", id, type_name(type));
  243. + DEBUG("[%05i] %s\n", req->id, type_name(type));
  244. pthread_mutex_unlock(&sshfs.lock);
  245. err = -EIO;
  246. - if (sftp_send_iov(type, id, iov, count) == -1) {
  247. + if (sftp_send_iov(type, req->id, iov, count) == -1) {
  248. gboolean rmed;
  249. pthread_mutex_lock(&sshfs.lock);
  250. - rmed = g_hash_table_remove(sshfs.reqtab, GUINT_TO_POINTER(id));
  251. + rmed = !!request_table_lookup(&sshfs.reqtab, req->id);
  252. + if (rmed)
  253. + request_table_remove(&sshfs.reqtab, req->id);
  254. pthread_mutex_unlock(&sshfs.lock);
  255. if (!rmed && !want_reply) {
  256. @@ -2041,7 +2080,7 @@ static int sftp_readdir_send(struct request **req, struct buffer *handle)
  257. static int sshfs_req_pending(struct request *req)
  258. {
  259. - if (g_hash_table_lookup(sshfs.reqtab, GUINT_TO_POINTER(req->id)))
  260. + if (request_table_lookup(&sshfs.reqtab, req->id))
  261. return 1;
  262. else
  263. return 0;
  264. @@ -3312,11 +3351,6 @@ static int processing_init(void)
  265. pthread_mutex_init(&sshfs.lock, NULL);
  266. pthread_mutex_init(&sshfs.lock_write, NULL);
  267. pthread_cond_init(&sshfs.outstanding_cond, NULL);
  268. - sshfs.reqtab = g_hash_table_new(NULL, NULL);
  269. - if (!sshfs.reqtab) {
  270. - fprintf(stderr, "failed to create hash table\n");
  271. - return -1;
  272. - }
  273. return 0;
  274. }
  275. --
  276. 2.24.0