#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
+#ifndef _DEFAULT_SOURCE
+#define _DEFAULT_SOURCE /* since glibc 2.20 _SVID_SOURCE is deprecated */
+#endif
#include "config.h"
#define O_DIRECT 0
#endif
+#if __GNUC_PREREQ (4, 6)
+#pragma GCC diagnostic push
+#ifndef CONFIG_MMP
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+#endif
+
errcode_t ext2fs_mmp_read(ext2_filsys fs, blk64_t mmp_blk, void *buf)
{
#ifdef CONFIG_MMP
* regardless of how the io_manager is doing reads, to avoid caching of
* the MMP block by the io_manager or the VM. It needs to be fresh. */
if (fs->mmp_fd <= 0) {
- fs->mmp_fd = open(fs->device_name, O_RDWR | O_DIRECT);
+ int flags = O_RDWR | O_DIRECT;
+
+retry:
+ fs->mmp_fd = open(fs->device_name, flags);
if (fs->mmp_fd < 0) {
+ struct stat st;
+
+ /* Avoid O_DIRECT for filesystem image files if open
+ * fails, since it breaks when running on tmpfs. */
+ if (errno == EINVAL && (flags & O_DIRECT) &&
+ stat(fs->device_name, &st) == 0 &&
+ S_ISREG(st.st_mode)) {
+ flags &= ~O_DIRECT;
+ goto retry;
+ }
retval = EXT2_ET_MMP_OPEN_DIRECT;
goto out;
}
#define rand() random()
#endif
-unsigned ext2fs_mmp_new_seq()
+unsigned ext2fs_mmp_new_seq(void)
{
#ifdef CONFIG_MMP
unsigned new_seq;
#endif
}
+#ifdef CONFIG_MMP
static errcode_t ext2fs_mmp_reset(ext2_filsys fs)
{
struct mmp_struct *mmp_s = NULL;
mmp_s->mmp_magic = EXT4_MMP_MAGIC;
mmp_s->mmp_seq = EXT4_MMP_SEQ_CLEAN;
mmp_s->mmp_time = 0;
-#if _BSD_SOURCE || _XOPEN_SOURCE >= 500
+#ifdef HAVE_GETHOSTNAME
gethostname(mmp_s->mmp_nodename, sizeof(mmp_s->mmp_nodename));
#else
mmp_s->mmp_nodename[0] = '\0';
out:
return retval;
}
+#endif
errcode_t ext2fs_mmp_update(ext2_filsys fs)
{
#endif
}
+#ifndef min
+#define min(x, y) ((x) < (y) ? (x) : (y))
+#endif
+
/*
* Make sure that the fs is not mounted or being fsck'ed while opening the fs.
*/
if (mmp_s->mmp_check_interval > mmp_check_interval)
mmp_check_interval = mmp_s->mmp_check_interval;
- sleep(2 * mmp_check_interval + 1);
+ sleep(min(mmp_check_interval * 2 + 1, mmp_check_interval + 60));
retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, fs->mmp_buf);
if (retval)
goto mmp_error;
mmp_s->mmp_seq = seq = ext2fs_mmp_new_seq();
-#if _BSD_SOURCE || _XOPEN_SOURCE >= 500
+#ifdef HAVE_GETHOSTNAME
gethostname(mmp_s->mmp_nodename, sizeof(mmp_s->mmp_nodename));
#else
strcpy(mmp_s->mmp_nodename, "unknown host");
if (retval)
goto mmp_error;
- sleep(2 * mmp_check_interval + 1);
+ sleep(min(2 * mmp_check_interval + 1, mmp_check_interval + 60));
retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, fs->mmp_buf);
if (retval)
struct mmp_struct *mmp, *mmp_cmp;
errcode_t retval = 0;
- if (!(fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) ||
+ if (!ext2fs_has_feature_mmp(fs->super) ||
!(fs->flags & EXT2_FLAG_RW) || (fs->flags & EXT2_FLAG_SKIP_MMP))
goto mmp_error;
return retval;
#else
+ if (!ext2fs_has_feature_mmp(fs->super) ||
+ !(fs->flags & EXT2_FLAG_RW) || (fs->flags & EXT2_FLAG_SKIP_MMP))
+ return 0;
+
return EXT2_ET_OP_NOT_SUPPORTED;
#endif
}
struct timeval tv;
errcode_t retval = 0;
- if (!(fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) ||
+ if (!ext2fs_has_feature_mmp(fs->super) ||
!(fs->flags & EXT2_FLAG_RW) || (fs->flags & EXT2_FLAG_SKIP_MMP))
return 0;
mmp_error:
return retval;
#else
+ if (!ext2fs_has_feature_mmp(fs->super) ||
+ !(fs->flags & EXT2_FLAG_RW) || (fs->flags & EXT2_FLAG_SKIP_MMP))
+ return 0;
+
return EXT2_ET_OP_NOT_SUPPORTED;
#endif
}
+#if __GNUC_PREREQ (4, 6)
+#pragma GCC diagnostic pop
+#endif