diff options
author | Ed Maste <emaste@FreeBSD.org> | 2015-06-29 13:48:44 +0000 |
---|---|---|
committer | Ed Maste <emaste@FreeBSD.org> | 2015-06-29 13:48:44 +0000 |
commit | 01715d8cd1e8e4591f7001a16e2c5badd5f34c99 (patch) | |
tree | 76a467440be53d306171b628d26cf158b2abeaf5 /usr.bin/ar | |
parent | 521987c3e5762f23ee273af85f4b2edbdd1acdfa (diff) | |
download | src-test2-01715d8cd1e8e4591f7001a16e2c5badd5f34c99.tar.gz src-test2-01715d8cd1e8e4591f7001a16e2c5badd5f34c99.zip |
Notes
Diffstat (limited to 'usr.bin/ar')
-rw-r--r-- | usr.bin/ar/write.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/usr.bin/ar/write.c b/usr.bin/ar/write.c index 9ce18069487a..10b912ec2b1a 100644 --- a/usr.bin/ar/write.c +++ b/usr.bin/ar/write.c @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include <stdlib.h> #include <string.h> #include <sysexits.h> +#include <unistd.h> #include "ar.h" @@ -61,6 +62,7 @@ static void create_symtab_entry(struct bsdar *bsdar, void *maddr, static void free_obj(struct bsdar *bsdar, struct ar_obj *obj); static void insert_obj(struct bsdar *bsdar, struct ar_obj *obj, struct ar_obj *pos); +static void prefault_buffer(const char *buf, size_t s); static void read_objs(struct bsdar *bsdar, const char *archive, int checkargv); static void write_archive(struct bsdar *bsdar, char mode); @@ -551,11 +553,35 @@ write_cleanup(struct bsdar *bsdar) } /* + * Fault in the buffer prior to writing as a workaround for poor performance + * due to interaction with kernel fs deadlock avoidance code. See the comment + * above vn_io_fault_doio() in sys/kern/vfs_vnops.c for details of the issue. + */ +static void +prefault_buffer(const char *buf, size_t s) +{ + volatile const char *p; + size_t page_size; + + if (s == 0) + return; + page_size = sysconf(_SC_PAGESIZE); + for (p = buf; p < buf + s; p += page_size) + *p; + /* + * Ensure we touch the last page as well, in case the buffer is not + * page-aligned. + */ + *(volatile const char *)(buf + s - 1); +} + +/* * Wrapper for archive_write_data(). */ static void write_data(struct bsdar *bsdar, struct archive *a, const void *buf, size_t s) { + prefault_buffer(buf, s); if (archive_write_data(a, buf, s) != (ssize_t)s) bsdar_errc(bsdar, EX_SOFTWARE, 0, "%s", archive_error_string(a)); |