Hi,

This patch adds nilfs_sb_read_unchecked() function for reading superblocks without checking. Moreover, it modifies nilfs_sb_is_valid() function with the purpose of making full superblock check in the future.

With the best regards,
Vyacheslav Dubeyko.
--
From: Vyacheslav Dubeyko <[email protected]>
Subject: [PATCH v2 6/7] nilfs-utils: fsck: add nilfs_sb_read_unchecked() and modify nilfs_sb_is_valid() functions

This patch adds nilfs_sb_read_unchecked() function for reading superblocks without checking. Moreover, it modifies nilfs_sb_is_valid() function with the purpose of making full superblock check in the future.

Signed-off-by: Vyacheslav Dubeyko <[email protected]>
---
diff --git a/lib/sb.c b/lib/sb.c
index 94bccaf..15190ca 100644
--- a/lib/sb.c
+++ b/lib/sb.c
@@ -30,6 +30,8 @@
 #include <stdlib.h>
 #endif /* HAVE_STDLIB_H */

+#include <stddef.h>
+
 #if HAVE_STRING_H
 #include <string.h>
 #endif /* HAVE_STRING_H */
@@ -63,6 +65,7 @@
 #include <errno.h>
 #include <assert.h>
 #include "nilfs.h"
+#include "fsck_messages.h"

 #define NILFS_MAX_SB_SIZE      1024

@@ -81,20 +84,143 @@ static __u32 nilfs_sb_check_sum(struct nilfs_super_block *sbp)
        return crc;
 }

-static int nilfs_sb_is_valid(struct nilfs_super_block *sbp, int check_crc)
+/*
+ * nilfs_sb_is_valid - Check that superblock is valid.
+ * @sbp: pointer on superblock.
+ * @check_crc: is it necessary to check CRC?
+ * @err_code: pointer on returned error code.
+ *
+ * Return value:
+ * NILFS_TRUE - superblock is valid.
+ * NILFS_FALSE - superblock is in corrupted state.
+ *
+ * In the case of valid pointer the err_code can contain:
+ * 0 - no errors were detected.
+ * INVALID_NILFS_SIGNATURE - superblock contains invalid signature.
+ * INVALID_SB_SIZE - superblock contains incorrect size in bytes.
+ * UNSUPPORTED_SB_REV - unsupported revision of NILFS superblock.
+ * INVALID_CRC - Invalid checksum of superblock was detected.
+ */
+int nilfs_sb_is_valid(struct nilfs_super_block *sbp,
+                               int check_crc,
+                               int *err_code,
+                               int *err_severity)
 {
+       __u16 sb_size;
        __u32 crc;
+       int err = 0;
+       int is_sb_ok = NILFS_TRUE;
+       int severity = FS_INFO;
+
+       /* <TODO: need to implement full check> */
+
+       /* Check magic */
+       if (le16_to_cpu(sbp->s_magic) != NILFS_SUPER_MAGIC) {
+               is_sb_ok = NILFS_FALSE;
+               err = INVALID_NILFS_SIGNATURE;
+               severity = FS_WARNING;
+               goto end_check;
+       }

-       if (le16_to_cpu(sbp->s_magic) != NILFS_SUPER_MAGIC)
-               return 0;
-       if (le16_to_cpu(sbp->s_bytes) > NILFS_MAX_SB_SIZE)
-               return 0;
-       if (!check_crc)
-               return 1;
+       /* Check s_bytes: size of superblock excluding s_reserved */
+       sb_size = le16_to_cpu(sbp->s_bytes);
+       if (sb_size > sizeof(struct nilfs_super_block)) {
+               is_sb_ok = NILFS_FALSE;
+               err = INVALID_SB_SIZE;
+               severity = FS_CRITICAL_ERROR;
+               goto end_check;
+       } else if (sb_size <
+                       offsetof(struct nilfs_super_block, s_reserved)) {
+               is_sb_ok = NILFS_FALSE;
+               err = INVALID_SB_SIZE;
+               severity = FS_CRITICAL_ERROR;
+               goto end_check;
+       } else if (sb_size >
+                       offsetof(struct nilfs_super_block, s_reserved)) {
+               is_sb_ok = NILFS_FALSE;
+               err = UNSUPPORTED_SB_REV;
+               severity = FS_WARNING;
+               goto end_check;
+       }

-       crc = nilfs_sb_check_sum(sbp);
+       /* Check CRC of superblock */
+       if (check_crc) {
+               crc = nilfs_sb_check_sum(sbp);
+               is_sb_ok = (crc == le32_to_cpu(sbp->s_sum));
+               if (NILFS_FALSE == is_sb_ok) {
+                       err = INVALID_CRC;
+                       severity = FS_CRITICAL_ERROR;
+                       goto end_check;
+               }
+       }

-       return crc == le32_to_cpu(sbp->s_sum);
+       /* Check revision level */
+       /* <TODO: implement> */
+       /* Check s_feature_compat: compatible feature set */
+       /* <TODO: implement> */
+       /* Check s_feature_compat_ro: read-only compatible feature set */
+       /* <TODO: implement> */
+       /* Check s_feature_incompat: incompatible feature set */
+       /* <TODO: implement> */
+       /* Check s_flags: file system independent flags */
+       /* <TODO: implement> */
+       /* Check s_log_block_size: block size */
+       /* <TODO: implement> */
+       /* Check s_dev_size: block device size in bytes */
+       /* <TODO: implement> */
+       /* Check s_blocks_per_segment: number of blocks per full segment */
+       /* <TODO: implement> */
+       /* Check s_nsegments: number of segments in file system */
+       /* <TODO: implement> */
+       /* Check s_first_data_block */
+       /* <TODO: implement> */
+       /* Check s_r_segments_percentage */
+       /* <TODO: implement> */
+       /* Check s_last_cno: last checkpoint number */
+       /* <TODO: implement> */
+       /* Check s_last_pseg: start block of latest segment */
+       /* <TODO: implement> */
+       /* Check s_last_seq: segment that was written last */
+       /* <TODO: implement> */
+       /* Preliminary check s_free_blocks_count */
+       /* <TODO: implement> */
+       /* Check s_ctime, s_mtime, s_wtime */
+       /* <TODO: implement> */
+       /* Check s_mnt_count and s_max_mnt_count */
+       /* <TODO: implement> */
+       /* Check s_state: file system states */
+       /* <TODO: implement> */
+       /* Check s_errors */
+       /* <TODO: implement> */
+       /* Check s_lastcheck and s_checkinterval */
+       /* <TODO: implement> */
+       /* Check s_creator_os */
+       /* <TODO: implement> */
+       /* Check s_def_resuid and s_def_resgid */
+       /* <TODO: implement> */
+       /* Check s_first_ino: first user's file inode number */
+       /* <TODO: implement> */
+       /* Check s_inode_size */
+       /* <TODO: implement> */
+       /* Check s_dat_entry_size */
+       /* <TODO: implement> */
+       /* Check s_checkpoint_size */
+       /* <TODO: implement> */
+       /* Check s_segment_usage_size */
+       /* <TODO: implement> */
+       /* Check s_c_interval: commit interval of segment */
+       /* <TODO: implement> */
+       /* Check s_c_block_max: number of blocks to create segment */
+       /* <TODO: implement> */
+
+end_check:
+       if (err_code)
+               (*err_code) = err;
+
+       if (err_severity)
+               (*err_severity) = severity;
+
+       return is_sb_ok;
 }

 static int __nilfs_sb_read(int devfd, struct nilfs_super_block **sbp,
@@ -112,7 +238,7 @@ static int __nilfs_sb_read(int devfd, struct nilfs_super_block **sbp,

        if (lseek(devfd, NILFS_SB_OFFSET_BYTES, SEEK_SET) < 0 ||
            read(devfd, sbp[0], NILFS_MAX_SB_SIZE) < 0 ||
-           !nilfs_sb_is_valid(sbp[0], 0)) {
+           !nilfs_sb_is_valid(sbp[0], 0, NULL, NULL)) {
                free(sbp[0]);
                sbp[0] = NULL;
        }
@@ -125,7 +251,7 @@ static int __nilfs_sb_read(int devfd, struct nilfs_super_block **sbp,

        if (lseek(devfd, sb2_offset, SEEK_SET) < 0 ||
            read(devfd, sbp[1], NILFS_MAX_SB_SIZE) < 0 ||
-           !nilfs_sb_is_valid(sbp[1], 0))
+           !nilfs_sb_is_valid(sbp[1], 0, NULL, NULL))
                goto sb2_failed;

        if (sb2_offset <
@@ -169,6 +295,55 @@ struct nilfs_super_block *nilfs_sb_read(int devfd)
        return sbp[0];
 }

+/*
+ * nilfs_sb_read_unchecked - Read superblocks without check.
+ * @devfd: file descriptor of opened device.
+ * @sbp1: pointer on first superblock (can be NULL).
+ * @sbp2: pointer on second superblock (can be NULL).
+ *
+ * Return value:
+ * 0 - no errors were detected.
+ * %-CANNOT_READ_SUPERBLOCK - cannot read superblock from disk.
+ * %-INVALID_SB_OFFSET - superblock offset has invalid value.
+ */
+int nilfs_sb_read_unchecked(int devfd,
+                               struct nilfs_super_block *sbp1,
+                               struct nilfs_super_block *sbp2)
+{
+       __u64 devsize, sb2_offset;
+       __u16 sb_size = sizeof(struct nilfs_super_block);
+
+       if (sbp1 == NULL && sbp2 == NULL)
+               return 0;
+
+       if (ioctl(devfd, BLKGETSIZE64, &devsize) != 0)
+               goto failed_read;
+
+       if (sbp1) {
+               if (lseek(devfd, NILFS_SB_OFFSET_BYTES, SEEK_SET) < 0 ||
+                               read(devfd, sbp1, sb_size) < 0)
+                       goto failed_read;
+       }
+
+       if (sbp2) {
+               sb2_offset = NILFS_SB2_OFFSET_BYTES(devsize);
+               if (sb2_offset <= (NILFS_SB_OFFSET_BYTES + sb_size))
+                       goto invalid_sb_offset;
+
+               if (lseek(devfd, sb2_offset, SEEK_SET) < 0 ||
+                               read(devfd, sbp2, sb_size) < 0)
+                       goto failed_read;
+       }
+
+       return 0;
+
+invalid_sb_offset:
+       return -INVALID_SB_OFFSET;
+
+failed_read:
+       return -CANNOT_READ_SUPERBLOCK;
+}
+
 int nilfs_sb_write(int devfd, struct nilfs_super_block *sbp, int mask)
 {
        __u64 offsets[2];
--

--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to