[PATCHv2 1/2] nilfs2-utils: add nilfs_sb_write
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 copes 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 | 128 ++++++++++++++++++++++++++++++++++++++++---------------
3 files changed, 116 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..201b9ad 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,65 @@ 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 (sbp == NULL)
+ return -1;
+
+ 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
[Linux Filesystem; Devel]
[Linux CIFS]
[Linux USB Devel]
[Video for Linux]
[Linux Audio Users]
[Photo]
[Yosemite News]
[Yosemite Photos]
[Free Online Dating]
[Linux Kernel]
[Linux SCSI]
[XFree86]