extmod/vfs_fat: Mount FatFS on creation so VFS methods can be used.
It's possible to use the methods (eg ilistdir) of a VFS FatFS object without it being mounted in the VFS itself. This previously worked but only because FatFS was "mounting" the filesystem automatically when any function (eg f_opendir) was called. But it didn't work for ports that used synchronisation objects (_FS_REENTRANT) because they are only initialised via a call to f_mount. So, call f_mount explicitly when creating a new FatFS object so that everything is set up correctly. Then also provide a finaliser to do the f_umount call, but only if synchronisation objects are enabled (since otherwise the f_umount call does nothing).
This commit is contained in:
parent
ccaa5f5b0b
commit
12ad64bc55
@ -69,9 +69,28 @@ STATIC mp_obj_t fat_vfs_make_new(const mp_obj_type_t *type, size_t n_args, size_
|
||||
mp_load_method(args[0], MP_QSTR_count, vfs->u.old.count);
|
||||
}
|
||||
|
||||
// mount the block device so the VFS methods can be used
|
||||
FRESULT res = f_mount(&vfs->fatfs);
|
||||
if (res == FR_NO_FILESYSTEM) {
|
||||
// don't error out if no filesystem, to let mkfs()/mount() create one if wanted
|
||||
vfs->flags |= FSUSER_NO_FILESYSTEM;
|
||||
} else if (res != FR_OK) {
|
||||
mp_raise_OSError(fresult_to_errno_table[res]);
|
||||
}
|
||||
|
||||
return MP_OBJ_FROM_PTR(vfs);
|
||||
}
|
||||
|
||||
#if _FS_REENTRANT
|
||||
STATIC mp_obj_t fat_vfs_del(mp_obj_t self_in) {
|
||||
mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
// f_umount only needs to be called to release the sync object
|
||||
f_umount(&self->fatfs);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_del_obj, fat_vfs_del);
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t fat_vfs_mkfs(mp_obj_t bdev_in) {
|
||||
// create new object
|
||||
fs_user_mount_t *vfs = MP_OBJ_TO_PTR(fat_vfs_make_new(&mp_fat_vfs_type, 1, 0, &bdev_in));
|
||||
@ -291,10 +310,8 @@ STATIC mp_obj_t vfs_fat_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs
|
||||
self->writeblocks[0] = MP_OBJ_NULL;
|
||||
}
|
||||
|
||||
// mount the block device
|
||||
FRESULT res = f_mount(&self->fatfs);
|
||||
|
||||
// check if we need to make the filesystem
|
||||
FRESULT res = (self->flags & FSUSER_NO_FILESYSTEM) ? FR_NO_FILESYSTEM : FR_OK;
|
||||
if (res == FR_NO_FILESYSTEM && mp_obj_is_true(mkfs)) {
|
||||
uint8_t working_buf[_MAX_SS];
|
||||
res = f_mkfs(&self->fatfs, FM_FAT | FM_SFD, 0, working_buf, sizeof(working_buf));
|
||||
@ -302,22 +319,23 @@ STATIC mp_obj_t vfs_fat_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs
|
||||
if (res != FR_OK) {
|
||||
mp_raise_OSError(fresult_to_errno_table[res]);
|
||||
}
|
||||
self->flags &= ~FSUSER_NO_FILESYSTEM;
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(vfs_fat_mount_obj, vfs_fat_mount);
|
||||
|
||||
STATIC mp_obj_t vfs_fat_umount(mp_obj_t self_in) {
|
||||
fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
FRESULT res = f_umount(&self->fatfs);
|
||||
if (res != FR_OK) {
|
||||
mp_raise_OSError(fresult_to_errno_table[res]);
|
||||
}
|
||||
(void)self_in;
|
||||
// keep the FAT filesystem mounted internally so the VFS methods can still be used
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_umount_obj, vfs_fat_umount);
|
||||
|
||||
STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = {
|
||||
#if _FS_REENTRANT
|
||||
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&fat_vfs_del_obj) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_mkfs), MP_ROM_PTR(&fat_vfs_mkfs_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&fat_vfs_open_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&fat_vfs_ilistdir_obj) },
|
||||
|
@ -35,6 +35,7 @@
|
||||
#define FSUSER_NATIVE (0x0001) // readblocks[2]/writeblocks[2] contain native func
|
||||
#define FSUSER_FREE_OBJ (0x0002) // fs_user_mount_t obj should be freed on umount
|
||||
#define FSUSER_HAVE_IOCTL (0x0004) // new protocol with ioctl
|
||||
#define FSUSER_NO_FILESYSTEM (0x0008) // the block device has no filesystem on it
|
||||
|
||||
typedef struct _fs_user_mount_t {
|
||||
mp_obj_base_t base;
|
||||
|
Loading…
Reference in New Issue
Block a user