|
@@ -1848,7 +1848,6 @@ static void ubifs_put_super(struct super_block *sb)
|
|
bdi_destroy(&c->bdi);
|
|
bdi_destroy(&c->bdi);
|
|
ubi_close_volume(c->ubi);
|
|
ubi_close_volume(c->ubi);
|
|
mutex_unlock(&c->umount_mutex);
|
|
mutex_unlock(&c->umount_mutex);
|
|
- kfree(c);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
|
|
static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
|
|
@@ -1971,61 +1970,65 @@ static struct ubi_volume_desc *open_ubi(const char *name, int mode)
|
|
return ERR_PTR(-EINVAL);
|
|
return ERR_PTR(-EINVAL);
|
|
}
|
|
}
|
|
|
|
|
|
-static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
|
|
|
+static struct ubifs_info *alloc_ubifs_info(struct ubi_volume_desc *ubi)
|
|
{
|
|
{
|
|
- struct ubi_volume_desc *ubi = sb->s_fs_info;
|
|
|
|
struct ubifs_info *c;
|
|
struct ubifs_info *c;
|
|
- struct inode *root;
|
|
|
|
- int err;
|
|
|
|
|
|
|
|
c = kzalloc(sizeof(struct ubifs_info), GFP_KERNEL);
|
|
c = kzalloc(sizeof(struct ubifs_info), GFP_KERNEL);
|
|
- if (!c)
|
|
|
|
- return -ENOMEM;
|
|
|
|
|
|
+ if (c) {
|
|
|
|
+ spin_lock_init(&c->cnt_lock);
|
|
|
|
+ spin_lock_init(&c->cs_lock);
|
|
|
|
+ spin_lock_init(&c->buds_lock);
|
|
|
|
+ spin_lock_init(&c->space_lock);
|
|
|
|
+ spin_lock_init(&c->orphan_lock);
|
|
|
|
+ init_rwsem(&c->commit_sem);
|
|
|
|
+ mutex_init(&c->lp_mutex);
|
|
|
|
+ mutex_init(&c->tnc_mutex);
|
|
|
|
+ mutex_init(&c->log_mutex);
|
|
|
|
+ mutex_init(&c->mst_mutex);
|
|
|
|
+ mutex_init(&c->umount_mutex);
|
|
|
|
+ mutex_init(&c->bu_mutex);
|
|
|
|
+ mutex_init(&c->write_reserve_mutex);
|
|
|
|
+ init_waitqueue_head(&c->cmt_wq);
|
|
|
|
+ c->buds = RB_ROOT;
|
|
|
|
+ c->old_idx = RB_ROOT;
|
|
|
|
+ c->size_tree = RB_ROOT;
|
|
|
|
+ c->orph_tree = RB_ROOT;
|
|
|
|
+ INIT_LIST_HEAD(&c->infos_list);
|
|
|
|
+ INIT_LIST_HEAD(&c->idx_gc);
|
|
|
|
+ INIT_LIST_HEAD(&c->replay_list);
|
|
|
|
+ INIT_LIST_HEAD(&c->replay_buds);
|
|
|
|
+ INIT_LIST_HEAD(&c->uncat_list);
|
|
|
|
+ INIT_LIST_HEAD(&c->empty_list);
|
|
|
|
+ INIT_LIST_HEAD(&c->freeable_list);
|
|
|
|
+ INIT_LIST_HEAD(&c->frdi_idx_list);
|
|
|
|
+ INIT_LIST_HEAD(&c->unclean_leb_list);
|
|
|
|
+ INIT_LIST_HEAD(&c->old_buds);
|
|
|
|
+ INIT_LIST_HEAD(&c->orph_list);
|
|
|
|
+ INIT_LIST_HEAD(&c->orph_new);
|
|
|
|
+ c->no_chk_data_crc = 1;
|
|
|
|
+
|
|
|
|
+ c->highest_inum = UBIFS_FIRST_INO;
|
|
|
|
+ c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM;
|
|
|
|
+
|
|
|
|
+ ubi_get_volume_info(ubi, &c->vi);
|
|
|
|
+ ubi_get_device_info(c->vi.ubi_num, &c->di);
|
|
|
|
+ }
|
|
|
|
+ return c;
|
|
|
|
+}
|
|
|
|
|
|
- spin_lock_init(&c->cnt_lock);
|
|
|
|
- spin_lock_init(&c->cs_lock);
|
|
|
|
- spin_lock_init(&c->buds_lock);
|
|
|
|
- spin_lock_init(&c->space_lock);
|
|
|
|
- spin_lock_init(&c->orphan_lock);
|
|
|
|
- init_rwsem(&c->commit_sem);
|
|
|
|
- mutex_init(&c->lp_mutex);
|
|
|
|
- mutex_init(&c->tnc_mutex);
|
|
|
|
- mutex_init(&c->log_mutex);
|
|
|
|
- mutex_init(&c->mst_mutex);
|
|
|
|
- mutex_init(&c->umount_mutex);
|
|
|
|
- mutex_init(&c->bu_mutex);
|
|
|
|
- mutex_init(&c->write_reserve_mutex);
|
|
|
|
- init_waitqueue_head(&c->cmt_wq);
|
|
|
|
- c->buds = RB_ROOT;
|
|
|
|
- c->old_idx = RB_ROOT;
|
|
|
|
- c->size_tree = RB_ROOT;
|
|
|
|
- c->orph_tree = RB_ROOT;
|
|
|
|
- INIT_LIST_HEAD(&c->infos_list);
|
|
|
|
- INIT_LIST_HEAD(&c->idx_gc);
|
|
|
|
- INIT_LIST_HEAD(&c->replay_list);
|
|
|
|
- INIT_LIST_HEAD(&c->replay_buds);
|
|
|
|
- INIT_LIST_HEAD(&c->uncat_list);
|
|
|
|
- INIT_LIST_HEAD(&c->empty_list);
|
|
|
|
- INIT_LIST_HEAD(&c->freeable_list);
|
|
|
|
- INIT_LIST_HEAD(&c->frdi_idx_list);
|
|
|
|
- INIT_LIST_HEAD(&c->unclean_leb_list);
|
|
|
|
- INIT_LIST_HEAD(&c->old_buds);
|
|
|
|
- INIT_LIST_HEAD(&c->orph_list);
|
|
|
|
- INIT_LIST_HEAD(&c->orph_new);
|
|
|
|
- c->no_chk_data_crc = 1;
|
|
|
|
|
|
+static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
|
+{
|
|
|
|
+ struct ubifs_info *c = sb->s_fs_info;
|
|
|
|
+ struct inode *root;
|
|
|
|
+ int err;
|
|
|
|
|
|
c->vfs_sb = sb;
|
|
c->vfs_sb = sb;
|
|
- c->highest_inum = UBIFS_FIRST_INO;
|
|
|
|
- c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM;
|
|
|
|
-
|
|
|
|
- ubi_get_volume_info(ubi, &c->vi);
|
|
|
|
- ubi_get_device_info(c->vi.ubi_num, &c->di);
|
|
|
|
-
|
|
|
|
/* Re-open the UBI device in read-write mode */
|
|
/* Re-open the UBI device in read-write mode */
|
|
c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READWRITE);
|
|
c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READWRITE);
|
|
if (IS_ERR(c->ubi)) {
|
|
if (IS_ERR(c->ubi)) {
|
|
err = PTR_ERR(c->ubi);
|
|
err = PTR_ERR(c->ubi);
|
|
- goto out_free;
|
|
|
|
|
|
+ goto out;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -2091,24 +2094,29 @@ out_bdi:
|
|
bdi_destroy(&c->bdi);
|
|
bdi_destroy(&c->bdi);
|
|
out_close:
|
|
out_close:
|
|
ubi_close_volume(c->ubi);
|
|
ubi_close_volume(c->ubi);
|
|
-out_free:
|
|
|
|
- kfree(c);
|
|
|
|
|
|
+out:
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
static int sb_test(struct super_block *sb, void *data)
|
|
static int sb_test(struct super_block *sb, void *data)
|
|
{
|
|
{
|
|
- dev_t *dev = data;
|
|
|
|
|
|
+ struct ubifs_info *c1 = data;
|
|
struct ubifs_info *c = sb->s_fs_info;
|
|
struct ubifs_info *c = sb->s_fs_info;
|
|
|
|
|
|
- return c->vi.cdev == *dev;
|
|
|
|
|
|
+ return c->vi.cdev == c1->vi.cdev;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int sb_set(struct super_block *sb, void *data)
|
|
|
|
+{
|
|
|
|
+ sb->s_fs_info = data;
|
|
|
|
+ return set_anon_super(sb, NULL);
|
|
}
|
|
}
|
|
|
|
|
|
static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags,
|
|
static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags,
|
|
const char *name, void *data)
|
|
const char *name, void *data)
|
|
{
|
|
{
|
|
struct ubi_volume_desc *ubi;
|
|
struct ubi_volume_desc *ubi;
|
|
- struct ubi_volume_info vi;
|
|
|
|
|
|
+ struct ubifs_info *c;
|
|
struct super_block *sb;
|
|
struct super_block *sb;
|
|
int err;
|
|
int err;
|
|
|
|
|
|
@@ -2125,19 +2133,24 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags,
|
|
name, (int)PTR_ERR(ubi));
|
|
name, (int)PTR_ERR(ubi));
|
|
return ERR_CAST(ubi);
|
|
return ERR_CAST(ubi);
|
|
}
|
|
}
|
|
- ubi_get_volume_info(ubi, &vi);
|
|
|
|
|
|
|
|
- dbg_gen("opened ubi%d_%d", vi.ubi_num, vi.vol_id);
|
|
|
|
|
|
+ c = alloc_ubifs_info(ubi);
|
|
|
|
+ if (!c) {
|
|
|
|
+ err = -ENOMEM;
|
|
|
|
+ goto out_close;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ dbg_gen("opened ubi%d_%d", c->vi.ubi_num, c->vi.vol_id);
|
|
|
|
|
|
- sb = sget(fs_type, &sb_test, &set_anon_super, &vi.cdev);
|
|
|
|
|
|
+ sb = sget(fs_type, sb_test, sb_set, c);
|
|
if (IS_ERR(sb)) {
|
|
if (IS_ERR(sb)) {
|
|
err = PTR_ERR(sb);
|
|
err = PTR_ERR(sb);
|
|
- goto out_close;
|
|
|
|
|
|
+ kfree(c);
|
|
}
|
|
}
|
|
|
|
|
|
if (sb->s_root) {
|
|
if (sb->s_root) {
|
|
struct ubifs_info *c1 = sb->s_fs_info;
|
|
struct ubifs_info *c1 = sb->s_fs_info;
|
|
-
|
|
|
|
|
|
+ kfree(c);
|
|
/* A new mount point for already mounted UBIFS */
|
|
/* A new mount point for already mounted UBIFS */
|
|
dbg_gen("this ubi volume is already mounted");
|
|
dbg_gen("this ubi volume is already mounted");
|
|
if (!!(flags & MS_RDONLY) != c1->ro_mount) {
|
|
if (!!(flags & MS_RDONLY) != c1->ro_mount) {
|
|
@@ -2146,11 +2159,6 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags,
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
sb->s_flags = flags;
|
|
sb->s_flags = flags;
|
|
- /*
|
|
|
|
- * Pass 'ubi' to 'fill_super()' in sb->s_fs_info where it is
|
|
|
|
- * replaced by 'c'.
|
|
|
|
- */
|
|
|
|
- sb->s_fs_info = ubi;
|
|
|
|
err = ubifs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
|
|
err = ubifs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
|
|
if (err)
|
|
if (err)
|
|
goto out_deact;
|
|
goto out_deact;
|
|
@@ -2170,11 +2178,18 @@ out_close:
|
|
return ERR_PTR(err);
|
|
return ERR_PTR(err);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void kill_ubifs_super(struct super_block *s)
|
|
|
|
+{
|
|
|
|
+ struct ubifs_info *c = s->s_fs_info;
|
|
|
|
+ kill_anon_super(s);
|
|
|
|
+ kfree(c);
|
|
|
|
+}
|
|
|
|
+
|
|
static struct file_system_type ubifs_fs_type = {
|
|
static struct file_system_type ubifs_fs_type = {
|
|
.name = "ubifs",
|
|
.name = "ubifs",
|
|
.owner = THIS_MODULE,
|
|
.owner = THIS_MODULE,
|
|
.mount = ubifs_mount,
|
|
.mount = ubifs_mount,
|
|
- .kill_sb = kill_anon_super,
|
|
|
|
|
|
+ .kill_sb = kill_ubifs_super,
|
|
};
|
|
};
|
|
|
|
|
|
/*
|
|
/*
|