162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * This file is part of UBIFS. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2006-2008 Nokia Corporation. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Authors: Artem Bityutskiy (Битюцкий Артём) 862306a36Sopenharmony_ci * Adrian Hunter 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci/* 1262306a36Sopenharmony_ci * This file implements UBIFS initialization and VFS superblock operations. Some 1362306a36Sopenharmony_ci * initialization stuff which is rather large and complex is placed at 1462306a36Sopenharmony_ci * corresponding subsystems, but most of it is here. 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <linux/init.h> 1862306a36Sopenharmony_ci#include <linux/slab.h> 1962306a36Sopenharmony_ci#include <linux/module.h> 2062306a36Sopenharmony_ci#include <linux/ctype.h> 2162306a36Sopenharmony_ci#include <linux/kthread.h> 2262306a36Sopenharmony_ci#include <linux/parser.h> 2362306a36Sopenharmony_ci#include <linux/seq_file.h> 2462306a36Sopenharmony_ci#include <linux/mount.h> 2562306a36Sopenharmony_ci#include <linux/math64.h> 2662306a36Sopenharmony_ci#include <linux/writeback.h> 2762306a36Sopenharmony_ci#include "ubifs.h" 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistatic int ubifs_default_version_set(const char *val, const struct kernel_param *kp) 3062306a36Sopenharmony_ci{ 3162306a36Sopenharmony_ci int n = 0, ret; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci ret = kstrtoint(val, 10, &n); 3462306a36Sopenharmony_ci if (ret != 0 || n < 4 || n > UBIFS_FORMAT_VERSION) 3562306a36Sopenharmony_ci return -EINVAL; 3662306a36Sopenharmony_ci return param_set_int(val, kp); 3762306a36Sopenharmony_ci} 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic const struct kernel_param_ops ubifs_default_version_ops = { 4062306a36Sopenharmony_ci .set = ubifs_default_version_set, 4162306a36Sopenharmony_ci .get = param_get_int, 4262306a36Sopenharmony_ci}; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ciint ubifs_default_version = UBIFS_FORMAT_VERSION; 4562306a36Sopenharmony_cimodule_param_cb(default_version, &ubifs_default_version_ops, &ubifs_default_version, 0600); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci/* 4862306a36Sopenharmony_ci * Maximum amount of memory we may 'kmalloc()' without worrying that we are 4962306a36Sopenharmony_ci * allocating too much. 5062306a36Sopenharmony_ci */ 5162306a36Sopenharmony_ci#define UBIFS_KMALLOC_OK (128*1024) 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci/* Slab cache for UBIFS inodes */ 5462306a36Sopenharmony_cistatic struct kmem_cache *ubifs_inode_slab; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* UBIFS TNC shrinker description */ 5762306a36Sopenharmony_cistatic struct shrinker ubifs_shrinker_info = { 5862306a36Sopenharmony_ci .scan_objects = ubifs_shrink_scan, 5962306a36Sopenharmony_ci .count_objects = ubifs_shrink_count, 6062306a36Sopenharmony_ci .seeks = DEFAULT_SEEKS, 6162306a36Sopenharmony_ci}; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci/** 6462306a36Sopenharmony_ci * validate_inode - validate inode. 6562306a36Sopenharmony_ci * @c: UBIFS file-system description object 6662306a36Sopenharmony_ci * @inode: the inode to validate 6762306a36Sopenharmony_ci * 6862306a36Sopenharmony_ci * This is a helper function for 'ubifs_iget()' which validates various fields 6962306a36Sopenharmony_ci * of a newly built inode to make sure they contain sane values and prevent 7062306a36Sopenharmony_ci * possible vulnerabilities. Returns zero if the inode is all right and 7162306a36Sopenharmony_ci * a non-zero error code if not. 7262306a36Sopenharmony_ci */ 7362306a36Sopenharmony_cistatic int validate_inode(struct ubifs_info *c, const struct inode *inode) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci int err; 7662306a36Sopenharmony_ci const struct ubifs_inode *ui = ubifs_inode(inode); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci if (inode->i_size > c->max_inode_sz) { 7962306a36Sopenharmony_ci ubifs_err(c, "inode is too large (%lld)", 8062306a36Sopenharmony_ci (long long)inode->i_size); 8162306a36Sopenharmony_ci return 1; 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci if (ui->compr_type >= UBIFS_COMPR_TYPES_CNT) { 8562306a36Sopenharmony_ci ubifs_err(c, "unknown compression type %d", ui->compr_type); 8662306a36Sopenharmony_ci return 2; 8762306a36Sopenharmony_ci } 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci if (ui->xattr_names + ui->xattr_cnt > XATTR_LIST_MAX) 9062306a36Sopenharmony_ci return 3; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci if (ui->data_len < 0 || ui->data_len > UBIFS_MAX_INO_DATA) 9362306a36Sopenharmony_ci return 4; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci if (ui->xattr && !S_ISREG(inode->i_mode)) 9662306a36Sopenharmony_ci return 5; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci if (!ubifs_compr_present(c, ui->compr_type)) { 9962306a36Sopenharmony_ci ubifs_warn(c, "inode %lu uses '%s' compression, but it was not compiled in", 10062306a36Sopenharmony_ci inode->i_ino, ubifs_compr_name(c, ui->compr_type)); 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci err = dbg_check_dir(c, inode); 10462306a36Sopenharmony_ci return err; 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistruct inode *ubifs_iget(struct super_block *sb, unsigned long inum) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci int err; 11062306a36Sopenharmony_ci union ubifs_key key; 11162306a36Sopenharmony_ci struct ubifs_ino_node *ino; 11262306a36Sopenharmony_ci struct ubifs_info *c = sb->s_fs_info; 11362306a36Sopenharmony_ci struct inode *inode; 11462306a36Sopenharmony_ci struct ubifs_inode *ui; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci dbg_gen("inode %lu", inum); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci inode = iget_locked(sb, inum); 11962306a36Sopenharmony_ci if (!inode) 12062306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 12162306a36Sopenharmony_ci if (!(inode->i_state & I_NEW)) 12262306a36Sopenharmony_ci return inode; 12362306a36Sopenharmony_ci ui = ubifs_inode(inode); 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci ino = kmalloc(UBIFS_MAX_INO_NODE_SZ, GFP_NOFS); 12662306a36Sopenharmony_ci if (!ino) { 12762306a36Sopenharmony_ci err = -ENOMEM; 12862306a36Sopenharmony_ci goto out; 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci ino_key_init(c, &key, inode->i_ino); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci err = ubifs_tnc_lookup(c, &key, ino); 13462306a36Sopenharmony_ci if (err) 13562306a36Sopenharmony_ci goto out_ino; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci inode->i_flags |= S_NOCMTIME; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci if (!IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT)) 14062306a36Sopenharmony_ci inode->i_flags |= S_NOATIME; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci set_nlink(inode, le32_to_cpu(ino->nlink)); 14362306a36Sopenharmony_ci i_uid_write(inode, le32_to_cpu(ino->uid)); 14462306a36Sopenharmony_ci i_gid_write(inode, le32_to_cpu(ino->gid)); 14562306a36Sopenharmony_ci inode->i_atime.tv_sec = (int64_t)le64_to_cpu(ino->atime_sec); 14662306a36Sopenharmony_ci inode->i_atime.tv_nsec = le32_to_cpu(ino->atime_nsec); 14762306a36Sopenharmony_ci inode->i_mtime.tv_sec = (int64_t)le64_to_cpu(ino->mtime_sec); 14862306a36Sopenharmony_ci inode->i_mtime.tv_nsec = le32_to_cpu(ino->mtime_nsec); 14962306a36Sopenharmony_ci inode_set_ctime(inode, (int64_t)le64_to_cpu(ino->ctime_sec), 15062306a36Sopenharmony_ci le32_to_cpu(ino->ctime_nsec)); 15162306a36Sopenharmony_ci inode->i_mode = le32_to_cpu(ino->mode); 15262306a36Sopenharmony_ci inode->i_size = le64_to_cpu(ino->size); 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci ui->data_len = le32_to_cpu(ino->data_len); 15562306a36Sopenharmony_ci ui->flags = le32_to_cpu(ino->flags); 15662306a36Sopenharmony_ci ui->compr_type = le16_to_cpu(ino->compr_type); 15762306a36Sopenharmony_ci ui->creat_sqnum = le64_to_cpu(ino->creat_sqnum); 15862306a36Sopenharmony_ci ui->xattr_cnt = le32_to_cpu(ino->xattr_cnt); 15962306a36Sopenharmony_ci ui->xattr_size = le32_to_cpu(ino->xattr_size); 16062306a36Sopenharmony_ci ui->xattr_names = le32_to_cpu(ino->xattr_names); 16162306a36Sopenharmony_ci ui->synced_i_size = ui->ui_size = inode->i_size; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci ui->xattr = (ui->flags & UBIFS_XATTR_FL) ? 1 : 0; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci err = validate_inode(c, inode); 16662306a36Sopenharmony_ci if (err) 16762306a36Sopenharmony_ci goto out_invalid; 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci switch (inode->i_mode & S_IFMT) { 17062306a36Sopenharmony_ci case S_IFREG: 17162306a36Sopenharmony_ci inode->i_mapping->a_ops = &ubifs_file_address_operations; 17262306a36Sopenharmony_ci inode->i_op = &ubifs_file_inode_operations; 17362306a36Sopenharmony_ci inode->i_fop = &ubifs_file_operations; 17462306a36Sopenharmony_ci if (ui->xattr) { 17562306a36Sopenharmony_ci ui->data = kmalloc(ui->data_len + 1, GFP_NOFS); 17662306a36Sopenharmony_ci if (!ui->data) { 17762306a36Sopenharmony_ci err = -ENOMEM; 17862306a36Sopenharmony_ci goto out_ino; 17962306a36Sopenharmony_ci } 18062306a36Sopenharmony_ci memcpy(ui->data, ino->data, ui->data_len); 18162306a36Sopenharmony_ci ((char *)ui->data)[ui->data_len] = '\0'; 18262306a36Sopenharmony_ci } else if (ui->data_len != 0) { 18362306a36Sopenharmony_ci err = 10; 18462306a36Sopenharmony_ci goto out_invalid; 18562306a36Sopenharmony_ci } 18662306a36Sopenharmony_ci break; 18762306a36Sopenharmony_ci case S_IFDIR: 18862306a36Sopenharmony_ci inode->i_op = &ubifs_dir_inode_operations; 18962306a36Sopenharmony_ci inode->i_fop = &ubifs_dir_operations; 19062306a36Sopenharmony_ci if (ui->data_len != 0) { 19162306a36Sopenharmony_ci err = 11; 19262306a36Sopenharmony_ci goto out_invalid; 19362306a36Sopenharmony_ci } 19462306a36Sopenharmony_ci break; 19562306a36Sopenharmony_ci case S_IFLNK: 19662306a36Sopenharmony_ci inode->i_op = &ubifs_symlink_inode_operations; 19762306a36Sopenharmony_ci if (ui->data_len <= 0 || ui->data_len > UBIFS_MAX_INO_DATA) { 19862306a36Sopenharmony_ci err = 12; 19962306a36Sopenharmony_ci goto out_invalid; 20062306a36Sopenharmony_ci } 20162306a36Sopenharmony_ci ui->data = kmalloc(ui->data_len + 1, GFP_NOFS); 20262306a36Sopenharmony_ci if (!ui->data) { 20362306a36Sopenharmony_ci err = -ENOMEM; 20462306a36Sopenharmony_ci goto out_ino; 20562306a36Sopenharmony_ci } 20662306a36Sopenharmony_ci memcpy(ui->data, ino->data, ui->data_len); 20762306a36Sopenharmony_ci ((char *)ui->data)[ui->data_len] = '\0'; 20862306a36Sopenharmony_ci break; 20962306a36Sopenharmony_ci case S_IFBLK: 21062306a36Sopenharmony_ci case S_IFCHR: 21162306a36Sopenharmony_ci { 21262306a36Sopenharmony_ci dev_t rdev; 21362306a36Sopenharmony_ci union ubifs_dev_desc *dev; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci ui->data = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS); 21662306a36Sopenharmony_ci if (!ui->data) { 21762306a36Sopenharmony_ci err = -ENOMEM; 21862306a36Sopenharmony_ci goto out_ino; 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci dev = (union ubifs_dev_desc *)ino->data; 22262306a36Sopenharmony_ci if (ui->data_len == sizeof(dev->new)) 22362306a36Sopenharmony_ci rdev = new_decode_dev(le32_to_cpu(dev->new)); 22462306a36Sopenharmony_ci else if (ui->data_len == sizeof(dev->huge)) 22562306a36Sopenharmony_ci rdev = huge_decode_dev(le64_to_cpu(dev->huge)); 22662306a36Sopenharmony_ci else { 22762306a36Sopenharmony_ci err = 13; 22862306a36Sopenharmony_ci goto out_invalid; 22962306a36Sopenharmony_ci } 23062306a36Sopenharmony_ci memcpy(ui->data, ino->data, ui->data_len); 23162306a36Sopenharmony_ci inode->i_op = &ubifs_file_inode_operations; 23262306a36Sopenharmony_ci init_special_inode(inode, inode->i_mode, rdev); 23362306a36Sopenharmony_ci break; 23462306a36Sopenharmony_ci } 23562306a36Sopenharmony_ci case S_IFSOCK: 23662306a36Sopenharmony_ci case S_IFIFO: 23762306a36Sopenharmony_ci inode->i_op = &ubifs_file_inode_operations; 23862306a36Sopenharmony_ci init_special_inode(inode, inode->i_mode, 0); 23962306a36Sopenharmony_ci if (ui->data_len != 0) { 24062306a36Sopenharmony_ci err = 14; 24162306a36Sopenharmony_ci goto out_invalid; 24262306a36Sopenharmony_ci } 24362306a36Sopenharmony_ci break; 24462306a36Sopenharmony_ci default: 24562306a36Sopenharmony_ci err = 15; 24662306a36Sopenharmony_ci goto out_invalid; 24762306a36Sopenharmony_ci } 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci kfree(ino); 25062306a36Sopenharmony_ci ubifs_set_inode_flags(inode); 25162306a36Sopenharmony_ci unlock_new_inode(inode); 25262306a36Sopenharmony_ci return inode; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ciout_invalid: 25562306a36Sopenharmony_ci ubifs_err(c, "inode %lu validation failed, error %d", inode->i_ino, err); 25662306a36Sopenharmony_ci ubifs_dump_node(c, ino, UBIFS_MAX_INO_NODE_SZ); 25762306a36Sopenharmony_ci ubifs_dump_inode(c, inode); 25862306a36Sopenharmony_ci err = -EINVAL; 25962306a36Sopenharmony_ciout_ino: 26062306a36Sopenharmony_ci kfree(ino); 26162306a36Sopenharmony_ciout: 26262306a36Sopenharmony_ci ubifs_err(c, "failed to read inode %lu, error %d", inode->i_ino, err); 26362306a36Sopenharmony_ci iget_failed(inode); 26462306a36Sopenharmony_ci return ERR_PTR(err); 26562306a36Sopenharmony_ci} 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_cistatic struct inode *ubifs_alloc_inode(struct super_block *sb) 26862306a36Sopenharmony_ci{ 26962306a36Sopenharmony_ci struct ubifs_inode *ui; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci ui = alloc_inode_sb(sb, ubifs_inode_slab, GFP_NOFS); 27262306a36Sopenharmony_ci if (!ui) 27362306a36Sopenharmony_ci return NULL; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci memset((void *)ui + sizeof(struct inode), 0, 27662306a36Sopenharmony_ci sizeof(struct ubifs_inode) - sizeof(struct inode)); 27762306a36Sopenharmony_ci mutex_init(&ui->ui_mutex); 27862306a36Sopenharmony_ci init_rwsem(&ui->xattr_sem); 27962306a36Sopenharmony_ci spin_lock_init(&ui->ui_lock); 28062306a36Sopenharmony_ci return &ui->vfs_inode; 28162306a36Sopenharmony_ci}; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_cistatic void ubifs_free_inode(struct inode *inode) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci struct ubifs_inode *ui = ubifs_inode(inode); 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci kfree(ui->data); 28862306a36Sopenharmony_ci fscrypt_free_inode(inode); 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci kmem_cache_free(ubifs_inode_slab, ui); 29162306a36Sopenharmony_ci} 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci/* 29462306a36Sopenharmony_ci * Note, Linux write-back code calls this without 'i_mutex'. 29562306a36Sopenharmony_ci */ 29662306a36Sopenharmony_cistatic int ubifs_write_inode(struct inode *inode, struct writeback_control *wbc) 29762306a36Sopenharmony_ci{ 29862306a36Sopenharmony_ci int err = 0; 29962306a36Sopenharmony_ci struct ubifs_info *c = inode->i_sb->s_fs_info; 30062306a36Sopenharmony_ci struct ubifs_inode *ui = ubifs_inode(inode); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci ubifs_assert(c, !ui->xattr); 30362306a36Sopenharmony_ci if (is_bad_inode(inode)) 30462306a36Sopenharmony_ci return 0; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci mutex_lock(&ui->ui_mutex); 30762306a36Sopenharmony_ci /* 30862306a36Sopenharmony_ci * Due to races between write-back forced by budgeting 30962306a36Sopenharmony_ci * (see 'sync_some_inodes()') and background write-back, the inode may 31062306a36Sopenharmony_ci * have already been synchronized, do not do this again. This might 31162306a36Sopenharmony_ci * also happen if it was synchronized in an VFS operation, e.g. 31262306a36Sopenharmony_ci * 'ubifs_link()'. 31362306a36Sopenharmony_ci */ 31462306a36Sopenharmony_ci if (!ui->dirty) { 31562306a36Sopenharmony_ci mutex_unlock(&ui->ui_mutex); 31662306a36Sopenharmony_ci return 0; 31762306a36Sopenharmony_ci } 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci /* 32062306a36Sopenharmony_ci * As an optimization, do not write orphan inodes to the media just 32162306a36Sopenharmony_ci * because this is not needed. 32262306a36Sopenharmony_ci */ 32362306a36Sopenharmony_ci dbg_gen("inode %lu, mode %#x, nlink %u", 32462306a36Sopenharmony_ci inode->i_ino, (int)inode->i_mode, inode->i_nlink); 32562306a36Sopenharmony_ci if (inode->i_nlink) { 32662306a36Sopenharmony_ci err = ubifs_jnl_write_inode(c, inode); 32762306a36Sopenharmony_ci if (err) 32862306a36Sopenharmony_ci ubifs_err(c, "can't write inode %lu, error %d", 32962306a36Sopenharmony_ci inode->i_ino, err); 33062306a36Sopenharmony_ci else 33162306a36Sopenharmony_ci err = dbg_check_inode_size(c, inode, ui->ui_size); 33262306a36Sopenharmony_ci } 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci ui->dirty = 0; 33562306a36Sopenharmony_ci mutex_unlock(&ui->ui_mutex); 33662306a36Sopenharmony_ci ubifs_release_dirty_inode_budget(c, ui); 33762306a36Sopenharmony_ci return err; 33862306a36Sopenharmony_ci} 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_cistatic int ubifs_drop_inode(struct inode *inode) 34162306a36Sopenharmony_ci{ 34262306a36Sopenharmony_ci int drop = generic_drop_inode(inode); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci if (!drop) 34562306a36Sopenharmony_ci drop = fscrypt_drop_inode(inode); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci return drop; 34862306a36Sopenharmony_ci} 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_cistatic void ubifs_evict_inode(struct inode *inode) 35162306a36Sopenharmony_ci{ 35262306a36Sopenharmony_ci int err; 35362306a36Sopenharmony_ci struct ubifs_info *c = inode->i_sb->s_fs_info; 35462306a36Sopenharmony_ci struct ubifs_inode *ui = ubifs_inode(inode); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci if (ui->xattr) 35762306a36Sopenharmony_ci /* 35862306a36Sopenharmony_ci * Extended attribute inode deletions are fully handled in 35962306a36Sopenharmony_ci * 'ubifs_removexattr()'. These inodes are special and have 36062306a36Sopenharmony_ci * limited usage, so there is nothing to do here. 36162306a36Sopenharmony_ci */ 36262306a36Sopenharmony_ci goto out; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci dbg_gen("inode %lu, mode %#x", inode->i_ino, (int)inode->i_mode); 36562306a36Sopenharmony_ci ubifs_assert(c, !atomic_read(&inode->i_count)); 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci truncate_inode_pages_final(&inode->i_data); 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci if (inode->i_nlink) 37062306a36Sopenharmony_ci goto done; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci if (is_bad_inode(inode)) 37362306a36Sopenharmony_ci goto out; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci ui->ui_size = inode->i_size = 0; 37662306a36Sopenharmony_ci err = ubifs_jnl_delete_inode(c, inode); 37762306a36Sopenharmony_ci if (err) 37862306a36Sopenharmony_ci /* 37962306a36Sopenharmony_ci * Worst case we have a lost orphan inode wasting space, so a 38062306a36Sopenharmony_ci * simple error message is OK here. 38162306a36Sopenharmony_ci */ 38262306a36Sopenharmony_ci ubifs_err(c, "can't delete inode %lu, error %d", 38362306a36Sopenharmony_ci inode->i_ino, err); 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ciout: 38662306a36Sopenharmony_ci if (ui->dirty) 38762306a36Sopenharmony_ci ubifs_release_dirty_inode_budget(c, ui); 38862306a36Sopenharmony_ci else { 38962306a36Sopenharmony_ci /* We've deleted something - clean the "no space" flags */ 39062306a36Sopenharmony_ci c->bi.nospace = c->bi.nospace_rp = 0; 39162306a36Sopenharmony_ci smp_wmb(); 39262306a36Sopenharmony_ci } 39362306a36Sopenharmony_cidone: 39462306a36Sopenharmony_ci clear_inode(inode); 39562306a36Sopenharmony_ci fscrypt_put_encryption_info(inode); 39662306a36Sopenharmony_ci} 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_cistatic void ubifs_dirty_inode(struct inode *inode, int flags) 39962306a36Sopenharmony_ci{ 40062306a36Sopenharmony_ci struct ubifs_info *c = inode->i_sb->s_fs_info; 40162306a36Sopenharmony_ci struct ubifs_inode *ui = ubifs_inode(inode); 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci ubifs_assert(c, mutex_is_locked(&ui->ui_mutex)); 40462306a36Sopenharmony_ci if (!ui->dirty) { 40562306a36Sopenharmony_ci ui->dirty = 1; 40662306a36Sopenharmony_ci dbg_gen("inode %lu", inode->i_ino); 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci} 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_cistatic int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf) 41162306a36Sopenharmony_ci{ 41262306a36Sopenharmony_ci struct ubifs_info *c = dentry->d_sb->s_fs_info; 41362306a36Sopenharmony_ci unsigned long long free; 41462306a36Sopenharmony_ci __le32 *uuid = (__le32 *)c->uuid; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci free = ubifs_get_free_space(c); 41762306a36Sopenharmony_ci dbg_gen("free space %lld bytes (%lld blocks)", 41862306a36Sopenharmony_ci free, free >> UBIFS_BLOCK_SHIFT); 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci buf->f_type = UBIFS_SUPER_MAGIC; 42162306a36Sopenharmony_ci buf->f_bsize = UBIFS_BLOCK_SIZE; 42262306a36Sopenharmony_ci buf->f_blocks = c->block_cnt; 42362306a36Sopenharmony_ci buf->f_bfree = free >> UBIFS_BLOCK_SHIFT; 42462306a36Sopenharmony_ci if (free > c->report_rp_size) 42562306a36Sopenharmony_ci buf->f_bavail = (free - c->report_rp_size) >> UBIFS_BLOCK_SHIFT; 42662306a36Sopenharmony_ci else 42762306a36Sopenharmony_ci buf->f_bavail = 0; 42862306a36Sopenharmony_ci buf->f_files = 0; 42962306a36Sopenharmony_ci buf->f_ffree = 0; 43062306a36Sopenharmony_ci buf->f_namelen = UBIFS_MAX_NLEN; 43162306a36Sopenharmony_ci buf->f_fsid.val[0] = le32_to_cpu(uuid[0]) ^ le32_to_cpu(uuid[2]); 43262306a36Sopenharmony_ci buf->f_fsid.val[1] = le32_to_cpu(uuid[1]) ^ le32_to_cpu(uuid[3]); 43362306a36Sopenharmony_ci ubifs_assert(c, buf->f_bfree <= c->block_cnt); 43462306a36Sopenharmony_ci return 0; 43562306a36Sopenharmony_ci} 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_cistatic int ubifs_show_options(struct seq_file *s, struct dentry *root) 43862306a36Sopenharmony_ci{ 43962306a36Sopenharmony_ci struct ubifs_info *c = root->d_sb->s_fs_info; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci if (c->mount_opts.unmount_mode == 2) 44262306a36Sopenharmony_ci seq_puts(s, ",fast_unmount"); 44362306a36Sopenharmony_ci else if (c->mount_opts.unmount_mode == 1) 44462306a36Sopenharmony_ci seq_puts(s, ",norm_unmount"); 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci if (c->mount_opts.bulk_read == 2) 44762306a36Sopenharmony_ci seq_puts(s, ",bulk_read"); 44862306a36Sopenharmony_ci else if (c->mount_opts.bulk_read == 1) 44962306a36Sopenharmony_ci seq_puts(s, ",no_bulk_read"); 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci if (c->mount_opts.chk_data_crc == 2) 45262306a36Sopenharmony_ci seq_puts(s, ",chk_data_crc"); 45362306a36Sopenharmony_ci else if (c->mount_opts.chk_data_crc == 1) 45462306a36Sopenharmony_ci seq_puts(s, ",no_chk_data_crc"); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci if (c->mount_opts.override_compr) { 45762306a36Sopenharmony_ci seq_printf(s, ",compr=%s", 45862306a36Sopenharmony_ci ubifs_compr_name(c, c->mount_opts.compr_type)); 45962306a36Sopenharmony_ci } 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci seq_printf(s, ",assert=%s", ubifs_assert_action_name(c)); 46262306a36Sopenharmony_ci seq_printf(s, ",ubi=%d,vol=%d", c->vi.ubi_num, c->vi.vol_id); 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci return 0; 46562306a36Sopenharmony_ci} 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_cistatic int ubifs_sync_fs(struct super_block *sb, int wait) 46862306a36Sopenharmony_ci{ 46962306a36Sopenharmony_ci int i, err; 47062306a36Sopenharmony_ci struct ubifs_info *c = sb->s_fs_info; 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci /* 47362306a36Sopenharmony_ci * Zero @wait is just an advisory thing to help the file system shove 47462306a36Sopenharmony_ci * lots of data into the queues, and there will be the second 47562306a36Sopenharmony_ci * '->sync_fs()' call, with non-zero @wait. 47662306a36Sopenharmony_ci */ 47762306a36Sopenharmony_ci if (!wait) 47862306a36Sopenharmony_ci return 0; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci /* 48162306a36Sopenharmony_ci * Synchronize write buffers, because 'ubifs_run_commit()' does not 48262306a36Sopenharmony_ci * do this if it waits for an already running commit. 48362306a36Sopenharmony_ci */ 48462306a36Sopenharmony_ci for (i = 0; i < c->jhead_cnt; i++) { 48562306a36Sopenharmony_ci err = ubifs_wbuf_sync(&c->jheads[i].wbuf); 48662306a36Sopenharmony_ci if (err) 48762306a36Sopenharmony_ci return err; 48862306a36Sopenharmony_ci } 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci /* 49162306a36Sopenharmony_ci * Strictly speaking, it is not necessary to commit the journal here, 49262306a36Sopenharmony_ci * synchronizing write-buffers would be enough. But committing makes 49362306a36Sopenharmony_ci * UBIFS free space predictions much more accurate, so we want to let 49462306a36Sopenharmony_ci * the user be able to get more accurate results of 'statfs()' after 49562306a36Sopenharmony_ci * they synchronize the file system. 49662306a36Sopenharmony_ci */ 49762306a36Sopenharmony_ci err = ubifs_run_commit(c); 49862306a36Sopenharmony_ci if (err) 49962306a36Sopenharmony_ci return err; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci return ubi_sync(c->vi.ubi_num); 50262306a36Sopenharmony_ci} 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci/** 50562306a36Sopenharmony_ci * init_constants_early - initialize UBIFS constants. 50662306a36Sopenharmony_ci * @c: UBIFS file-system description object 50762306a36Sopenharmony_ci * 50862306a36Sopenharmony_ci * This function initialize UBIFS constants which do not need the superblock to 50962306a36Sopenharmony_ci * be read. It also checks that the UBI volume satisfies basic UBIFS 51062306a36Sopenharmony_ci * requirements. Returns zero in case of success and a negative error code in 51162306a36Sopenharmony_ci * case of failure. 51262306a36Sopenharmony_ci */ 51362306a36Sopenharmony_cistatic int init_constants_early(struct ubifs_info *c) 51462306a36Sopenharmony_ci{ 51562306a36Sopenharmony_ci if (c->vi.corrupted) { 51662306a36Sopenharmony_ci ubifs_warn(c, "UBI volume is corrupted - read-only mode"); 51762306a36Sopenharmony_ci c->ro_media = 1; 51862306a36Sopenharmony_ci } 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci if (c->di.ro_mode) { 52162306a36Sopenharmony_ci ubifs_msg(c, "read-only UBI device"); 52262306a36Sopenharmony_ci c->ro_media = 1; 52362306a36Sopenharmony_ci } 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci if (c->vi.vol_type == UBI_STATIC_VOLUME) { 52662306a36Sopenharmony_ci ubifs_msg(c, "static UBI volume - read-only mode"); 52762306a36Sopenharmony_ci c->ro_media = 1; 52862306a36Sopenharmony_ci } 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci c->leb_cnt = c->vi.size; 53162306a36Sopenharmony_ci c->leb_size = c->vi.usable_leb_size; 53262306a36Sopenharmony_ci c->leb_start = c->di.leb_start; 53362306a36Sopenharmony_ci c->half_leb_size = c->leb_size / 2; 53462306a36Sopenharmony_ci c->min_io_size = c->di.min_io_size; 53562306a36Sopenharmony_ci c->min_io_shift = fls(c->min_io_size) - 1; 53662306a36Sopenharmony_ci c->max_write_size = c->di.max_write_size; 53762306a36Sopenharmony_ci c->max_write_shift = fls(c->max_write_size) - 1; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci if (c->leb_size < UBIFS_MIN_LEB_SZ) { 54062306a36Sopenharmony_ci ubifs_errc(c, "too small LEBs (%d bytes), min. is %d bytes", 54162306a36Sopenharmony_ci c->leb_size, UBIFS_MIN_LEB_SZ); 54262306a36Sopenharmony_ci return -EINVAL; 54362306a36Sopenharmony_ci } 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci if (c->leb_cnt < UBIFS_MIN_LEB_CNT) { 54662306a36Sopenharmony_ci ubifs_errc(c, "too few LEBs (%d), min. is %d", 54762306a36Sopenharmony_ci c->leb_cnt, UBIFS_MIN_LEB_CNT); 54862306a36Sopenharmony_ci return -EINVAL; 54962306a36Sopenharmony_ci } 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci if (!is_power_of_2(c->min_io_size)) { 55262306a36Sopenharmony_ci ubifs_errc(c, "bad min. I/O size %d", c->min_io_size); 55362306a36Sopenharmony_ci return -EINVAL; 55462306a36Sopenharmony_ci } 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci /* 55762306a36Sopenharmony_ci * Maximum write size has to be greater or equivalent to min. I/O 55862306a36Sopenharmony_ci * size, and be multiple of min. I/O size. 55962306a36Sopenharmony_ci */ 56062306a36Sopenharmony_ci if (c->max_write_size < c->min_io_size || 56162306a36Sopenharmony_ci c->max_write_size % c->min_io_size || 56262306a36Sopenharmony_ci !is_power_of_2(c->max_write_size)) { 56362306a36Sopenharmony_ci ubifs_errc(c, "bad write buffer size %d for %d min. I/O unit", 56462306a36Sopenharmony_ci c->max_write_size, c->min_io_size); 56562306a36Sopenharmony_ci return -EINVAL; 56662306a36Sopenharmony_ci } 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci /* 56962306a36Sopenharmony_ci * UBIFS aligns all node to 8-byte boundary, so to make function in 57062306a36Sopenharmony_ci * io.c simpler, assume minimum I/O unit size to be 8 bytes if it is 57162306a36Sopenharmony_ci * less than 8. 57262306a36Sopenharmony_ci */ 57362306a36Sopenharmony_ci if (c->min_io_size < 8) { 57462306a36Sopenharmony_ci c->min_io_size = 8; 57562306a36Sopenharmony_ci c->min_io_shift = 3; 57662306a36Sopenharmony_ci if (c->max_write_size < c->min_io_size) { 57762306a36Sopenharmony_ci c->max_write_size = c->min_io_size; 57862306a36Sopenharmony_ci c->max_write_shift = c->min_io_shift; 57962306a36Sopenharmony_ci } 58062306a36Sopenharmony_ci } 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci c->ref_node_alsz = ALIGN(UBIFS_REF_NODE_SZ, c->min_io_size); 58362306a36Sopenharmony_ci c->mst_node_alsz = ALIGN(UBIFS_MST_NODE_SZ, c->min_io_size); 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci /* 58662306a36Sopenharmony_ci * Initialize node length ranges which are mostly needed for node 58762306a36Sopenharmony_ci * length validation. 58862306a36Sopenharmony_ci */ 58962306a36Sopenharmony_ci c->ranges[UBIFS_PAD_NODE].len = UBIFS_PAD_NODE_SZ; 59062306a36Sopenharmony_ci c->ranges[UBIFS_SB_NODE].len = UBIFS_SB_NODE_SZ; 59162306a36Sopenharmony_ci c->ranges[UBIFS_MST_NODE].len = UBIFS_MST_NODE_SZ; 59262306a36Sopenharmony_ci c->ranges[UBIFS_REF_NODE].len = UBIFS_REF_NODE_SZ; 59362306a36Sopenharmony_ci c->ranges[UBIFS_TRUN_NODE].len = UBIFS_TRUN_NODE_SZ; 59462306a36Sopenharmony_ci c->ranges[UBIFS_CS_NODE].len = UBIFS_CS_NODE_SZ; 59562306a36Sopenharmony_ci c->ranges[UBIFS_AUTH_NODE].min_len = UBIFS_AUTH_NODE_SZ; 59662306a36Sopenharmony_ci c->ranges[UBIFS_AUTH_NODE].max_len = UBIFS_AUTH_NODE_SZ + 59762306a36Sopenharmony_ci UBIFS_MAX_HMAC_LEN; 59862306a36Sopenharmony_ci c->ranges[UBIFS_SIG_NODE].min_len = UBIFS_SIG_NODE_SZ; 59962306a36Sopenharmony_ci c->ranges[UBIFS_SIG_NODE].max_len = c->leb_size - UBIFS_SB_NODE_SZ; 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci c->ranges[UBIFS_INO_NODE].min_len = UBIFS_INO_NODE_SZ; 60262306a36Sopenharmony_ci c->ranges[UBIFS_INO_NODE].max_len = UBIFS_MAX_INO_NODE_SZ; 60362306a36Sopenharmony_ci c->ranges[UBIFS_ORPH_NODE].min_len = 60462306a36Sopenharmony_ci UBIFS_ORPH_NODE_SZ + sizeof(__le64); 60562306a36Sopenharmony_ci c->ranges[UBIFS_ORPH_NODE].max_len = c->leb_size; 60662306a36Sopenharmony_ci c->ranges[UBIFS_DENT_NODE].min_len = UBIFS_DENT_NODE_SZ; 60762306a36Sopenharmony_ci c->ranges[UBIFS_DENT_NODE].max_len = UBIFS_MAX_DENT_NODE_SZ; 60862306a36Sopenharmony_ci c->ranges[UBIFS_XENT_NODE].min_len = UBIFS_XENT_NODE_SZ; 60962306a36Sopenharmony_ci c->ranges[UBIFS_XENT_NODE].max_len = UBIFS_MAX_XENT_NODE_SZ; 61062306a36Sopenharmony_ci c->ranges[UBIFS_DATA_NODE].min_len = UBIFS_DATA_NODE_SZ; 61162306a36Sopenharmony_ci c->ranges[UBIFS_DATA_NODE].max_len = UBIFS_MAX_DATA_NODE_SZ; 61262306a36Sopenharmony_ci /* 61362306a36Sopenharmony_ci * Minimum indexing node size is amended later when superblock is 61462306a36Sopenharmony_ci * read and the key length is known. 61562306a36Sopenharmony_ci */ 61662306a36Sopenharmony_ci c->ranges[UBIFS_IDX_NODE].min_len = UBIFS_IDX_NODE_SZ + UBIFS_BRANCH_SZ; 61762306a36Sopenharmony_ci /* 61862306a36Sopenharmony_ci * Maximum indexing node size is amended later when superblock is 61962306a36Sopenharmony_ci * read and the fanout is known. 62062306a36Sopenharmony_ci */ 62162306a36Sopenharmony_ci c->ranges[UBIFS_IDX_NODE].max_len = INT_MAX; 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci /* 62462306a36Sopenharmony_ci * Initialize dead and dark LEB space watermarks. See gc.c for comments 62562306a36Sopenharmony_ci * about these values. 62662306a36Sopenharmony_ci */ 62762306a36Sopenharmony_ci c->dead_wm = ALIGN(MIN_WRITE_SZ, c->min_io_size); 62862306a36Sopenharmony_ci c->dark_wm = ALIGN(UBIFS_MAX_NODE_SZ, c->min_io_size); 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci /* 63162306a36Sopenharmony_ci * Calculate how many bytes would be wasted at the end of LEB if it was 63262306a36Sopenharmony_ci * fully filled with data nodes of maximum size. This is used in 63362306a36Sopenharmony_ci * calculations when reporting free space. 63462306a36Sopenharmony_ci */ 63562306a36Sopenharmony_ci c->leb_overhead = c->leb_size % UBIFS_MAX_DATA_NODE_SZ; 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci /* Buffer size for bulk-reads */ 63862306a36Sopenharmony_ci c->max_bu_buf_len = UBIFS_MAX_BULK_READ * UBIFS_MAX_DATA_NODE_SZ; 63962306a36Sopenharmony_ci if (c->max_bu_buf_len > c->leb_size) 64062306a36Sopenharmony_ci c->max_bu_buf_len = c->leb_size; 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci /* Log is ready, preserve one LEB for commits. */ 64362306a36Sopenharmony_ci c->min_log_bytes = c->leb_size; 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci return 0; 64662306a36Sopenharmony_ci} 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci/** 64962306a36Sopenharmony_ci * bud_wbuf_callback - bud LEB write-buffer synchronization call-back. 65062306a36Sopenharmony_ci * @c: UBIFS file-system description object 65162306a36Sopenharmony_ci * @lnum: LEB the write-buffer was synchronized to 65262306a36Sopenharmony_ci * @free: how many free bytes left in this LEB 65362306a36Sopenharmony_ci * @pad: how many bytes were padded 65462306a36Sopenharmony_ci * 65562306a36Sopenharmony_ci * This is a callback function which is called by the I/O unit when the 65662306a36Sopenharmony_ci * write-buffer is synchronized. We need this to correctly maintain space 65762306a36Sopenharmony_ci * accounting in bud logical eraseblocks. This function returns zero in case of 65862306a36Sopenharmony_ci * success and a negative error code in case of failure. 65962306a36Sopenharmony_ci * 66062306a36Sopenharmony_ci * This function actually belongs to the journal, but we keep it here because 66162306a36Sopenharmony_ci * we want to keep it static. 66262306a36Sopenharmony_ci */ 66362306a36Sopenharmony_cistatic int bud_wbuf_callback(struct ubifs_info *c, int lnum, int free, int pad) 66462306a36Sopenharmony_ci{ 66562306a36Sopenharmony_ci return ubifs_update_one_lp(c, lnum, free, pad, 0, 0); 66662306a36Sopenharmony_ci} 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci/* 66962306a36Sopenharmony_ci * init_constants_sb - initialize UBIFS constants. 67062306a36Sopenharmony_ci * @c: UBIFS file-system description object 67162306a36Sopenharmony_ci * 67262306a36Sopenharmony_ci * This is a helper function which initializes various UBIFS constants after 67362306a36Sopenharmony_ci * the superblock has been read. It also checks various UBIFS parameters and 67462306a36Sopenharmony_ci * makes sure they are all right. Returns zero in case of success and a 67562306a36Sopenharmony_ci * negative error code in case of failure. 67662306a36Sopenharmony_ci */ 67762306a36Sopenharmony_cistatic int init_constants_sb(struct ubifs_info *c) 67862306a36Sopenharmony_ci{ 67962306a36Sopenharmony_ci int tmp, err; 68062306a36Sopenharmony_ci long long tmp64; 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci c->main_bytes = (long long)c->main_lebs * c->leb_size; 68362306a36Sopenharmony_ci c->max_znode_sz = sizeof(struct ubifs_znode) + 68462306a36Sopenharmony_ci c->fanout * sizeof(struct ubifs_zbranch); 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci tmp = ubifs_idx_node_sz(c, 1); 68762306a36Sopenharmony_ci c->ranges[UBIFS_IDX_NODE].min_len = tmp; 68862306a36Sopenharmony_ci c->min_idx_node_sz = ALIGN(tmp, 8); 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci tmp = ubifs_idx_node_sz(c, c->fanout); 69162306a36Sopenharmony_ci c->ranges[UBIFS_IDX_NODE].max_len = tmp; 69262306a36Sopenharmony_ci c->max_idx_node_sz = ALIGN(tmp, 8); 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci /* Make sure LEB size is large enough to fit full commit */ 69562306a36Sopenharmony_ci tmp = UBIFS_CS_NODE_SZ + UBIFS_REF_NODE_SZ * c->jhead_cnt; 69662306a36Sopenharmony_ci tmp = ALIGN(tmp, c->min_io_size); 69762306a36Sopenharmony_ci if (tmp > c->leb_size) { 69862306a36Sopenharmony_ci ubifs_err(c, "too small LEB size %d, at least %d needed", 69962306a36Sopenharmony_ci c->leb_size, tmp); 70062306a36Sopenharmony_ci return -EINVAL; 70162306a36Sopenharmony_ci } 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci /* 70462306a36Sopenharmony_ci * Make sure that the log is large enough to fit reference nodes for 70562306a36Sopenharmony_ci * all buds plus one reserved LEB. 70662306a36Sopenharmony_ci */ 70762306a36Sopenharmony_ci tmp64 = c->max_bud_bytes + c->leb_size - 1; 70862306a36Sopenharmony_ci c->max_bud_cnt = div_u64(tmp64, c->leb_size); 70962306a36Sopenharmony_ci tmp = (c->ref_node_alsz * c->max_bud_cnt + c->leb_size - 1); 71062306a36Sopenharmony_ci tmp /= c->leb_size; 71162306a36Sopenharmony_ci tmp += 1; 71262306a36Sopenharmony_ci if (c->log_lebs < tmp) { 71362306a36Sopenharmony_ci ubifs_err(c, "too small log %d LEBs, required min. %d LEBs", 71462306a36Sopenharmony_ci c->log_lebs, tmp); 71562306a36Sopenharmony_ci return -EINVAL; 71662306a36Sopenharmony_ci } 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci /* 71962306a36Sopenharmony_ci * When budgeting we assume worst-case scenarios when the pages are not 72062306a36Sopenharmony_ci * be compressed and direntries are of the maximum size. 72162306a36Sopenharmony_ci * 72262306a36Sopenharmony_ci * Note, data, which may be stored in inodes is budgeted separately, so 72362306a36Sopenharmony_ci * it is not included into 'c->bi.inode_budget'. 72462306a36Sopenharmony_ci */ 72562306a36Sopenharmony_ci c->bi.page_budget = UBIFS_MAX_DATA_NODE_SZ * UBIFS_BLOCKS_PER_PAGE; 72662306a36Sopenharmony_ci c->bi.inode_budget = UBIFS_INO_NODE_SZ; 72762306a36Sopenharmony_ci c->bi.dent_budget = UBIFS_MAX_DENT_NODE_SZ; 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci /* 73062306a36Sopenharmony_ci * When the amount of flash space used by buds becomes 73162306a36Sopenharmony_ci * 'c->max_bud_bytes', UBIFS just blocks all writers and starts commit. 73262306a36Sopenharmony_ci * The writers are unblocked when the commit is finished. To avoid 73362306a36Sopenharmony_ci * writers to be blocked UBIFS initiates background commit in advance, 73462306a36Sopenharmony_ci * when number of bud bytes becomes above the limit defined below. 73562306a36Sopenharmony_ci */ 73662306a36Sopenharmony_ci c->bg_bud_bytes = (c->max_bud_bytes * 13) >> 4; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci /* 73962306a36Sopenharmony_ci * Ensure minimum journal size. All the bytes in the journal heads are 74062306a36Sopenharmony_ci * considered to be used, when calculating the current journal usage. 74162306a36Sopenharmony_ci * Consequently, if the journal is too small, UBIFS will treat it as 74262306a36Sopenharmony_ci * always full. 74362306a36Sopenharmony_ci */ 74462306a36Sopenharmony_ci tmp64 = (long long)(c->jhead_cnt + 1) * c->leb_size + 1; 74562306a36Sopenharmony_ci if (c->bg_bud_bytes < tmp64) 74662306a36Sopenharmony_ci c->bg_bud_bytes = tmp64; 74762306a36Sopenharmony_ci if (c->max_bud_bytes < tmp64 + c->leb_size) 74862306a36Sopenharmony_ci c->max_bud_bytes = tmp64 + c->leb_size; 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci err = ubifs_calc_lpt_geom(c); 75162306a36Sopenharmony_ci if (err) 75262306a36Sopenharmony_ci return err; 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci /* Initialize effective LEB size used in budgeting calculations */ 75562306a36Sopenharmony_ci c->idx_leb_size = c->leb_size - c->max_idx_node_sz; 75662306a36Sopenharmony_ci return 0; 75762306a36Sopenharmony_ci} 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci/* 76062306a36Sopenharmony_ci * init_constants_master - initialize UBIFS constants. 76162306a36Sopenharmony_ci * @c: UBIFS file-system description object 76262306a36Sopenharmony_ci * 76362306a36Sopenharmony_ci * This is a helper function which initializes various UBIFS constants after 76462306a36Sopenharmony_ci * the master node has been read. It also checks various UBIFS parameters and 76562306a36Sopenharmony_ci * makes sure they are all right. 76662306a36Sopenharmony_ci */ 76762306a36Sopenharmony_cistatic void init_constants_master(struct ubifs_info *c) 76862306a36Sopenharmony_ci{ 76962306a36Sopenharmony_ci long long tmp64; 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci c->bi.min_idx_lebs = ubifs_calc_min_idx_lebs(c); 77262306a36Sopenharmony_ci c->report_rp_size = ubifs_reported_space(c, c->rp_size); 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci /* 77562306a36Sopenharmony_ci * Calculate total amount of FS blocks. This number is not used 77662306a36Sopenharmony_ci * internally because it does not make much sense for UBIFS, but it is 77762306a36Sopenharmony_ci * necessary to report something for the 'statfs()' call. 77862306a36Sopenharmony_ci * 77962306a36Sopenharmony_ci * Subtract the LEB reserved for GC, the LEB which is reserved for 78062306a36Sopenharmony_ci * deletions, minimum LEBs for the index, and assume only one journal 78162306a36Sopenharmony_ci * head is available. 78262306a36Sopenharmony_ci */ 78362306a36Sopenharmony_ci tmp64 = c->main_lebs - 1 - 1 - MIN_INDEX_LEBS - c->jhead_cnt + 1; 78462306a36Sopenharmony_ci tmp64 *= (long long)c->leb_size - c->leb_overhead; 78562306a36Sopenharmony_ci tmp64 = ubifs_reported_space(c, tmp64); 78662306a36Sopenharmony_ci c->block_cnt = tmp64 >> UBIFS_BLOCK_SHIFT; 78762306a36Sopenharmony_ci} 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci/** 79062306a36Sopenharmony_ci * take_gc_lnum - reserve GC LEB. 79162306a36Sopenharmony_ci * @c: UBIFS file-system description object 79262306a36Sopenharmony_ci * 79362306a36Sopenharmony_ci * This function ensures that the LEB reserved for garbage collection is marked 79462306a36Sopenharmony_ci * as "taken" in lprops. We also have to set free space to LEB size and dirty 79562306a36Sopenharmony_ci * space to zero, because lprops may contain out-of-date information if the 79662306a36Sopenharmony_ci * file-system was un-mounted before it has been committed. This function 79762306a36Sopenharmony_ci * returns zero in case of success and a negative error code in case of 79862306a36Sopenharmony_ci * failure. 79962306a36Sopenharmony_ci */ 80062306a36Sopenharmony_cistatic int take_gc_lnum(struct ubifs_info *c) 80162306a36Sopenharmony_ci{ 80262306a36Sopenharmony_ci int err; 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci if (c->gc_lnum == -1) { 80562306a36Sopenharmony_ci ubifs_err(c, "no LEB for GC"); 80662306a36Sopenharmony_ci return -EINVAL; 80762306a36Sopenharmony_ci } 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci /* And we have to tell lprops that this LEB is taken */ 81062306a36Sopenharmony_ci err = ubifs_change_one_lp(c, c->gc_lnum, c->leb_size, 0, 81162306a36Sopenharmony_ci LPROPS_TAKEN, 0, 0); 81262306a36Sopenharmony_ci return err; 81362306a36Sopenharmony_ci} 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci/** 81662306a36Sopenharmony_ci * alloc_wbufs - allocate write-buffers. 81762306a36Sopenharmony_ci * @c: UBIFS file-system description object 81862306a36Sopenharmony_ci * 81962306a36Sopenharmony_ci * This helper function allocates and initializes UBIFS write-buffers. Returns 82062306a36Sopenharmony_ci * zero in case of success and %-ENOMEM in case of failure. 82162306a36Sopenharmony_ci */ 82262306a36Sopenharmony_cistatic int alloc_wbufs(struct ubifs_info *c) 82362306a36Sopenharmony_ci{ 82462306a36Sopenharmony_ci int i, err; 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci c->jheads = kcalloc(c->jhead_cnt, sizeof(struct ubifs_jhead), 82762306a36Sopenharmony_ci GFP_KERNEL); 82862306a36Sopenharmony_ci if (!c->jheads) 82962306a36Sopenharmony_ci return -ENOMEM; 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci /* Initialize journal heads */ 83262306a36Sopenharmony_ci for (i = 0; i < c->jhead_cnt; i++) { 83362306a36Sopenharmony_ci INIT_LIST_HEAD(&c->jheads[i].buds_list); 83462306a36Sopenharmony_ci err = ubifs_wbuf_init(c, &c->jheads[i].wbuf); 83562306a36Sopenharmony_ci if (err) 83662306a36Sopenharmony_ci goto out_wbuf; 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci c->jheads[i].wbuf.sync_callback = &bud_wbuf_callback; 83962306a36Sopenharmony_ci c->jheads[i].wbuf.jhead = i; 84062306a36Sopenharmony_ci c->jheads[i].grouped = 1; 84162306a36Sopenharmony_ci c->jheads[i].log_hash = ubifs_hash_get_desc(c); 84262306a36Sopenharmony_ci if (IS_ERR(c->jheads[i].log_hash)) { 84362306a36Sopenharmony_ci err = PTR_ERR(c->jheads[i].log_hash); 84462306a36Sopenharmony_ci goto out_log_hash; 84562306a36Sopenharmony_ci } 84662306a36Sopenharmony_ci } 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci /* 84962306a36Sopenharmony_ci * Garbage Collector head does not need to be synchronized by timer. 85062306a36Sopenharmony_ci * Also GC head nodes are not grouped. 85162306a36Sopenharmony_ci */ 85262306a36Sopenharmony_ci c->jheads[GCHD].wbuf.no_timer = 1; 85362306a36Sopenharmony_ci c->jheads[GCHD].grouped = 0; 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci return 0; 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ciout_log_hash: 85862306a36Sopenharmony_ci kfree(c->jheads[i].wbuf.buf); 85962306a36Sopenharmony_ci kfree(c->jheads[i].wbuf.inodes); 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ciout_wbuf: 86262306a36Sopenharmony_ci while (i--) { 86362306a36Sopenharmony_ci kfree(c->jheads[i].wbuf.buf); 86462306a36Sopenharmony_ci kfree(c->jheads[i].wbuf.inodes); 86562306a36Sopenharmony_ci kfree(c->jheads[i].log_hash); 86662306a36Sopenharmony_ci } 86762306a36Sopenharmony_ci kfree(c->jheads); 86862306a36Sopenharmony_ci c->jheads = NULL; 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci return err; 87162306a36Sopenharmony_ci} 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_ci/** 87462306a36Sopenharmony_ci * free_wbufs - free write-buffers. 87562306a36Sopenharmony_ci * @c: UBIFS file-system description object 87662306a36Sopenharmony_ci */ 87762306a36Sopenharmony_cistatic void free_wbufs(struct ubifs_info *c) 87862306a36Sopenharmony_ci{ 87962306a36Sopenharmony_ci int i; 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_ci if (c->jheads) { 88262306a36Sopenharmony_ci for (i = 0; i < c->jhead_cnt; i++) { 88362306a36Sopenharmony_ci kfree(c->jheads[i].wbuf.buf); 88462306a36Sopenharmony_ci kfree(c->jheads[i].wbuf.inodes); 88562306a36Sopenharmony_ci kfree(c->jheads[i].log_hash); 88662306a36Sopenharmony_ci } 88762306a36Sopenharmony_ci kfree(c->jheads); 88862306a36Sopenharmony_ci c->jheads = NULL; 88962306a36Sopenharmony_ci } 89062306a36Sopenharmony_ci} 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci/** 89362306a36Sopenharmony_ci * free_orphans - free orphans. 89462306a36Sopenharmony_ci * @c: UBIFS file-system description object 89562306a36Sopenharmony_ci */ 89662306a36Sopenharmony_cistatic void free_orphans(struct ubifs_info *c) 89762306a36Sopenharmony_ci{ 89862306a36Sopenharmony_ci struct ubifs_orphan *orph; 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci while (c->orph_dnext) { 90162306a36Sopenharmony_ci orph = c->orph_dnext; 90262306a36Sopenharmony_ci c->orph_dnext = orph->dnext; 90362306a36Sopenharmony_ci list_del(&orph->list); 90462306a36Sopenharmony_ci kfree(orph); 90562306a36Sopenharmony_ci } 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci while (!list_empty(&c->orph_list)) { 90862306a36Sopenharmony_ci orph = list_entry(c->orph_list.next, struct ubifs_orphan, list); 90962306a36Sopenharmony_ci list_del(&orph->list); 91062306a36Sopenharmony_ci kfree(orph); 91162306a36Sopenharmony_ci ubifs_err(c, "orphan list not empty at unmount"); 91262306a36Sopenharmony_ci } 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci vfree(c->orph_buf); 91562306a36Sopenharmony_ci c->orph_buf = NULL; 91662306a36Sopenharmony_ci} 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci/** 91962306a36Sopenharmony_ci * free_buds - free per-bud objects. 92062306a36Sopenharmony_ci * @c: UBIFS file-system description object 92162306a36Sopenharmony_ci */ 92262306a36Sopenharmony_cistatic void free_buds(struct ubifs_info *c) 92362306a36Sopenharmony_ci{ 92462306a36Sopenharmony_ci struct ubifs_bud *bud, *n; 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_ci rbtree_postorder_for_each_entry_safe(bud, n, &c->buds, rb) 92762306a36Sopenharmony_ci kfree(bud); 92862306a36Sopenharmony_ci} 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ci/** 93162306a36Sopenharmony_ci * check_volume_empty - check if the UBI volume is empty. 93262306a36Sopenharmony_ci * @c: UBIFS file-system description object 93362306a36Sopenharmony_ci * 93462306a36Sopenharmony_ci * This function checks if the UBIFS volume is empty by looking if its LEBs are 93562306a36Sopenharmony_ci * mapped or not. The result of checking is stored in the @c->empty variable. 93662306a36Sopenharmony_ci * Returns zero in case of success and a negative error code in case of 93762306a36Sopenharmony_ci * failure. 93862306a36Sopenharmony_ci */ 93962306a36Sopenharmony_cistatic int check_volume_empty(struct ubifs_info *c) 94062306a36Sopenharmony_ci{ 94162306a36Sopenharmony_ci int lnum, err; 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci c->empty = 1; 94462306a36Sopenharmony_ci for (lnum = 0; lnum < c->leb_cnt; lnum++) { 94562306a36Sopenharmony_ci err = ubifs_is_mapped(c, lnum); 94662306a36Sopenharmony_ci if (unlikely(err < 0)) 94762306a36Sopenharmony_ci return err; 94862306a36Sopenharmony_ci if (err == 1) { 94962306a36Sopenharmony_ci c->empty = 0; 95062306a36Sopenharmony_ci break; 95162306a36Sopenharmony_ci } 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_ci cond_resched(); 95462306a36Sopenharmony_ci } 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci return 0; 95762306a36Sopenharmony_ci} 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci/* 96062306a36Sopenharmony_ci * UBIFS mount options. 96162306a36Sopenharmony_ci * 96262306a36Sopenharmony_ci * Opt_fast_unmount: do not run a journal commit before un-mounting 96362306a36Sopenharmony_ci * Opt_norm_unmount: run a journal commit before un-mounting 96462306a36Sopenharmony_ci * Opt_bulk_read: enable bulk-reads 96562306a36Sopenharmony_ci * Opt_no_bulk_read: disable bulk-reads 96662306a36Sopenharmony_ci * Opt_chk_data_crc: check CRCs when reading data nodes 96762306a36Sopenharmony_ci * Opt_no_chk_data_crc: do not check CRCs when reading data nodes 96862306a36Sopenharmony_ci * Opt_override_compr: override default compressor 96962306a36Sopenharmony_ci * Opt_assert: set ubifs_assert() action 97062306a36Sopenharmony_ci * Opt_auth_key: The key name used for authentication 97162306a36Sopenharmony_ci * Opt_auth_hash_name: The hash type used for authentication 97262306a36Sopenharmony_ci * Opt_err: just end of array marker 97362306a36Sopenharmony_ci */ 97462306a36Sopenharmony_cienum { 97562306a36Sopenharmony_ci Opt_fast_unmount, 97662306a36Sopenharmony_ci Opt_norm_unmount, 97762306a36Sopenharmony_ci Opt_bulk_read, 97862306a36Sopenharmony_ci Opt_no_bulk_read, 97962306a36Sopenharmony_ci Opt_chk_data_crc, 98062306a36Sopenharmony_ci Opt_no_chk_data_crc, 98162306a36Sopenharmony_ci Opt_override_compr, 98262306a36Sopenharmony_ci Opt_assert, 98362306a36Sopenharmony_ci Opt_auth_key, 98462306a36Sopenharmony_ci Opt_auth_hash_name, 98562306a36Sopenharmony_ci Opt_ignore, 98662306a36Sopenharmony_ci Opt_err, 98762306a36Sopenharmony_ci}; 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_cistatic const match_table_t tokens = { 99062306a36Sopenharmony_ci {Opt_fast_unmount, "fast_unmount"}, 99162306a36Sopenharmony_ci {Opt_norm_unmount, "norm_unmount"}, 99262306a36Sopenharmony_ci {Opt_bulk_read, "bulk_read"}, 99362306a36Sopenharmony_ci {Opt_no_bulk_read, "no_bulk_read"}, 99462306a36Sopenharmony_ci {Opt_chk_data_crc, "chk_data_crc"}, 99562306a36Sopenharmony_ci {Opt_no_chk_data_crc, "no_chk_data_crc"}, 99662306a36Sopenharmony_ci {Opt_override_compr, "compr=%s"}, 99762306a36Sopenharmony_ci {Opt_auth_key, "auth_key=%s"}, 99862306a36Sopenharmony_ci {Opt_auth_hash_name, "auth_hash_name=%s"}, 99962306a36Sopenharmony_ci {Opt_ignore, "ubi=%s"}, 100062306a36Sopenharmony_ci {Opt_ignore, "vol=%s"}, 100162306a36Sopenharmony_ci {Opt_assert, "assert=%s"}, 100262306a36Sopenharmony_ci {Opt_err, NULL}, 100362306a36Sopenharmony_ci}; 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_ci/** 100662306a36Sopenharmony_ci * parse_standard_option - parse a standard mount option. 100762306a36Sopenharmony_ci * @option: the option to parse 100862306a36Sopenharmony_ci * 100962306a36Sopenharmony_ci * Normally, standard mount options like "sync" are passed to file-systems as 101062306a36Sopenharmony_ci * flags. However, when a "rootflags=" kernel boot parameter is used, they may 101162306a36Sopenharmony_ci * be present in the options string. This function tries to deal with this 101262306a36Sopenharmony_ci * situation and parse standard options. Returns 0 if the option was not 101362306a36Sopenharmony_ci * recognized, and the corresponding integer flag if it was. 101462306a36Sopenharmony_ci * 101562306a36Sopenharmony_ci * UBIFS is only interested in the "sync" option, so do not check for anything 101662306a36Sopenharmony_ci * else. 101762306a36Sopenharmony_ci */ 101862306a36Sopenharmony_cistatic int parse_standard_option(const char *option) 101962306a36Sopenharmony_ci{ 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci pr_notice("UBIFS: parse %s\n", option); 102262306a36Sopenharmony_ci if (!strcmp(option, "sync")) 102362306a36Sopenharmony_ci return SB_SYNCHRONOUS; 102462306a36Sopenharmony_ci return 0; 102562306a36Sopenharmony_ci} 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci/** 102862306a36Sopenharmony_ci * ubifs_parse_options - parse mount parameters. 102962306a36Sopenharmony_ci * @c: UBIFS file-system description object 103062306a36Sopenharmony_ci * @options: parameters to parse 103162306a36Sopenharmony_ci * @is_remount: non-zero if this is FS re-mount 103262306a36Sopenharmony_ci * 103362306a36Sopenharmony_ci * This function parses UBIFS mount options and returns zero in case success 103462306a36Sopenharmony_ci * and a negative error code in case of failure. 103562306a36Sopenharmony_ci */ 103662306a36Sopenharmony_cistatic int ubifs_parse_options(struct ubifs_info *c, char *options, 103762306a36Sopenharmony_ci int is_remount) 103862306a36Sopenharmony_ci{ 103962306a36Sopenharmony_ci char *p; 104062306a36Sopenharmony_ci substring_t args[MAX_OPT_ARGS]; 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci if (!options) 104362306a36Sopenharmony_ci return 0; 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_ci while ((p = strsep(&options, ","))) { 104662306a36Sopenharmony_ci int token; 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ci if (!*p) 104962306a36Sopenharmony_ci continue; 105062306a36Sopenharmony_ci 105162306a36Sopenharmony_ci token = match_token(p, tokens, args); 105262306a36Sopenharmony_ci switch (token) { 105362306a36Sopenharmony_ci /* 105462306a36Sopenharmony_ci * %Opt_fast_unmount and %Opt_norm_unmount options are ignored. 105562306a36Sopenharmony_ci * We accept them in order to be backward-compatible. But this 105662306a36Sopenharmony_ci * should be removed at some point. 105762306a36Sopenharmony_ci */ 105862306a36Sopenharmony_ci case Opt_fast_unmount: 105962306a36Sopenharmony_ci c->mount_opts.unmount_mode = 2; 106062306a36Sopenharmony_ci break; 106162306a36Sopenharmony_ci case Opt_norm_unmount: 106262306a36Sopenharmony_ci c->mount_opts.unmount_mode = 1; 106362306a36Sopenharmony_ci break; 106462306a36Sopenharmony_ci case Opt_bulk_read: 106562306a36Sopenharmony_ci c->mount_opts.bulk_read = 2; 106662306a36Sopenharmony_ci c->bulk_read = 1; 106762306a36Sopenharmony_ci break; 106862306a36Sopenharmony_ci case Opt_no_bulk_read: 106962306a36Sopenharmony_ci c->mount_opts.bulk_read = 1; 107062306a36Sopenharmony_ci c->bulk_read = 0; 107162306a36Sopenharmony_ci break; 107262306a36Sopenharmony_ci case Opt_chk_data_crc: 107362306a36Sopenharmony_ci c->mount_opts.chk_data_crc = 2; 107462306a36Sopenharmony_ci c->no_chk_data_crc = 0; 107562306a36Sopenharmony_ci break; 107662306a36Sopenharmony_ci case Opt_no_chk_data_crc: 107762306a36Sopenharmony_ci c->mount_opts.chk_data_crc = 1; 107862306a36Sopenharmony_ci c->no_chk_data_crc = 1; 107962306a36Sopenharmony_ci break; 108062306a36Sopenharmony_ci case Opt_override_compr: 108162306a36Sopenharmony_ci { 108262306a36Sopenharmony_ci char *name = match_strdup(&args[0]); 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_ci if (!name) 108562306a36Sopenharmony_ci return -ENOMEM; 108662306a36Sopenharmony_ci if (!strcmp(name, "none")) 108762306a36Sopenharmony_ci c->mount_opts.compr_type = UBIFS_COMPR_NONE; 108862306a36Sopenharmony_ci else if (!strcmp(name, "lzo")) 108962306a36Sopenharmony_ci c->mount_opts.compr_type = UBIFS_COMPR_LZO; 109062306a36Sopenharmony_ci else if (!strcmp(name, "zlib")) 109162306a36Sopenharmony_ci c->mount_opts.compr_type = UBIFS_COMPR_ZLIB; 109262306a36Sopenharmony_ci else if (!strcmp(name, "zstd")) 109362306a36Sopenharmony_ci c->mount_opts.compr_type = UBIFS_COMPR_ZSTD; 109462306a36Sopenharmony_ci else { 109562306a36Sopenharmony_ci ubifs_err(c, "unknown compressor \"%s\"", name); //FIXME: is c ready? 109662306a36Sopenharmony_ci kfree(name); 109762306a36Sopenharmony_ci return -EINVAL; 109862306a36Sopenharmony_ci } 109962306a36Sopenharmony_ci kfree(name); 110062306a36Sopenharmony_ci c->mount_opts.override_compr = 1; 110162306a36Sopenharmony_ci c->default_compr = c->mount_opts.compr_type; 110262306a36Sopenharmony_ci break; 110362306a36Sopenharmony_ci } 110462306a36Sopenharmony_ci case Opt_assert: 110562306a36Sopenharmony_ci { 110662306a36Sopenharmony_ci char *act = match_strdup(&args[0]); 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci if (!act) 110962306a36Sopenharmony_ci return -ENOMEM; 111062306a36Sopenharmony_ci if (!strcmp(act, "report")) 111162306a36Sopenharmony_ci c->assert_action = ASSACT_REPORT; 111262306a36Sopenharmony_ci else if (!strcmp(act, "read-only")) 111362306a36Sopenharmony_ci c->assert_action = ASSACT_RO; 111462306a36Sopenharmony_ci else if (!strcmp(act, "panic")) 111562306a36Sopenharmony_ci c->assert_action = ASSACT_PANIC; 111662306a36Sopenharmony_ci else { 111762306a36Sopenharmony_ci ubifs_err(c, "unknown assert action \"%s\"", act); 111862306a36Sopenharmony_ci kfree(act); 111962306a36Sopenharmony_ci return -EINVAL; 112062306a36Sopenharmony_ci } 112162306a36Sopenharmony_ci kfree(act); 112262306a36Sopenharmony_ci break; 112362306a36Sopenharmony_ci } 112462306a36Sopenharmony_ci case Opt_auth_key: 112562306a36Sopenharmony_ci if (!is_remount) { 112662306a36Sopenharmony_ci c->auth_key_name = kstrdup(args[0].from, 112762306a36Sopenharmony_ci GFP_KERNEL); 112862306a36Sopenharmony_ci if (!c->auth_key_name) 112962306a36Sopenharmony_ci return -ENOMEM; 113062306a36Sopenharmony_ci } 113162306a36Sopenharmony_ci break; 113262306a36Sopenharmony_ci case Opt_auth_hash_name: 113362306a36Sopenharmony_ci if (!is_remount) { 113462306a36Sopenharmony_ci c->auth_hash_name = kstrdup(args[0].from, 113562306a36Sopenharmony_ci GFP_KERNEL); 113662306a36Sopenharmony_ci if (!c->auth_hash_name) 113762306a36Sopenharmony_ci return -ENOMEM; 113862306a36Sopenharmony_ci } 113962306a36Sopenharmony_ci break; 114062306a36Sopenharmony_ci case Opt_ignore: 114162306a36Sopenharmony_ci break; 114262306a36Sopenharmony_ci default: 114362306a36Sopenharmony_ci { 114462306a36Sopenharmony_ci unsigned long flag; 114562306a36Sopenharmony_ci struct super_block *sb = c->vfs_sb; 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci flag = parse_standard_option(p); 114862306a36Sopenharmony_ci if (!flag) { 114962306a36Sopenharmony_ci ubifs_err(c, "unrecognized mount option \"%s\" or missing value", 115062306a36Sopenharmony_ci p); 115162306a36Sopenharmony_ci return -EINVAL; 115262306a36Sopenharmony_ci } 115362306a36Sopenharmony_ci sb->s_flags |= flag; 115462306a36Sopenharmony_ci break; 115562306a36Sopenharmony_ci } 115662306a36Sopenharmony_ci } 115762306a36Sopenharmony_ci } 115862306a36Sopenharmony_ci 115962306a36Sopenharmony_ci return 0; 116062306a36Sopenharmony_ci} 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci/* 116362306a36Sopenharmony_ci * ubifs_release_options - release mount parameters which have been dumped. 116462306a36Sopenharmony_ci * @c: UBIFS file-system description object 116562306a36Sopenharmony_ci */ 116662306a36Sopenharmony_cistatic void ubifs_release_options(struct ubifs_info *c) 116762306a36Sopenharmony_ci{ 116862306a36Sopenharmony_ci kfree(c->auth_key_name); 116962306a36Sopenharmony_ci c->auth_key_name = NULL; 117062306a36Sopenharmony_ci kfree(c->auth_hash_name); 117162306a36Sopenharmony_ci c->auth_hash_name = NULL; 117262306a36Sopenharmony_ci} 117362306a36Sopenharmony_ci 117462306a36Sopenharmony_ci/** 117562306a36Sopenharmony_ci * destroy_journal - destroy journal data structures. 117662306a36Sopenharmony_ci * @c: UBIFS file-system description object 117762306a36Sopenharmony_ci * 117862306a36Sopenharmony_ci * This function destroys journal data structures including those that may have 117962306a36Sopenharmony_ci * been created by recovery functions. 118062306a36Sopenharmony_ci */ 118162306a36Sopenharmony_cistatic void destroy_journal(struct ubifs_info *c) 118262306a36Sopenharmony_ci{ 118362306a36Sopenharmony_ci while (!list_empty(&c->unclean_leb_list)) { 118462306a36Sopenharmony_ci struct ubifs_unclean_leb *ucleb; 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci ucleb = list_entry(c->unclean_leb_list.next, 118762306a36Sopenharmony_ci struct ubifs_unclean_leb, list); 118862306a36Sopenharmony_ci list_del(&ucleb->list); 118962306a36Sopenharmony_ci kfree(ucleb); 119062306a36Sopenharmony_ci } 119162306a36Sopenharmony_ci while (!list_empty(&c->old_buds)) { 119262306a36Sopenharmony_ci struct ubifs_bud *bud; 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci bud = list_entry(c->old_buds.next, struct ubifs_bud, list); 119562306a36Sopenharmony_ci list_del(&bud->list); 119662306a36Sopenharmony_ci kfree(bud); 119762306a36Sopenharmony_ci } 119862306a36Sopenharmony_ci ubifs_destroy_idx_gc(c); 119962306a36Sopenharmony_ci ubifs_destroy_size_tree(c); 120062306a36Sopenharmony_ci ubifs_tnc_close(c); 120162306a36Sopenharmony_ci free_buds(c); 120262306a36Sopenharmony_ci} 120362306a36Sopenharmony_ci 120462306a36Sopenharmony_ci/** 120562306a36Sopenharmony_ci * bu_init - initialize bulk-read information. 120662306a36Sopenharmony_ci * @c: UBIFS file-system description object 120762306a36Sopenharmony_ci */ 120862306a36Sopenharmony_cistatic void bu_init(struct ubifs_info *c) 120962306a36Sopenharmony_ci{ 121062306a36Sopenharmony_ci ubifs_assert(c, c->bulk_read == 1); 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ci if (c->bu.buf) 121362306a36Sopenharmony_ci return; /* Already initialized */ 121462306a36Sopenharmony_ci 121562306a36Sopenharmony_ciagain: 121662306a36Sopenharmony_ci c->bu.buf = kmalloc(c->max_bu_buf_len, GFP_KERNEL | __GFP_NOWARN); 121762306a36Sopenharmony_ci if (!c->bu.buf) { 121862306a36Sopenharmony_ci if (c->max_bu_buf_len > UBIFS_KMALLOC_OK) { 121962306a36Sopenharmony_ci c->max_bu_buf_len = UBIFS_KMALLOC_OK; 122062306a36Sopenharmony_ci goto again; 122162306a36Sopenharmony_ci } 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_ci /* Just disable bulk-read */ 122462306a36Sopenharmony_ci ubifs_warn(c, "cannot allocate %d bytes of memory for bulk-read, disabling it", 122562306a36Sopenharmony_ci c->max_bu_buf_len); 122662306a36Sopenharmony_ci c->mount_opts.bulk_read = 1; 122762306a36Sopenharmony_ci c->bulk_read = 0; 122862306a36Sopenharmony_ci return; 122962306a36Sopenharmony_ci } 123062306a36Sopenharmony_ci} 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_ci/** 123362306a36Sopenharmony_ci * check_free_space - check if there is enough free space to mount. 123462306a36Sopenharmony_ci * @c: UBIFS file-system description object 123562306a36Sopenharmony_ci * 123662306a36Sopenharmony_ci * This function makes sure UBIFS has enough free space to be mounted in 123762306a36Sopenharmony_ci * read/write mode. UBIFS must always have some free space to allow deletions. 123862306a36Sopenharmony_ci */ 123962306a36Sopenharmony_cistatic int check_free_space(struct ubifs_info *c) 124062306a36Sopenharmony_ci{ 124162306a36Sopenharmony_ci ubifs_assert(c, c->dark_wm > 0); 124262306a36Sopenharmony_ci if (c->lst.total_free + c->lst.total_dirty < c->dark_wm) { 124362306a36Sopenharmony_ci ubifs_err(c, "insufficient free space to mount in R/W mode"); 124462306a36Sopenharmony_ci ubifs_dump_budg(c, &c->bi); 124562306a36Sopenharmony_ci ubifs_dump_lprops(c); 124662306a36Sopenharmony_ci return -ENOSPC; 124762306a36Sopenharmony_ci } 124862306a36Sopenharmony_ci return 0; 124962306a36Sopenharmony_ci} 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci/** 125262306a36Sopenharmony_ci * mount_ubifs - mount UBIFS file-system. 125362306a36Sopenharmony_ci * @c: UBIFS file-system description object 125462306a36Sopenharmony_ci * 125562306a36Sopenharmony_ci * This function mounts UBIFS file system. Returns zero in case of success and 125662306a36Sopenharmony_ci * a negative error code in case of failure. 125762306a36Sopenharmony_ci */ 125862306a36Sopenharmony_cistatic int mount_ubifs(struct ubifs_info *c) 125962306a36Sopenharmony_ci{ 126062306a36Sopenharmony_ci int err; 126162306a36Sopenharmony_ci long long x, y; 126262306a36Sopenharmony_ci size_t sz; 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_ci c->ro_mount = !!sb_rdonly(c->vfs_sb); 126562306a36Sopenharmony_ci /* Suppress error messages while probing if SB_SILENT is set */ 126662306a36Sopenharmony_ci c->probing = !!(c->vfs_sb->s_flags & SB_SILENT); 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci err = init_constants_early(c); 126962306a36Sopenharmony_ci if (err) 127062306a36Sopenharmony_ci return err; 127162306a36Sopenharmony_ci 127262306a36Sopenharmony_ci err = ubifs_debugging_init(c); 127362306a36Sopenharmony_ci if (err) 127462306a36Sopenharmony_ci return err; 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_ci err = ubifs_sysfs_register(c); 127762306a36Sopenharmony_ci if (err) 127862306a36Sopenharmony_ci goto out_debugging; 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_ci err = check_volume_empty(c); 128162306a36Sopenharmony_ci if (err) 128262306a36Sopenharmony_ci goto out_free; 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci if (c->empty && (c->ro_mount || c->ro_media)) { 128562306a36Sopenharmony_ci /* 128662306a36Sopenharmony_ci * This UBI volume is empty, and read-only, or the file system 128762306a36Sopenharmony_ci * is mounted read-only - we cannot format it. 128862306a36Sopenharmony_ci */ 128962306a36Sopenharmony_ci ubifs_err(c, "can't format empty UBI volume: read-only %s", 129062306a36Sopenharmony_ci c->ro_media ? "UBI volume" : "mount"); 129162306a36Sopenharmony_ci err = -EROFS; 129262306a36Sopenharmony_ci goto out_free; 129362306a36Sopenharmony_ci } 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci if (c->ro_media && !c->ro_mount) { 129662306a36Sopenharmony_ci ubifs_err(c, "cannot mount read-write - read-only media"); 129762306a36Sopenharmony_ci err = -EROFS; 129862306a36Sopenharmony_ci goto out_free; 129962306a36Sopenharmony_ci } 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci /* 130262306a36Sopenharmony_ci * The requirement for the buffer is that it should fit indexing B-tree 130362306a36Sopenharmony_ci * height amount of integers. We assume the height if the TNC tree will 130462306a36Sopenharmony_ci * never exceed 64. 130562306a36Sopenharmony_ci */ 130662306a36Sopenharmony_ci err = -ENOMEM; 130762306a36Sopenharmony_ci c->bottom_up_buf = kmalloc_array(BOTTOM_UP_HEIGHT, sizeof(int), 130862306a36Sopenharmony_ci GFP_KERNEL); 130962306a36Sopenharmony_ci if (!c->bottom_up_buf) 131062306a36Sopenharmony_ci goto out_free; 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ci c->sbuf = vmalloc(c->leb_size); 131362306a36Sopenharmony_ci if (!c->sbuf) 131462306a36Sopenharmony_ci goto out_free; 131562306a36Sopenharmony_ci 131662306a36Sopenharmony_ci if (!c->ro_mount) { 131762306a36Sopenharmony_ci c->ileb_buf = vmalloc(c->leb_size); 131862306a36Sopenharmony_ci if (!c->ileb_buf) 131962306a36Sopenharmony_ci goto out_free; 132062306a36Sopenharmony_ci } 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci if (c->bulk_read == 1) 132362306a36Sopenharmony_ci bu_init(c); 132462306a36Sopenharmony_ci 132562306a36Sopenharmony_ci if (!c->ro_mount) { 132662306a36Sopenharmony_ci c->write_reserve_buf = kmalloc(COMPRESSED_DATA_NODE_BUF_SZ + \ 132762306a36Sopenharmony_ci UBIFS_CIPHER_BLOCK_SIZE, 132862306a36Sopenharmony_ci GFP_KERNEL); 132962306a36Sopenharmony_ci if (!c->write_reserve_buf) 133062306a36Sopenharmony_ci goto out_free; 133162306a36Sopenharmony_ci } 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci c->mounting = 1; 133462306a36Sopenharmony_ci 133562306a36Sopenharmony_ci if (c->auth_key_name) { 133662306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_UBIFS_FS_AUTHENTICATION)) { 133762306a36Sopenharmony_ci err = ubifs_init_authentication(c); 133862306a36Sopenharmony_ci if (err) 133962306a36Sopenharmony_ci goto out_free; 134062306a36Sopenharmony_ci } else { 134162306a36Sopenharmony_ci ubifs_err(c, "auth_key_name, but UBIFS is built without" 134262306a36Sopenharmony_ci " authentication support"); 134362306a36Sopenharmony_ci err = -EINVAL; 134462306a36Sopenharmony_ci goto out_free; 134562306a36Sopenharmony_ci } 134662306a36Sopenharmony_ci } 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci err = ubifs_read_superblock(c); 134962306a36Sopenharmony_ci if (err) 135062306a36Sopenharmony_ci goto out_auth; 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_ci c->probing = 0; 135362306a36Sopenharmony_ci 135462306a36Sopenharmony_ci /* 135562306a36Sopenharmony_ci * Make sure the compressor which is set as default in the superblock 135662306a36Sopenharmony_ci * or overridden by mount options is actually compiled in. 135762306a36Sopenharmony_ci */ 135862306a36Sopenharmony_ci if (!ubifs_compr_present(c, c->default_compr)) { 135962306a36Sopenharmony_ci ubifs_err(c, "'compressor \"%s\" is not compiled in", 136062306a36Sopenharmony_ci ubifs_compr_name(c, c->default_compr)); 136162306a36Sopenharmony_ci err = -ENOTSUPP; 136262306a36Sopenharmony_ci goto out_auth; 136362306a36Sopenharmony_ci } 136462306a36Sopenharmony_ci 136562306a36Sopenharmony_ci err = init_constants_sb(c); 136662306a36Sopenharmony_ci if (err) 136762306a36Sopenharmony_ci goto out_auth; 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci sz = ALIGN(c->max_idx_node_sz, c->min_io_size) * 2; 137062306a36Sopenharmony_ci c->cbuf = kmalloc(sz, GFP_NOFS); 137162306a36Sopenharmony_ci if (!c->cbuf) { 137262306a36Sopenharmony_ci err = -ENOMEM; 137362306a36Sopenharmony_ci goto out_auth; 137462306a36Sopenharmony_ci } 137562306a36Sopenharmony_ci 137662306a36Sopenharmony_ci err = alloc_wbufs(c); 137762306a36Sopenharmony_ci if (err) 137862306a36Sopenharmony_ci goto out_cbuf; 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_ci sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id); 138162306a36Sopenharmony_ci if (!c->ro_mount) { 138262306a36Sopenharmony_ci /* Create background thread */ 138362306a36Sopenharmony_ci c->bgt = kthread_run(ubifs_bg_thread, c, "%s", c->bgt_name); 138462306a36Sopenharmony_ci if (IS_ERR(c->bgt)) { 138562306a36Sopenharmony_ci err = PTR_ERR(c->bgt); 138662306a36Sopenharmony_ci c->bgt = NULL; 138762306a36Sopenharmony_ci ubifs_err(c, "cannot spawn \"%s\", error %d", 138862306a36Sopenharmony_ci c->bgt_name, err); 138962306a36Sopenharmony_ci goto out_wbufs; 139062306a36Sopenharmony_ci } 139162306a36Sopenharmony_ci } 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci err = ubifs_read_master(c); 139462306a36Sopenharmony_ci if (err) 139562306a36Sopenharmony_ci goto out_master; 139662306a36Sopenharmony_ci 139762306a36Sopenharmony_ci init_constants_master(c); 139862306a36Sopenharmony_ci 139962306a36Sopenharmony_ci if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) { 140062306a36Sopenharmony_ci ubifs_msg(c, "recovery needed"); 140162306a36Sopenharmony_ci c->need_recovery = 1; 140262306a36Sopenharmony_ci } 140362306a36Sopenharmony_ci 140462306a36Sopenharmony_ci if (c->need_recovery && !c->ro_mount) { 140562306a36Sopenharmony_ci err = ubifs_recover_inl_heads(c, c->sbuf); 140662306a36Sopenharmony_ci if (err) 140762306a36Sopenharmony_ci goto out_master; 140862306a36Sopenharmony_ci } 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_ci err = ubifs_lpt_init(c, 1, !c->ro_mount); 141162306a36Sopenharmony_ci if (err) 141262306a36Sopenharmony_ci goto out_master; 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_ci if (!c->ro_mount && c->space_fixup) { 141562306a36Sopenharmony_ci err = ubifs_fixup_free_space(c); 141662306a36Sopenharmony_ci if (err) 141762306a36Sopenharmony_ci goto out_lpt; 141862306a36Sopenharmony_ci } 141962306a36Sopenharmony_ci 142062306a36Sopenharmony_ci if (!c->ro_mount && !c->need_recovery) { 142162306a36Sopenharmony_ci /* 142262306a36Sopenharmony_ci * Set the "dirty" flag so that if we reboot uncleanly we 142362306a36Sopenharmony_ci * will notice this immediately on the next mount. 142462306a36Sopenharmony_ci */ 142562306a36Sopenharmony_ci c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY); 142662306a36Sopenharmony_ci err = ubifs_write_master(c); 142762306a36Sopenharmony_ci if (err) 142862306a36Sopenharmony_ci goto out_lpt; 142962306a36Sopenharmony_ci } 143062306a36Sopenharmony_ci 143162306a36Sopenharmony_ci /* 143262306a36Sopenharmony_ci * Handle offline signed images: Now that the master node is 143362306a36Sopenharmony_ci * written and its validation no longer depends on the hash 143462306a36Sopenharmony_ci * in the superblock, we can update the offline signed 143562306a36Sopenharmony_ci * superblock with a HMAC version, 143662306a36Sopenharmony_ci */ 143762306a36Sopenharmony_ci if (ubifs_authenticated(c) && ubifs_hmac_zero(c, c->sup_node->hmac)) { 143862306a36Sopenharmony_ci err = ubifs_hmac_wkm(c, c->sup_node->hmac_wkm); 143962306a36Sopenharmony_ci if (err) 144062306a36Sopenharmony_ci goto out_lpt; 144162306a36Sopenharmony_ci c->superblock_need_write = 1; 144262306a36Sopenharmony_ci } 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_ci if (!c->ro_mount && c->superblock_need_write) { 144562306a36Sopenharmony_ci err = ubifs_write_sb_node(c, c->sup_node); 144662306a36Sopenharmony_ci if (err) 144762306a36Sopenharmony_ci goto out_lpt; 144862306a36Sopenharmony_ci c->superblock_need_write = 0; 144962306a36Sopenharmony_ci } 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_ci err = dbg_check_idx_size(c, c->bi.old_idx_sz); 145262306a36Sopenharmony_ci if (err) 145362306a36Sopenharmony_ci goto out_lpt; 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_ci err = ubifs_replay_journal(c); 145662306a36Sopenharmony_ci if (err) 145762306a36Sopenharmony_ci goto out_journal; 145862306a36Sopenharmony_ci 145962306a36Sopenharmony_ci /* Calculate 'min_idx_lebs' after journal replay */ 146062306a36Sopenharmony_ci c->bi.min_idx_lebs = ubifs_calc_min_idx_lebs(c); 146162306a36Sopenharmony_ci 146262306a36Sopenharmony_ci err = ubifs_mount_orphans(c, c->need_recovery, c->ro_mount); 146362306a36Sopenharmony_ci if (err) 146462306a36Sopenharmony_ci goto out_orphans; 146562306a36Sopenharmony_ci 146662306a36Sopenharmony_ci if (!c->ro_mount) { 146762306a36Sopenharmony_ci int lnum; 146862306a36Sopenharmony_ci 146962306a36Sopenharmony_ci err = check_free_space(c); 147062306a36Sopenharmony_ci if (err) 147162306a36Sopenharmony_ci goto out_orphans; 147262306a36Sopenharmony_ci 147362306a36Sopenharmony_ci /* Check for enough log space */ 147462306a36Sopenharmony_ci lnum = c->lhead_lnum + 1; 147562306a36Sopenharmony_ci if (lnum >= UBIFS_LOG_LNUM + c->log_lebs) 147662306a36Sopenharmony_ci lnum = UBIFS_LOG_LNUM; 147762306a36Sopenharmony_ci if (lnum == c->ltail_lnum) { 147862306a36Sopenharmony_ci err = ubifs_consolidate_log(c); 147962306a36Sopenharmony_ci if (err) 148062306a36Sopenharmony_ci goto out_orphans; 148162306a36Sopenharmony_ci } 148262306a36Sopenharmony_ci 148362306a36Sopenharmony_ci if (c->need_recovery) { 148462306a36Sopenharmony_ci if (!ubifs_authenticated(c)) { 148562306a36Sopenharmony_ci err = ubifs_recover_size(c, true); 148662306a36Sopenharmony_ci if (err) 148762306a36Sopenharmony_ci goto out_orphans; 148862306a36Sopenharmony_ci } 148962306a36Sopenharmony_ci 149062306a36Sopenharmony_ci err = ubifs_rcvry_gc_commit(c); 149162306a36Sopenharmony_ci if (err) 149262306a36Sopenharmony_ci goto out_orphans; 149362306a36Sopenharmony_ci 149462306a36Sopenharmony_ci if (ubifs_authenticated(c)) { 149562306a36Sopenharmony_ci err = ubifs_recover_size(c, false); 149662306a36Sopenharmony_ci if (err) 149762306a36Sopenharmony_ci goto out_orphans; 149862306a36Sopenharmony_ci } 149962306a36Sopenharmony_ci } else { 150062306a36Sopenharmony_ci err = take_gc_lnum(c); 150162306a36Sopenharmony_ci if (err) 150262306a36Sopenharmony_ci goto out_orphans; 150362306a36Sopenharmony_ci 150462306a36Sopenharmony_ci /* 150562306a36Sopenharmony_ci * GC LEB may contain garbage if there was an unclean 150662306a36Sopenharmony_ci * reboot, and it should be un-mapped. 150762306a36Sopenharmony_ci */ 150862306a36Sopenharmony_ci err = ubifs_leb_unmap(c, c->gc_lnum); 150962306a36Sopenharmony_ci if (err) 151062306a36Sopenharmony_ci goto out_orphans; 151162306a36Sopenharmony_ci } 151262306a36Sopenharmony_ci 151362306a36Sopenharmony_ci err = dbg_check_lprops(c); 151462306a36Sopenharmony_ci if (err) 151562306a36Sopenharmony_ci goto out_orphans; 151662306a36Sopenharmony_ci } else if (c->need_recovery) { 151762306a36Sopenharmony_ci err = ubifs_recover_size(c, false); 151862306a36Sopenharmony_ci if (err) 151962306a36Sopenharmony_ci goto out_orphans; 152062306a36Sopenharmony_ci } else { 152162306a36Sopenharmony_ci /* 152262306a36Sopenharmony_ci * Even if we mount read-only, we have to set space in GC LEB 152362306a36Sopenharmony_ci * to proper value because this affects UBIFS free space 152462306a36Sopenharmony_ci * reporting. We do not want to have a situation when 152562306a36Sopenharmony_ci * re-mounting from R/O to R/W changes amount of free space. 152662306a36Sopenharmony_ci */ 152762306a36Sopenharmony_ci err = take_gc_lnum(c); 152862306a36Sopenharmony_ci if (err) 152962306a36Sopenharmony_ci goto out_orphans; 153062306a36Sopenharmony_ci } 153162306a36Sopenharmony_ci 153262306a36Sopenharmony_ci spin_lock(&ubifs_infos_lock); 153362306a36Sopenharmony_ci list_add_tail(&c->infos_list, &ubifs_infos); 153462306a36Sopenharmony_ci spin_unlock(&ubifs_infos_lock); 153562306a36Sopenharmony_ci 153662306a36Sopenharmony_ci if (c->need_recovery) { 153762306a36Sopenharmony_ci if (c->ro_mount) 153862306a36Sopenharmony_ci ubifs_msg(c, "recovery deferred"); 153962306a36Sopenharmony_ci else { 154062306a36Sopenharmony_ci c->need_recovery = 0; 154162306a36Sopenharmony_ci ubifs_msg(c, "recovery completed"); 154262306a36Sopenharmony_ci /* 154362306a36Sopenharmony_ci * GC LEB has to be empty and taken at this point. But 154462306a36Sopenharmony_ci * the journal head LEBs may also be accounted as 154562306a36Sopenharmony_ci * "empty taken" if they are empty. 154662306a36Sopenharmony_ci */ 154762306a36Sopenharmony_ci ubifs_assert(c, c->lst.taken_empty_lebs > 0); 154862306a36Sopenharmony_ci } 154962306a36Sopenharmony_ci } else 155062306a36Sopenharmony_ci ubifs_assert(c, c->lst.taken_empty_lebs > 0); 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_ci err = dbg_check_filesystem(c); 155362306a36Sopenharmony_ci if (err) 155462306a36Sopenharmony_ci goto out_infos; 155562306a36Sopenharmony_ci 155662306a36Sopenharmony_ci dbg_debugfs_init_fs(c); 155762306a36Sopenharmony_ci 155862306a36Sopenharmony_ci c->mounting = 0; 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci ubifs_msg(c, "UBIFS: mounted UBI device %d, volume %d, name \"%s\"%s", 156162306a36Sopenharmony_ci c->vi.ubi_num, c->vi.vol_id, c->vi.name, 156262306a36Sopenharmony_ci c->ro_mount ? ", R/O mode" : ""); 156362306a36Sopenharmony_ci x = (long long)c->main_lebs * c->leb_size; 156462306a36Sopenharmony_ci y = (long long)c->log_lebs * c->leb_size + c->max_bud_bytes; 156562306a36Sopenharmony_ci ubifs_msg(c, "LEB size: %d bytes (%d KiB), min./max. I/O unit sizes: %d bytes/%d bytes", 156662306a36Sopenharmony_ci c->leb_size, c->leb_size >> 10, c->min_io_size, 156762306a36Sopenharmony_ci c->max_write_size); 156862306a36Sopenharmony_ci ubifs_msg(c, "FS size: %lld bytes (%lld MiB, %d LEBs), max %d LEBs, journal size %lld bytes (%lld MiB, %d LEBs)", 156962306a36Sopenharmony_ci x, x >> 20, c->main_lebs, c->max_leb_cnt, 157062306a36Sopenharmony_ci y, y >> 20, c->log_lebs + c->max_bud_cnt); 157162306a36Sopenharmony_ci ubifs_msg(c, "reserved for root: %llu bytes (%llu KiB)", 157262306a36Sopenharmony_ci c->report_rp_size, c->report_rp_size >> 10); 157362306a36Sopenharmony_ci ubifs_msg(c, "media format: w%d/r%d (latest is w%d/r%d), UUID %pUB%s", 157462306a36Sopenharmony_ci c->fmt_version, c->ro_compat_version, 157562306a36Sopenharmony_ci UBIFS_FORMAT_VERSION, UBIFS_RO_COMPAT_VERSION, c->uuid, 157662306a36Sopenharmony_ci c->big_lpt ? ", big LPT model" : ", small LPT model"); 157762306a36Sopenharmony_ci 157862306a36Sopenharmony_ci dbg_gen("default compressor: %s", ubifs_compr_name(c, c->default_compr)); 157962306a36Sopenharmony_ci dbg_gen("data journal heads: %d", 158062306a36Sopenharmony_ci c->jhead_cnt - NONDATA_JHEADS_CNT); 158162306a36Sopenharmony_ci dbg_gen("log LEBs: %d (%d - %d)", 158262306a36Sopenharmony_ci c->log_lebs, UBIFS_LOG_LNUM, c->log_last); 158362306a36Sopenharmony_ci dbg_gen("LPT area LEBs: %d (%d - %d)", 158462306a36Sopenharmony_ci c->lpt_lebs, c->lpt_first, c->lpt_last); 158562306a36Sopenharmony_ci dbg_gen("orphan area LEBs: %d (%d - %d)", 158662306a36Sopenharmony_ci c->orph_lebs, c->orph_first, c->orph_last); 158762306a36Sopenharmony_ci dbg_gen("main area LEBs: %d (%d - %d)", 158862306a36Sopenharmony_ci c->main_lebs, c->main_first, c->leb_cnt - 1); 158962306a36Sopenharmony_ci dbg_gen("index LEBs: %d", c->lst.idx_lebs); 159062306a36Sopenharmony_ci dbg_gen("total index bytes: %llu (%llu KiB, %llu MiB)", 159162306a36Sopenharmony_ci c->bi.old_idx_sz, c->bi.old_idx_sz >> 10, 159262306a36Sopenharmony_ci c->bi.old_idx_sz >> 20); 159362306a36Sopenharmony_ci dbg_gen("key hash type: %d", c->key_hash_type); 159462306a36Sopenharmony_ci dbg_gen("tree fanout: %d", c->fanout); 159562306a36Sopenharmony_ci dbg_gen("reserved GC LEB: %d", c->gc_lnum); 159662306a36Sopenharmony_ci dbg_gen("max. znode size %d", c->max_znode_sz); 159762306a36Sopenharmony_ci dbg_gen("max. index node size %d", c->max_idx_node_sz); 159862306a36Sopenharmony_ci dbg_gen("node sizes: data %zu, inode %zu, dentry %zu", 159962306a36Sopenharmony_ci UBIFS_DATA_NODE_SZ, UBIFS_INO_NODE_SZ, UBIFS_DENT_NODE_SZ); 160062306a36Sopenharmony_ci dbg_gen("node sizes: trun %zu, sb %zu, master %zu", 160162306a36Sopenharmony_ci UBIFS_TRUN_NODE_SZ, UBIFS_SB_NODE_SZ, UBIFS_MST_NODE_SZ); 160262306a36Sopenharmony_ci dbg_gen("node sizes: ref %zu, cmt. start %zu, orph %zu", 160362306a36Sopenharmony_ci UBIFS_REF_NODE_SZ, UBIFS_CS_NODE_SZ, UBIFS_ORPH_NODE_SZ); 160462306a36Sopenharmony_ci dbg_gen("max. node sizes: data %zu, inode %zu dentry %zu, idx %d", 160562306a36Sopenharmony_ci UBIFS_MAX_DATA_NODE_SZ, UBIFS_MAX_INO_NODE_SZ, 160662306a36Sopenharmony_ci UBIFS_MAX_DENT_NODE_SZ, ubifs_idx_node_sz(c, c->fanout)); 160762306a36Sopenharmony_ci dbg_gen("dead watermark: %d", c->dead_wm); 160862306a36Sopenharmony_ci dbg_gen("dark watermark: %d", c->dark_wm); 160962306a36Sopenharmony_ci dbg_gen("LEB overhead: %d", c->leb_overhead); 161062306a36Sopenharmony_ci x = (long long)c->main_lebs * c->dark_wm; 161162306a36Sopenharmony_ci dbg_gen("max. dark space: %lld (%lld KiB, %lld MiB)", 161262306a36Sopenharmony_ci x, x >> 10, x >> 20); 161362306a36Sopenharmony_ci dbg_gen("maximum bud bytes: %lld (%lld KiB, %lld MiB)", 161462306a36Sopenharmony_ci c->max_bud_bytes, c->max_bud_bytes >> 10, 161562306a36Sopenharmony_ci c->max_bud_bytes >> 20); 161662306a36Sopenharmony_ci dbg_gen("BG commit bud bytes: %lld (%lld KiB, %lld MiB)", 161762306a36Sopenharmony_ci c->bg_bud_bytes, c->bg_bud_bytes >> 10, 161862306a36Sopenharmony_ci c->bg_bud_bytes >> 20); 161962306a36Sopenharmony_ci dbg_gen("current bud bytes %lld (%lld KiB, %lld MiB)", 162062306a36Sopenharmony_ci c->bud_bytes, c->bud_bytes >> 10, c->bud_bytes >> 20); 162162306a36Sopenharmony_ci dbg_gen("max. seq. number: %llu", c->max_sqnum); 162262306a36Sopenharmony_ci dbg_gen("commit number: %llu", c->cmt_no); 162362306a36Sopenharmony_ci dbg_gen("max. xattrs per inode: %d", ubifs_xattr_max_cnt(c)); 162462306a36Sopenharmony_ci dbg_gen("max orphans: %d", c->max_orphans); 162562306a36Sopenharmony_ci 162662306a36Sopenharmony_ci return 0; 162762306a36Sopenharmony_ci 162862306a36Sopenharmony_ciout_infos: 162962306a36Sopenharmony_ci spin_lock(&ubifs_infos_lock); 163062306a36Sopenharmony_ci list_del(&c->infos_list); 163162306a36Sopenharmony_ci spin_unlock(&ubifs_infos_lock); 163262306a36Sopenharmony_ciout_orphans: 163362306a36Sopenharmony_ci free_orphans(c); 163462306a36Sopenharmony_ciout_journal: 163562306a36Sopenharmony_ci destroy_journal(c); 163662306a36Sopenharmony_ciout_lpt: 163762306a36Sopenharmony_ci ubifs_lpt_free(c, 0); 163862306a36Sopenharmony_ciout_master: 163962306a36Sopenharmony_ci kfree(c->mst_node); 164062306a36Sopenharmony_ci kfree(c->rcvrd_mst_node); 164162306a36Sopenharmony_ci if (c->bgt) 164262306a36Sopenharmony_ci kthread_stop(c->bgt); 164362306a36Sopenharmony_ciout_wbufs: 164462306a36Sopenharmony_ci free_wbufs(c); 164562306a36Sopenharmony_ciout_cbuf: 164662306a36Sopenharmony_ci kfree(c->cbuf); 164762306a36Sopenharmony_ciout_auth: 164862306a36Sopenharmony_ci ubifs_exit_authentication(c); 164962306a36Sopenharmony_ciout_free: 165062306a36Sopenharmony_ci kfree(c->write_reserve_buf); 165162306a36Sopenharmony_ci kfree(c->bu.buf); 165262306a36Sopenharmony_ci vfree(c->ileb_buf); 165362306a36Sopenharmony_ci vfree(c->sbuf); 165462306a36Sopenharmony_ci kfree(c->bottom_up_buf); 165562306a36Sopenharmony_ci kfree(c->sup_node); 165662306a36Sopenharmony_ci ubifs_sysfs_unregister(c); 165762306a36Sopenharmony_ciout_debugging: 165862306a36Sopenharmony_ci ubifs_debugging_exit(c); 165962306a36Sopenharmony_ci return err; 166062306a36Sopenharmony_ci} 166162306a36Sopenharmony_ci 166262306a36Sopenharmony_ci/** 166362306a36Sopenharmony_ci * ubifs_umount - un-mount UBIFS file-system. 166462306a36Sopenharmony_ci * @c: UBIFS file-system description object 166562306a36Sopenharmony_ci * 166662306a36Sopenharmony_ci * Note, this function is called to free allocated resourced when un-mounting, 166762306a36Sopenharmony_ci * as well as free resources when an error occurred while we were half way 166862306a36Sopenharmony_ci * through mounting (error path cleanup function). So it has to make sure the 166962306a36Sopenharmony_ci * resource was actually allocated before freeing it. 167062306a36Sopenharmony_ci */ 167162306a36Sopenharmony_cistatic void ubifs_umount(struct ubifs_info *c) 167262306a36Sopenharmony_ci{ 167362306a36Sopenharmony_ci dbg_gen("un-mounting UBI device %d, volume %d", c->vi.ubi_num, 167462306a36Sopenharmony_ci c->vi.vol_id); 167562306a36Sopenharmony_ci 167662306a36Sopenharmony_ci dbg_debugfs_exit_fs(c); 167762306a36Sopenharmony_ci spin_lock(&ubifs_infos_lock); 167862306a36Sopenharmony_ci list_del(&c->infos_list); 167962306a36Sopenharmony_ci spin_unlock(&ubifs_infos_lock); 168062306a36Sopenharmony_ci 168162306a36Sopenharmony_ci if (c->bgt) 168262306a36Sopenharmony_ci kthread_stop(c->bgt); 168362306a36Sopenharmony_ci 168462306a36Sopenharmony_ci destroy_journal(c); 168562306a36Sopenharmony_ci free_wbufs(c); 168662306a36Sopenharmony_ci free_orphans(c); 168762306a36Sopenharmony_ci ubifs_lpt_free(c, 0); 168862306a36Sopenharmony_ci ubifs_exit_authentication(c); 168962306a36Sopenharmony_ci 169062306a36Sopenharmony_ci ubifs_release_options(c); 169162306a36Sopenharmony_ci kfree(c->cbuf); 169262306a36Sopenharmony_ci kfree(c->rcvrd_mst_node); 169362306a36Sopenharmony_ci kfree(c->mst_node); 169462306a36Sopenharmony_ci kfree(c->write_reserve_buf); 169562306a36Sopenharmony_ci kfree(c->bu.buf); 169662306a36Sopenharmony_ci vfree(c->ileb_buf); 169762306a36Sopenharmony_ci vfree(c->sbuf); 169862306a36Sopenharmony_ci kfree(c->bottom_up_buf); 169962306a36Sopenharmony_ci kfree(c->sup_node); 170062306a36Sopenharmony_ci ubifs_debugging_exit(c); 170162306a36Sopenharmony_ci ubifs_sysfs_unregister(c); 170262306a36Sopenharmony_ci} 170362306a36Sopenharmony_ci 170462306a36Sopenharmony_ci/** 170562306a36Sopenharmony_ci * ubifs_remount_rw - re-mount in read-write mode. 170662306a36Sopenharmony_ci * @c: UBIFS file-system description object 170762306a36Sopenharmony_ci * 170862306a36Sopenharmony_ci * UBIFS avoids allocating many unnecessary resources when mounted in read-only 170962306a36Sopenharmony_ci * mode. This function allocates the needed resources and re-mounts UBIFS in 171062306a36Sopenharmony_ci * read-write mode. 171162306a36Sopenharmony_ci */ 171262306a36Sopenharmony_cistatic int ubifs_remount_rw(struct ubifs_info *c) 171362306a36Sopenharmony_ci{ 171462306a36Sopenharmony_ci int err, lnum; 171562306a36Sopenharmony_ci 171662306a36Sopenharmony_ci if (c->rw_incompat) { 171762306a36Sopenharmony_ci ubifs_err(c, "the file-system is not R/W-compatible"); 171862306a36Sopenharmony_ci ubifs_msg(c, "on-flash format version is w%d/r%d, but software only supports up to version w%d/r%d", 171962306a36Sopenharmony_ci c->fmt_version, c->ro_compat_version, 172062306a36Sopenharmony_ci UBIFS_FORMAT_VERSION, UBIFS_RO_COMPAT_VERSION); 172162306a36Sopenharmony_ci return -EROFS; 172262306a36Sopenharmony_ci } 172362306a36Sopenharmony_ci 172462306a36Sopenharmony_ci mutex_lock(&c->umount_mutex); 172562306a36Sopenharmony_ci dbg_save_space_info(c); 172662306a36Sopenharmony_ci c->remounting_rw = 1; 172762306a36Sopenharmony_ci c->ro_mount = 0; 172862306a36Sopenharmony_ci 172962306a36Sopenharmony_ci if (c->space_fixup) { 173062306a36Sopenharmony_ci err = ubifs_fixup_free_space(c); 173162306a36Sopenharmony_ci if (err) 173262306a36Sopenharmony_ci goto out; 173362306a36Sopenharmony_ci } 173462306a36Sopenharmony_ci 173562306a36Sopenharmony_ci err = check_free_space(c); 173662306a36Sopenharmony_ci if (err) 173762306a36Sopenharmony_ci goto out; 173862306a36Sopenharmony_ci 173962306a36Sopenharmony_ci if (c->need_recovery) { 174062306a36Sopenharmony_ci ubifs_msg(c, "completing deferred recovery"); 174162306a36Sopenharmony_ci err = ubifs_write_rcvrd_mst_node(c); 174262306a36Sopenharmony_ci if (err) 174362306a36Sopenharmony_ci goto out; 174462306a36Sopenharmony_ci if (!ubifs_authenticated(c)) { 174562306a36Sopenharmony_ci err = ubifs_recover_size(c, true); 174662306a36Sopenharmony_ci if (err) 174762306a36Sopenharmony_ci goto out; 174862306a36Sopenharmony_ci } 174962306a36Sopenharmony_ci err = ubifs_clean_lebs(c, c->sbuf); 175062306a36Sopenharmony_ci if (err) 175162306a36Sopenharmony_ci goto out; 175262306a36Sopenharmony_ci err = ubifs_recover_inl_heads(c, c->sbuf); 175362306a36Sopenharmony_ci if (err) 175462306a36Sopenharmony_ci goto out; 175562306a36Sopenharmony_ci } else { 175662306a36Sopenharmony_ci /* A readonly mount is not allowed to have orphans */ 175762306a36Sopenharmony_ci ubifs_assert(c, c->tot_orphans == 0); 175862306a36Sopenharmony_ci err = ubifs_clear_orphans(c); 175962306a36Sopenharmony_ci if (err) 176062306a36Sopenharmony_ci goto out; 176162306a36Sopenharmony_ci } 176262306a36Sopenharmony_ci 176362306a36Sopenharmony_ci if (!(c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY))) { 176462306a36Sopenharmony_ci c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY); 176562306a36Sopenharmony_ci err = ubifs_write_master(c); 176662306a36Sopenharmony_ci if (err) 176762306a36Sopenharmony_ci goto out; 176862306a36Sopenharmony_ci } 176962306a36Sopenharmony_ci 177062306a36Sopenharmony_ci if (c->superblock_need_write) { 177162306a36Sopenharmony_ci struct ubifs_sb_node *sup = c->sup_node; 177262306a36Sopenharmony_ci 177362306a36Sopenharmony_ci err = ubifs_write_sb_node(c, sup); 177462306a36Sopenharmony_ci if (err) 177562306a36Sopenharmony_ci goto out; 177662306a36Sopenharmony_ci 177762306a36Sopenharmony_ci c->superblock_need_write = 0; 177862306a36Sopenharmony_ci } 177962306a36Sopenharmony_ci 178062306a36Sopenharmony_ci c->ileb_buf = vmalloc(c->leb_size); 178162306a36Sopenharmony_ci if (!c->ileb_buf) { 178262306a36Sopenharmony_ci err = -ENOMEM; 178362306a36Sopenharmony_ci goto out; 178462306a36Sopenharmony_ci } 178562306a36Sopenharmony_ci 178662306a36Sopenharmony_ci c->write_reserve_buf = kmalloc(COMPRESSED_DATA_NODE_BUF_SZ + \ 178762306a36Sopenharmony_ci UBIFS_CIPHER_BLOCK_SIZE, GFP_KERNEL); 178862306a36Sopenharmony_ci if (!c->write_reserve_buf) { 178962306a36Sopenharmony_ci err = -ENOMEM; 179062306a36Sopenharmony_ci goto out; 179162306a36Sopenharmony_ci } 179262306a36Sopenharmony_ci 179362306a36Sopenharmony_ci err = ubifs_lpt_init(c, 0, 1); 179462306a36Sopenharmony_ci if (err) 179562306a36Sopenharmony_ci goto out; 179662306a36Sopenharmony_ci 179762306a36Sopenharmony_ci /* Create background thread */ 179862306a36Sopenharmony_ci c->bgt = kthread_run(ubifs_bg_thread, c, "%s", c->bgt_name); 179962306a36Sopenharmony_ci if (IS_ERR(c->bgt)) { 180062306a36Sopenharmony_ci err = PTR_ERR(c->bgt); 180162306a36Sopenharmony_ci c->bgt = NULL; 180262306a36Sopenharmony_ci ubifs_err(c, "cannot spawn \"%s\", error %d", 180362306a36Sopenharmony_ci c->bgt_name, err); 180462306a36Sopenharmony_ci goto out; 180562306a36Sopenharmony_ci } 180662306a36Sopenharmony_ci 180762306a36Sopenharmony_ci c->orph_buf = vmalloc(c->leb_size); 180862306a36Sopenharmony_ci if (!c->orph_buf) { 180962306a36Sopenharmony_ci err = -ENOMEM; 181062306a36Sopenharmony_ci goto out; 181162306a36Sopenharmony_ci } 181262306a36Sopenharmony_ci 181362306a36Sopenharmony_ci /* Check for enough log space */ 181462306a36Sopenharmony_ci lnum = c->lhead_lnum + 1; 181562306a36Sopenharmony_ci if (lnum >= UBIFS_LOG_LNUM + c->log_lebs) 181662306a36Sopenharmony_ci lnum = UBIFS_LOG_LNUM; 181762306a36Sopenharmony_ci if (lnum == c->ltail_lnum) { 181862306a36Sopenharmony_ci err = ubifs_consolidate_log(c); 181962306a36Sopenharmony_ci if (err) 182062306a36Sopenharmony_ci goto out; 182162306a36Sopenharmony_ci } 182262306a36Sopenharmony_ci 182362306a36Sopenharmony_ci if (c->need_recovery) { 182462306a36Sopenharmony_ci err = ubifs_rcvry_gc_commit(c); 182562306a36Sopenharmony_ci if (err) 182662306a36Sopenharmony_ci goto out; 182762306a36Sopenharmony_ci 182862306a36Sopenharmony_ci if (ubifs_authenticated(c)) { 182962306a36Sopenharmony_ci err = ubifs_recover_size(c, false); 183062306a36Sopenharmony_ci if (err) 183162306a36Sopenharmony_ci goto out; 183262306a36Sopenharmony_ci } 183362306a36Sopenharmony_ci } else { 183462306a36Sopenharmony_ci err = ubifs_leb_unmap(c, c->gc_lnum); 183562306a36Sopenharmony_ci } 183662306a36Sopenharmony_ci if (err) 183762306a36Sopenharmony_ci goto out; 183862306a36Sopenharmony_ci 183962306a36Sopenharmony_ci dbg_gen("re-mounted read-write"); 184062306a36Sopenharmony_ci c->remounting_rw = 0; 184162306a36Sopenharmony_ci 184262306a36Sopenharmony_ci if (c->need_recovery) { 184362306a36Sopenharmony_ci c->need_recovery = 0; 184462306a36Sopenharmony_ci ubifs_msg(c, "deferred recovery completed"); 184562306a36Sopenharmony_ci } else { 184662306a36Sopenharmony_ci /* 184762306a36Sopenharmony_ci * Do not run the debugging space check if the were doing 184862306a36Sopenharmony_ci * recovery, because when we saved the information we had the 184962306a36Sopenharmony_ci * file-system in a state where the TNC and lprops has been 185062306a36Sopenharmony_ci * modified in memory, but all the I/O operations (including a 185162306a36Sopenharmony_ci * commit) were deferred. So the file-system was in 185262306a36Sopenharmony_ci * "non-committed" state. Now the file-system is in committed 185362306a36Sopenharmony_ci * state, and of course the amount of free space will change 185462306a36Sopenharmony_ci * because, for example, the old index size was imprecise. 185562306a36Sopenharmony_ci */ 185662306a36Sopenharmony_ci err = dbg_check_space_info(c); 185762306a36Sopenharmony_ci } 185862306a36Sopenharmony_ci 185962306a36Sopenharmony_ci mutex_unlock(&c->umount_mutex); 186062306a36Sopenharmony_ci return err; 186162306a36Sopenharmony_ci 186262306a36Sopenharmony_ciout: 186362306a36Sopenharmony_ci c->ro_mount = 1; 186462306a36Sopenharmony_ci vfree(c->orph_buf); 186562306a36Sopenharmony_ci c->orph_buf = NULL; 186662306a36Sopenharmony_ci if (c->bgt) { 186762306a36Sopenharmony_ci kthread_stop(c->bgt); 186862306a36Sopenharmony_ci c->bgt = NULL; 186962306a36Sopenharmony_ci } 187062306a36Sopenharmony_ci kfree(c->write_reserve_buf); 187162306a36Sopenharmony_ci c->write_reserve_buf = NULL; 187262306a36Sopenharmony_ci vfree(c->ileb_buf); 187362306a36Sopenharmony_ci c->ileb_buf = NULL; 187462306a36Sopenharmony_ci ubifs_lpt_free(c, 1); 187562306a36Sopenharmony_ci c->remounting_rw = 0; 187662306a36Sopenharmony_ci mutex_unlock(&c->umount_mutex); 187762306a36Sopenharmony_ci return err; 187862306a36Sopenharmony_ci} 187962306a36Sopenharmony_ci 188062306a36Sopenharmony_ci/** 188162306a36Sopenharmony_ci * ubifs_remount_ro - re-mount in read-only mode. 188262306a36Sopenharmony_ci * @c: UBIFS file-system description object 188362306a36Sopenharmony_ci * 188462306a36Sopenharmony_ci * We assume VFS has stopped writing. Possibly the background thread could be 188562306a36Sopenharmony_ci * running a commit, however kthread_stop will wait in that case. 188662306a36Sopenharmony_ci */ 188762306a36Sopenharmony_cistatic void ubifs_remount_ro(struct ubifs_info *c) 188862306a36Sopenharmony_ci{ 188962306a36Sopenharmony_ci int i, err; 189062306a36Sopenharmony_ci 189162306a36Sopenharmony_ci ubifs_assert(c, !c->need_recovery); 189262306a36Sopenharmony_ci ubifs_assert(c, !c->ro_mount); 189362306a36Sopenharmony_ci 189462306a36Sopenharmony_ci mutex_lock(&c->umount_mutex); 189562306a36Sopenharmony_ci if (c->bgt) { 189662306a36Sopenharmony_ci kthread_stop(c->bgt); 189762306a36Sopenharmony_ci c->bgt = NULL; 189862306a36Sopenharmony_ci } 189962306a36Sopenharmony_ci 190062306a36Sopenharmony_ci dbg_save_space_info(c); 190162306a36Sopenharmony_ci 190262306a36Sopenharmony_ci for (i = 0; i < c->jhead_cnt; i++) { 190362306a36Sopenharmony_ci err = ubifs_wbuf_sync(&c->jheads[i].wbuf); 190462306a36Sopenharmony_ci if (err) 190562306a36Sopenharmony_ci ubifs_ro_mode(c, err); 190662306a36Sopenharmony_ci } 190762306a36Sopenharmony_ci 190862306a36Sopenharmony_ci c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY); 190962306a36Sopenharmony_ci c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS); 191062306a36Sopenharmony_ci c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum); 191162306a36Sopenharmony_ci err = ubifs_write_master(c); 191262306a36Sopenharmony_ci if (err) 191362306a36Sopenharmony_ci ubifs_ro_mode(c, err); 191462306a36Sopenharmony_ci 191562306a36Sopenharmony_ci vfree(c->orph_buf); 191662306a36Sopenharmony_ci c->orph_buf = NULL; 191762306a36Sopenharmony_ci kfree(c->write_reserve_buf); 191862306a36Sopenharmony_ci c->write_reserve_buf = NULL; 191962306a36Sopenharmony_ci vfree(c->ileb_buf); 192062306a36Sopenharmony_ci c->ileb_buf = NULL; 192162306a36Sopenharmony_ci ubifs_lpt_free(c, 1); 192262306a36Sopenharmony_ci c->ro_mount = 1; 192362306a36Sopenharmony_ci err = dbg_check_space_info(c); 192462306a36Sopenharmony_ci if (err) 192562306a36Sopenharmony_ci ubifs_ro_mode(c, err); 192662306a36Sopenharmony_ci mutex_unlock(&c->umount_mutex); 192762306a36Sopenharmony_ci} 192862306a36Sopenharmony_ci 192962306a36Sopenharmony_cistatic void ubifs_put_super(struct super_block *sb) 193062306a36Sopenharmony_ci{ 193162306a36Sopenharmony_ci int i; 193262306a36Sopenharmony_ci struct ubifs_info *c = sb->s_fs_info; 193362306a36Sopenharmony_ci 193462306a36Sopenharmony_ci ubifs_msg(c, "un-mount UBI device %d", c->vi.ubi_num); 193562306a36Sopenharmony_ci 193662306a36Sopenharmony_ci /* 193762306a36Sopenharmony_ci * The following asserts are only valid if there has not been a failure 193862306a36Sopenharmony_ci * of the media. For example, there will be dirty inodes if we failed 193962306a36Sopenharmony_ci * to write them back because of I/O errors. 194062306a36Sopenharmony_ci */ 194162306a36Sopenharmony_ci if (!c->ro_error) { 194262306a36Sopenharmony_ci ubifs_assert(c, c->bi.idx_growth == 0); 194362306a36Sopenharmony_ci ubifs_assert(c, c->bi.dd_growth == 0); 194462306a36Sopenharmony_ci ubifs_assert(c, c->bi.data_growth == 0); 194562306a36Sopenharmony_ci } 194662306a36Sopenharmony_ci 194762306a36Sopenharmony_ci /* 194862306a36Sopenharmony_ci * The 'c->umount_lock' prevents races between UBIFS memory shrinker 194962306a36Sopenharmony_ci * and file system un-mount. Namely, it prevents the shrinker from 195062306a36Sopenharmony_ci * picking this superblock for shrinking - it will be just skipped if 195162306a36Sopenharmony_ci * the mutex is locked. 195262306a36Sopenharmony_ci */ 195362306a36Sopenharmony_ci mutex_lock(&c->umount_mutex); 195462306a36Sopenharmony_ci if (!c->ro_mount) { 195562306a36Sopenharmony_ci /* 195662306a36Sopenharmony_ci * First of all kill the background thread to make sure it does 195762306a36Sopenharmony_ci * not interfere with un-mounting and freeing resources. 195862306a36Sopenharmony_ci */ 195962306a36Sopenharmony_ci if (c->bgt) { 196062306a36Sopenharmony_ci kthread_stop(c->bgt); 196162306a36Sopenharmony_ci c->bgt = NULL; 196262306a36Sopenharmony_ci } 196362306a36Sopenharmony_ci 196462306a36Sopenharmony_ci /* 196562306a36Sopenharmony_ci * On fatal errors c->ro_error is set to 1, in which case we do 196662306a36Sopenharmony_ci * not write the master node. 196762306a36Sopenharmony_ci */ 196862306a36Sopenharmony_ci if (!c->ro_error) { 196962306a36Sopenharmony_ci int err; 197062306a36Sopenharmony_ci 197162306a36Sopenharmony_ci /* Synchronize write-buffers */ 197262306a36Sopenharmony_ci for (i = 0; i < c->jhead_cnt; i++) { 197362306a36Sopenharmony_ci err = ubifs_wbuf_sync(&c->jheads[i].wbuf); 197462306a36Sopenharmony_ci if (err) 197562306a36Sopenharmony_ci ubifs_ro_mode(c, err); 197662306a36Sopenharmony_ci } 197762306a36Sopenharmony_ci 197862306a36Sopenharmony_ci /* 197962306a36Sopenharmony_ci * We are being cleanly unmounted which means the 198062306a36Sopenharmony_ci * orphans were killed - indicate this in the master 198162306a36Sopenharmony_ci * node. Also save the reserved GC LEB number. 198262306a36Sopenharmony_ci */ 198362306a36Sopenharmony_ci c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY); 198462306a36Sopenharmony_ci c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS); 198562306a36Sopenharmony_ci c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum); 198662306a36Sopenharmony_ci err = ubifs_write_master(c); 198762306a36Sopenharmony_ci if (err) 198862306a36Sopenharmony_ci /* 198962306a36Sopenharmony_ci * Recovery will attempt to fix the master area 199062306a36Sopenharmony_ci * next mount, so we just print a message and 199162306a36Sopenharmony_ci * continue to unmount normally. 199262306a36Sopenharmony_ci */ 199362306a36Sopenharmony_ci ubifs_err(c, "failed to write master node, error %d", 199462306a36Sopenharmony_ci err); 199562306a36Sopenharmony_ci } else { 199662306a36Sopenharmony_ci for (i = 0; i < c->jhead_cnt; i++) 199762306a36Sopenharmony_ci /* Make sure write-buffer timers are canceled */ 199862306a36Sopenharmony_ci hrtimer_cancel(&c->jheads[i].wbuf.timer); 199962306a36Sopenharmony_ci } 200062306a36Sopenharmony_ci } 200162306a36Sopenharmony_ci 200262306a36Sopenharmony_ci ubifs_umount(c); 200362306a36Sopenharmony_ci ubi_close_volume(c->ubi); 200462306a36Sopenharmony_ci mutex_unlock(&c->umount_mutex); 200562306a36Sopenharmony_ci} 200662306a36Sopenharmony_ci 200762306a36Sopenharmony_cistatic int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) 200862306a36Sopenharmony_ci{ 200962306a36Sopenharmony_ci int err; 201062306a36Sopenharmony_ci struct ubifs_info *c = sb->s_fs_info; 201162306a36Sopenharmony_ci 201262306a36Sopenharmony_ci sync_filesystem(sb); 201362306a36Sopenharmony_ci dbg_gen("old flags %#lx, new flags %#x", sb->s_flags, *flags); 201462306a36Sopenharmony_ci 201562306a36Sopenharmony_ci err = ubifs_parse_options(c, data, 1); 201662306a36Sopenharmony_ci if (err) { 201762306a36Sopenharmony_ci ubifs_err(c, "invalid or unknown remount parameter"); 201862306a36Sopenharmony_ci return err; 201962306a36Sopenharmony_ci } 202062306a36Sopenharmony_ci 202162306a36Sopenharmony_ci if (c->ro_mount && !(*flags & SB_RDONLY)) { 202262306a36Sopenharmony_ci if (c->ro_error) { 202362306a36Sopenharmony_ci ubifs_msg(c, "cannot re-mount R/W due to prior errors"); 202462306a36Sopenharmony_ci return -EROFS; 202562306a36Sopenharmony_ci } 202662306a36Sopenharmony_ci if (c->ro_media) { 202762306a36Sopenharmony_ci ubifs_msg(c, "cannot re-mount R/W - UBI volume is R/O"); 202862306a36Sopenharmony_ci return -EROFS; 202962306a36Sopenharmony_ci } 203062306a36Sopenharmony_ci err = ubifs_remount_rw(c); 203162306a36Sopenharmony_ci if (err) 203262306a36Sopenharmony_ci return err; 203362306a36Sopenharmony_ci } else if (!c->ro_mount && (*flags & SB_RDONLY)) { 203462306a36Sopenharmony_ci if (c->ro_error) { 203562306a36Sopenharmony_ci ubifs_msg(c, "cannot re-mount R/O due to prior errors"); 203662306a36Sopenharmony_ci return -EROFS; 203762306a36Sopenharmony_ci } 203862306a36Sopenharmony_ci ubifs_remount_ro(c); 203962306a36Sopenharmony_ci } 204062306a36Sopenharmony_ci 204162306a36Sopenharmony_ci if (c->bulk_read == 1) 204262306a36Sopenharmony_ci bu_init(c); 204362306a36Sopenharmony_ci else { 204462306a36Sopenharmony_ci dbg_gen("disable bulk-read"); 204562306a36Sopenharmony_ci mutex_lock(&c->bu_mutex); 204662306a36Sopenharmony_ci kfree(c->bu.buf); 204762306a36Sopenharmony_ci c->bu.buf = NULL; 204862306a36Sopenharmony_ci mutex_unlock(&c->bu_mutex); 204962306a36Sopenharmony_ci } 205062306a36Sopenharmony_ci 205162306a36Sopenharmony_ci if (!c->need_recovery) 205262306a36Sopenharmony_ci ubifs_assert(c, c->lst.taken_empty_lebs > 0); 205362306a36Sopenharmony_ci 205462306a36Sopenharmony_ci return 0; 205562306a36Sopenharmony_ci} 205662306a36Sopenharmony_ci 205762306a36Sopenharmony_ciconst struct super_operations ubifs_super_operations = { 205862306a36Sopenharmony_ci .alloc_inode = ubifs_alloc_inode, 205962306a36Sopenharmony_ci .free_inode = ubifs_free_inode, 206062306a36Sopenharmony_ci .put_super = ubifs_put_super, 206162306a36Sopenharmony_ci .write_inode = ubifs_write_inode, 206262306a36Sopenharmony_ci .drop_inode = ubifs_drop_inode, 206362306a36Sopenharmony_ci .evict_inode = ubifs_evict_inode, 206462306a36Sopenharmony_ci .statfs = ubifs_statfs, 206562306a36Sopenharmony_ci .dirty_inode = ubifs_dirty_inode, 206662306a36Sopenharmony_ci .remount_fs = ubifs_remount_fs, 206762306a36Sopenharmony_ci .show_options = ubifs_show_options, 206862306a36Sopenharmony_ci .sync_fs = ubifs_sync_fs, 206962306a36Sopenharmony_ci}; 207062306a36Sopenharmony_ci 207162306a36Sopenharmony_ci/** 207262306a36Sopenharmony_ci * open_ubi - parse UBI device name string and open the UBI device. 207362306a36Sopenharmony_ci * @name: UBI volume name 207462306a36Sopenharmony_ci * @mode: UBI volume open mode 207562306a36Sopenharmony_ci * 207662306a36Sopenharmony_ci * The primary method of mounting UBIFS is by specifying the UBI volume 207762306a36Sopenharmony_ci * character device node path. However, UBIFS may also be mounted without any 207862306a36Sopenharmony_ci * character device node using one of the following methods: 207962306a36Sopenharmony_ci * 208062306a36Sopenharmony_ci * o ubiX_Y - mount UBI device number X, volume Y; 208162306a36Sopenharmony_ci * o ubiY - mount UBI device number 0, volume Y; 208262306a36Sopenharmony_ci * o ubiX:NAME - mount UBI device X, volume with name NAME; 208362306a36Sopenharmony_ci * o ubi:NAME - mount UBI device 0, volume with name NAME. 208462306a36Sopenharmony_ci * 208562306a36Sopenharmony_ci * Alternative '!' separator may be used instead of ':' (because some shells 208662306a36Sopenharmony_ci * like busybox may interpret ':' as an NFS host name separator). This function 208762306a36Sopenharmony_ci * returns UBI volume description object in case of success and a negative 208862306a36Sopenharmony_ci * error code in case of failure. 208962306a36Sopenharmony_ci */ 209062306a36Sopenharmony_cistatic struct ubi_volume_desc *open_ubi(const char *name, int mode) 209162306a36Sopenharmony_ci{ 209262306a36Sopenharmony_ci struct ubi_volume_desc *ubi; 209362306a36Sopenharmony_ci int dev, vol; 209462306a36Sopenharmony_ci char *endptr; 209562306a36Sopenharmony_ci 209662306a36Sopenharmony_ci if (!name || !*name) 209762306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 209862306a36Sopenharmony_ci 209962306a36Sopenharmony_ci /* First, try to open using the device node path method */ 210062306a36Sopenharmony_ci ubi = ubi_open_volume_path(name, mode); 210162306a36Sopenharmony_ci if (!IS_ERR(ubi)) 210262306a36Sopenharmony_ci return ubi; 210362306a36Sopenharmony_ci 210462306a36Sopenharmony_ci /* Try the "nodev" method */ 210562306a36Sopenharmony_ci if (name[0] != 'u' || name[1] != 'b' || name[2] != 'i') 210662306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 210762306a36Sopenharmony_ci 210862306a36Sopenharmony_ci /* ubi:NAME method */ 210962306a36Sopenharmony_ci if ((name[3] == ':' || name[3] == '!') && name[4] != '\0') 211062306a36Sopenharmony_ci return ubi_open_volume_nm(0, name + 4, mode); 211162306a36Sopenharmony_ci 211262306a36Sopenharmony_ci if (!isdigit(name[3])) 211362306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 211462306a36Sopenharmony_ci 211562306a36Sopenharmony_ci dev = simple_strtoul(name + 3, &endptr, 0); 211662306a36Sopenharmony_ci 211762306a36Sopenharmony_ci /* ubiY method */ 211862306a36Sopenharmony_ci if (*endptr == '\0') 211962306a36Sopenharmony_ci return ubi_open_volume(0, dev, mode); 212062306a36Sopenharmony_ci 212162306a36Sopenharmony_ci /* ubiX_Y method */ 212262306a36Sopenharmony_ci if (*endptr == '_' && isdigit(endptr[1])) { 212362306a36Sopenharmony_ci vol = simple_strtoul(endptr + 1, &endptr, 0); 212462306a36Sopenharmony_ci if (*endptr != '\0') 212562306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 212662306a36Sopenharmony_ci return ubi_open_volume(dev, vol, mode); 212762306a36Sopenharmony_ci } 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_ci /* ubiX:NAME method */ 213062306a36Sopenharmony_ci if ((*endptr == ':' || *endptr == '!') && endptr[1] != '\0') 213162306a36Sopenharmony_ci return ubi_open_volume_nm(dev, ++endptr, mode); 213262306a36Sopenharmony_ci 213362306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 213462306a36Sopenharmony_ci} 213562306a36Sopenharmony_ci 213662306a36Sopenharmony_cistatic struct ubifs_info *alloc_ubifs_info(struct ubi_volume_desc *ubi) 213762306a36Sopenharmony_ci{ 213862306a36Sopenharmony_ci struct ubifs_info *c; 213962306a36Sopenharmony_ci 214062306a36Sopenharmony_ci c = kzalloc(sizeof(struct ubifs_info), GFP_KERNEL); 214162306a36Sopenharmony_ci if (c) { 214262306a36Sopenharmony_ci spin_lock_init(&c->cnt_lock); 214362306a36Sopenharmony_ci spin_lock_init(&c->cs_lock); 214462306a36Sopenharmony_ci spin_lock_init(&c->buds_lock); 214562306a36Sopenharmony_ci spin_lock_init(&c->space_lock); 214662306a36Sopenharmony_ci spin_lock_init(&c->orphan_lock); 214762306a36Sopenharmony_ci init_rwsem(&c->commit_sem); 214862306a36Sopenharmony_ci mutex_init(&c->lp_mutex); 214962306a36Sopenharmony_ci mutex_init(&c->tnc_mutex); 215062306a36Sopenharmony_ci mutex_init(&c->log_mutex); 215162306a36Sopenharmony_ci mutex_init(&c->umount_mutex); 215262306a36Sopenharmony_ci mutex_init(&c->bu_mutex); 215362306a36Sopenharmony_ci mutex_init(&c->write_reserve_mutex); 215462306a36Sopenharmony_ci init_waitqueue_head(&c->cmt_wq); 215562306a36Sopenharmony_ci c->buds = RB_ROOT; 215662306a36Sopenharmony_ci c->old_idx = RB_ROOT; 215762306a36Sopenharmony_ci c->size_tree = RB_ROOT; 215862306a36Sopenharmony_ci c->orph_tree = RB_ROOT; 215962306a36Sopenharmony_ci INIT_LIST_HEAD(&c->infos_list); 216062306a36Sopenharmony_ci INIT_LIST_HEAD(&c->idx_gc); 216162306a36Sopenharmony_ci INIT_LIST_HEAD(&c->replay_list); 216262306a36Sopenharmony_ci INIT_LIST_HEAD(&c->replay_buds); 216362306a36Sopenharmony_ci INIT_LIST_HEAD(&c->uncat_list); 216462306a36Sopenharmony_ci INIT_LIST_HEAD(&c->empty_list); 216562306a36Sopenharmony_ci INIT_LIST_HEAD(&c->freeable_list); 216662306a36Sopenharmony_ci INIT_LIST_HEAD(&c->frdi_idx_list); 216762306a36Sopenharmony_ci INIT_LIST_HEAD(&c->unclean_leb_list); 216862306a36Sopenharmony_ci INIT_LIST_HEAD(&c->old_buds); 216962306a36Sopenharmony_ci INIT_LIST_HEAD(&c->orph_list); 217062306a36Sopenharmony_ci INIT_LIST_HEAD(&c->orph_new); 217162306a36Sopenharmony_ci c->no_chk_data_crc = 1; 217262306a36Sopenharmony_ci c->assert_action = ASSACT_RO; 217362306a36Sopenharmony_ci 217462306a36Sopenharmony_ci c->highest_inum = UBIFS_FIRST_INO; 217562306a36Sopenharmony_ci c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM; 217662306a36Sopenharmony_ci 217762306a36Sopenharmony_ci ubi_get_volume_info(ubi, &c->vi); 217862306a36Sopenharmony_ci ubi_get_device_info(c->vi.ubi_num, &c->di); 217962306a36Sopenharmony_ci } 218062306a36Sopenharmony_ci return c; 218162306a36Sopenharmony_ci} 218262306a36Sopenharmony_ci 218362306a36Sopenharmony_cistatic int ubifs_fill_super(struct super_block *sb, void *data, int silent) 218462306a36Sopenharmony_ci{ 218562306a36Sopenharmony_ci struct ubifs_info *c = sb->s_fs_info; 218662306a36Sopenharmony_ci struct inode *root; 218762306a36Sopenharmony_ci int err; 218862306a36Sopenharmony_ci 218962306a36Sopenharmony_ci c->vfs_sb = sb; 219062306a36Sopenharmony_ci /* Re-open the UBI device in read-write mode */ 219162306a36Sopenharmony_ci c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READWRITE); 219262306a36Sopenharmony_ci if (IS_ERR(c->ubi)) { 219362306a36Sopenharmony_ci err = PTR_ERR(c->ubi); 219462306a36Sopenharmony_ci goto out; 219562306a36Sopenharmony_ci } 219662306a36Sopenharmony_ci 219762306a36Sopenharmony_ci err = ubifs_parse_options(c, data, 0); 219862306a36Sopenharmony_ci if (err) 219962306a36Sopenharmony_ci goto out_close; 220062306a36Sopenharmony_ci 220162306a36Sopenharmony_ci /* 220262306a36Sopenharmony_ci * UBIFS provides 'backing_dev_info' in order to disable read-ahead. For 220362306a36Sopenharmony_ci * UBIFS, I/O is not deferred, it is done immediately in read_folio, 220462306a36Sopenharmony_ci * which means the user would have to wait not just for their own I/O 220562306a36Sopenharmony_ci * but the read-ahead I/O as well i.e. completely pointless. 220662306a36Sopenharmony_ci * 220762306a36Sopenharmony_ci * Read-ahead will be disabled because @sb->s_bdi->ra_pages is 0. Also 220862306a36Sopenharmony_ci * @sb->s_bdi->capabilities are initialized to 0 so there won't be any 220962306a36Sopenharmony_ci * writeback happening. 221062306a36Sopenharmony_ci */ 221162306a36Sopenharmony_ci err = super_setup_bdi_name(sb, "ubifs_%d_%d", c->vi.ubi_num, 221262306a36Sopenharmony_ci c->vi.vol_id); 221362306a36Sopenharmony_ci if (err) 221462306a36Sopenharmony_ci goto out_close; 221562306a36Sopenharmony_ci sb->s_bdi->ra_pages = 0; 221662306a36Sopenharmony_ci sb->s_bdi->io_pages = 0; 221762306a36Sopenharmony_ci 221862306a36Sopenharmony_ci sb->s_fs_info = c; 221962306a36Sopenharmony_ci sb->s_magic = UBIFS_SUPER_MAGIC; 222062306a36Sopenharmony_ci sb->s_blocksize = UBIFS_BLOCK_SIZE; 222162306a36Sopenharmony_ci sb->s_blocksize_bits = UBIFS_BLOCK_SHIFT; 222262306a36Sopenharmony_ci sb->s_maxbytes = c->max_inode_sz = key_max_inode_size(c); 222362306a36Sopenharmony_ci if (c->max_inode_sz > MAX_LFS_FILESIZE) 222462306a36Sopenharmony_ci sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE; 222562306a36Sopenharmony_ci sb->s_op = &ubifs_super_operations; 222662306a36Sopenharmony_ci sb->s_xattr = ubifs_xattr_handlers; 222762306a36Sopenharmony_ci fscrypt_set_ops(sb, &ubifs_crypt_operations); 222862306a36Sopenharmony_ci 222962306a36Sopenharmony_ci mutex_lock(&c->umount_mutex); 223062306a36Sopenharmony_ci err = mount_ubifs(c); 223162306a36Sopenharmony_ci if (err) { 223262306a36Sopenharmony_ci ubifs_assert(c, err < 0); 223362306a36Sopenharmony_ci goto out_unlock; 223462306a36Sopenharmony_ci } 223562306a36Sopenharmony_ci 223662306a36Sopenharmony_ci /* Read the root inode */ 223762306a36Sopenharmony_ci root = ubifs_iget(sb, UBIFS_ROOT_INO); 223862306a36Sopenharmony_ci if (IS_ERR(root)) { 223962306a36Sopenharmony_ci err = PTR_ERR(root); 224062306a36Sopenharmony_ci goto out_umount; 224162306a36Sopenharmony_ci } 224262306a36Sopenharmony_ci 224362306a36Sopenharmony_ci sb->s_root = d_make_root(root); 224462306a36Sopenharmony_ci if (!sb->s_root) { 224562306a36Sopenharmony_ci err = -ENOMEM; 224662306a36Sopenharmony_ci goto out_umount; 224762306a36Sopenharmony_ci } 224862306a36Sopenharmony_ci 224962306a36Sopenharmony_ci import_uuid(&sb->s_uuid, c->uuid); 225062306a36Sopenharmony_ci 225162306a36Sopenharmony_ci mutex_unlock(&c->umount_mutex); 225262306a36Sopenharmony_ci return 0; 225362306a36Sopenharmony_ci 225462306a36Sopenharmony_ciout_umount: 225562306a36Sopenharmony_ci ubifs_umount(c); 225662306a36Sopenharmony_ciout_unlock: 225762306a36Sopenharmony_ci mutex_unlock(&c->umount_mutex); 225862306a36Sopenharmony_ciout_close: 225962306a36Sopenharmony_ci ubifs_release_options(c); 226062306a36Sopenharmony_ci ubi_close_volume(c->ubi); 226162306a36Sopenharmony_ciout: 226262306a36Sopenharmony_ci return err; 226362306a36Sopenharmony_ci} 226462306a36Sopenharmony_ci 226562306a36Sopenharmony_cistatic int sb_test(struct super_block *sb, void *data) 226662306a36Sopenharmony_ci{ 226762306a36Sopenharmony_ci struct ubifs_info *c1 = data; 226862306a36Sopenharmony_ci struct ubifs_info *c = sb->s_fs_info; 226962306a36Sopenharmony_ci 227062306a36Sopenharmony_ci return c->vi.cdev == c1->vi.cdev; 227162306a36Sopenharmony_ci} 227262306a36Sopenharmony_ci 227362306a36Sopenharmony_cistatic int sb_set(struct super_block *sb, void *data) 227462306a36Sopenharmony_ci{ 227562306a36Sopenharmony_ci sb->s_fs_info = data; 227662306a36Sopenharmony_ci return set_anon_super(sb, NULL); 227762306a36Sopenharmony_ci} 227862306a36Sopenharmony_ci 227962306a36Sopenharmony_cistatic struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags, 228062306a36Sopenharmony_ci const char *name, void *data) 228162306a36Sopenharmony_ci{ 228262306a36Sopenharmony_ci struct ubi_volume_desc *ubi; 228362306a36Sopenharmony_ci struct ubifs_info *c; 228462306a36Sopenharmony_ci struct super_block *sb; 228562306a36Sopenharmony_ci int err; 228662306a36Sopenharmony_ci 228762306a36Sopenharmony_ci dbg_gen("name %s, flags %#x", name, flags); 228862306a36Sopenharmony_ci 228962306a36Sopenharmony_ci /* 229062306a36Sopenharmony_ci * Get UBI device number and volume ID. Mount it read-only so far 229162306a36Sopenharmony_ci * because this might be a new mount point, and UBI allows only one 229262306a36Sopenharmony_ci * read-write user at a time. 229362306a36Sopenharmony_ci */ 229462306a36Sopenharmony_ci ubi = open_ubi(name, UBI_READONLY); 229562306a36Sopenharmony_ci if (IS_ERR(ubi)) { 229662306a36Sopenharmony_ci if (!(flags & SB_SILENT)) 229762306a36Sopenharmony_ci pr_err("UBIFS error (pid: %d): cannot open \"%s\", error %d", 229862306a36Sopenharmony_ci current->pid, name, (int)PTR_ERR(ubi)); 229962306a36Sopenharmony_ci return ERR_CAST(ubi); 230062306a36Sopenharmony_ci } 230162306a36Sopenharmony_ci 230262306a36Sopenharmony_ci c = alloc_ubifs_info(ubi); 230362306a36Sopenharmony_ci if (!c) { 230462306a36Sopenharmony_ci err = -ENOMEM; 230562306a36Sopenharmony_ci goto out_close; 230662306a36Sopenharmony_ci } 230762306a36Sopenharmony_ci 230862306a36Sopenharmony_ci dbg_gen("opened ubi%d_%d", c->vi.ubi_num, c->vi.vol_id); 230962306a36Sopenharmony_ci 231062306a36Sopenharmony_ci sb = sget(fs_type, sb_test, sb_set, flags, c); 231162306a36Sopenharmony_ci if (IS_ERR(sb)) { 231262306a36Sopenharmony_ci err = PTR_ERR(sb); 231362306a36Sopenharmony_ci kfree(c); 231462306a36Sopenharmony_ci goto out_close; 231562306a36Sopenharmony_ci } 231662306a36Sopenharmony_ci 231762306a36Sopenharmony_ci if (sb->s_root) { 231862306a36Sopenharmony_ci struct ubifs_info *c1 = sb->s_fs_info; 231962306a36Sopenharmony_ci kfree(c); 232062306a36Sopenharmony_ci /* A new mount point for already mounted UBIFS */ 232162306a36Sopenharmony_ci dbg_gen("this ubi volume is already mounted"); 232262306a36Sopenharmony_ci if (!!(flags & SB_RDONLY) != c1->ro_mount) { 232362306a36Sopenharmony_ci err = -EBUSY; 232462306a36Sopenharmony_ci goto out_deact; 232562306a36Sopenharmony_ci } 232662306a36Sopenharmony_ci } else { 232762306a36Sopenharmony_ci err = ubifs_fill_super(sb, data, flags & SB_SILENT ? 1 : 0); 232862306a36Sopenharmony_ci if (err) 232962306a36Sopenharmony_ci goto out_deact; 233062306a36Sopenharmony_ci /* We do not support atime */ 233162306a36Sopenharmony_ci sb->s_flags |= SB_ACTIVE; 233262306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT)) 233362306a36Sopenharmony_ci ubifs_msg(c, "full atime support is enabled."); 233462306a36Sopenharmony_ci else 233562306a36Sopenharmony_ci sb->s_flags |= SB_NOATIME; 233662306a36Sopenharmony_ci } 233762306a36Sopenharmony_ci 233862306a36Sopenharmony_ci /* 'fill_super()' opens ubi again so we must close it here */ 233962306a36Sopenharmony_ci ubi_close_volume(ubi); 234062306a36Sopenharmony_ci 234162306a36Sopenharmony_ci return dget(sb->s_root); 234262306a36Sopenharmony_ci 234362306a36Sopenharmony_ciout_deact: 234462306a36Sopenharmony_ci deactivate_locked_super(sb); 234562306a36Sopenharmony_ciout_close: 234662306a36Sopenharmony_ci ubi_close_volume(ubi); 234762306a36Sopenharmony_ci return ERR_PTR(err); 234862306a36Sopenharmony_ci} 234962306a36Sopenharmony_ci 235062306a36Sopenharmony_cistatic void kill_ubifs_super(struct super_block *s) 235162306a36Sopenharmony_ci{ 235262306a36Sopenharmony_ci struct ubifs_info *c = s->s_fs_info; 235362306a36Sopenharmony_ci kill_anon_super(s); 235462306a36Sopenharmony_ci kfree(c); 235562306a36Sopenharmony_ci} 235662306a36Sopenharmony_ci 235762306a36Sopenharmony_cistatic struct file_system_type ubifs_fs_type = { 235862306a36Sopenharmony_ci .name = "ubifs", 235962306a36Sopenharmony_ci .owner = THIS_MODULE, 236062306a36Sopenharmony_ci .mount = ubifs_mount, 236162306a36Sopenharmony_ci .kill_sb = kill_ubifs_super, 236262306a36Sopenharmony_ci}; 236362306a36Sopenharmony_ciMODULE_ALIAS_FS("ubifs"); 236462306a36Sopenharmony_ci 236562306a36Sopenharmony_ci/* 236662306a36Sopenharmony_ci * Inode slab cache constructor. 236762306a36Sopenharmony_ci */ 236862306a36Sopenharmony_cistatic void inode_slab_ctor(void *obj) 236962306a36Sopenharmony_ci{ 237062306a36Sopenharmony_ci struct ubifs_inode *ui = obj; 237162306a36Sopenharmony_ci inode_init_once(&ui->vfs_inode); 237262306a36Sopenharmony_ci} 237362306a36Sopenharmony_ci 237462306a36Sopenharmony_cistatic int __init ubifs_init(void) 237562306a36Sopenharmony_ci{ 237662306a36Sopenharmony_ci int err; 237762306a36Sopenharmony_ci 237862306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(struct ubifs_ch) != 24); 237962306a36Sopenharmony_ci 238062306a36Sopenharmony_ci /* Make sure node sizes are 8-byte aligned */ 238162306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_CH_SZ & 7); 238262306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_INO_NODE_SZ & 7); 238362306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_DENT_NODE_SZ & 7); 238462306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_XENT_NODE_SZ & 7); 238562306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_DATA_NODE_SZ & 7); 238662306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_TRUN_NODE_SZ & 7); 238762306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_SB_NODE_SZ & 7); 238862306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_MST_NODE_SZ & 7); 238962306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_REF_NODE_SZ & 7); 239062306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_CS_NODE_SZ & 7); 239162306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_ORPH_NODE_SZ & 7); 239262306a36Sopenharmony_ci 239362306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_MAX_DENT_NODE_SZ & 7); 239462306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_MAX_XENT_NODE_SZ & 7); 239562306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_MAX_DATA_NODE_SZ & 7); 239662306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_MAX_INO_NODE_SZ & 7); 239762306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_MAX_NODE_SZ & 7); 239862306a36Sopenharmony_ci BUILD_BUG_ON(MIN_WRITE_SZ & 7); 239962306a36Sopenharmony_ci 240062306a36Sopenharmony_ci /* Check min. node size */ 240162306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_INO_NODE_SZ < MIN_WRITE_SZ); 240262306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_DENT_NODE_SZ < MIN_WRITE_SZ); 240362306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_XENT_NODE_SZ < MIN_WRITE_SZ); 240462306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_TRUN_NODE_SZ < MIN_WRITE_SZ); 240562306a36Sopenharmony_ci 240662306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_MAX_DENT_NODE_SZ > UBIFS_MAX_NODE_SZ); 240762306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_MAX_XENT_NODE_SZ > UBIFS_MAX_NODE_SZ); 240862306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_MAX_DATA_NODE_SZ > UBIFS_MAX_NODE_SZ); 240962306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_MAX_INO_NODE_SZ > UBIFS_MAX_NODE_SZ); 241062306a36Sopenharmony_ci 241162306a36Sopenharmony_ci /* Defined node sizes */ 241262306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_SB_NODE_SZ != 4096); 241362306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_MST_NODE_SZ != 512); 241462306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_INO_NODE_SZ != 160); 241562306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_REF_NODE_SZ != 64); 241662306a36Sopenharmony_ci 241762306a36Sopenharmony_ci /* 241862306a36Sopenharmony_ci * We use 2 bit wide bit-fields to store compression type, which should 241962306a36Sopenharmony_ci * be amended if more compressors are added. The bit-fields are: 242062306a36Sopenharmony_ci * @compr_type in 'struct ubifs_inode', @default_compr in 242162306a36Sopenharmony_ci * 'struct ubifs_info' and @compr_type in 'struct ubifs_mount_opts'. 242262306a36Sopenharmony_ci */ 242362306a36Sopenharmony_ci BUILD_BUG_ON(UBIFS_COMPR_TYPES_CNT > 4); 242462306a36Sopenharmony_ci 242562306a36Sopenharmony_ci /* 242662306a36Sopenharmony_ci * We require that PAGE_SIZE is greater-than-or-equal-to 242762306a36Sopenharmony_ci * UBIFS_BLOCK_SIZE. It is assumed that both are powers of 2. 242862306a36Sopenharmony_ci */ 242962306a36Sopenharmony_ci if (PAGE_SIZE < UBIFS_BLOCK_SIZE) { 243062306a36Sopenharmony_ci pr_err("UBIFS error (pid %d): VFS page cache size is %u bytes, but UBIFS requires at least 4096 bytes", 243162306a36Sopenharmony_ci current->pid, (unsigned int)PAGE_SIZE); 243262306a36Sopenharmony_ci return -EINVAL; 243362306a36Sopenharmony_ci } 243462306a36Sopenharmony_ci 243562306a36Sopenharmony_ci ubifs_inode_slab = kmem_cache_create("ubifs_inode_slab", 243662306a36Sopenharmony_ci sizeof(struct ubifs_inode), 0, 243762306a36Sopenharmony_ci SLAB_MEM_SPREAD | SLAB_RECLAIM_ACCOUNT | 243862306a36Sopenharmony_ci SLAB_ACCOUNT, &inode_slab_ctor); 243962306a36Sopenharmony_ci if (!ubifs_inode_slab) 244062306a36Sopenharmony_ci return -ENOMEM; 244162306a36Sopenharmony_ci 244262306a36Sopenharmony_ci err = register_shrinker(&ubifs_shrinker_info, "ubifs-slab"); 244362306a36Sopenharmony_ci if (err) 244462306a36Sopenharmony_ci goto out_slab; 244562306a36Sopenharmony_ci 244662306a36Sopenharmony_ci err = ubifs_compressors_init(); 244762306a36Sopenharmony_ci if (err) 244862306a36Sopenharmony_ci goto out_shrinker; 244962306a36Sopenharmony_ci 245062306a36Sopenharmony_ci dbg_debugfs_init(); 245162306a36Sopenharmony_ci 245262306a36Sopenharmony_ci err = ubifs_sysfs_init(); 245362306a36Sopenharmony_ci if (err) 245462306a36Sopenharmony_ci goto out_dbg; 245562306a36Sopenharmony_ci 245662306a36Sopenharmony_ci err = register_filesystem(&ubifs_fs_type); 245762306a36Sopenharmony_ci if (err) { 245862306a36Sopenharmony_ci pr_err("UBIFS error (pid %d): cannot register file system, error %d", 245962306a36Sopenharmony_ci current->pid, err); 246062306a36Sopenharmony_ci goto out_sysfs; 246162306a36Sopenharmony_ci } 246262306a36Sopenharmony_ci return 0; 246362306a36Sopenharmony_ci 246462306a36Sopenharmony_ciout_sysfs: 246562306a36Sopenharmony_ci ubifs_sysfs_exit(); 246662306a36Sopenharmony_ciout_dbg: 246762306a36Sopenharmony_ci dbg_debugfs_exit(); 246862306a36Sopenharmony_ci ubifs_compressors_exit(); 246962306a36Sopenharmony_ciout_shrinker: 247062306a36Sopenharmony_ci unregister_shrinker(&ubifs_shrinker_info); 247162306a36Sopenharmony_ciout_slab: 247262306a36Sopenharmony_ci kmem_cache_destroy(ubifs_inode_slab); 247362306a36Sopenharmony_ci return err; 247462306a36Sopenharmony_ci} 247562306a36Sopenharmony_ci/* late_initcall to let compressors initialize first */ 247662306a36Sopenharmony_cilate_initcall(ubifs_init); 247762306a36Sopenharmony_ci 247862306a36Sopenharmony_cistatic void __exit ubifs_exit(void) 247962306a36Sopenharmony_ci{ 248062306a36Sopenharmony_ci WARN_ON(!list_empty(&ubifs_infos)); 248162306a36Sopenharmony_ci WARN_ON(atomic_long_read(&ubifs_clean_zn_cnt) != 0); 248262306a36Sopenharmony_ci 248362306a36Sopenharmony_ci dbg_debugfs_exit(); 248462306a36Sopenharmony_ci ubifs_sysfs_exit(); 248562306a36Sopenharmony_ci ubifs_compressors_exit(); 248662306a36Sopenharmony_ci unregister_shrinker(&ubifs_shrinker_info); 248762306a36Sopenharmony_ci 248862306a36Sopenharmony_ci /* 248962306a36Sopenharmony_ci * Make sure all delayed rcu free inodes are flushed before we 249062306a36Sopenharmony_ci * destroy cache. 249162306a36Sopenharmony_ci */ 249262306a36Sopenharmony_ci rcu_barrier(); 249362306a36Sopenharmony_ci kmem_cache_destroy(ubifs_inode_slab); 249462306a36Sopenharmony_ci unregister_filesystem(&ubifs_fs_type); 249562306a36Sopenharmony_ci} 249662306a36Sopenharmony_cimodule_exit(ubifs_exit); 249762306a36Sopenharmony_ci 249862306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 249962306a36Sopenharmony_ciMODULE_VERSION(__stringify(UBIFS_VERSION)); 250062306a36Sopenharmony_ciMODULE_AUTHOR("Artem Bityutskiy, Adrian Hunter"); 250162306a36Sopenharmony_ciMODULE_DESCRIPTION("UBIFS - UBI File System"); 2502