ソースを参照

ext4: add read_only parameter to ext4_mount routine.

Now users can mount a filesystem as read-only mode explicitly.
ngkaho1234 10 年 前
コミット
8929c98e42
8 ファイル変更88 行追加18 行削除
  1. 1 1
      fs_test/common/test_lwext4.c
  2. 1 1
      fs_test/lwext4_server.c
  3. 4 1
      include/ext4.h
  4. 3 1
      include/ext4_fs.h
  5. 2 0
      include/ext4_types.h
  6. 60 2
      src/ext4.c
  7. 16 11
      src/ext4_fs.c
  8. 1 1
      src/ext4_mkfs.c

+ 1 - 1
fs_test/common/test_lwext4.c

@@ -336,7 +336,7 @@ bool test_lwext4_mount(struct ext4_blockdev *bdev, struct ext4_bcache *bcache)
 		return false;
 	}
 
-	r = ext4_mount("ext4_fs", "/mp/");
+	r = ext4_mount("ext4_fs", "/mp/", false);
 	if (r != EOK) {
 		printf("ext4_mount: rc = %d\n", r);
 		return false;

+ 1 - 1
fs_test/lwext4_server.c

@@ -419,7 +419,7 @@ int _mount(char *p)
 	if (verbose)
 		ext4_dmask_set(DEBUG_ALL);
 
-	rc = ext4_mount(dev_name, mount_point);
+	rc = ext4_mount(dev_name, mount_point, false);
 	if (rc != EOK)
 		return rc;
 

+ 4 - 1
include/ext4.h

@@ -122,9 +122,12 @@ int ext4_device_register(struct ext4_blockdev *bd, struct ext4_bcache *bc,
  *          -   /
  *          -   /my_partition/
  *          -   /my_second_partition/
+ * @param   read_only mount as read-only mode.
  *
  * @return standard error code */
-int ext4_mount(const char *dev_name, const char *mount_point);
+int ext4_mount(const char *dev_name,
+	       const char *mount_point,
+	       bool read_only);
 
 /**@brief   Umount operation.
  * @param   mount_point mount name

+ 3 - 1
include/ext4_fs.h

@@ -93,9 +93,11 @@ static inline ext4_fsblk_t ext4_fs_first_bg_block_no(struct ext4_sblock *s,
 /**@brief Initialize filesystem and read all needed data.
  * @param fs Filesystem instance to be initialized
  * @param bdev Identifier if device with the filesystem
+ * @param read_only Mark the filesystem as read-only.
  * @return Error code
  */
-int ext4_fs_init(struct ext4_fs *fs, struct ext4_blockdev *bdev);
+int ext4_fs_init(struct ext4_fs *fs, struct ext4_blockdev *bdev,
+		 bool read_only);
 
 /**@brief Destroy filesystem instance (used by unmount operation).
  * @param fs Filesystem to be destroyed

+ 2 - 0
include/ext4_types.h

@@ -303,6 +303,8 @@ struct ext4_sblock {
 #endif
 
 struct ext4_fs {
+	bool read_only;
+
 	struct ext4_blockdev *bdev;
 	struct ext4_sblock sb;
 

+ 60 - 2
src/ext4.c

@@ -329,7 +329,8 @@ static int ext4_unlink(struct ext4_mountpoint *mp,
 
 /****************************************************************************/
 
-int ext4_mount(const char *dev_name, const char *mount_point)
+int ext4_mount(const char *dev_name, const char *mount_point,
+	       bool read_only)
 {
 	ext4_assert(mount_point && dev_name);
 	int r;
@@ -375,7 +376,7 @@ int ext4_mount(const char *dev_name, const char *mount_point)
 	if (r != EOK)
 		return r;
 
-	r = ext4_fs_init(&mp->fs, bd);
+	r = ext4_fs_init(&mp->fs, bd, read_only);
 	if (r != EOK) {
 		ext4_block_fini(bd);
 		return r;
@@ -475,6 +476,9 @@ static int __ext4_journal_start(const char *mount_point)
 	if (!mp)
 		return ENOENT;
 
+	if (mp->fs.read_only)
+		return EOK;
+
 	if (ext4_sb_feature_com(&mp->fs.sb,
 				EXT4_FCOM_HAS_JOURNAL)) {
 		r = jbd_get_fs(&mp->fs, &mp->jbd_fs);
@@ -502,6 +506,9 @@ static int __ext4_journal_stop(const char *mount_point)
 	if (!mp)
 		return ENOENT;
 
+	if (mp->fs.read_only)
+		return EOK;
+
 	if (ext4_sb_feature_com(&mp->fs.sb,
 				EXT4_FCOM_HAS_JOURNAL)) {
 		r = jbd_journal_stop(&mp->jbd_journal);
@@ -893,6 +900,9 @@ static int ext4_generic_open2(ext4_file *f, const char *path, int flags,
 	struct ext4_fs *const fs = &mp->fs;
 	struct ext4_sblock *const sb = &mp->fs.sb;
 
+	if (fs->read_only && flags & O_CREAT)
+		return EROFS;
+
 	f->flags = flags;
 
 	/*Skip mount point*/
@@ -1218,6 +1228,9 @@ int ext4_flink(const char *path, const char *hardlink_path)
 	if (!mp)
 		return ENOENT;
 
+	if (mp->fs.read_only)
+		return EROFS;
+
 	/* Will that happen? Anyway return EINVAL for such case. */
 	if (mp != target_mp)
 		return EINVAL;
@@ -1276,6 +1289,9 @@ int ext4_frename(const char *path, const char *new_path)
 	if (!mp)
 		return ENOENT;
 
+	if (mp->fs.read_only)
+		return EROFS;
+
 	EXT4_MP_LOCK(mp);
 	ext4_trans_start(mp);
 
@@ -1367,6 +1383,9 @@ int ext4_fremove(const char *path)
 	if (!mp)
 		return ENOENT;
 
+	if (mp->fs.read_only)
+		return EROFS;
+
 	EXT4_MP_LOCK(mp);
 	ext4_trans_start(mp);
 
@@ -1590,6 +1609,9 @@ int ext4_ftruncate(ext4_file *f, uint64_t size)
 	int r;
 	ext4_assert(f && f->mp);
 
+	if (f->mp->fs.read_only)
+		return EROFS;
+
 	if (f->flags & O_RDONLY)
 		return EPERM;
 
@@ -1623,6 +1645,9 @@ int ext4_fread(ext4_file *f, void *buf, size_t size, size_t *rcnt)
 
 	ext4_assert(f && f->mp);
 
+	if (f->mp->fs.read_only)
+		return EROFS;
+
 	if (f->flags & O_WRONLY)
 		return EPERM;
 
@@ -1783,6 +1808,9 @@ int ext4_fwrite(ext4_file *f, const void *buf, size_t size, size_t *wcnt)
 
 	ext4_assert(f && f->mp);
 
+	if (f->mp->fs.read_only)
+		return EROFS;
+
 	if (f->flags & O_RDONLY)
 		return EPERM;
 
@@ -1998,6 +2026,9 @@ int ext4_chmod(const char *path, uint32_t mode)
 	if (!mp)
 		return ENOENT;
 
+	if (mp->fs.read_only)
+		return EROFS;
+
 	EXT4_MP_LOCK(mp);
 	ext4_trans_start(mp);
 
@@ -2044,6 +2075,9 @@ int ext4_chown(const char *path, uint32_t uid, uint32_t gid)
 	if (!mp)
 		return ENOENT;
 
+	if (mp->fs.read_only)
+		return EROFS;
+
 	EXT4_MP_LOCK(mp);
 	ext4_trans_start(mp);
 
@@ -2087,6 +2121,9 @@ int ext4_file_set_atime(const char *path, uint32_t atime)
 	if (!mp)
 		return ENOENT;
 
+	if (mp->fs.read_only)
+		return EROFS;
+
 	EXT4_MP_LOCK(mp);
 	ext4_trans_start(mp);
 
@@ -2129,6 +2166,9 @@ int ext4_file_set_mtime(const char *path, uint32_t mtime)
 	if (!mp)
 		return ENOENT;
 
+	if (mp->fs.read_only)
+		return EROFS;
+
 	EXT4_MP_LOCK(mp);
 	ext4_trans_start(mp);
 
@@ -2171,6 +2211,9 @@ int ext4_file_set_ctime(const char *path, uint32_t ctime)
 	if (!mp)
 		return ENOENT;
 
+	if (mp->fs.read_only)
+		return EROFS;
+
 	EXT4_MP_LOCK(mp);
 	ext4_trans_start(mp);
 
@@ -2279,6 +2322,9 @@ int ext4_fsymlink(const char *target, const char *path)
 	if (!mp)
 		return ENOENT;
 
+	if (mp->fs.read_only)
+		return EROFS;
+
 	filetype = EXT4_DE_SYMLINK;
 
 	EXT4_MP_LOCK(mp);
@@ -2356,6 +2402,9 @@ int ext4_setxattr(const char *path, const char *name, size_t name_len,
 	if (!mp)
 		return ENOENT;
 
+	if (mp->fs.read_only)
+		return EROFS;
+
 	dissected_name = ext4_extract_xattr_name(name, name_len,
 				&name_index, &dissected_len);
 	if (!dissected_len)
@@ -2545,6 +2594,9 @@ int ext4_removexattr(const char *path, const char *name, size_t name_len)
 	if (!mp)
 		return ENOENT;
 
+	if (mp->fs.read_only)
+		return EROFS;
+
 	dissected_name = ext4_extract_xattr_name(name, name_len,
 						&name_index, &dissected_len);
 	if (!dissected_len)
@@ -2610,6 +2662,9 @@ int ext4_dir_rm(const char *path)
 	if (!mp)
 		return ENOENT;
 
+	if (mp->fs.read_only)
+		return EROFS;
+
 	EXT4_MP_LOCK(mp);
 
 	struct ext4_fs *const fs = &mp->fs;
@@ -2838,6 +2893,9 @@ int ext4_dir_mk(const char *path)
 	if (!mp)
 		return ENOENT;
 
+	if (mp->fs.read_only)
+		return EROFS;
+
 	EXT4_MP_LOCK(mp);
 	ext4_trans_start(mp);
 

+ 16 - 11
src/ext4_fs.c

@@ -55,12 +55,12 @@
 
 #include <string.h>
 
-int ext4_fs_init(struct ext4_fs *fs, struct ext4_blockdev *bdev)
+int ext4_fs_init(struct ext4_fs *fs, struct ext4_blockdev *bdev,
+		 bool read_only)
 {
 	int r, i;
 	uint16_t tmp;
 	uint32_t bsize;
-	bool read_only = false;
 
 	ext4_assert(fs && bdev);
 
@@ -82,7 +82,7 @@ int ext4_fs_init(struct ext4_fs *fs, struct ext4_blockdev *bdev)
 		return r;
 
 	if (read_only)
-		return ENOTSUP;
+		fs->read_only = true;
 
 	/* Compute limits for indirect block levels */
 	uint32_t blocks_id = bsize / sizeof(uint32_t);
@@ -104,14 +104,16 @@ int ext4_fs_init(struct ext4_fs *fs, struct ext4_blockdev *bdev)
 				"last umount error: superblock fs_error flag\n");
 
 
-	/* Mark system as mounted */
-	ext4_set16(&fs->sb, state, EXT4_SUPERBLOCK_STATE_ERROR_FS);
-	r = ext4_sb_write(fs->bdev, &fs->sb);
-	if (r != EOK)
-		return r;
+	if (!fs->read_only) {
+		/* Mark system as mounted */
+		ext4_set16(&fs->sb, state, EXT4_SUPERBLOCK_STATE_ERROR_FS);
+		r = ext4_sb_write(fs->bdev, &fs->sb);
+		if (r != EOK)
+			return r;
 
-	/*Update mount count*/
-	ext4_set16(&fs->sb, mount_count, ext4_get16(&fs->sb, mount_count) + 1);
+		/*Update mount count*/
+		ext4_set16(&fs->sb, mount_count, ext4_get16(&fs->sb, mount_count) + 1);
+	}
 
 	return r;
 }
@@ -123,7 +125,10 @@ int ext4_fs_fini(struct ext4_fs *fs)
 	/*Set superblock state*/
 	ext4_set16(&fs->sb, state, EXT4_SUPERBLOCK_STATE_VALID_FS);
 
-	return ext4_sb_write(fs->bdev, &fs->sb);
+	if (!fs->read_only)
+		return ext4_sb_write(fs->bdev, &fs->sb);
+
+	return EOK;
 }
 
 static void ext4_fs_debug_features_inc(uint32_t features_incompatible)

+ 1 - 1
src/ext4_mkfs.c

@@ -740,7 +740,7 @@ int ext4_mkfs(struct ext4_fs *fs, struct ext4_blockdev *bd,
 	if (r != EOK)
 		goto cache_fini;
 
-	r = ext4_fs_init(fs, bd);
+	r = ext4_fs_init(fs, bd, false);
 	if (r != EOK)
 		goto cache_fini;