-
Notifications
You must be signed in to change notification settings - Fork 41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
libkmod: Improve index dump performance #250
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -810,22 +810,37 @@ | |
|
||
KMOD_EXPORT int kmod_dump_index(struct kmod_ctx *ctx, enum kmod_index type, int fd) | ||
{ | ||
int err = 0, fd2; | ||
FILE *fp; | ||
|
||
if (ctx == NULL) | ||
return -ENOSYS; | ||
|
||
fd2 = dup(fd); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AFAICT libraries should really be using CLOEXEC, aka There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
if (fd2 == -1) | ||
return -errno; | ||
fp = fdopen(fd2, "ae"); | ||
if (fp == NULL) { | ||
err = -errno; | ||
close(fd2); | ||
return err; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's move all the whole dup/fdopen hunk after all the input validation - aka after the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would adjust it if we decide if it's even worth it:
So ... let's see. I wouldn't mind keeping everything as it is right now and, if we ever adjust the API in a release, reconsider turning it FILE-based. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
My slight inclination towards a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I second that. What we could have is one additional API that receives a FILE* as argument.... we are not really going to change the API and break users because of this. However if we add the new API, then we don't drop the old code since converting it to use FILE* would mean to lose EINTR handling. So.... I'm leaning towards the wbuf approach. |
||
} | ||
|
||
#if defined(__clang__) | ||
#pragma clang diagnostic push | ||
#pragma clang diagnostic ignored "-Wtautological-unsigned-enum-zero-compare" | ||
#endif | ||
if (type < 0 || type >= _KMOD_INDEX_MODULES_SIZE) | ||
return -ENOENT; | ||
if (type < 0 || type >= _KMOD_INDEX_MODULES_SIZE) { | ||
err = -ENOENT; | ||
goto done; | ||
} | ||
#if defined(__clang__) | ||
#pragma clang diagnostic pop | ||
#endif | ||
|
||
if (ctx->indexes[type] != NULL) { | ||
DBG(ctx, "use mmapped index '%s'\n", index_files[type].fn); | ||
index_mm_dump(ctx->indexes[type], fd, index_files[type].alias_prefix); | ||
index_mm_dump(ctx->indexes[type], fp, index_files[type].alias_prefix); | ||
} else { | ||
char fn[PATH_MAX]; | ||
struct index_file *idx; | ||
|
@@ -835,14 +850,18 @@ | |
DBG(ctx, "file=%s\n", fn); | ||
|
||
idx = index_file_open(fn); | ||
if (idx == NULL) | ||
return -ENOSYS; | ||
if (idx == NULL) { | ||
err = -ENOSYS; | ||
goto done; | ||
} | ||
|
||
index_dump(idx, fd, index_files[type].alias_prefix); | ||
index_dump(idx, fp, index_files[type].alias_prefix); | ||
index_file_close(idx); | ||
} | ||
|
||
return 0; | ||
done: | ||
fclose(fp); | ||
return err; | ||
} | ||
|
||
const struct kmod_config *kmod_get_config(const struct kmod_ctx *ctx) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -237,32 +237,6 @@ ssize_t read_str_safe(int fd, char *buf, size_t buflen) | |
return done; | ||
} | ||
|
||
ssize_t write_str_safe(int fd, const char *buf, size_t buflen) | ||
{ | ||
size_t todo = buflen; | ||
size_t done = 0; | ||
|
||
assert_cc(EAGAIN == EWOULDBLOCK); | ||
|
||
do { | ||
ssize_t r = write(fd, buf + done, todo); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why did we remove the helper instead of adapting it to use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The problem with FILE output is that I mistakenly believed that FILE itself handles short writes, but I was wrong. So if we want to keep interrupt-safe writes, we cannot use FILE here. At best, we would adjust the API, but ... Not in a simple PR. :) |
||
|
||
if (r == 0) | ||
break; | ||
else if (r > 0) { | ||
todo -= r; | ||
done += r; | ||
} else { | ||
if (errno == EAGAIN || errno == EINTR) | ||
continue; | ||
else | ||
return -errno; | ||
} | ||
} while (todo > 0); | ||
|
||
return done; | ||
} | ||
|
||
int read_str_long(int fd, long *value, int base) | ||
{ | ||
char buf[32], *end; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of curiosity: have you tried placing the contents into a buffer (on the stack) and doing a single write for given value instead of 4? Does it make a difference?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This already helps by almost 50 %, which is nice. At first I tried scratchbuf (and soon strbuf), but we could also keep a buffer around for longer. See #252 as an example.