summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorngkaho1234 <ngkaho1234@gmail.com>2016-01-30 23:26:22 +0800
committerngkaho1234 <ngkaho1234@gmail.com>2016-01-30 23:26:22 +0800
commit8929c98e42e81dce0b00d03a1c7b2f45ee85fe87 (patch)
tree4105a1ca03e0c61983402e087d600e973e43faa9 /src
parent9b40d089d6cf5912b558dd3e0ca1a246baa6750a (diff)
ext4: add read_only parameter to ext4_mount routine.
Now users can mount a filesystem as read-only mode explicitly.
Diffstat (limited to 'src')
-rw-r--r--src/ext4.c62
-rw-r--r--src/ext4_fs.c27
-rw-r--r--src/ext4_mkfs.c2
3 files changed, 77 insertions, 14 deletions
diff --git a/src/ext4.c b/src/ext4.c
index 38ec6d4..e0923e4 100644
--- a/src/ext4.c
+++ b/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);
diff --git a/src/ext4_fs.c b/src/ext4_fs.c
index 392728d..7a97bc6 100644
--- a/src/ext4_fs.c
+++ b/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)
diff --git a/src/ext4_mkfs.c b/src/ext4_mkfs.c
index 5712ef3..e331c0d 100644
--- a/src/ext4_mkfs.c
+++ b/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;