summaryrefslogtreecommitdiff
path: root/extstore.c
diff options
context:
space:
mode:
authordormando <dormando@rydia.net>2020-11-10 22:20:10 -0800
committerdormando <dormando@rydia.net>2020-11-11 21:23:35 -0800
commit2251d98cd7ecb7dd4b2f58fe9b97f5799eb39edc (patch)
tree089383cc7b09fdf7b98e778b354ce612200cf8bd /extstore.c
parent19aac5aeca5aaf588dc58d5c04264c6be14ff7c0 (diff)
downloadmemcached-2251d98cd7ecb7dd4b2f58fe9b97f5799eb39edc.tar.gz
extstore: use fcntl locking on disk file
if you accidentally start memcached with the same options twice, extstore is initiated before the listener sockets and will happily truncate its own file. So this avoids that. Keep in mind any other process can still wipe the file clean!
Diffstat (limited to 'extstore.c')
-rw-r--r--extstore.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/extstore.c b/extstore.c
index 9e2a981..8f32f51 100644
--- a/extstore.c
+++ b/extstore.c
@@ -253,15 +253,32 @@ void *extstore_init(struct extstore_conf_file *fh, struct extstore_conf *cf,
e->page_size = cf->page_size;
uint64_t temp_page_count = 0;
for (f = fh; f != NULL; f = f->next) {
- f->fd = open(f->file, O_RDWR | O_CREAT | O_TRUNC, 0644);
+ f->fd = open(f->file, O_RDWR | O_CREAT, 0644);
if (f->fd < 0) {
*res = EXTSTORE_INIT_OPEN_FAIL;
#ifdef EXTSTORE_DEBUG
- perror("open");
+ perror("extstore open");
#endif
free(e);
return NULL;
}
+ // use an fcntl lock to help avoid double starting.
+ struct flock lock;
+ lock.l_type = F_WRLCK;
+ lock.l_start = 0;
+ lock.l_whence = SEEK_SET;
+ lock.l_len = 0;
+ if (fcntl(f->fd, F_SETLK, &lock) < 0) {
+ *res = EXTSTORE_INIT_OPEN_FAIL;
+ free(e);
+ return NULL;
+ }
+ if (ftruncate(f->fd, 0) < 0) {
+ *res = EXTSTORE_INIT_OPEN_FAIL;
+ free(e);
+ return NULL;
+ }
+
temp_page_count += f->page_count;
f->offset = 0;
}