__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);
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;
}
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)) {
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;
}
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];
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++;
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
_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;
#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>
struct llist_header gds;
GDESC_FREE_LISTS;
};
+
+ mutex_t lock;
};
#define EXT2_SB(vsb) (fsapi_impl_data(vsb, struct ext2_sbinfo))
struct ext2_sbinfo* sb;
bbuf_t buf;
bcobj_t cache_ref;
+
+ mutex_t lock;
};
/*
// 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))
{
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))
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))
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
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
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 ************ */
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
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
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 */
struct ext2_file* e_file;
e_file = valloc(sizeof(*e_file));
- e_file->b_ino = EXT2_INO(inode);
file->data = e_file;
}
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;
.ino_base = index * ext2sb->raw->s_ino_per_grp
};
+ mutex_init(&gd->lock);
+
*out = gd;
if (!ext2sb->read_only) {
__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);
}
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);
}
void
-ext2bmp_discard(struct ext2_bmp* e_bmp)
+ext2bmp_discard_nolock(struct ext2_bmp* e_bmp)
{
assert(e_bmp->raw);
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*
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)) {
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;
}
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);
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;