add locks to the shared objects of ext2 fs
authorLunaixsky <lunaixsky@qq.com>
Sat, 3 May 2025 18:10:01 +0000 (19:10 +0100)
committerLunaixsky <lunaixsky@qq.com>
Sat, 3 May 2025 18:10:01 +0000 (19:10 +0100)
lunaix-os/kernel/fs/ext2/alloc.c
lunaix-os/kernel/fs/ext2/dir.c
lunaix-os/kernel/fs/ext2/ext2.h
lunaix-os/kernel/fs/ext2/file.c
lunaix-os/kernel/fs/ext2/group.c
lunaix-os/kernel/fs/ext2/inode.c
lunaix-os/kernel/fs/ext2/mount.c

index 29961410ff24b4d55030906ecc0ef5266be818a9..62dfb6b92bb657103fb5ca124f670df75c9cab5d 100644 (file)
@@ -4,12 +4,20 @@ static inline unsigned int
 __ext2_global_slot_alloc(struct v_superblock* vsb, int type_sel, 
                          struct ext2_gdesc** gd_out)
 {
+    int alloc;
     struct ext2_sbinfo* sb;
     struct ext2_gdesc *pos;
     struct llist_header *header;
     
+    alloc = ALLOC_FAIL;
     sb = EXT2_SB(vsb);
+
+    ext2sb_lock(sb);
     header = &sb->free_list_sel[type_sel];
+
+    // we have used up all avaliable inodes/blocks
+    if (llist_empty(header))
+        goto done;
     
     if (type_sel == GDESC_INO_SEL) {
         pos = list_entry(header->next, struct ext2_gdesc, free_grps_ino);
@@ -18,12 +26,14 @@ __ext2_global_slot_alloc(struct v_superblock* vsb, int type_sel,
         pos = list_entry(header->next, struct ext2_gdesc, free_grps_blk);
     }
 
-    int alloc = ext2gd_alloc_slot(pos, type_sel);
+    alloc = ext2gd_alloc_slot(pos, type_sel);
 
     if (valid_bmp_slot(alloc)) {
         *gd_out = pos;
     }
 
+done:
+    ext2sb_unlock(sb);
     return alloc;
 }
 
@@ -45,13 +55,15 @@ ext2gd_alloc_slot(struct ext2_gdesc* gd, int type_sel)
     struct ext2_bmp* bmp;
     struct ext2_sbinfo *sb;
     int alloc;
+
+    ext2gd_lock(gd);
     
     sb = gd->sb;
     bmp = &gd->bmps[type_sel];
-    alloc = ext2bmp_alloc_one(bmp);
+    alloc = ext2bmp_alloc_nolock(bmp);
     
     if (alloc < 0) {
-        return alloc;
+        goto done;
     }
 
     if (!ext2bmp_check_free(bmp)) {
@@ -66,8 +78,11 @@ ext2gd_alloc_slot(struct ext2_gdesc* gd, int type_sel)
         sb->raw->s_free_blk_cnt--;
     }
 
-    fsblock_dirty(gd->buf);
-    fsblock_dirty(sb->buf);
+    ext2gd_schedule_sync(gd);
+    ext2sb_schedule_sync(sb);
+
+done:
+    ext2gd_unlock(gd);
     return alloc;
 }
 
@@ -77,7 +92,9 @@ ext2gd_free_slot(struct ext2_gdesc* gd, int type_sel, int slot)
     struct llist_header *free_ent, *free_list;
     struct ext2_sbinfo *sb;
 
-    ext2bmp_free_one(&gd->bmps[type_sel], slot);
+    ext2gd_lock(gd);
+
+    ext2bmp_free_nolock(&gd->bmps[type_sel], slot);
 
     sb = gd->sb;
     free_ent  = &gd->free_list_sel[slot];
@@ -86,6 +103,7 @@ ext2gd_free_slot(struct ext2_gdesc* gd, int type_sel, int slot)
         llist_append(free_list, free_ent);
     }
 
+    // FIXME might need arch-depedent impl for atomic operations
     if (type_sel == GDESC_INO_SEL) {
         gd->info->bg_free_ino_cnt++;
         sb->raw->s_free_ino_cnt++;
@@ -94,6 +112,8 @@ ext2gd_free_slot(struct ext2_gdesc* gd, int type_sel, int slot)
         sb->raw->s_free_blk_cnt++;
     }
 
-    fsblock_dirty(gd->buf);
-    fsblock_dirty(sb->buf);
+    ext2gd_schedule_sync(gd);
+    ext2sb_schedule_sync(sb);
+
+    ext2gd_unlock(gd);
 }
\ No newline at end of file
index e09a17be657b423942414cbb4d860aee74e97b9e..9058c8a5e8dffdb66334cf15d15037a2c5b706e4 100644 (file)
@@ -57,10 +57,11 @@ done:
 _ret:
     fsblock_put(prev_buf);
     ext2dr_itend(&iter);
+    
     return itstate_sel(&iter, errno);
 }
 
-static size_t
+static inline size_t
 __dirent_realsize(struct ext2b_dirent* dirent)
 {
     return sizeof(*dirent) - sizeof(dirent->name) + dirent->name_len;
index 93996cda0505c0d6a791f75962ac10ca4309d979..8a6e8523a7e7c41609fee71c21b843ec7a8f3972 100644 (file)
@@ -6,6 +6,7 @@
 #include <lunaix/ds/llist.h>
 #include <lunaix/ds/hashtable.h>
 #include <lunaix/ds/lru.h>
+#include <lunaix/ds/mutex.h>
 
 #ifdef CONFIG_EXT2_DEBUG_MSG
 #   include <lunaix/syslog.h>
@@ -209,6 +210,8 @@ struct ext2_sbinfo
         struct llist_header gds;
         GDESC_FREE_LISTS;
     };
+
+    mutex_t lock;
 };
 #define EXT2_SB(vsb) (fsapi_impl_data(vsb, struct ext2_sbinfo))
 
@@ -241,6 +244,8 @@ struct ext2_gdesc
     struct ext2_sbinfo* sb;
     bbuf_t buf;
     bcobj_t cache_ref;
+
+    mutex_t lock;
 };
 
 /*
@@ -298,6 +303,8 @@ struct ext2_inode
     // prefetched block for 1st order of indirection
     bbuf_t ind_ord1;
     char* symlink;
+
+    // No lock required, it shares lock context with v_inode.
 };
 #define EXT2_INO(v_inode) (fsapi_impl_data(v_inode, struct ext2_inode))
 
@@ -311,6 +318,8 @@ struct ext2_dnode
 {
     struct ext2_dnode_sub self;
     struct ext2_dnode_sub prev;
+
+    // No lock required, it shares lock context with v_dnode.
 };
 #define EXT2_DNO(v_dnode) (fsapi_impl_data(v_dnode, struct ext2_dnode))
 
@@ -344,7 +353,6 @@ struct ext2_iterator
 struct ext2_file
 {
     struct ext2_iterator iter;
-    struct ext2_inode* b_ino;
 };
 #define EXT2_FILE(v_file) (fsapi_impl_data(v_file, struct ext2_file))
 
@@ -379,6 +387,27 @@ ext2_feature(struct v_superblock* vsb, unsigned int feat)
     return !!(EXT2_SB(vsb)->all_feature & feat);
 }
 
+/* ************   Superblock   ************ */
+
+static inline void
+ext2sb_schedule_sync(struct ext2_sbinfo* sb)
+{
+    fsblock_dirty(sb->buf);
+}
+
+static inline void must_inline
+ext2sb_lock(struct ext2_sbinfo* sb)
+{
+    mutex_lock(&sb->lock);
+}
+
+static inline void must_inline
+ext2sb_unlock(struct ext2_sbinfo* sb)
+{
+    mutex_unlock(&sb->lock);
+}
+
+
 /* ************   Inodes   ************ */
 
 void
@@ -413,6 +442,15 @@ ext2ino_linkto(struct ext2_inode* e_ino, struct ext2b_dirent* dirent)
     fsblock_dirty(e_ino->buf);
 }
 
+static inline void
+ext2ino_schedule_sync(struct ext2_inode* ino)
+{
+    fsblock_dirty(ino->buf);
+}
+
+
+/* ************* Data blocks ************* */
+
 #define DBIT_MODE_ISIZE 0
 #define DBIT_MODE_BLOCK 1
 
@@ -497,14 +535,33 @@ void
 ext2gd_release_gdt(struct v_superblock* vsb);
 
 int
-ext2gd_take(struct v_superblock* vsb, 
+ext2gd_take_at(struct v_superblock* vsb, 
                unsigned int index, struct ext2_gdesc** out);
 
+static inline struct ext2_gdesc*
+ext2gd_take(struct ext2_gdesc* gd) {
+    bcache_refonce(gd->cache_ref);
+
+    return gd;
+}
+
 static inline void
 ext2gd_put(struct ext2_gdesc* gd) {
     bcache_return(gd->cache_ref);
 }
 
+static inline void must_inline
+ext2gd_lock(struct ext2_gdesc* gd)
+{
+    mutex_lock(&gd->lock);
+}
+
+static inline void must_inline
+ext2gd_unlock(struct ext2_gdesc* gd)
+{
+    mutex_unlock(&gd->lock);
+}
+
 
 /* ************ Directory ************ */
 
@@ -610,23 +667,6 @@ ext2_get_symlink(struct v_inode *this, const char **path_out);
 int
 ext2_set_symlink(struct v_inode *this, const char *target);
 
-/* ***********   Bitmap   *********** */
-
-void
-ext2bmp_init(struct ext2_bmp* e_bmp, bbuf_t bmp_buf, unsigned int nr_bits);
-
-bool
-ext2bmp_check_free(struct ext2_bmp* e_bmp);
-
-int
-ext2bmp_alloc_one(struct ext2_bmp* e_bmp);
-
-void
-ext2bmp_free_one(struct ext2_bmp* e_bmp, unsigned int pos);
-
-void
-ext2bmp_discard(struct ext2_bmp* e_bmp);
-
 /* ***********   Allocations   *********** */
 
 #define ALLOC_FAIL -1
@@ -667,6 +707,13 @@ ext2gd_free_block(struct ext2_gdesc* gd, int slot)
     ext2gd_free_slot(gd, GDESC_BLK_SEL, slot);
 }
 
+static inline void
+ext2gd_schedule_sync(struct ext2_gdesc* gd)
+{
+    fsblock_dirty(gd->buf);
+    fsblock_dirty(gd->ino_bmp.raw);
+    fsblock_dirty(gd->blk_bmp.raw);
+}
 
 /**
  * @brief Allocate a free inode
@@ -716,4 +763,26 @@ int
 ext2db_alloc_slot(struct v_superblock* vsb, struct ext2_gdesc** gd_out);
 
 
+/* ***********   Bitmap   *********** */
+
+void
+ext2bmp_init(struct ext2_bmp* e_bmp, bbuf_t bmp_buf, unsigned int nr_bits);
+
+int
+ext2bmp_alloc_nolock(struct ext2_bmp* e_bmp);
+
+void
+ext2bmp_free_nolock(struct ext2_bmp* e_bmp, unsigned int pos);
+
+void
+ext2bmp_discard_nolock(struct ext2_bmp* e_bmp);
+
+static inline bool
+ext2bmp_check_free(struct ext2_bmp* e_bmp)
+{
+    assert(e_bmp->raw);
+
+    return valid_bmp_slot(e_bmp->next_free);
+}
+
 #endif /* __LUNAIX_EXT2_H */
index d94371d3e31df49db805a7b612414eb93cfe65c0..bd14785d6391934fc1a8ebbd7bde4701b78ad874 100644 (file)
@@ -12,7 +12,6 @@ ext2_open_inode(struct v_inode* inode, struct v_file* file)
     struct ext2_file* e_file;
 
     e_file = valloc(sizeof(*e_file));
-    e_file->b_ino = EXT2_INO(inode);
     
     file->data = e_file;
 
index 277d6904b256f786a2956a7c71aa549bc4923a71..d11e510030c4d401ca8a14e5e95222bac453aa38 100644 (file)
@@ -126,7 +126,7 @@ __try_load_bitmap(struct v_superblock* vsb,
 }
 
 int
-ext2gd_take(struct v_superblock* vsb, 
+ext2gd_take_at(struct v_superblock* vsb, 
                unsigned int index, struct ext2_gdesc** out)
 {
     bbuf_t part, buf;
@@ -169,6 +169,8 @@ ext2gd_take(struct v_superblock* vsb,
         .ino_base = index * ext2sb->raw->s_ino_per_grp
     };
 
+    mutex_init(&gd->lock);
+
     *out = gd;
     
     if (!ext2sb->read_only) {
@@ -235,16 +237,8 @@ ext2bmp_init(struct ext2_bmp* e_bmp, bbuf_t bmp_buf, unsigned int nr_bits)
     __ext2bmp_update_next_free_cell(e_bmp);
 }
 
-bool
-ext2bmp_check_free(struct ext2_bmp* e_bmp)
-{
-    assert(e_bmp->raw);
-
-    return valid_bmp_slot(e_bmp->next_free);
-}
-
 int
-ext2bmp_alloc_one(struct ext2_bmp* e_bmp)
+ext2bmp_alloc_nolock(struct ext2_bmp* e_bmp)
 {
     assert(e_bmp->raw);
     
@@ -275,7 +269,7 @@ ext2bmp_alloc_one(struct ext2_bmp* e_bmp)
 }
 
 void
-ext2bmp_free_one(struct ext2_bmp* e_bmp, unsigned int pos)
+ext2bmp_free_nolock(struct ext2_bmp* e_bmp, unsigned int pos)
 {
     assert(e_bmp->raw);
 
@@ -291,7 +285,7 @@ ext2bmp_free_one(struct ext2_bmp* e_bmp, unsigned int pos)
 }
 
 void
-ext2bmp_discard(struct ext2_bmp* e_bmp)
+ext2bmp_discard_nolock(struct ext2_bmp* e_bmp)
 {
     assert(e_bmp->raw);
 
index b784b386ffb708b6cd2472870b103dc7a54abb9d..0956b1e71c5355fb40f76a94f794aa9a78d87b8d 100644 (file)
@@ -391,7 +391,7 @@ __get_group_desc(struct v_superblock* vsb, int ino,
     sb = EXT2_SB(vsb);
 
     blkgrp_id = to_fsblock_id(ino) / sb->raw->s_ino_per_grp;
-    return ext2gd_take(vsb, blkgrp_id, gd_out);
+    return ext2gd_take_at(vsb, blkgrp_id, gd_out);
 }
 
 static struct ext2b_inode*
@@ -443,7 +443,7 @@ __create_inode(struct v_superblock* vsb, struct ext2_gdesc* gd, int ino_index)
     inode->btlb      = vzalloc(sizeof(struct ext2_btlb));
     inode->buf       = ino_tab;
     inode->ino       = b_inode;
-    inode->blk_grp   = gd;
+    inode->blk_grp   = ext2gd_take(gd);
     inode->isize     = b_inode->i_size;
 
     if (ext2_feature(vsb, FEAT_LARGE_FILE)) {
@@ -592,7 +592,7 @@ __free_block_at(struct v_superblock *vsb, unsigned int block_pos)
     sb = EXT2_SB(vsb);
     gd_index = block_pos / sb->raw->s_blk_per_grp;
 
-    if ((errno = ext2gd_take(vsb, gd_index, &gd))) {
+    if ((errno = ext2gd_take_at(vsb, gd_index, &gd))) {
         return errno;
     }
 
index 05fbdce029ea6243dd0f6c6fbde4b6bd1b2be01a..0d328e796df31a079cdc820391eeea9dd68ac66b 100644 (file)
@@ -170,6 +170,8 @@ ext2_mount(struct v_superblock* vsb, struct v_dnode* mnt)
     ext2sb->raw = rawsb;
     ext2sb->all_feature = __translate_feature(rawsb);
 
+    mutex_init(&ext2sb->lock);
+
     fsapi_set_vsb_ops(vsb, &vsb_ops);
     fsapi_complete_vsb_setup(vsb, ext2sb);
 
@@ -188,6 +190,9 @@ ext2_mount(struct v_superblock* vsb, struct v_dnode* mnt)
         ext2sb->raw = offset(blkbuf_data(buf), EXT2_BASE_BLKSZ);
     }
 
+    ext2sb->raw->s_mnt_cnt++;
+    ext2sb->raw->s_mtime = clock_unixtime();
+
     ext2sb->buf = buf;
     vfree(rawsb);
     return 0;