fsck.f2fs: trigger fsck.f2fs when new change was made
This patch remains user specified triggering information in superblock.
Then, if the information was changed, fsck.f2fs is triggered.
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
diff --git a/fsck/mount.c b/fsck/mount.c
index 9a9c842..37bd8c7 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -133,6 +133,7 @@
DISP_u32(sb, node_ino);
DISP_u32(sb, meta_ino);
DISP_u32(sb, cp_payload);
+ DISP("%s", sb, version);
printf("\n");
}
@@ -225,6 +226,7 @@
int validate_super_block(struct f2fs_sb_info *sbi, int block)
{
u64 offset;
+
sbi->raw_super = malloc(sizeof(struct f2fs_super_block));
if (block == 0)
@@ -235,8 +237,35 @@
if (dev_read(sbi->raw_super, offset, sizeof(struct f2fs_super_block)))
return -1;
- if (!sanity_check_raw_super(sbi->raw_super))
+ if (!sanity_check_raw_super(sbi->raw_super)) {
+ /* get kernel version */
+ if (config.kd >= 0) {
+ dev_read_version(config.version, 0, VERSION_LEN);
+ get_kernel_version(config.version);
+ } else {
+ memset(config.version, 0, VERSION_LEN);
+ }
+
+ /* build sb version */
+ memcpy(config.sb_version, sbi->raw_super->version, VERSION_LEN);
+ get_kernel_version(config.sb_version);
+
+ MSG(0, "Info: FSCK version\n from \"%s\"\n to \"%s\"\n",
+ config.sb_version, config.version);
+ if (memcmp(config.sb_version, config.version, VERSION_LEN)) {
+ int ret;
+
+ memcpy(sbi->raw_super->version,
+ config.version, VERSION_LEN);
+ ret = dev_write(sbi->raw_super, offset,
+ sizeof(struct f2fs_super_block));
+ ASSERT(ret >= 0);
+
+ config.auto_fix = 0;
+ config.fix_on = 1;
+ }
return 0;
+ }
free(sbi->raw_super);
MSG(0, "\tCan't find a valid F2FS superblock at 0x%x\n", block);
diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
index b02002c..0ec9ee7 100644
--- a/include/f2fs_fs.h
+++ b/include/f2fs_fs.h
@@ -216,6 +216,8 @@
#define DEFAULT_BLOCKS_PER_SEGMENT 512
#define DEFAULT_SEGMENTS_PER_SECTION 1
+#define VERSION_LEN 256
+
enum f2fs_config_func {
FSCK,
DUMP,
@@ -232,9 +234,11 @@
u_int64_t total_sectors;
u_int32_t sectors_per_blk;
u_int32_t blks_per_seg;
+ __u8 sb_version[VERSION_LEN + 1];
+ __u8 version[VERSION_LEN + 1];
char *vol_label;
int heap;
- int32_t fd;
+ int32_t fd, kd;
int32_t dump_fd;
char *device_name;
char *extension_list;
@@ -345,6 +349,7 @@
__le32 extension_count; /* # of extensions below */
__u8 extension_list[F2FS_MAX_EXTENSION][8]; /* extension array */
__le32 cp_payload;
+ __u8 version[VERSION_LEN]; /* the kernel version */
} __attribute__((packed));
/*
@@ -773,6 +778,8 @@
extern int dev_read_block(void *, __u64);
extern int dev_read_blocks(void *, __u64, __u32 );
+extern int dev_read_version(void *, __u64, size_t);
+extern void get_kernel_version(__u8 *);
f2fs_hash_t f2fs_dentry_hash(const unsigned char *, int);
extern struct f2fs_configuration config;
diff --git a/lib/libf2fs.c b/lib/libf2fs.c
index 73c551b..14e4164 100644
--- a/lib/libf2fs.c
+++ b/lib/libf2fs.c
@@ -418,6 +418,16 @@
return 0;
}
+void get_kernel_version(__u8 *version)
+{
+ int i;
+ for (i = 0; i < VERSION_LEN; i++) {
+ if (version[i] == '\n')
+ break;
+ }
+ memset(version + i, 0, VERSION_LEN + 1 - i);
+}
+
int f2fs_get_device_info(struct f2fs_configuration *c)
{
int32_t fd = 0;
@@ -436,6 +446,10 @@
}
c->fd = fd;
+ c->kd = open("/proc/version", O_RDONLY);
+ if (c->kd < 0)
+ MSG(0, "\tInfo: No support kernel version!\n");
+
if (fstat(fd, &stat_buf) < 0 ) {
MSG(0, "\tError: Failed to get the device stat!\n");
return -1;
diff --git a/lib/libf2fs_io.c b/lib/libf2fs_io.c
index 0c89ee4..6ed45fd 100644
--- a/lib/libf2fs_io.c
+++ b/lib/libf2fs_io.c
@@ -28,6 +28,15 @@
/*
* IO interfaces
*/
+int dev_read_version(void *buf, __u64 offset, size_t len)
+{
+ if (lseek64(config.kd, (off64_t)offset, SEEK_SET) < 0)
+ return -1;
+ if (read(config.kd, buf, len) < 0)
+ return -1;
+ return 0;
+}
+
int dev_read(void *buf, __u64 offset, size_t len)
{
if (lseek64(config.fd, (off64_t)offset, SEEK_SET) < 0)
@@ -93,4 +102,6 @@
if (close(c->fd) < 0)
MSG(0, "\tError: Failed to close device file!!!\n");
+
+ close(c->kd);
}