This patch adds nilfs_sb_write to modify super blocks. To modify a part of both super blocks, it first reads both super blocks then copys fields specified as "mask". To read the super blocks, new functions nilfs_sb_read and __nilfs_sb_read are introduced. __nilfs_sb_read reads both super blocks and returns both super blocks. nilfs_sb_read calls __nilfs_sb_read and returns effective super block out of two super blocks. nilfs_read_sb now calls nilfs_sb_read to read super block. Signed-off-by: Jiro SEKIBA <jir@xxxxxxxxx> --- include/nilfs.h | 7 +++ lib/nilfs.c | 16 +++++++ lib/sb.c | 125 +++++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 113 insertions(+), 35 deletions(-) diff --git a/include/nilfs.h b/include/nilfs.h index 5feac85..8a83dd3 100644 --- a/include/nilfs.h +++ b/include/nilfs.h @@ -94,6 +94,10 @@ typedef __u64 nilfs_cno_t; #define NILFS_CNO_MIN ((nilfs_cno_t)1) #define NILFS_CNO_MAX (~(nilfs_cno_t)0) +#define NILFS_SB_LABEL 0x0001 +#define NILFS_SB_UUID 0x0002 +#define NILFS_SB_COMMIT_INTERVAL 0x4000 +#define NILFS_SB_BLOCK_MAX 0x8000 /** * struct nilfs - nilfs object @@ -287,6 +291,9 @@ static inline int nilfs_block_is_node(const struct nilfs_block *blk) #define NILFS_SB_BLOCK_SIZE_SHIFT 10 +struct nilfs_super_block *nilfs_sb_read(int devfd); +int nilfs_sb_write(int devfd, struct nilfs_super_block *sbp, int mask); + int nilfs_read_sb(struct nilfs *); ssize_t nilfs_get_segment(struct nilfs *, unsigned long, void **); diff --git a/lib/nilfs.c b/lib/nilfs.c index 44e368b..19bf6e4 100644 --- a/lib/nilfs.c +++ b/lib/nilfs.c @@ -939,3 +939,19 @@ nilfs_cno_t nilfs_get_oldest_cno(struct nilfs *nilfs) nilfs_get_cpinfo(nilfs, nilfs->n_mincno, NILFS_CHECKPOINT, cpinfo, 1); return nilfs->n_mincno; } + +struct nilfs_super_block *nilfs_get_sb(struct nilfs *nilfs) +{ + return nilfs->n_sb; +} + +int nilfs_read_sb(struct nilfs *nilfs) +{ + assert(nilfs->n_sb == NULL); + + nilfs->n_sb = nilfs_sb_read(nilfs->n_devfd); + if (!nilfs->n_sb) + return -1; + + return 0; +} diff --git a/lib/sb.c b/lib/sb.c index ae10e55..c7c50d7 100644 --- a/lib/sb.c +++ b/lib/sb.c @@ -36,6 +36,10 @@ #include <stdlib.h> #endif /* HAVE_STDLIB_H */ +#if HAVE_STRING_H +#include <string.h> +#endif /* HAVE_STRING_H */ + #if HAVE_UNISTD_H #include <unistd.h> #endif /* HAVE_UNISTD_H */ @@ -68,15 +72,22 @@ #define NILFS_MAX_SB_SIZE 1024 -struct nilfs_super_block *nilfs_get_sb(struct nilfs *nilfs) +static __u32 nilfs_sb_check_sum(struct nilfs_super_block *sbp) { - return nilfs->n_sb; + __u32 seed, crc; + __le32 sum; + + seed = le32_to_cpu(sbp->s_crc_seed); + sum = sbp->s_sum; + sbp->s_sum = 0; + crc = crc32_le(seed, (unsigned char *)sbp, le16_to_cpu(sbp->s_bytes)); + sbp->s_sum = sum; + return crc; } static int nilfs_sb_is_valid(struct nilfs_super_block *sbp, int check_crc) { - __le32 sum; - __u32 seed, crc; + __u32 crc; if (le16_to_cpu(sbp->s_magic) != NILFS_SUPER_MAGIC) return 0; @@ -85,39 +96,39 @@ static int nilfs_sb_is_valid(struct nilfs_super_block *sbp, int check_crc) if (!check_crc) return 1; - seed = le32_to_cpu(sbp->s_crc_seed); - sum = sbp->s_sum; - sbp->s_sum = 0; - crc = crc32_le(seed, (unsigned char *)sbp, le16_to_cpu(sbp->s_bytes)); - sbp->s_sum = sum; - return crc == le32_to_cpu(sum); + crc = nilfs_sb_check_sum(sbp); + + return crc == le32_to_cpu(sbp->s_sum); } -int nilfs_read_sb(struct nilfs *nilfs) +static int __nilfs_sb_read(int devfd, struct nilfs_super_block **sbp, + __u64 *offsets) { - struct nilfs_super_block *sbp[2]; __u64 devsize, sb2_offset; - assert(nilfs->n_sb == NULL); - sbp[0] = malloc(NILFS_MAX_SB_SIZE); sbp[1] = malloc(NILFS_MAX_SB_SIZE); if (sbp[0] == NULL || sbp[1] == NULL) goto failed; - if (ioctl(nilfs->n_devfd, BLKGETSIZE64, &devsize) != 0) + if (ioctl(devfd, BLKGETSIZE64, &devsize) != 0) goto failed; - if (lseek64(nilfs->n_devfd, NILFS_SB_OFFSET_BYTES, SEEK_SET) < 0 || - read(nilfs->n_devfd, sbp[0], NILFS_MAX_SB_SIZE) < 0 || + if (lseek64(devfd, NILFS_SB_OFFSET_BYTES, SEEK_SET) < 0 || + read(devfd, sbp[0], NILFS_MAX_SB_SIZE) < 0 || !nilfs_sb_is_valid(sbp[0], 0)) { free(sbp[0]); sbp[0] = NULL; } sb2_offset = NILFS_SB2_OFFSET_BYTES(devsize); - if (lseek64(nilfs->n_devfd, sb2_offset, SEEK_SET) < 0 || - read(nilfs->n_devfd, sbp[1], NILFS_MAX_SB_SIZE) < 0 || + if (offsets) { + offsets[0] = NILFS_SB_OFFSET_BYTES; + offsets[1] = sb2_offset; + } + + if (lseek64(devfd, sb2_offset, SEEK_SET) < 0 || + read(devfd, sbp[1], NILFS_MAX_SB_SIZE) < 0 || !nilfs_sb_is_valid(sbp[1], 0)) goto sb2_failed; @@ -129,22 +140,7 @@ int nilfs_read_sb(struct nilfs *nilfs) goto sb2_failed; sb2_done: - if (!sbp[0]) { - sbp[0] = sbp[1]; - sbp[1] = NULL; - } - -#if 0 - if (sbp[1] && - le64_to_cpu(sbp[1]->s_wtime) > le64_to_cpu(sbp[0]->s_wtime)) { - nilfs->n_sb = sbp[1]; - free(sbp[0]); - } else -#endif - if (sbp[0]) { - nilfs->n_sb = sbp[0]; - free(sbp[1]); - } else + if (!sbp[0] && !sbp[1]) goto failed; return 0; @@ -159,3 +155,62 @@ int nilfs_read_sb(struct nilfs *nilfs) sbp[1] = NULL; goto sb2_done; } + +struct nilfs_super_block *nilfs_sb_read(int devfd) +{ + struct nilfs_super_block *sbp[2]; + + if (__nilfs_sb_read(devfd, sbp, NULL)) + return -1; + + if (!sbp[0]) { + sbp[0] = sbp[1]; + sbp[1] = NULL; + } + + free(sbp[1]); + + return sbp[0]; +} + +int nilfs_sb_write(int devfd, struct nilfs_super_block *sbp, int mask) +{ + __u64 offsets[2]; + struct nilfs_super_block *sbps[2]; + int i; + __u32 crc; + + assert(devfd != 0); + + if (__nilfs_sb_read(devfd, sbps, offsets)) + return -1; + + for (i=0;i<2;i++) { + if (!sbps[i]) + continue; + + if (mask & NILFS_SB_LABEL) + memcpy(sbps[i]->s_volume_name, + sbp->s_volume_name, sizeof(sbp->s_volume_name)); + + if (mask & NILFS_SB_COMMIT_INTERVAL) + sbps[i]->s_c_interval = sbp->s_c_interval; + + if (mask & NILFS_SB_BLOCK_MAX) + sbps[i]->s_c_block_max = sbp->s_c_block_max; + + if (mask & NILFS_SB_UUID) + memcpy(sbps[i]->s_uuid, sbp->s_uuid, + sizeof(sbp->s_uuid)); + + crc = nilfs_sb_check_sum(sbps[i]); + sbps[i]->s_sum = cpu_to_le32(crc); + if (lseek(devfd, offsets[i], SEEK_SET) > 0) + write(devfd, sbps[i], NILFS_MAX_SB_SIZE); + } + + free(sbps[0]); + free(sbps[1]); + + return 0; +} -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html