mirror of
https://github.com/oasislinux/oasis.git
synced 2026-06-27 12:21:59 +02:00
294 lines
7.8 KiB
Diff
294 lines
7.8 KiB
Diff
From 9e0a40fee13134d47980f01c68ec3b10e0d31bc3 Mon Sep 17 00:00:00 2001
|
|
From: Michael Forney <mforney@mforney.org>
|
|
Date: Sun, 5 Jun 2016 17:25:36 -0700
|
|
Subject: [PATCH] Use a compact array and free list for requests
|
|
|
|
---
|
|
sshfs.c | 126 +++++++++++++++++++++++++++++++++++---------------------
|
|
1 file changed, 80 insertions(+), 46 deletions(-)
|
|
|
|
diff --git a/sshfs.c b/sshfs.c
|
|
index d4d624d..92b893e 100644
|
|
--- a/sshfs.c
|
|
+++ b/sshfs.c
|
|
@@ -171,6 +171,17 @@ struct request {
|
|
struct list_head list;
|
|
};
|
|
|
|
+union request_entry {
|
|
+ struct request *req;
|
|
+ uintptr_t next;
|
|
+};
|
|
+
|
|
+struct request_table {
|
|
+ union request_entry *entries;
|
|
+ int len, cap;
|
|
+ uint32_t free;
|
|
+};
|
|
+
|
|
struct sshfs_io {
|
|
int num_reqs;
|
|
pthread_cond_t finished;
|
|
@@ -253,7 +264,7 @@ struct sshfs {
|
|
int slave;
|
|
char *host;
|
|
char *base_path;
|
|
- GHashTable *reqtab;
|
|
+ struct request_table reqtab;
|
|
pthread_mutex_t lock;
|
|
pthread_mutex_t lock_write;
|
|
int processing_thread_started;
|
|
@@ -1171,12 +1182,6 @@ static int do_write(struct iovec *iov, size_t count)
|
|
return 0;
|
|
}
|
|
|
|
-static uint32_t sftp_get_id(void)
|
|
-{
|
|
- static uint32_t idctr;
|
|
- return idctr++;
|
|
-}
|
|
-
|
|
static void buf_to_iov(const struct buffer *buf, struct iovec *iov)
|
|
{
|
|
iov->iov_base = buf->p;
|
|
@@ -1269,6 +1274,43 @@ static void request_free(struct request *req)
|
|
g_free(req);
|
|
}
|
|
|
|
+static int request_table_insert(struct request_table *reqtab, struct request *req)
|
|
+{
|
|
+ union request_entry *entries;
|
|
+ size_t cap;
|
|
+
|
|
+ if (reqtab->free) {
|
|
+ req->id = reqtab->free;
|
|
+ reqtab->free = reqtab->entries[req->id-1].next >> 1;
|
|
+ } else {
|
|
+ if (reqtab->len == reqtab->cap) {
|
|
+ cap = reqtab->cap * 2 + 1;
|
|
+ entries = realloc(reqtab->entries, cap * sizeof(reqtab->entries[0]));
|
|
+ if (!entries)
|
|
+ return -1;
|
|
+ reqtab->cap = cap;
|
|
+ reqtab->entries = entries;
|
|
+ }
|
|
+ req->id = ++reqtab->len;
|
|
+ }
|
|
+
|
|
+ reqtab->entries[req->id-1].req = req;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static struct request *request_table_lookup(struct request_table *reqtab, uint32_t id)
|
|
+{
|
|
+ if (reqtab->entries[id-1].next & 1)
|
|
+ return NULL;
|
|
+ return reqtab->entries[id-1].req;
|
|
+}
|
|
+
|
|
+static void request_table_remove(struct request_table *reqtab, uint32_t id)
|
|
+{
|
|
+ reqtab->entries[id-1].next = (reqtab->free << 1) | 1;
|
|
+ reqtab->free = id;
|
|
+}
|
|
+
|
|
static void chunk_free(struct read_chunk *chunk)
|
|
{
|
|
while (!list_empty(&chunk->reqs)) {
|
|
@@ -1298,22 +1340,6 @@ static void chunk_put_locked(struct read_chunk *chunk)
|
|
pthread_mutex_unlock(&sshfs.lock);
|
|
}
|
|
|
|
-static int clean_req(void *key_, struct request *req, gpointer user_data_)
|
|
-{
|
|
- (void) key_;
|
|
- (void) user_data_;
|
|
-
|
|
- req->error = -EIO;
|
|
- if (req->want_reply)
|
|
- sem_post(&req->ready);
|
|
- else {
|
|
- if (req->end_func)
|
|
- req->end_func(req);
|
|
- request_free(req);
|
|
- }
|
|
- return TRUE;
|
|
-}
|
|
-
|
|
static int process_one_request(void)
|
|
{
|
|
int res;
|
|
@@ -1330,8 +1356,7 @@ static int process_one_request(void)
|
|
return -1;
|
|
|
|
pthread_mutex_lock(&sshfs.lock);
|
|
- req = (struct request *)
|
|
- g_hash_table_lookup(sshfs.reqtab, GUINT_TO_POINTER(id));
|
|
+ req = request_table_lookup(&sshfs.reqtab, id);
|
|
if (req == NULL)
|
|
fprintf(stderr, "request %i not found\n", id);
|
|
else {
|
|
@@ -1343,7 +1368,7 @@ static int process_one_request(void)
|
|
sshfs.outstanding_len <= sshfs.max_outstanding_len) {
|
|
pthread_cond_broadcast(&sshfs.outstanding_cond);
|
|
}
|
|
- g_hash_table_remove(sshfs.reqtab, GUINT_TO_POINTER(id));
|
|
+ request_table_remove(&sshfs.reqtab, id);
|
|
}
|
|
pthread_mutex_unlock(&sshfs.lock);
|
|
if (req != NULL) {
|
|
@@ -1404,6 +1429,9 @@ static void close_conn(void)
|
|
|
|
static void *process_requests(void *data_)
|
|
{
|
|
+ int i;
|
|
+ struct request *req;
|
|
+
|
|
(void) data_;
|
|
|
|
while (1) {
|
|
@@ -1414,7 +1442,20 @@ static void *process_requests(void *data_)
|
|
pthread_mutex_lock(&sshfs.lock);
|
|
sshfs.processing_thread_started = 0;
|
|
close_conn();
|
|
- g_hash_table_foreach_remove(sshfs.reqtab, (GHRFunc) clean_req, NULL);
|
|
+ for (i = 0; i < sshfs.reqtab.len; ++i) {
|
|
+ if (sshfs.reqtab.entries[i].next & 1)
|
|
+ continue;
|
|
+ req = sshfs.reqtab.entries[i].req;
|
|
+ req->error = -EIO;
|
|
+ if (req->want_reply)
|
|
+ sem_post(&req->ready);
|
|
+ else {
|
|
+ if (req->end_func)
|
|
+ req->end_func(req);
|
|
+ request_free(req);
|
|
+ }
|
|
+ request_table_remove(&sshfs.reqtab, i + 1);
|
|
+ }
|
|
sshfs.connver ++;
|
|
sshfs.outstanding_len = 0;
|
|
pthread_cond_broadcast(&sshfs.outstanding_cond);
|
|
@@ -1562,7 +1603,6 @@ static int sftp_error_to_errno(uint32_t error)
|
|
static void sftp_detect_uid()
|
|
{
|
|
int flags;
|
|
- uint32_t id = sftp_get_id();
|
|
uint32_t replid;
|
|
uint8_t type;
|
|
struct buffer buf;
|
|
@@ -1572,7 +1612,7 @@ static void sftp_detect_uid()
|
|
buf_init(&buf, 5);
|
|
buf_add_string(&buf, ".");
|
|
buf_to_iov(&buf, &iov[0]);
|
|
- if (sftp_send_iov(SSH_FXP_STAT, id, iov, 1) == -1)
|
|
+ if (sftp_send_iov(SSH_FXP_STAT, 0, iov, 1) == -1)
|
|
goto out;
|
|
buf_clear(&buf);
|
|
if (sftp_read(&type, &buf) == -1)
|
|
@@ -1583,7 +1623,7 @@ static void sftp_detect_uid()
|
|
}
|
|
if (buf_get_uint32(&buf, &replid) == -1)
|
|
goto out;
|
|
- if (replid != id) {
|
|
+ if (replid != 0) {
|
|
fprintf(stderr, "bad reply ID\n");
|
|
goto out;
|
|
}
|
|
@@ -1618,7 +1658,6 @@ out:
|
|
static int sftp_check_root(const char *base_path)
|
|
{
|
|
int flags;
|
|
- uint32_t id = sftp_get_id();
|
|
uint32_t replid;
|
|
uint8_t type;
|
|
struct buffer buf;
|
|
@@ -1630,7 +1669,7 @@ static int sftp_check_root(const char *base_path)
|
|
buf_init(&buf, 0);
|
|
buf_add_string(&buf, remote_dir);
|
|
buf_to_iov(&buf, &iov[0]);
|
|
- if (sftp_send_iov(SSH_FXP_LSTAT, id, iov, 1) == -1)
|
|
+ if (sftp_send_iov(SSH_FXP_LSTAT, 0, iov, 1) == -1)
|
|
goto out;
|
|
buf_clear(&buf);
|
|
if (sftp_read(&type, &buf) == -1)
|
|
@@ -1641,7 +1680,7 @@ static int sftp_check_root(const char *base_path)
|
|
}
|
|
if (buf_get_uint32(&buf, &replid) == -1)
|
|
goto out;
|
|
- if (replid != id) {
|
|
+ if (replid != 0) {
|
|
fprintf(stderr, "bad reply ID\n");
|
|
goto out;
|
|
}
|
|
@@ -1831,7 +1870,6 @@ static int sftp_request_send(uint8_t type, struct iovec *iov, size_t count,
|
|
struct request **reqp)
|
|
{
|
|
int err;
|
|
- uint32_t id;
|
|
struct request *req = g_new0(struct request, 1);
|
|
|
|
req->want_reply = want_reply;
|
|
@@ -1842,8 +1880,6 @@ static int sftp_request_send(uint8_t type, struct iovec *iov, size_t count,
|
|
pthread_mutex_lock(&sshfs.lock);
|
|
if (begin_func)
|
|
begin_func(req);
|
|
- id = sftp_get_id();
|
|
- req->id = id;
|
|
err = start_processing_thread();
|
|
if (err) {
|
|
pthread_mutex_unlock(&sshfs.lock);
|
|
@@ -1854,21 +1890,24 @@ static int sftp_request_send(uint8_t type, struct iovec *iov, size_t count,
|
|
while (sshfs.outstanding_len > sshfs.max_outstanding_len)
|
|
pthread_cond_wait(&sshfs.outstanding_cond, &sshfs.lock);
|
|
|
|
- g_hash_table_insert(sshfs.reqtab, GUINT_TO_POINTER(id), req);
|
|
+ if (request_table_insert(&sshfs.reqtab, req) < 0)
|
|
+ abort();
|
|
if (sshfs.debug) {
|
|
gettimeofday(&req->start, NULL);
|
|
sshfs.num_sent++;
|
|
sshfs.bytes_sent += req->len;
|
|
}
|
|
- DEBUG("[%05i] %s\n", id, type_name(type));
|
|
+ DEBUG("[%05i] %s\n", req->id, type_name(type));
|
|
pthread_mutex_unlock(&sshfs.lock);
|
|
|
|
err = -EIO;
|
|
- if (sftp_send_iov(type, id, iov, count) == -1) {
|
|
+ if (sftp_send_iov(type, req->id, iov, count) == -1) {
|
|
gboolean rmed;
|
|
|
|
pthread_mutex_lock(&sshfs.lock);
|
|
- rmed = g_hash_table_remove(sshfs.reqtab, GUINT_TO_POINTER(id));
|
|
+ rmed = !!request_table_lookup(&sshfs.reqtab, req->id);
|
|
+ if (rmed)
|
|
+ request_table_remove(&sshfs.reqtab, req->id);
|
|
pthread_mutex_unlock(&sshfs.lock);
|
|
|
|
if (!rmed && !want_reply) {
|
|
@@ -2041,7 +2080,7 @@ static int sftp_readdir_send(struct request **req, struct buffer *handle)
|
|
|
|
static int sshfs_req_pending(struct request *req)
|
|
{
|
|
- if (g_hash_table_lookup(sshfs.reqtab, GUINT_TO_POINTER(req->id)))
|
|
+ if (request_table_lookup(&sshfs.reqtab, req->id))
|
|
return 1;
|
|
else
|
|
return 0;
|
|
@@ -3312,11 +3351,6 @@ static int processing_init(void)
|
|
pthread_mutex_init(&sshfs.lock, NULL);
|
|
pthread_mutex_init(&sshfs.lock_write, NULL);
|
|
pthread_cond_init(&sshfs.outstanding_cond, NULL);
|
|
- sshfs.reqtab = g_hash_table_new(NULL, NULL);
|
|
- if (!sshfs.reqtab) {
|
|
- fprintf(stderr, "failed to create hash table\n");
|
|
- return -1;
|
|
- }
|
|
return 0;
|
|
}
|
|
|
|
--
|
|
2.24.0
|
|
|