fix sync writes - don't use O_EXCL

This commit is contained in:
Kent Overstreet 2017-05-05 00:27:01 -08:00
parent 5db58a0bae
commit e004b95b88
5 changed files with 98 additions and 72 deletions

View File

@ -129,10 +129,10 @@ int cmd_dump(int argc, char *argv[])
BUG_ON(!nr_devices);
for_each_online_member(ca, c, i) {
int mode = O_WRONLY|O_CREAT|O_TRUNC;
int flags = O_WRONLY|O_CREAT|O_TRUNC;
if (!force)
mode |= O_EXCL;
flags |= O_EXCL;
if (!c->devs[i])
continue;
@ -140,7 +140,7 @@ int cmd_dump(int argc, char *argv[])
char *path = nr_devices > 1
? mprintf("%s.%u", out, i)
: strdup(out);
fd = xopen(path, mode, 0600);
fd = xopen(path, flags, 0600);
free(path);
dump_one_device(c, ca, fd);

View File

@ -79,7 +79,7 @@ static void usage(void)
" --no_passphrase Don't encrypt master encryption key\n"
" --error_action=(continue|readonly|panic)\n"
" Action to take on filesystem error\n"
" -l, --label=label\n"
" -L, --label=label\n"
" --uuid=uuid\n"
" -f, --force\n"
"\n"

View File

@ -167,15 +167,19 @@ struct block_device *blkdev_get_by_path(const char *path, fmode_t mode,
else if (mode & FMODE_WRITE)
flags = O_WRONLY;
#if 0
/* using O_EXCL doesn't work with opening twice for an O_SYNC fd: */
if (mode & FMODE_EXCL)
flags |= O_EXCL;
#endif
fd = open(path, flags);
if (fd < 0)
return ERR_PTR(-errno);
sync_fd = open(path, flags|O_SYNC);
if (fd < 0) {
if (sync_fd < 0) {
assert(0);
close(fd);
return ERR_PTR(-errno);
}

View File

@ -23,6 +23,87 @@
#include "tools-util.h"
#include "util.h"
void die(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
fputc('\n', stderr);
exit(EXIT_FAILURE);
}
char *mprintf(const char *fmt, ...)
{
va_list args;
char *str;
int ret;
va_start(args, fmt);
ret = vasprintf(&str, fmt, args);
va_end(args);
if (ret < 0)
die("insufficient memory");
return str;
}
void *xcalloc(size_t count, size_t size)
{
void *p = calloc(count, size);
if (!p)
die("insufficient memory");
return p;
}
void *xmalloc(size_t size)
{
void *p = malloc(size);
if (!p)
die("insufficient memory");
memset(p, 0, size);
return p;
}
void xpread(int fd, void *buf, size_t count, off_t offset)
{
ssize_t r = pread(fd, buf, count, offset);
if (r != count)
die("read error (ret %zi)", r);
}
void xpwrite(int fd, const void *buf, size_t count, off_t offset)
{
ssize_t r = pwrite(fd, buf, count, offset);
if (r != count)
die("write error (ret %zi err %m)", r);
}
struct stat xfstatat(int dirfd, const char *path, int flags)
{
struct stat stat;
if (fstatat(dirfd, path, &stat, flags))
die("stat error: %m");
return stat;
}
struct stat xfstat(int fd)
{
struct stat stat;
if (fstat(fd, &stat))
die("stat error: %m");
return stat;
}
/* Integer stuff: */
struct units_buf __pr_units(u64 v, enum units units)

View File

@ -17,57 +17,14 @@
#include <linux/types.h>
#include "ccan/darray/darray.h"
#define die(arg, ...) \
do { \
fprintf(stderr, arg "\n", ##__VA_ARGS__); \
exit(EXIT_FAILURE); \
} while (0)
#define mprintf(...) \
({ \
char *_str; \
int ret = asprintf(&_str, __VA_ARGS__); \
if (ret < 0) \
die("insufficient memory"); \
_str; \
})
static inline void *xcalloc(size_t count, size_t size)
{
void *p = calloc(count, size);
if (!p)
die("insufficient memory");
return p;
}
static inline void *xmalloc(size_t size)
{
void *p = malloc(size);
if (!p)
die("insufficient memory");
memset(p, 0, size);
return p;
}
static inline void xpread(int fd, void *buf, size_t count, off_t offset)
{
ssize_t r = pread(fd, buf, count, offset);
if (r != count)
die("read error (ret %zi)", r);
}
static inline void xpwrite(int fd, const void *buf, size_t count, off_t offset)
{
ssize_t r = pwrite(fd, buf, count, offset);
if (r != count)
die("write error (ret %zi err %m)", r);
}
void die(const char *, ...);
char *mprintf(const char *, ...);
void *xcalloc(size_t, size_t);
void *xmalloc(size_t);
void xpread(int, void *, size_t, off_t);
void xpwrite(int, const void *, size_t, off_t);
struct stat xfstatat(int, const char *, int);
struct stat xfstat(int);
#define xopenat(_dirfd, _path, ...) \
({ \
@ -79,22 +36,6 @@ static inline void xpwrite(int fd, const void *buf, size_t count, off_t offset)
#define xopen(...) xopenat(AT_FDCWD, __VA_ARGS__)
static inline struct stat xfstatat(int dirfd, const char *path, int flags)
{
struct stat stat;
if (fstatat(dirfd, path, &stat, flags))
die("stat error: %m");
return stat;
}
static inline struct stat xfstat(int fd)
{
struct stat stat;
if (fstat(fd, &stat))
die("stat error: %m");
return stat;
}
#define xioctl(_fd, _nr, ...) \
do { \
if (ioctl((_fd), (_nr), ##__VA_ARGS__)) \