Commit 7e2d0ba7 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'ubifs-for-linus-6.11-rc1-take2' of...

Merge tag 'ubifs-for-linus-6.11-rc1-take2' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs

Pull UBI and UBIFS updates from Richard Weinberger:

 - Many fixes for power-cut issues by Zhihao Cheng

 - Another ubiblock error path fix

 - ubiblock section mismatch fix

 - Misc fixes all over the place

* tag 'ubifs-for-linus-6.11-rc1-take2' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs:
  ubi: Fix ubi_init() ubiblock_exit() section mismatch
  ubifs: add check for crypto_shash_tfm_digest
  ubifs: Fix inconsistent inode size when powercut happens during appendant writing
  ubi: block: fix null-pointer-dereference in ubiblock_create()
  ubifs: fix kernel-doc warnings
  ubifs: correct UBIFS_DFS_DIR_LEN macro definition and improve code clarity
  mtd: ubi: Restore missing cleanup on ubi_init() failure path
  ubifs: dbg_orphan_check: Fix missed key type checking
  ubifs: Fix unattached inode when powercut happens in creating
  ubifs: Fix space leak when powercut happens in linking tmpfile
  ubifs: Move ui->data initialization after initializing security
  ubifs: Fix adding orphan entry twice for the same inode
  ubifs: Remove insert_dead_orphan from replaying orphan process
  Revert "ubifs: ubifs_symlink: Fix memleak of inode->i_link in error path"
  ubifs: Don't add xattr inode into orphan area
  ubifs: Fix unattached xattr inode if powercut happens after deleting
  mtd: ubi: avoid expensive do_div() on 32-bit machines
  mtd: ubi: make ubi_class constant
  ubi: eba: properly rollback inside self_check_eba
parents e172f1e9 92a286e9
...@@ -390,7 +390,8 @@ int ubiblock_create(struct ubi_volume_info *vi) ...@@ -390,7 +390,8 @@ int ubiblock_create(struct ubi_volume_info *vi)
ret = blk_mq_alloc_tag_set(&dev->tag_set); ret = blk_mq_alloc_tag_set(&dev->tag_set);
if (ret) { if (ret) {
dev_err(disk_to_dev(dev->gd), "blk_mq_alloc_tag_set failed"); pr_err("ubiblock%d_%d: blk_mq_alloc_tag_set failed\n",
dev->ubi_num, dev->vol_id);
goto out_free_dev; goto out_free_dev;
} }
...@@ -407,8 +408,8 @@ int ubiblock_create(struct ubi_volume_info *vi) ...@@ -407,8 +408,8 @@ int ubiblock_create(struct ubi_volume_info *vi)
gd->minors = 1; gd->minors = 1;
gd->first_minor = idr_alloc(&ubiblock_minor_idr, dev, 0, 0, GFP_KERNEL); gd->first_minor = idr_alloc(&ubiblock_minor_idr, dev, 0, 0, GFP_KERNEL);
if (gd->first_minor < 0) { if (gd->first_minor < 0) {
dev_err(disk_to_dev(gd), pr_err("ubiblock%d_%d: block: dynamic minor allocation failed\n",
"block: dynamic minor allocation failed"); dev->ubi_num, dev->vol_id);
ret = -ENODEV; ret = -ENODEV;
goto out_cleanup_disk; goto out_cleanup_disk;
} }
...@@ -669,7 +670,7 @@ int __init ubiblock_init(void) ...@@ -669,7 +670,7 @@ int __init ubiblock_init(void)
return ret; return ret;
} }
void __exit ubiblock_exit(void) void ubiblock_exit(void)
{ {
ubi_unregister_volume_notifier(&ubiblock_notifier); ubi_unregister_volume_notifier(&ubiblock_notifier);
ubiblock_remove_all(); ubiblock_remove_all();
......
...@@ -112,7 +112,7 @@ static struct attribute *ubi_class_attrs[] = { ...@@ -112,7 +112,7 @@ static struct attribute *ubi_class_attrs[] = {
ATTRIBUTE_GROUPS(ubi_class); ATTRIBUTE_GROUPS(ubi_class);
/* Root UBI "class" object (corresponds to '/<sysfs>/class/ubi/') */ /* Root UBI "class" object (corresponds to '/<sysfs>/class/ubi/') */
struct class ubi_class = { const struct class ubi_class = {
.name = UBI_NAME_STR, .name = UBI_NAME_STR,
.class_groups = ubi_class_groups, .class_groups = ubi_class_groups,
}; };
...@@ -1372,7 +1372,7 @@ static int __init ubi_init(void) ...@@ -1372,7 +1372,7 @@ static int __init ubi_init(void)
/* See comment above re-ubi_is_module(). */ /* See comment above re-ubi_is_module(). */
if (ubi_is_module()) if (ubi_is_module())
goto out_slab; goto out_debugfs;
} }
register_mtd_user(&ubi_mtd_notifier); register_mtd_user(&ubi_mtd_notifier);
...@@ -1387,6 +1387,9 @@ static int __init ubi_init(void) ...@@ -1387,6 +1387,9 @@ static int __init ubi_init(void)
out_mtd_notifier: out_mtd_notifier:
unregister_mtd_user(&ubi_mtd_notifier); unregister_mtd_user(&ubi_mtd_notifier);
ubiblock_exit();
out_debugfs:
ubi_debugfs_exit();
out_slab: out_slab:
kmem_cache_destroy(ubi_wl_entry_slab); kmem_cache_destroy(ubi_wl_entry_slab);
out_dev_unreg: out_dev_unreg:
......
...@@ -598,9 +598,9 @@ int ubi_debugfs_init_dev(struct ubi_device *ubi) ...@@ -598,9 +598,9 @@ int ubi_debugfs_init_dev(struct ubi_device *ubi)
if (!IS_ENABLED(CONFIG_DEBUG_FS)) if (!IS_ENABLED(CONFIG_DEBUG_FS))
return 0; return 0;
n = snprintf(d->dfs_dir_name, UBI_DFS_DIR_LEN + 1, UBI_DFS_DIR_NAME, n = snprintf(d->dfs_dir_name, UBI_DFS_DIR_LEN, UBI_DFS_DIR_NAME,
ubi->ubi_num); ubi->ubi_num);
if (n > UBI_DFS_DIR_LEN) { if (n >= UBI_DFS_DIR_LEN) {
/* The array size is too small */ /* The array size is too small */
return -EINVAL; return -EINVAL;
} }
......
...@@ -1564,6 +1564,7 @@ int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap, ...@@ -1564,6 +1564,7 @@ int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap,
GFP_KERNEL); GFP_KERNEL);
if (!fm_eba[i]) { if (!fm_eba[i]) {
ret = -ENOMEM; ret = -ENOMEM;
kfree(scan_eba[i]);
goto out_free; goto out_free;
} }
...@@ -1599,7 +1600,7 @@ int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap, ...@@ -1599,7 +1600,7 @@ int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap,
} }
out_free: out_free:
for (i = 0; i < num_volumes; i++) { while (--i >= 0) {
if (!ubi->volumes[i]) if (!ubi->volumes[i])
continue; continue;
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
/* UBI NVMEM provider */ /* UBI NVMEM provider */
#include "ubi.h" #include "ubi.h"
#include <linux/nvmem-provider.h> #include <linux/nvmem-provider.h>
#include <asm/div64.h>
/* List of all NVMEM devices */ /* List of all NVMEM devices */
static LIST_HEAD(nvmem_devices); static LIST_HEAD(nvmem_devices);
...@@ -27,14 +26,15 @@ static int ubi_nvmem_reg_read(void *priv, unsigned int from, ...@@ -27,14 +26,15 @@ static int ubi_nvmem_reg_read(void *priv, unsigned int from,
struct ubi_nvmem *unv = priv; struct ubi_nvmem *unv = priv;
struct ubi_volume_desc *desc; struct ubi_volume_desc *desc;
uint32_t offs; uint32_t offs;
uint64_t lnum = from; uint32_t lnum;
int err = 0; int err = 0;
desc = ubi_open_volume(unv->ubi_num, unv->vol_id, UBI_READONLY); desc = ubi_open_volume(unv->ubi_num, unv->vol_id, UBI_READONLY);
if (IS_ERR(desc)) if (IS_ERR(desc))
return PTR_ERR(desc); return PTR_ERR(desc);
offs = do_div(lnum, unv->usable_leb_size); offs = from % unv->usable_leb_size;
lnum = from / unv->usable_leb_size;
while (bytes_left) { while (bytes_left) {
to_read = unv->usable_leb_size - offs; to_read = unv->usable_leb_size - offs;
......
...@@ -420,7 +420,7 @@ struct ubi_debug_info { ...@@ -420,7 +420,7 @@ struct ubi_debug_info {
unsigned int power_cut_min; unsigned int power_cut_min;
unsigned int power_cut_max; unsigned int power_cut_max;
unsigned int emulate_failures; unsigned int emulate_failures;
char dfs_dir_name[UBI_DFS_DIR_LEN + 1]; char dfs_dir_name[UBI_DFS_DIR_LEN];
struct dentry *dfs_dir; struct dentry *dfs_dir;
struct dentry *dfs_chk_gen; struct dentry *dfs_chk_gen;
struct dentry *dfs_chk_io; struct dentry *dfs_chk_io;
...@@ -814,7 +814,7 @@ extern struct kmem_cache *ubi_wl_entry_slab; ...@@ -814,7 +814,7 @@ extern struct kmem_cache *ubi_wl_entry_slab;
extern const struct file_operations ubi_ctrl_cdev_operations; extern const struct file_operations ubi_ctrl_cdev_operations;
extern const struct file_operations ubi_cdev_operations; extern const struct file_operations ubi_cdev_operations;
extern const struct file_operations ubi_vol_cdev_operations; extern const struct file_operations ubi_vol_cdev_operations;
extern struct class ubi_class; extern const struct class ubi_class;
extern struct mutex ubi_devices_mutex; extern struct mutex ubi_devices_mutex;
extern struct blocking_notifier_head ubi_notifiers; extern struct blocking_notifier_head ubi_notifiers;
......
...@@ -82,6 +82,7 @@ struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT]; ...@@ -82,6 +82,7 @@ struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
/** /**
* ubifs_compress - compress data. * ubifs_compress - compress data.
* @c: UBIFS file-system description object
* @in_buf: data to compress * @in_buf: data to compress
* @in_len: length of the data to compress * @in_len: length of the data to compress
* @out_buf: output buffer where compressed data should be stored * @out_buf: output buffer where compressed data should be stored
...@@ -140,6 +141,7 @@ void ubifs_compress(const struct ubifs_info *c, const void *in_buf, ...@@ -140,6 +141,7 @@ void ubifs_compress(const struct ubifs_info *c, const void *in_buf,
/** /**
* ubifs_decompress - decompress data. * ubifs_decompress - decompress data.
* @c: UBIFS file-system description object
* @in_buf: data to decompress * @in_buf: data to decompress
* @in_len: length of the data to decompress * @in_len: length of the data to decompress
* @out_buf: output buffer where decompressed data should * @out_buf: output buffer where decompressed data should
......
...@@ -2827,9 +2827,9 @@ void dbg_debugfs_init_fs(struct ubifs_info *c) ...@@ -2827,9 +2827,9 @@ void dbg_debugfs_init_fs(struct ubifs_info *c)
const char *fname; const char *fname;
struct ubifs_debug_info *d = c->dbg; struct ubifs_debug_info *d = c->dbg;
n = snprintf(d->dfs_dir_name, UBIFS_DFS_DIR_LEN + 1, UBIFS_DFS_DIR_NAME, n = snprintf(d->dfs_dir_name, UBIFS_DFS_DIR_LEN, UBIFS_DFS_DIR_NAME,
c->vi.ubi_num, c->vi.vol_id); c->vi.ubi_num, c->vi.vol_id);
if (n > UBIFS_DFS_DIR_LEN) { if (n >= UBIFS_DFS_DIR_LEN) {
/* The array size is too small */ /* The array size is too small */
return; return;
} }
......
...@@ -19,10 +19,11 @@ typedef int (*dbg_znode_callback)(struct ubifs_info *c, ...@@ -19,10 +19,11 @@ typedef int (*dbg_znode_callback)(struct ubifs_info *c,
/* /*
* The UBIFS debugfs directory name pattern and maximum name length (3 for "ubi" * The UBIFS debugfs directory name pattern and maximum name length (3 for "ubi"
* + 1 for "_" and plus 2x2 for 2 UBI numbers and 1 for the trailing zero byte. * + 1 for "_" and 2 for UBI device numbers and 3 for volume number and 1 for
* the trailing zero byte.
*/ */
#define UBIFS_DFS_DIR_NAME "ubi%d_%d" #define UBIFS_DFS_DIR_NAME "ubi%d_%d"
#define UBIFS_DFS_DIR_LEN (3 + 1 + 2*2 + 1) #define UBIFS_DFS_DIR_LEN (3 + 1 + 2 + 3 + 1)
/** /**
* ubifs_debug_info - per-FS debugging information. * ubifs_debug_info - per-FS debugging information.
...@@ -103,7 +104,7 @@ struct ubifs_debug_info { ...@@ -103,7 +104,7 @@ struct ubifs_debug_info {
unsigned int chk_fs:1; unsigned int chk_fs:1;
unsigned int tst_rcvry:1; unsigned int tst_rcvry:1;
char dfs_dir_name[UBIFS_DFS_DIR_LEN + 1]; char dfs_dir_name[UBIFS_DFS_DIR_LEN];
struct dentry *dfs_dir; struct dentry *dfs_dir;
struct dentry *dfs_dump_lprops; struct dentry *dfs_dump_lprops;
struct dentry *dfs_dump_budg; struct dentry *dfs_dump_budg;
......
...@@ -71,8 +71,13 @@ static int inherit_flags(const struct inode *dir, umode_t mode) ...@@ -71,8 +71,13 @@ static int inherit_flags(const struct inode *dir, umode_t mode)
* @is_xattr: whether the inode is xattr inode * @is_xattr: whether the inode is xattr inode
* *
* This function finds an unused inode number, allocates new inode and * This function finds an unused inode number, allocates new inode and
* initializes it. Returns new inode in case of success and an error code in * initializes it. Non-xattr new inode may be written with xattrs(selinux/
* case of failure. * encryption) before writing dentry, which could cause inconsistent problem
* when powercut happens between two operations. To deal with it, non-xattr
* new inode is initialized with zero-nlink and added into orphan list, caller
* should make sure that inode is relinked later, and make sure that orphan
* removing and journal writing into an committing atomic operation. Returns
* new inode in case of success and an error code in case of failure.
*/ */
struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir, struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir,
umode_t mode, bool is_xattr) umode_t mode, bool is_xattr)
...@@ -163,9 +168,25 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir, ...@@ -163,9 +168,25 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir,
ui->creat_sqnum = ++c->max_sqnum; ui->creat_sqnum = ++c->max_sqnum;
spin_unlock(&c->cnt_lock); spin_unlock(&c->cnt_lock);
if (!is_xattr) {
set_nlink(inode, 0);
err = ubifs_add_orphan(c, inode->i_ino);
if (err) {
ubifs_err(c, "ubifs_add_orphan failed: %i", err);
goto out_iput;
}
down_read(&c->commit_sem);
ui->del_cmtno = c->cmt_no;
up_read(&c->commit_sem);
}
if (encrypted) { if (encrypted) {
err = fscrypt_set_context(inode, NULL); err = fscrypt_set_context(inode, NULL);
if (err) { if (err) {
if (!is_xattr) {
set_nlink(inode, 1);
ubifs_delete_orphan(c, inode->i_ino);
}
ubifs_err(c, "fscrypt_set_context failed: %i", err); ubifs_err(c, "fscrypt_set_context failed: %i", err);
goto out_iput; goto out_iput;
} }
...@@ -320,12 +341,13 @@ static int ubifs_create(struct mnt_idmap *idmap, struct inode *dir, ...@@ -320,12 +341,13 @@ static int ubifs_create(struct mnt_idmap *idmap, struct inode *dir,
if (err) if (err)
goto out_inode; goto out_inode;
set_nlink(inode, 1);
mutex_lock(&dir_ui->ui_mutex); mutex_lock(&dir_ui->ui_mutex);
dir->i_size += sz_change; dir->i_size += sz_change;
dir_ui->ui_size = dir->i_size; dir_ui->ui_size = dir->i_size;
inode_set_mtime_to_ts(dir, inode_set_mtime_to_ts(dir,
inode_set_ctime_to_ts(dir, inode_get_ctime(inode))); inode_set_ctime_to_ts(dir, inode_get_ctime(inode)));
err = ubifs_jnl_update(c, dir, &nm, inode, 0, 0); err = ubifs_jnl_update(c, dir, &nm, inode, 0, 0, 1);
if (err) if (err)
goto out_cancel; goto out_cancel;
mutex_unlock(&dir_ui->ui_mutex); mutex_unlock(&dir_ui->ui_mutex);
...@@ -340,8 +362,8 @@ static int ubifs_create(struct mnt_idmap *idmap, struct inode *dir, ...@@ -340,8 +362,8 @@ static int ubifs_create(struct mnt_idmap *idmap, struct inode *dir,
dir->i_size -= sz_change; dir->i_size -= sz_change;
dir_ui->ui_size = dir->i_size; dir_ui->ui_size = dir->i_size;
mutex_unlock(&dir_ui->ui_mutex); mutex_unlock(&dir_ui->ui_mutex);
set_nlink(inode, 0);
out_inode: out_inode:
make_bad_inode(inode);
iput(inode); iput(inode);
out_fname: out_fname:
fscrypt_free_filename(&nm); fscrypt_free_filename(&nm);
...@@ -386,7 +408,6 @@ static struct inode *create_whiteout(struct inode *dir, struct dentry *dentry) ...@@ -386,7 +408,6 @@ static struct inode *create_whiteout(struct inode *dir, struct dentry *dentry)
return inode; return inode;
out_inode: out_inode:
make_bad_inode(inode);
iput(inode); iput(inode);
out_free: out_free:
ubifs_err(c, "cannot create whiteout file, error %d", err); ubifs_err(c, "cannot create whiteout file, error %d", err);
...@@ -470,6 +491,7 @@ static int ubifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir, ...@@ -470,6 +491,7 @@ static int ubifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
if (err) if (err)
goto out_inode; goto out_inode;
set_nlink(inode, 1);
mutex_lock(&ui->ui_mutex); mutex_lock(&ui->ui_mutex);
insert_inode_hash(inode); insert_inode_hash(inode);
d_tmpfile(file, inode); d_tmpfile(file, inode);
...@@ -479,7 +501,7 @@ static int ubifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir, ...@@ -479,7 +501,7 @@ static int ubifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
mutex_unlock(&ui->ui_mutex); mutex_unlock(&ui->ui_mutex);
lock_2_inodes(dir, inode); lock_2_inodes(dir, inode);
err = ubifs_jnl_update(c, dir, &nm, inode, 1, 0); err = ubifs_jnl_update(c, dir, &nm, inode, 1, 0, 1);
if (err) if (err)
goto out_cancel; goto out_cancel;
unlock_2_inodes(dir, inode); unlock_2_inodes(dir, inode);
...@@ -492,7 +514,6 @@ static int ubifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir, ...@@ -492,7 +514,6 @@ static int ubifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
out_cancel: out_cancel:
unlock_2_inodes(dir, inode); unlock_2_inodes(dir, inode);
out_inode: out_inode:
make_bad_inode(inode);
if (!instantiated) if (!instantiated)
iput(inode); iput(inode);
out_budg: out_budg:
...@@ -760,10 +781,6 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir, ...@@ -760,10 +781,6 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
lock_2_inodes(dir, inode); lock_2_inodes(dir, inode);
/* Handle O_TMPFILE corner case, it is allowed to link a O_TMPFILE. */
if (inode->i_nlink == 0)
ubifs_delete_orphan(c, inode->i_ino);
inc_nlink(inode); inc_nlink(inode);
ihold(inode); ihold(inode);
inode_set_ctime_current(inode); inode_set_ctime_current(inode);
...@@ -771,7 +788,7 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir, ...@@ -771,7 +788,7 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
dir_ui->ui_size = dir->i_size; dir_ui->ui_size = dir->i_size;
inode_set_mtime_to_ts(dir, inode_set_mtime_to_ts(dir,
inode_set_ctime_to_ts(dir, inode_get_ctime(inode))); inode_set_ctime_to_ts(dir, inode_get_ctime(inode)));
err = ubifs_jnl_update(c, dir, &nm, inode, 0, 0); err = ubifs_jnl_update(c, dir, &nm, inode, 0, 0, inode->i_nlink == 1);
if (err) if (err)
goto out_cancel; goto out_cancel;
unlock_2_inodes(dir, inode); unlock_2_inodes(dir, inode);
...@@ -785,8 +802,6 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir, ...@@ -785,8 +802,6 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
dir->i_size -= sz_change; dir->i_size -= sz_change;
dir_ui->ui_size = dir->i_size; dir_ui->ui_size = dir->i_size;
drop_nlink(inode); drop_nlink(inode);
if (inode->i_nlink == 0)
ubifs_add_orphan(c, inode->i_ino);
unlock_2_inodes(dir, inode); unlock_2_inodes(dir, inode);
ubifs_release_budget(c, &req); ubifs_release_budget(c, &req);
iput(inode); iput(inode);
...@@ -846,7 +861,7 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -846,7 +861,7 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
dir_ui->ui_size = dir->i_size; dir_ui->ui_size = dir->i_size;
inode_set_mtime_to_ts(dir, inode_set_mtime_to_ts(dir,
inode_set_ctime_to_ts(dir, inode_get_ctime(inode))); inode_set_ctime_to_ts(dir, inode_get_ctime(inode)));
err = ubifs_jnl_update(c, dir, &nm, inode, 1, 0); err = ubifs_jnl_update(c, dir, &nm, inode, 1, 0, 0);
if (err) if (err)
goto out_cancel; goto out_cancel;
unlock_2_inodes(dir, inode); unlock_2_inodes(dir, inode);
...@@ -950,7 +965,7 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -950,7 +965,7 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry)
dir_ui->ui_size = dir->i_size; dir_ui->ui_size = dir->i_size;
inode_set_mtime_to_ts(dir, inode_set_mtime_to_ts(dir,
inode_set_ctime_to_ts(dir, inode_get_ctime(inode))); inode_set_ctime_to_ts(dir, inode_get_ctime(inode)));
err = ubifs_jnl_update(c, dir, &nm, inode, 1, 0); err = ubifs_jnl_update(c, dir, &nm, inode, 1, 0, 0);
if (err) if (err)
goto out_cancel; goto out_cancel;
unlock_2_inodes(dir, inode); unlock_2_inodes(dir, inode);
...@@ -1017,6 +1032,7 @@ static int ubifs_mkdir(struct mnt_idmap *idmap, struct inode *dir, ...@@ -1017,6 +1032,7 @@ static int ubifs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
if (err) if (err)
goto out_inode; goto out_inode;
set_nlink(inode, 1);
mutex_lock(&dir_ui->ui_mutex); mutex_lock(&dir_ui->ui_mutex);
insert_inode_hash(inode); insert_inode_hash(inode);
inc_nlink(inode); inc_nlink(inode);
...@@ -1025,7 +1041,7 @@ static int ubifs_mkdir(struct mnt_idmap *idmap, struct inode *dir, ...@@ -1025,7 +1041,7 @@ static int ubifs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
dir_ui->ui_size = dir->i_size; dir_ui->ui_size = dir->i_size;
inode_set_mtime_to_ts(dir, inode_set_mtime_to_ts(dir,
inode_set_ctime_to_ts(dir, inode_get_ctime(inode))); inode_set_ctime_to_ts(dir, inode_get_ctime(inode)));
err = ubifs_jnl_update(c, dir, &nm, inode, 0, 0); err = ubifs_jnl_update(c, dir, &nm, inode, 0, 0, 1);
if (err) { if (err) {
ubifs_err(c, "cannot create directory, error %d", err); ubifs_err(c, "cannot create directory, error %d", err);
goto out_cancel; goto out_cancel;
...@@ -1042,8 +1058,8 @@ static int ubifs_mkdir(struct mnt_idmap *idmap, struct inode *dir, ...@@ -1042,8 +1058,8 @@ static int ubifs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
dir_ui->ui_size = dir->i_size; dir_ui->ui_size = dir->i_size;
drop_nlink(dir); drop_nlink(dir);
mutex_unlock(&dir_ui->ui_mutex); mutex_unlock(&dir_ui->ui_mutex);
set_nlink(inode, 0);
out_inode: out_inode:
make_bad_inode(inode);
iput(inode); iput(inode);
out_fname: out_fname:
fscrypt_free_filename(&nm); fscrypt_free_filename(&nm);
...@@ -1102,22 +1118,25 @@ static int ubifs_mknod(struct mnt_idmap *idmap, struct inode *dir, ...@@ -1102,22 +1118,25 @@ static int ubifs_mknod(struct mnt_idmap *idmap, struct inode *dir,
goto out_fname; goto out_fname;
} }
err = ubifs_init_security(dir, inode, &dentry->d_name);
if (err) {
kfree(dev);
goto out_inode;
}
init_special_inode(inode, inode->i_mode, rdev); init_special_inode(inode, inode->i_mode, rdev);
inode->i_size = ubifs_inode(inode)->ui_size = devlen; inode->i_size = ubifs_inode(inode)->ui_size = devlen;
ui = ubifs_inode(inode); ui = ubifs_inode(inode);
ui->data = dev; ui->data = dev;
ui->data_len = devlen; ui->data_len = devlen;
set_nlink(inode, 1);
err = ubifs_init_security(dir, inode, &dentry->d_name);
if (err)
goto out_inode;
mutex_lock(&dir_ui->ui_mutex); mutex_lock(&dir_ui->ui_mutex);
dir->i_size += sz_change; dir->i_size += sz_change;
dir_ui->ui_size = dir->i_size; dir_ui->ui_size = dir->i_size;
inode_set_mtime_to_ts(dir, inode_set_mtime_to_ts(dir,
inode_set_ctime_to_ts(dir, inode_get_ctime(inode))); inode_set_ctime_to_ts(dir, inode_get_ctime(inode)));
err = ubifs_jnl_update(c, dir, &nm, inode, 0, 0); err = ubifs_jnl_update(c, dir, &nm, inode, 0, 0, 1);
if (err) if (err)
goto out_cancel; goto out_cancel;
mutex_unlock(&dir_ui->ui_mutex); mutex_unlock(&dir_ui->ui_mutex);
...@@ -1132,10 +1151,8 @@ static int ubifs_mknod(struct mnt_idmap *idmap, struct inode *dir, ...@@ -1132,10 +1151,8 @@ static int ubifs_mknod(struct mnt_idmap *idmap, struct inode *dir,
dir->i_size -= sz_change; dir->i_size -= sz_change;
dir_ui->ui_size = dir->i_size; dir_ui->ui_size = dir->i_size;
mutex_unlock(&dir_ui->ui_mutex); mutex_unlock(&dir_ui->ui_mutex);
set_nlink(inode, 0);
out_inode: out_inode:
/* Free inode->i_link before inode is marked as bad. */
fscrypt_free_inode(inode);
make_bad_inode(inode);
iput(inode); iput(inode);
out_fname: out_fname:
fscrypt_free_filename(&nm); fscrypt_free_filename(&nm);
...@@ -1186,6 +1203,10 @@ static int ubifs_symlink(struct mnt_idmap *idmap, struct inode *dir, ...@@ -1186,6 +1203,10 @@ static int ubifs_symlink(struct mnt_idmap *idmap, struct inode *dir,
goto out_fname; goto out_fname;
} }
err = ubifs_init_security(dir, inode, &dentry->d_name);
if (err)
goto out_inode;
ui = ubifs_inode(inode); ui = ubifs_inode(inode);
ui->data = kmalloc(disk_link.len, GFP_NOFS); ui->data = kmalloc(disk_link.len, GFP_NOFS);
if (!ui->data) { if (!ui->data) {
...@@ -1210,17 +1231,14 @@ static int ubifs_symlink(struct mnt_idmap *idmap, struct inode *dir, ...@@ -1210,17 +1231,14 @@ static int ubifs_symlink(struct mnt_idmap *idmap, struct inode *dir,
*/ */
ui->data_len = disk_link.len - 1; ui->data_len = disk_link.len - 1;
inode->i_size = ubifs_inode(inode)->ui_size = disk_link.len - 1; inode->i_size = ubifs_inode(inode)->ui_size = disk_link.len - 1;
set_nlink(inode, 1);
err = ubifs_init_security(dir, inode, &dentry->d_name);
if (err)
goto out_inode;
mutex_lock(&dir_ui->ui_mutex); mutex_lock(&dir_ui->ui_mutex);
dir->i_size += sz_change; dir->i_size += sz_change;
dir_ui->ui_size = dir->i_size; dir_ui->ui_size = dir->i_size;
inode_set_mtime_to_ts(dir, inode_set_mtime_to_ts(dir,
inode_set_ctime_to_ts(dir, inode_get_ctime(inode))); inode_set_ctime_to_ts(dir, inode_get_ctime(inode)));
err = ubifs_jnl_update(c, dir, &nm, inode, 0, 0); err = ubifs_jnl_update(c, dir, &nm, inode, 0, 0, 1);
if (err) if (err)
goto out_cancel; goto out_cancel;
mutex_unlock(&dir_ui->ui_mutex); mutex_unlock(&dir_ui->ui_mutex);
...@@ -1234,10 +1252,10 @@ static int ubifs_symlink(struct mnt_idmap *idmap, struct inode *dir, ...@@ -1234,10 +1252,10 @@ static int ubifs_symlink(struct mnt_idmap *idmap, struct inode *dir,
dir->i_size -= sz_change; dir->i_size -= sz_change;
dir_ui->ui_size = dir->i_size; dir_ui->ui_size = dir->i_size;
mutex_unlock(&dir_ui->ui_mutex); mutex_unlock(&dir_ui->ui_mutex);
set_nlink(inode, 0);
out_inode: out_inode:
/* Free inode->i_link before inode is marked as bad. */ /* Free inode->i_link before inode is marked as bad. */
fscrypt_free_inode(inode); fscrypt_free_inode(inode);
make_bad_inode(inode);
iput(inode); iput(inode);
out_fname: out_fname:
fscrypt_free_filename(&nm); fscrypt_free_filename(&nm);
...@@ -1405,14 +1423,10 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1405,14 +1423,10 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
*/ */
err = ubifs_budget_space(c, &wht_req); err = ubifs_budget_space(c, &wht_req);
if (err) { if (err) {
/*
* Whiteout inode can not be written on flash by
* ubifs_jnl_write_inode(), because it's neither
* dirty nor zero-nlink.
*/
iput(whiteout); iput(whiteout);
goto out_release; goto out_release;
} }
set_nlink(whiteout, 1);
/* Add the old_dentry size to the old_dir size. */ /* Add the old_dentry size to the old_dir size. */
old_sz -= CALC_DENT_SIZE(fname_len(&old_nm)); old_sz -= CALC_DENT_SIZE(fname_len(&old_nm));
...@@ -1491,7 +1505,7 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1491,7 +1505,7 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
} }
err = ubifs_jnl_rename(c, old_dir, old_inode, &old_nm, new_dir, err = ubifs_jnl_rename(c, old_dir, old_inode, &old_nm, new_dir,
new_inode, &new_nm, whiteout, sync); new_inode, &new_nm, whiteout, sync, !!whiteout);
if (err) if (err)
goto out_cancel; goto out_cancel;
...@@ -1544,6 +1558,7 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1544,6 +1558,7 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
unlock_4_inodes(old_dir, new_dir, new_inode, whiteout); unlock_4_inodes(old_dir, new_dir, new_inode, whiteout);
if (whiteout) { if (whiteout) {
ubifs_release_budget(c, &wht_req); ubifs_release_budget(c, &wht_req);
set_nlink(whiteout, 0);
iput(whiteout); iput(whiteout);
} }
out_release: out_release:
......
...@@ -1027,7 +1027,7 @@ static int ubifs_writepage(struct folio *folio, struct writeback_control *wbc, ...@@ -1027,7 +1027,7 @@ static int ubifs_writepage(struct folio *folio, struct writeback_control *wbc,
/* Is the folio fully inside i_size? */ /* Is the folio fully inside i_size? */
if (folio_pos(folio) + len <= i_size) { if (folio_pos(folio) + len <= i_size) {
if (folio_pos(folio) >= synced_i_size) { if (folio_pos(folio) + len > synced_i_size) {
err = inode->i_sb->s_op->write_inode(inode, NULL); err = inode->i_sb->s_op->write_inode(inode, NULL);
if (err) if (err)
goto out_redirty; goto out_redirty;
......
...@@ -73,7 +73,7 @@ static int valuable(struct ubifs_info *c, const struct ubifs_lprops *lprops) ...@@ -73,7 +73,7 @@ static int valuable(struct ubifs_info *c, const struct ubifs_lprops *lprops)
* @c: the UBIFS file-system description object * @c: the UBIFS file-system description object
* @lprops: LEB properties to scan * @lprops: LEB properties to scan
* @in_tree: whether the LEB properties are in main memory * @in_tree: whether the LEB properties are in main memory
* @data: information passed to and from the caller of the scan * @arg: information passed to and from the caller of the scan
* *
* This function returns a code that indicates whether the scan should continue * This function returns a code that indicates whether the scan should continue
* (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree * (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree
...@@ -340,7 +340,7 @@ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp, ...@@ -340,7 +340,7 @@ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp,
* @c: the UBIFS file-system description object * @c: the UBIFS file-system description object
* @lprops: LEB properties to scan * @lprops: LEB properties to scan
* @in_tree: whether the LEB properties are in main memory * @in_tree: whether the LEB properties are in main memory
* @data: information passed to and from the caller of the scan * @arg: information passed to and from the caller of the scan
* *
* This function returns a code that indicates whether the scan should continue * This function returns a code that indicates whether the scan should continue
* (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree * (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree
...@@ -581,7 +581,7 @@ int ubifs_find_free_space(struct ubifs_info *c, int min_space, int *offs, ...@@ -581,7 +581,7 @@ int ubifs_find_free_space(struct ubifs_info *c, int min_space, int *offs,
* @c: the UBIFS file-system description object * @c: the UBIFS file-system description object
* @lprops: LEB properties to scan * @lprops: LEB properties to scan
* @in_tree: whether the LEB properties are in main memory * @in_tree: whether the LEB properties are in main memory
* @data: information passed to and from the caller of the scan * @arg: information passed to and from the caller of the scan
* *
* This function returns a code that indicates whether the scan should continue * This function returns a code that indicates whether the scan should continue
* (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree * (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree
...@@ -773,7 +773,7 @@ int ubifs_save_dirty_idx_lnums(struct ubifs_info *c) ...@@ -773,7 +773,7 @@ int ubifs_save_dirty_idx_lnums(struct ubifs_info *c)
* @c: the UBIFS file-system description object * @c: the UBIFS file-system description object
* @lprops: LEB properties to scan * @lprops: LEB properties to scan
* @in_tree: whether the LEB properties are in main memory * @in_tree: whether the LEB properties are in main memory
* @data: information passed to and from the caller of the scan * @arg: information passed to and from the caller of the scan
* *
* This function returns a code that indicates whether the scan should continue * This function returns a code that indicates whether the scan should continue
* (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree * (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree
......
...@@ -359,7 +359,7 @@ static void wake_up_reservation(struct ubifs_info *c) ...@@ -359,7 +359,7 @@ static void wake_up_reservation(struct ubifs_info *c)
} }
/** /**
* wake_up_reservation - add current task in queue or start queuing. * add_or_start_queue - add current task in queue or start queuing.
* @c: UBIFS file-system description object * @c: UBIFS file-system description object
* *
* This function starts queuing if queuing is not started, otherwise adds * This function starts queuing if queuing is not started, otherwise adds
...@@ -643,6 +643,7 @@ static void set_dent_cookie(struct ubifs_info *c, struct ubifs_dent_node *dent) ...@@ -643,6 +643,7 @@ static void set_dent_cookie(struct ubifs_info *c, struct ubifs_dent_node *dent)
* @inode: inode to update * @inode: inode to update
* @deletion: indicates a directory entry deletion i.e unlink or rmdir * @deletion: indicates a directory entry deletion i.e unlink or rmdir
* @xent: non-zero if the directory entry is an extended attribute entry * @xent: non-zero if the directory entry is an extended attribute entry
* @in_orphan: indicates whether the @inode is in orphan list
* *
* This function updates an inode by writing a directory entry (or extended * This function updates an inode by writing a directory entry (or extended
* attribute entry), the inode itself, and the parent directory inode (or the * attribute entry), the inode itself, and the parent directory inode (or the
...@@ -664,7 +665,7 @@ static void set_dent_cookie(struct ubifs_info *c, struct ubifs_dent_node *dent) ...@@ -664,7 +665,7 @@ static void set_dent_cookie(struct ubifs_info *c, struct ubifs_dent_node *dent)
*/ */
int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
const struct fscrypt_name *nm, const struct inode *inode, const struct fscrypt_name *nm, const struct inode *inode,
int deletion, int xent) int deletion, int xent, int in_orphan)
{ {
int err, dlen, ilen, len, lnum, ino_offs, dent_offs, orphan_added = 0; int err, dlen, ilen, len, lnum, ino_offs, dent_offs, orphan_added = 0;
int aligned_dlen, aligned_ilen, sync = IS_DIRSYNC(dir); int aligned_dlen, aligned_ilen, sync = IS_DIRSYNC(dir);
...@@ -750,7 +751,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, ...@@ -750,7 +751,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
if (err) if (err)
goto out_release; goto out_release;
if (last_reference) { if (last_reference && !in_orphan) {
err = ubifs_add_orphan(c, inode->i_ino); err = ubifs_add_orphan(c, inode->i_ino);
if (err) { if (err) {
release_head(c, BASEHD); release_head(c, BASEHD);
...@@ -806,6 +807,9 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, ...@@ -806,6 +807,9 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
if (err) if (err)
goto out_ro; goto out_ro;
if (in_orphan && inode->i_nlink)
ubifs_delete_orphan(c, inode->i_ino);
finish_reservation(c); finish_reservation(c);
spin_lock(&ui->ui_lock); spin_lock(&ui->ui_lock);
ui->synced_i_size = ui->ui_size; ui->synced_i_size = ui->ui_size;
...@@ -1336,6 +1340,7 @@ int ubifs_jnl_xrename(struct ubifs_info *c, const struct inode *fst_dir, ...@@ -1336,6 +1340,7 @@ int ubifs_jnl_xrename(struct ubifs_info *c, const struct inode *fst_dir,
* @new_nm: new name of the new directory entry * @new_nm: new name of the new directory entry
* @whiteout: whiteout inode * @whiteout: whiteout inode
* @sync: non-zero if the write-buffer has to be synchronized * @sync: non-zero if the write-buffer has to be synchronized
* @delete_orphan: indicates an orphan entry deletion for @whiteout
* *
* This function implements the re-name operation which may involve writing up * This function implements the re-name operation which may involve writing up
* to 4 inodes(new inode, whiteout inode, old and new parent directory inodes) * to 4 inodes(new inode, whiteout inode, old and new parent directory inodes)
...@@ -1348,7 +1353,7 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, ...@@ -1348,7 +1353,7 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
const struct inode *new_dir, const struct inode *new_dir,
const struct inode *new_inode, const struct inode *new_inode,
const struct fscrypt_name *new_nm, const struct fscrypt_name *new_nm,
const struct inode *whiteout, int sync) const struct inode *whiteout, int sync, int delete_orphan)
{ {
void *p; void *p;
union ubifs_key key; union ubifs_key key;
...@@ -1565,6 +1570,9 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, ...@@ -1565,6 +1570,9 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
goto out_ro; goto out_ro;
} }
if (delete_orphan)
ubifs_delete_orphan(c, whiteout->i_ino);
finish_reservation(c); finish_reservation(c);
if (new_inode) { if (new_inode) {
mark_inode_clean(c, new_ui); mark_inode_clean(c, new_ui);
......
...@@ -1005,7 +1005,7 @@ void dbg_check_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat, ...@@ -1005,7 +1005,7 @@ void dbg_check_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat,
* @c: the UBIFS file-system description object * @c: the UBIFS file-system description object
* @lp: LEB properties to scan * @lp: LEB properties to scan
* @in_tree: whether the LEB properties are in main memory * @in_tree: whether the LEB properties are in main memory
* @lst: lprops statistics to update * @arg: lprops statistics to update
* *
* This function returns a code that indicates whether the scan should continue * This function returns a code that indicates whether the scan should continue
* (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree * (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree
......
...@@ -1918,6 +1918,7 @@ int ubifs_lpt_init(struct ubifs_info *c, int rd, int wr) ...@@ -1918,6 +1918,7 @@ int ubifs_lpt_init(struct ubifs_info *c, int rd, int wr)
* @pnode: where to keep a pnode * @pnode: where to keep a pnode
* @cnode: where to keep a cnode * @cnode: where to keep a cnode
* @in_tree: is the node in the tree in memory * @in_tree: is the node in the tree in memory
* @ptr: union of node pointers
* @ptr.nnode: pointer to the nnode (if it is an nnode) which may be here or in * @ptr.nnode: pointer to the nnode (if it is an nnode) which may be here or in
* the tree * the tree
* @ptr.pnode: ditto for pnode * @ptr.pnode: ditto for pnode
......
...@@ -67,10 +67,13 @@ static int mst_node_check_hash(const struct ubifs_info *c, ...@@ -67,10 +67,13 @@ static int mst_node_check_hash(const struct ubifs_info *c,
{ {
u8 calc[UBIFS_MAX_HASH_LEN]; u8 calc[UBIFS_MAX_HASH_LEN];
const void *node = mst; const void *node = mst;
int ret;
crypto_shash_tfm_digest(c->hash_tfm, node + sizeof(struct ubifs_ch), ret = crypto_shash_tfm_digest(c->hash_tfm, node + sizeof(struct ubifs_ch),
UBIFS_MST_NODE_SZ - sizeof(struct ubifs_ch), UBIFS_MST_NODE_SZ - sizeof(struct ubifs_ch),
calc); calc);
if (ret)
return ret;
if (ubifs_check_hash(c, expected, calc)) if (ubifs_check_hash(c, expected, calc))
return -EPERM; return -EPERM;
......
...@@ -42,24 +42,30 @@ ...@@ -42,24 +42,30 @@
static int dbg_check_orphans(struct ubifs_info *c); static int dbg_check_orphans(struct ubifs_info *c);
static struct ubifs_orphan *orphan_add(struct ubifs_info *c, ino_t inum, /**
struct ubifs_orphan *parent_orphan) * ubifs_add_orphan - add an orphan.
* @c: UBIFS file-system description object
* @inum: orphan inode number
*
* Add an orphan. This function is called when an inodes link count drops to
* zero.
*/
int ubifs_add_orphan(struct ubifs_info *c, ino_t inum)
{ {
struct ubifs_orphan *orphan, *o; struct ubifs_orphan *orphan, *o;
struct rb_node **p, *parent = NULL; struct rb_node **p, *parent = NULL;
orphan = kzalloc(sizeof(struct ubifs_orphan), GFP_NOFS); orphan = kzalloc(sizeof(struct ubifs_orphan), GFP_NOFS);
if (!orphan) if (!orphan)
return ERR_PTR(-ENOMEM); return -ENOMEM;
orphan->inum = inum; orphan->inum = inum;
orphan->new = 1; orphan->new = 1;
INIT_LIST_HEAD(&orphan->child_list);
spin_lock(&c->orphan_lock); spin_lock(&c->orphan_lock);
if (c->tot_orphans >= c->max_orphans) { if (c->tot_orphans >= c->max_orphans) {
spin_unlock(&c->orphan_lock); spin_unlock(&c->orphan_lock);
kfree(orphan); kfree(orphan);
return ERR_PTR(-ENFILE); return -ENFILE;
} }
p = &c->orph_tree.rb_node; p = &c->orph_tree.rb_node;
while (*p) { while (*p) {
...@@ -73,7 +79,7 @@ static struct ubifs_orphan *orphan_add(struct ubifs_info *c, ino_t inum, ...@@ -73,7 +79,7 @@ static struct ubifs_orphan *orphan_add(struct ubifs_info *c, ino_t inum,
ubifs_err(c, "orphaned twice"); ubifs_err(c, "orphaned twice");
spin_unlock(&c->orphan_lock); spin_unlock(&c->orphan_lock);
kfree(orphan); kfree(orphan);
return ERR_PTR(-EINVAL); return -EINVAL;
} }
} }
c->tot_orphans += 1; c->tot_orphans += 1;
...@@ -83,14 +89,9 @@ static struct ubifs_orphan *orphan_add(struct ubifs_info *c, ino_t inum, ...@@ -83,14 +89,9 @@ static struct ubifs_orphan *orphan_add(struct ubifs_info *c, ino_t inum,
list_add_tail(&orphan->list, &c->orph_list); list_add_tail(&orphan->list, &c->orph_list);
list_add_tail(&orphan->new_list, &c->orph_new); list_add_tail(&orphan->new_list, &c->orph_new);
if (parent_orphan) {
list_add_tail(&orphan->child_list,
&parent_orphan->child_list);
}
spin_unlock(&c->orphan_lock); spin_unlock(&c->orphan_lock);
dbg_gen("ino %lu", (unsigned long)inum); dbg_gen("ino %lu", (unsigned long)inum);
return orphan; return 0;
} }
static struct ubifs_orphan *lookup_orphan(struct ubifs_info *c, ino_t inum) static struct ubifs_orphan *lookup_orphan(struct ubifs_info *c, ino_t inum)
...@@ -135,6 +136,7 @@ static void orphan_delete(struct ubifs_info *c, struct ubifs_orphan *orph) ...@@ -135,6 +136,7 @@ static void orphan_delete(struct ubifs_info *c, struct ubifs_orphan *orph)
if (orph->cmt) { if (orph->cmt) {
orph->del = 1; orph->del = 1;
rb_erase(&orph->rb, &c->orph_tree);
orph->dnext = c->orph_dnext; orph->dnext = c->orph_dnext;
c->orph_dnext = orph; c->orph_dnext = orph;
dbg_gen("delete later ino %lu", (unsigned long)orph->inum); dbg_gen("delete later ino %lu", (unsigned long)orph->inum);
...@@ -144,59 +146,6 @@ static void orphan_delete(struct ubifs_info *c, struct ubifs_orphan *orph) ...@@ -144,59 +146,6 @@ static void orphan_delete(struct ubifs_info *c, struct ubifs_orphan *orph)
__orphan_drop(c, orph); __orphan_drop(c, orph);
} }
/**
* ubifs_add_orphan - add an orphan.
* @c: UBIFS file-system description object
* @inum: orphan inode number
*
* Add an orphan. This function is called when an inodes link count drops to
* zero.
*/
int ubifs_add_orphan(struct ubifs_info *c, ino_t inum)
{
int err = 0;
ino_t xattr_inum;
union ubifs_key key;
struct ubifs_dent_node *xent, *pxent = NULL;
struct fscrypt_name nm = {0};
struct ubifs_orphan *xattr_orphan;
struct ubifs_orphan *orphan;
orphan = orphan_add(c, inum, NULL);
if (IS_ERR(orphan))
return PTR_ERR(orphan);
lowest_xent_key(c, &key, inum);
while (1) {
xent = ubifs_tnc_next_ent(c, &key, &nm);
if (IS_ERR(xent)) {
err = PTR_ERR(xent);
if (err == -ENOENT)
break;
kfree(pxent);
return err;
}
fname_name(&nm) = xent->name;
fname_len(&nm) = le16_to_cpu(xent->nlen);
xattr_inum = le64_to_cpu(xent->inum);
xattr_orphan = orphan_add(c, xattr_inum, orphan);
if (IS_ERR(xattr_orphan)) {
kfree(pxent);
kfree(xent);
return PTR_ERR(xattr_orphan);
}
kfree(pxent);
pxent = xent;
key_read(c, &xent->key, &key);
}
kfree(pxent);
return 0;
}
/** /**
* ubifs_delete_orphan - delete an orphan. * ubifs_delete_orphan - delete an orphan.
* @c: UBIFS file-system description object * @c: UBIFS file-system description object
...@@ -206,7 +155,7 @@ int ubifs_add_orphan(struct ubifs_info *c, ino_t inum) ...@@ -206,7 +155,7 @@ int ubifs_add_orphan(struct ubifs_info *c, ino_t inum)
*/ */
void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum) void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum)
{ {
struct ubifs_orphan *orph, *child_orph, *tmp_o; struct ubifs_orphan *orph;
spin_lock(&c->orphan_lock); spin_lock(&c->orphan_lock);
...@@ -219,11 +168,6 @@ void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum) ...@@ -219,11 +168,6 @@ void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum)
return; return;
} }
list_for_each_entry_safe(child_orph, tmp_o, &orph->child_list, child_list) {
list_del(&child_orph->child_list);
orphan_delete(c, child_orph);
}
orphan_delete(c, orph); orphan_delete(c, orph);
spin_unlock(&c->orphan_lock); spin_unlock(&c->orphan_lock);
...@@ -518,7 +462,6 @@ static void erase_deleted(struct ubifs_info *c) ...@@ -518,7 +462,6 @@ static void erase_deleted(struct ubifs_info *c)
dnext = orphan->dnext; dnext = orphan->dnext;
ubifs_assert(c, !orphan->new); ubifs_assert(c, !orphan->new);
ubifs_assert(c, orphan->del); ubifs_assert(c, orphan->del);
rb_erase(&orphan->rb, &c->orph_tree);
list_del(&orphan->list); list_del(&orphan->list);
c->tot_orphans -= 1; c->tot_orphans -= 1;
dbg_gen("deleting orphan ino %lu", (unsigned long)orphan->inum); dbg_gen("deleting orphan ino %lu", (unsigned long)orphan->inum);
...@@ -570,51 +513,6 @@ int ubifs_clear_orphans(struct ubifs_info *c) ...@@ -570,51 +513,6 @@ int ubifs_clear_orphans(struct ubifs_info *c)
return 0; return 0;
} }
/**
* insert_dead_orphan - insert an orphan.
* @c: UBIFS file-system description object
* @inum: orphan inode number
*
* This function is a helper to the 'do_kill_orphans()' function. The orphan
* must be kept until the next commit, so it is added to the rb-tree and the
* deletion list.
*/
static int insert_dead_orphan(struct ubifs_info *c, ino_t inum)
{
struct ubifs_orphan *orphan, *o;
struct rb_node **p, *parent = NULL;
orphan = kzalloc(sizeof(struct ubifs_orphan), GFP_KERNEL);
if (!orphan)
return -ENOMEM;
orphan->inum = inum;
p = &c->orph_tree.rb_node;
while (*p) {
parent = *p;
o = rb_entry(parent, struct ubifs_orphan, rb);
if (inum < o->inum)
p = &(*p)->rb_left;
else if (inum > o->inum)
p = &(*p)->rb_right;
else {
/* Already added - no problem */
kfree(orphan);
return 0;
}
}
c->tot_orphans += 1;
rb_link_node(&orphan->rb, parent, p);
rb_insert_color(&orphan->rb, &c->orph_tree);
list_add_tail(&orphan->list, &c->orph_list);
orphan->del = 1;
orphan->dnext = c->orph_dnext;
c->orph_dnext = orphan;
dbg_mnt("ino %lu, new %d, tot %d", (unsigned long)inum,
c->new_orphans, c->tot_orphans);
return 0;
}
/** /**
* do_kill_orphans - remove orphan inodes from the index. * do_kill_orphans - remove orphan inodes from the index.
* @c: UBIFS file-system description object * @c: UBIFS file-system description object
...@@ -691,12 +589,12 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb, ...@@ -691,12 +589,12 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
n = (le32_to_cpu(orph->ch.len) - UBIFS_ORPH_NODE_SZ) >> 3; n = (le32_to_cpu(orph->ch.len) - UBIFS_ORPH_NODE_SZ) >> 3;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
union ubifs_key key1, key2; union ubifs_key key;
inum = le64_to_cpu(orph->inos[i]); inum = le64_to_cpu(orph->inos[i]);
ino_key_init(c, &key1, inum); ino_key_init(c, &key, inum);
err = ubifs_tnc_lookup(c, &key1, ino); err = ubifs_tnc_lookup(c, &key, ino);
if (err && err != -ENOENT) if (err && err != -ENOENT)
goto out_free; goto out_free;
...@@ -708,17 +606,10 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb, ...@@ -708,17 +606,10 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
dbg_rcvry("deleting orphaned inode %lu", dbg_rcvry("deleting orphaned inode %lu",
(unsigned long)inum); (unsigned long)inum);
lowest_ino_key(c, &key1, inum); err = ubifs_tnc_remove_ino(c, inum);
highest_ino_key(c, &key2, inum);
err = ubifs_tnc_remove_range(c, &key1, &key2);
if (err) if (err)
goto out_ro; goto out_ro;
} }
err = insert_dead_orphan(c, inum);
if (err)
goto out_free;
} }
*last_cmt_no = cmt_no; *last_cmt_no = cmt_no;
...@@ -925,8 +816,12 @@ static int dbg_orphan_check(struct ubifs_info *c, struct ubifs_zbranch *zbr, ...@@ -925,8 +816,12 @@ static int dbg_orphan_check(struct ubifs_info *c, struct ubifs_zbranch *zbr,
inum = key_inum(c, &zbr->key); inum = key_inum(c, &zbr->key);
if (inum != ci->last_ino) { if (inum != ci->last_ino) {
/* Lowest node type is the inode node, so it comes first */ /*
if (key_type(c, &zbr->key) != UBIFS_INO_KEY) * Lowest node type is the inode node or xattr entry(when
* selinux/encryption is enabled), so it comes first
*/
if (key_type(c, &zbr->key) != UBIFS_INO_KEY &&
key_type(c, &zbr->key) != UBIFS_XENT_KEY)
ubifs_err(c, "found orphan node ino %lu, type %d", ubifs_err(c, "found orphan node ino %lu, type %d",
(unsigned long)inum, key_type(c, &zbr->key)); (unsigned long)inum, key_type(c, &zbr->key));
ci->last_ino = inum; ci->last_ino = inum;
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
* @lnum: logical eraseblock number of the node * @lnum: logical eraseblock number of the node
* @offs: node offset * @offs: node offset
* @len: node length * @len: node length
* @hash: node hash
* @deletion: non-zero if this entry corresponds to a node deletion * @deletion: non-zero if this entry corresponds to a node deletion
* @sqnum: node sequence number * @sqnum: node sequence number
* @list: links the replay list * @list: links the replay list
......
...@@ -91,17 +91,17 @@ static struct kset ubifs_kset = { ...@@ -91,17 +91,17 @@ static struct kset ubifs_kset = {
int ubifs_sysfs_register(struct ubifs_info *c) int ubifs_sysfs_register(struct ubifs_info *c)
{ {
int ret, n; int ret, n;
char dfs_dir_name[UBIFS_DFS_DIR_LEN+1]; char dfs_dir_name[UBIFS_DFS_DIR_LEN];
c->stats = kzalloc(sizeof(struct ubifs_stats_info), GFP_KERNEL); c->stats = kzalloc(sizeof(struct ubifs_stats_info), GFP_KERNEL);
if (!c->stats) { if (!c->stats) {
ret = -ENOMEM; ret = -ENOMEM;
goto out_last; goto out_last;
} }
n = snprintf(dfs_dir_name, UBIFS_DFS_DIR_LEN + 1, UBIFS_DFS_DIR_NAME, n = snprintf(dfs_dir_name, UBIFS_DFS_DIR_LEN, UBIFS_DFS_DIR_NAME,
c->vi.ubi_num, c->vi.vol_id); c->vi.ubi_num, c->vi.vol_id);
if (n > UBIFS_DFS_DIR_LEN) { if (n >= UBIFS_DFS_DIR_LEN) {
/* The array size is too small */ /* The array size is too small */
ret = -EINVAL; ret = -EINVAL;
goto out_free; goto out_free;
......
...@@ -157,13 +157,6 @@ ...@@ -157,13 +157,6 @@
#define UBIFS_HMAC_ARR_SZ 0 #define UBIFS_HMAC_ARR_SZ 0
#endif #endif
/*
* The UBIFS sysfs directory name pattern and maximum name length (3 for "ubi"
* + 1 for "_" and plus 2x2 for 2 UBI numbers and 1 for the trailing zero byte.
*/
#define UBIFS_DFS_DIR_NAME "ubi%d_%d"
#define UBIFS_DFS_DIR_LEN (3 + 1 + 2*2 + 1)
/* /*
* Lockdep classes for UBIFS inode @ui_mutex. * Lockdep classes for UBIFS inode @ui_mutex.
*/ */
...@@ -923,8 +916,6 @@ struct ubifs_budget_req { ...@@ -923,8 +916,6 @@ struct ubifs_budget_req {
* @rb: rb-tree node of rb-tree of orphans sorted by inode number * @rb: rb-tree node of rb-tree of orphans sorted by inode number
* @list: list head of list of orphans in order added * @list: list head of list of orphans in order added
* @new_list: list head of list of orphans added since the last commit * @new_list: list head of list of orphans added since the last commit
* @child_list: list of xattr children if this orphan hosts xattrs, list head
* if this orphan is a xattr, not used otherwise.
* @cnext: next orphan to commit * @cnext: next orphan to commit
* @dnext: next orphan to delete * @dnext: next orphan to delete
* @inum: inode number * @inum: inode number
...@@ -936,7 +927,6 @@ struct ubifs_orphan { ...@@ -936,7 +927,6 @@ struct ubifs_orphan {
struct rb_node rb; struct rb_node rb;
struct list_head list; struct list_head list;
struct list_head new_list; struct list_head new_list;
struct list_head child_list;
struct ubifs_orphan *cnext; struct ubifs_orphan *cnext;
struct ubifs_orphan *dnext; struct ubifs_orphan *dnext;
ino_t inum; ino_t inum;
...@@ -1803,7 +1793,7 @@ int ubifs_consolidate_log(struct ubifs_info *c); ...@@ -1803,7 +1793,7 @@ int ubifs_consolidate_log(struct ubifs_info *c);
/* journal.c */ /* journal.c */
int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
const struct fscrypt_name *nm, const struct inode *inode, const struct fscrypt_name *nm, const struct inode *inode,
int deletion, int xent); int deletion, int xent, int in_orphan);
int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode, int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
const union ubifs_key *key, const void *buf, int len); const union ubifs_key *key, const void *buf, int len);
int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode); int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode);
...@@ -1820,7 +1810,7 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, ...@@ -1820,7 +1810,7 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
const struct inode *new_dir, const struct inode *new_dir,
const struct inode *new_inode, const struct inode *new_inode,
const struct fscrypt_name *new_nm, const struct fscrypt_name *new_nm,
const struct inode *whiteout, int sync); const struct inode *whiteout, int sync, int delete_orphan);
int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode, int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode,
loff_t old_size, loff_t new_size); loff_t old_size, loff_t new_size);
int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host, int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host,
......
...@@ -149,7 +149,7 @@ static int create_xattr(struct ubifs_info *c, struct inode *host, ...@@ -149,7 +149,7 @@ static int create_xattr(struct ubifs_info *c, struct inode *host,
if (strcmp(fname_name(nm), UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT) == 0) if (strcmp(fname_name(nm), UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT) == 0)
host_ui->flags |= UBIFS_CRYPT_FL; host_ui->flags |= UBIFS_CRYPT_FL;
err = ubifs_jnl_update(c, host, nm, inode, 0, 1); err = ubifs_jnl_update(c, host, nm, inode, 0, 1, 0);
if (err) if (err)
goto out_cancel; goto out_cancel;
ubifs_set_inode_flags(host); ubifs_set_inode_flags(host);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment