Commit d7a02fa0 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'upstream-5.2-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/rw/ubifs

Pull UBI/UBIFS updates from Richard Weinberger:

 - fscrypt framework usage updates

 - One huge fix for xattr unlink

 - Cleanup of fscrypt ifdefs

 - Fix for our new UBIFS auth feature

* tag 'upstream-5.2-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/rw/ubifs:
  ubi: wl: Fix uninitialized variable
  ubifs: Drop unnecessary setting of zbr->znode
  ubifs: Remove ifdefs around CONFIG_UBIFS_ATIME_SUPPORT
  ubifs: Remove #ifdef around CONFIG_FS_ENCRYPTION
  ubifs: Limit number of xattrs per inode
  ubifs: orphan: Handle xattrs like files
  ubifs: journal: Handle xattrs like files
  ubifs: find.c: replace swap function with built-in one
  ubifs: Do not skip hash checking in data nodes
  ubifs: work around high stack usage with clang
  ubifs: remove unused function __ubifs_shash_final
  ubifs: remove unnecessary #ifdef around fscrypt_ioctl_get_policy()
  ubifs: remove unnecessary calls to set up directory key
parents 4dbf09fe 04d37e5a
......@@ -1475,7 +1475,7 @@ static bool scrub_possible(struct ubi_device *ubi, struct ubi_wl_entry *e)
*/
int ubi_bitflip_check(struct ubi_device *ubi, int pnum, int force)
{
int err;
int err = 0;
struct ubi_wl_entry *e;
if (pnum < 0 || pnum >= ubi->peb_count) {
......
......@@ -76,7 +76,6 @@ static int ubifs_hash_calc_hmac(const struct ubifs_info *c, const u8 *hash,
int ubifs_prepare_auth_node(struct ubifs_info *c, void *node,
struct shash_desc *inhash)
{
SHASH_DESC_ON_STACK(hash_desc, c->hash_tfm);
struct ubifs_auth_node *auth = node;
u8 *hash;
int err;
......@@ -85,12 +84,16 @@ int ubifs_prepare_auth_node(struct ubifs_info *c, void *node,
if (!hash)
return -ENOMEM;
{
SHASH_DESC_ON_STACK(hash_desc, c->hash_tfm);
hash_desc->tfm = c->hash_tfm;
ubifs_shash_copy_state(c, inhash, hash_desc);
err = crypto_shash_final(hash_desc, hash);
if (err)
goto out;
}
err = ubifs_hash_calc_hmac(c, hash, auth->hmac);
if (err)
......@@ -142,24 +145,6 @@ struct shash_desc *__ubifs_hash_get_desc(const struct ubifs_info *c)
return ubifs_get_desc(c, c->hash_tfm);
}
/**
* __ubifs_shash_final - finalize shash
* @c: UBIFS file-system description object
* @desc: the descriptor
* @out: the output hash
*
* Simple wrapper around crypto_shash_final(), safe to be called with
* disabled authentication.
*/
int __ubifs_shash_final(const struct ubifs_info *c, struct shash_desc *desc,
u8 *out)
{
if (ubifs_authenticated(c))
return crypto_shash_final(desc, out);
return 0;
}
/**
* ubifs_bad_hash - Report hash mismatches
* @c: UBIFS file-system description object
......
......@@ -1603,7 +1603,6 @@ int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb,
err = PTR_ERR(child);
goto out_unlock;
}
zbr->znode = child;
}
znode = child;
......
......@@ -790,13 +790,11 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
dentry, inode->i_ino,
inode->i_nlink, dir->i_ino);
if (ubifs_crypt_is_encrypted(dir)) {
err = fscrypt_get_encryption_info(dir);
if (err && err != -ENOKEY)
err = fscrypt_setup_filename(dir, &dentry->d_name, 1, &nm);
if (err)
return err;
}
err = fscrypt_setup_filename(dir, &dentry->d_name, 1, &nm);
err = ubifs_purge_xattrs(inode);
if (err)
return err;
......@@ -900,13 +898,11 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry)
if (err)
return err;
if (ubifs_crypt_is_encrypted(dir)) {
err = fscrypt_get_encryption_info(dir);
if (err && err != -ENOKEY)
err = fscrypt_setup_filename(dir, &dentry->d_name, 1, &nm);
if (err)
return err;
}
err = fscrypt_setup_filename(dir, &dentry->d_name, 1, &nm);
err = ubifs_purge_xattrs(inode);
if (err)
return err;
......@@ -1292,9 +1288,14 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
old_dentry, old_inode->i_ino, old_dir->i_ino,
new_dentry, new_dir->i_ino, flags);
if (unlink)
if (unlink) {
ubifs_assert(c, inode_is_locked(new_inode));
err = ubifs_purge_xattrs(new_inode);
if (err)
return err;
}
if (unlink && is_dir) {
err = ubifs_check_dir_empty(new_inode);
if (err)
......@@ -1650,9 +1651,7 @@ const struct inode_operations ubifs_dir_inode_operations = {
#ifdef CONFIG_UBIFS_FS_XATTR
.listxattr = ubifs_listxattr,
#endif
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
.update_time = ubifs_update_time,
#endif
.tmpfile = ubifs_tmpfile,
};
......
......@@ -1375,7 +1375,6 @@ static inline int mctime_update_needed(const struct inode *inode,
return 0;
}
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
/**
* ubifs_update_time - update time of inode.
* @inode: inode to update
......@@ -1392,6 +1391,9 @@ int ubifs_update_time(struct inode *inode, struct timespec64 *time,
int iflags = I_DIRTY_TIME;
int err, release;
if (!IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT))
return generic_update_time(inode, time, flags);
err = ubifs_budget_space(c, &req);
if (err)
return err;
......@@ -1414,7 +1416,6 @@ int ubifs_update_time(struct inode *inode, struct timespec64 *time,
ubifs_release_budget(c, &req);
return 0;
}
#endif
/**
* update_mctime - update mtime and ctime of an inode.
......@@ -1623,9 +1624,10 @@ static int ubifs_file_mmap(struct file *file, struct vm_area_struct *vma)
if (err)
return err;
vma->vm_ops = &ubifs_file_vm_ops;
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
if (IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT))
file_accessed(file);
#endif
return 0;
}
......@@ -1663,9 +1665,7 @@ const struct inode_operations ubifs_file_inode_operations = {
#ifdef CONFIG_UBIFS_FS_XATTR
.listxattr = ubifs_listxattr,
#endif
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
.update_time = ubifs_update_time,
#endif
};
const struct inode_operations ubifs_symlink_inode_operations = {
......@@ -1675,9 +1675,7 @@ const struct inode_operations ubifs_symlink_inode_operations = {
#ifdef CONFIG_UBIFS_FS_XATTR
.listxattr = ubifs_listxattr,
#endif
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
.update_time = ubifs_update_time,
#endif
};
const struct file_operations ubifs_file_operations = {
......
......@@ -747,12 +747,6 @@ static int cmp_dirty_idx(const struct ubifs_lprops **a,
return lpa->dirty + lpa->free - lpb->dirty - lpb->free;
}
static void swap_dirty_idx(struct ubifs_lprops **a, struct ubifs_lprops **b,
int size)
{
swap(*a, *b);
}
/**
* ubifs_save_dirty_idx_lnums - save an array of the most dirty index LEB nos.
* @c: the UBIFS file-system description object
......@@ -772,8 +766,7 @@ int ubifs_save_dirty_idx_lnums(struct ubifs_info *c)
sizeof(void *) * c->dirty_idx.cnt);
/* Sort it so that the dirtiest is now at the end */
sort(c->dirty_idx.arr, c->dirty_idx.cnt, sizeof(void *),
(int (*)(const void *, const void *))cmp_dirty_idx,
(void (*)(void *, void *, int))swap_dirty_idx);
(int (*)(const void *, const void *))cmp_dirty_idx, NULL);
dbg_find("found %d dirty index LEBs", c->dirty_idx.cnt);
if (c->dirty_idx.cnt)
dbg_find("dirtiest index LEB is %d with dirty %d and free %d",
......
......@@ -193,7 +193,6 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return err;
}
case FS_IOC_SET_ENCRYPTION_POLICY: {
#ifdef CONFIG_FS_ENCRYPTION
struct ubifs_info *c = inode->i_sb->s_fs_info;
err = ubifs_enable_encryption(c);
......@@ -201,17 +200,9 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return err;
return fscrypt_ioctl_set_policy(file, (const void __user *)arg);
#else
return -EOPNOTSUPP;
#endif
}
case FS_IOC_GET_ENCRYPTION_POLICY: {
#ifdef CONFIG_FS_ENCRYPTION
case FS_IOC_GET_ENCRYPTION_POLICY:
return fscrypt_ioctl_get_policy(file, (void __user *)arg);
#else
return -EOPNOTSUPP;
#endif
}
default:
return -ENOTTY;
......
......@@ -852,10 +852,11 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)
{
int err, lnum, offs;
struct ubifs_ino_node *ino;
struct ubifs_ino_node *ino, *ino_start;
struct ubifs_inode *ui = ubifs_inode(inode);
int sync = 0, write_len, ilen = UBIFS_INO_NODE_SZ;
int sync = 0, write_len = 0, ilen = UBIFS_INO_NODE_SZ;
int last_reference = !inode->i_nlink;
int kill_xattrs = ui->xattr_cnt && last_reference;
u8 hash[UBIFS_HASH_ARR_SZ];
dbg_jnl("ino %lu, nlink %u", inode->i_ino, inode->i_nlink);
......@@ -867,14 +868,16 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)
if (!last_reference) {
ilen += ui->data_len;
sync = IS_SYNC(inode);
} else if (kill_xattrs) {
write_len += UBIFS_INO_NODE_SZ * ui->xattr_cnt;
}
if (ubifs_authenticated(c))
write_len = ALIGN(ilen, 8) + ubifs_auth_node_sz(c);
write_len += ALIGN(ilen, 8) + ubifs_auth_node_sz(c);
else
write_len = ilen;
write_len += ilen;
ino = kmalloc(write_len, GFP_NOFS);
ino_start = ino = kmalloc(write_len, GFP_NOFS);
if (!ino)
return -ENOMEM;
......@@ -883,12 +886,59 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)
if (err)
goto out_free;
if (kill_xattrs) {
union ubifs_key key;
struct fscrypt_name nm = {0};
struct inode *xino;
struct ubifs_dent_node *xent, *pxent = NULL;
if (ui->xattr_cnt >= ubifs_xattr_max_cnt(c)) {
ubifs_err(c, "Cannot delete inode, it has too much xattrs!");
goto out_release;
}
lowest_xent_key(c, &key, inode->i_ino);
while (1) {
xent = ubifs_tnc_next_ent(c, &key, &nm);
if (IS_ERR(xent)) {
err = PTR_ERR(xent);
if (err == -ENOENT)
break;
goto out_release;
}
fname_name(&nm) = xent->name;
fname_len(&nm) = le16_to_cpu(xent->nlen);
xino = ubifs_iget(c->vfs_sb, xent->inum);
if (IS_ERR(xino)) {
err = PTR_ERR(xino);
ubifs_err(c, "dead directory entry '%s', error %d",
xent->name, err);
ubifs_ro_mode(c, err);
goto out_release;
}
ubifs_assert(c, ubifs_inode(xino)->xattr);
clear_nlink(xino);
pack_inode(c, ino, xino, 0);
ino = (void *)ino + UBIFS_INO_NODE_SZ;
iput(xino);
kfree(pxent);
pxent = xent;
key_read(c, &xent->key, &key);
}
kfree(pxent);
}
pack_inode(c, ino, inode, 1);
err = ubifs_node_calc_hash(c, ino, hash);
if (err)
goto out_release;
err = write_head(c, BASEHD, ino, write_len, &lnum, &offs, sync);
err = write_head(c, BASEHD, ino_start, write_len, &lnum, &offs, sync);
if (err)
goto out_release;
if (!sync)
......@@ -903,7 +953,7 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)
if (err)
goto out_ro;
ubifs_delete_orphan(c, inode->i_ino);
err = ubifs_add_dirt(c, lnum, ilen);
err = ubifs_add_dirt(c, lnum, write_len);
} else {
union ubifs_key key;
......@@ -917,7 +967,7 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)
spin_lock(&ui->ui_lock);
ui->synced_i_size = ui->ui_size;
spin_unlock(&ui->ui_lock);
kfree(ino);
kfree(ino_start);
return 0;
out_release:
......@@ -926,7 +976,7 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)
ubifs_ro_mode(c, err);
finish_reservation(c);
out_free:
kfree(ino);
kfree(ino_start);
return err;
}
......@@ -966,8 +1016,8 @@ int ubifs_jnl_delete_inode(struct ubifs_info *c, const struct inode *inode)
ubifs_assert(c, inode->i_nlink == 0);
if (ui->del_cmtno != c->cmt_no)
/* A commit happened for sure */
if (ui->xattr_cnt || ui->del_cmtno != c->cmt_no)
/* A commit happened for sure or inode hosts xattrs */
return ubifs_jnl_write_inode(c, inode);
down_read(&c->commit_sem);
......
......@@ -288,6 +288,14 @@ static inline int ubifs_next_log_lnum(const struct ubifs_info *c, int lnum)
return lnum;
}
static inline int ubifs_xattr_max_cnt(struct ubifs_info *c)
{
int max_xattrs = (c->leb_size / 2) / UBIFS_INO_NODE_SZ;
ubifs_assert(c, max_xattrs < c->max_orphans);
return max_xattrs;
}
const char *ubifs_assert_action_name(struct ubifs_info *c);
#endif /* __UBIFS_MISC_H__ */
......@@ -54,30 +54,24 @@
static int dbg_check_orphans(struct ubifs_info *c);
/**
* 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)
static struct ubifs_orphan *orphan_add(struct ubifs_info *c, ino_t inum,
struct ubifs_orphan *parent_orphan)
{
struct ubifs_orphan *orphan, *o;
struct rb_node **p, *parent = NULL;
orphan = kzalloc(sizeof(struct ubifs_orphan), GFP_NOFS);
if (!orphan)
return -ENOMEM;
return ERR_PTR(-ENOMEM);
orphan->inum = inum;
orphan->new = 1;
INIT_LIST_HEAD(&orphan->child_list);
spin_lock(&c->orphan_lock);
if (c->tot_orphans >= c->max_orphans) {
spin_unlock(&c->orphan_lock);
kfree(orphan);
return -ENFILE;
return ERR_PTR(-ENFILE);
}
p = &c->orph_tree.rb_node;
while (*p) {
......@@ -91,7 +85,7 @@ int ubifs_add_orphan(struct ubifs_info *c, ino_t inum)
ubifs_err(c, "orphaned twice");
spin_unlock(&c->orphan_lock);
kfree(orphan);
return 0;
return ERR_PTR(-EINVAL);
}
}
c->tot_orphans += 1;
......@@ -100,24 +94,22 @@ int ubifs_add_orphan(struct ubifs_info *c, ino_t inum)
rb_insert_color(&orphan->rb, &c->orph_tree);
list_add_tail(&orphan->list, &c->orph_list);
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);
dbg_gen("ino %lu", (unsigned long)inum);
return 0;
return orphan;
}
/**
* ubifs_delete_orphan - delete an orphan.
* @c: UBIFS file-system description object
* @inum: orphan inode number
*
* Delete an orphan. This function is called when an inode is deleted.
*/
void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum)
static struct ubifs_orphan *lookup_orphan(struct ubifs_info *c, ino_t inum)
{
struct ubifs_orphan *o;
struct rb_node *p;
spin_lock(&c->orphan_lock);
p = c->orph_tree.rb_node;
while (p) {
o = rb_entry(p, struct ubifs_orphan, rb);
......@@ -126,37 +118,124 @@ void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum)
else if (inum > o->inum)
p = p->rb_right;
else {
if (o->del) {
return o;
}
}
return NULL;
}
static void __orphan_drop(struct ubifs_info *c, struct ubifs_orphan *o)
{
rb_erase(&o->rb, &c->orph_tree);
list_del(&o->list);
c->tot_orphans -= 1;
if (o->new) {
list_del(&o->new_list);
c->new_orphans -= 1;
}
kfree(o);
}
static void orphan_delete(struct ubifs_info *c, ino_t inum)
{
struct ubifs_orphan *orph, *child_orph, *tmp_o;
spin_lock(&c->orphan_lock);
orph = lookup_orphan(c, inum);
if (!orph) {
spin_unlock(&c->orphan_lock);
ubifs_err(c, "missing orphan ino %lu", (unsigned long)inum);
dump_stack();
return;
}
if (orph->del) {
spin_unlock(&c->orphan_lock);
dbg_gen("deleted twice ino %lu",
(unsigned long)inum);
return;
}
if (o->cmt) {
o->del = 1;
o->dnext = c->orph_dnext;
c->orph_dnext = o;
if (orph->cmt) {
orph->del = 1;
orph->dnext = c->orph_dnext;
c->orph_dnext = orph;
spin_unlock(&c->orphan_lock);
dbg_gen("delete later ino %lu",
(unsigned long)inum);
return;
}
rb_erase(p, &c->orph_tree);
list_del(&o->list);
c->tot_orphans -= 1;
if (o->new) {
list_del(&o->new_list);
c->new_orphans -= 1;
list_for_each_entry_safe(child_orph, tmp_o, &orph->child_list, child_list) {
list_del(&child_orph->child_list);
__orphan_drop(c, child_orph);
}
__orphan_drop(c, orph);
spin_unlock(&c->orphan_lock);
kfree(o);
dbg_gen("inum %lu", (unsigned long)inum);
return;
}
/**
* 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;
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;
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))
return PTR_ERR(xattr_orphan);
key_read(c, &xent->key, &key);
}
spin_unlock(&c->orphan_lock);
ubifs_err(c, "missing orphan ino %lu", (unsigned long)inum);
dump_stack();
return 0;
}
/**
* ubifs_delete_orphan - delete an orphan.
* @c: UBIFS file-system description object
* @inum: orphan inode number
*
* Delete an orphan. This function is called when an inode is deleted.
*/
void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum)
{
orphan_delete(c, inum);
}
/**
......@@ -611,10 +690,16 @@ 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;
for (i = 0; i < n; i++) {
union ubifs_key key1, key2;
inum = le64_to_cpu(orph->inos[i]);
dbg_rcvry("deleting orphaned inode %lu",
(unsigned long)inum);
err = ubifs_tnc_remove_ino(c, inum);
lowest_ino_key(c, &key1, inum);
highest_ino_key(c, &key2, inum);
err = ubifs_tnc_remove_range(c, &key1, &key2);
if (err)
return err;
err = insert_dead_orphan(c, inum);
......@@ -744,26 +829,15 @@ struct check_info {
struct rb_root root;
};
static int dbg_find_orphan(struct ubifs_info *c, ino_t inum)
static bool dbg_find_orphan(struct ubifs_info *c, ino_t inum)
{
struct ubifs_orphan *o;
struct rb_node *p;
bool found = false;
spin_lock(&c->orphan_lock);
p = c->orph_tree.rb_node;
while (p) {
o = rb_entry(p, struct ubifs_orphan, rb);
if (inum < o->inum)
p = p->rb_left;
else if (inum > o->inum)
p = p->rb_right;
else {
found = !!lookup_orphan(c, inum);
spin_unlock(&c->orphan_lock);
return 1;
}
}
spin_unlock(&c->orphan_lock);
return 0;
return found;
}
static int dbg_ins_check_orphan(struct rb_root *root, ino_t inum)
......
......@@ -748,14 +748,12 @@ int ubifs_read_superblock(struct ubifs_info *c)
goto out;
}
#ifndef CONFIG_FS_ENCRYPTION
if (c->encrypted) {
if (!IS_ENABLED(CONFIG_UBIFS_FS_ENCRYPTION) && c->encrypted) {
ubifs_err(c, "file system contains encrypted files but UBIFS"
" was built without crypto support.");
err = -EINVAL;
goto out;
}
#endif
/* Automatically increase file system size to the maximum size */
c->old_leb_cnt = c->leb_cnt;
......@@ -943,6 +941,9 @@ int ubifs_enable_encryption(struct ubifs_info *c)
int err;
struct ubifs_sb_node *sup = c->sup_node;
if (!IS_ENABLED(CONFIG_UBIFS_FS_ENCRYPTION))
return -EOPNOTSUPP;
if (c->encrypted)
return 0;
......
......@@ -129,9 +129,10 @@ struct inode *ubifs_iget(struct super_block *sb, unsigned long inum)
goto out_ino;
inode->i_flags |= S_NOCMTIME;
#ifndef CONFIG_UBIFS_ATIME_SUPPORT
if (!IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT))
inode->i_flags |= S_NOATIME;
#endif
set_nlink(inode, le32_to_cpu(ino->nlink));
i_uid_write(inode, le32_to_cpu(ino->uid));
i_gid_write(inode, le32_to_cpu(ino->gid));
......@@ -1545,6 +1546,8 @@ static int mount_ubifs(struct ubifs_info *c)
c->bud_bytes, c->bud_bytes >> 10, c->bud_bytes >> 20);
dbg_gen("max. seq. number: %llu", c->max_sqnum);
dbg_gen("commit number: %llu", c->cmt_no);
dbg_gen("max. xattrs per inode: %d", ubifs_xattr_max_cnt(c));
dbg_gen("max orphans: %d", c->max_orphans);
return 0;
......@@ -2141,9 +2144,7 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
#ifdef CONFIG_UBIFS_FS_XATTR
sb->s_xattr = ubifs_xattr_handlers;
#endif
#ifdef CONFIG_FS_ENCRYPTION
sb->s_cop = &ubifs_crypt_operations;
#endif
fscrypt_set_ops(sb, &ubifs_crypt_operations);
mutex_lock(&c->umount_mutex);
err = mount_ubifs(c);
......@@ -2245,11 +2246,10 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags,
goto out_deact;
/* We do not support atime */
sb->s_flags |= SB_ACTIVE;
#ifndef CONFIG_UBIFS_ATIME_SUPPORT
sb->s_flags |= SB_NOATIME;
#else
if (IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT))
ubifs_msg(c, "full atime support is enabled.");
#endif
else
sb->s_flags |= SB_NOATIME;
}
/* 'fill_super()' opens ubi again so we must close it here */
......
......@@ -479,14 +479,13 @@ static int try_read_node(const struct ubifs_info *c, void *buf, int type,
if (node_len != len)
return 0;
if (type == UBIFS_DATA_NODE && c->no_chk_data_crc && !c->mounting &&
!c->remounting_rw)
return 1;
if (type != UBIFS_DATA_NODE || !c->no_chk_data_crc || c->mounting ||
c->remounting_rw) {
crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8);
node_crc = le32_to_cpu(ch->crc);
if (crc != node_crc)
return 0;
}
err = ubifs_node_check_hash(c, buf, zbr->hash);
if (err) {
......
......@@ -924,6 +924,8 @@ struct ubifs_budget_req {
* @rb: rb-tree node of rb-tree of orphans sorted by inode number
* @list: list head of list of orphans in order added
* @new_list: list head of list of orphans added since the last commit
* @child_list: list of xattr childs if this orphan hosts xattrs, list head
* if this orphan is a xattr, not used otherwise.
* @cnext: next orphan to commit
* @dnext: next orphan to delete
* @inum: inode number
......@@ -935,6 +937,7 @@ struct ubifs_orphan {
struct rb_node rb;
struct list_head list;
struct list_head new_list;
struct list_head child_list;
struct ubifs_orphan *cnext;
struct ubifs_orphan *dnext;
ino_t inum;
......@@ -1996,9 +1999,7 @@ int ubifs_calc_dark(const struct ubifs_info *c, int spc);
/* file.c */
int ubifs_fsync(struct file *file, loff_t start, loff_t end, int datasync);
int ubifs_setattr(struct dentry *dentry, struct iattr *attr);
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
int ubifs_update_time(struct inode *inode, struct timespec64 *time, int flags);
#endif
/* dir.c */
struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir,
......@@ -2014,6 +2015,7 @@ int ubifs_xattr_set(struct inode *host, const char *name, const void *value,
size_t size, int flags, bool check_lock);
ssize_t ubifs_xattr_get(struct inode *host, const char *name, void *buf,
size_t size);
int ubifs_purge_xattrs(struct inode *host);
#ifdef CONFIG_UBIFS_FS_XATTR
void ubifs_evict_xattr_inode(struct ubifs_info *c, ino_t xattr_inum);
......
......@@ -60,12 +60,6 @@
#include <linux/slab.h>
#include <linux/xattr.h>
/*
* Limit the number of extended attributes per inode so that the total size
* (@xattr_size) is guaranteeded to fit in an 'unsigned int'.
*/
#define MAX_XATTRS_PER_INODE 65535
/*
* Extended attribute type constants.
*
......@@ -106,7 +100,7 @@ static int create_xattr(struct ubifs_info *c, struct inode *host,
.new_ino_d = ALIGN(size, 8), .dirtied_ino = 1,
.dirtied_ino_d = ALIGN(host_ui->data_len, 8) };
if (host_ui->xattr_cnt >= MAX_XATTRS_PER_INODE) {
if (host_ui->xattr_cnt >= ubifs_xattr_max_cnt(c)) {
ubifs_err(c, "inode %lu already has too many xattrs (%d), cannot create more",
host->i_ino, host_ui->xattr_cnt);
return -ENOSPC;
......@@ -507,6 +501,69 @@ static int remove_xattr(struct ubifs_info *c, struct inode *host,
return err;
}
int ubifs_purge_xattrs(struct inode *host)
{
union ubifs_key key;
struct ubifs_info *c = host->i_sb->s_fs_info;
struct ubifs_dent_node *xent, *pxent = NULL;
struct inode *xino;
struct fscrypt_name nm = {0};
int err;
if (ubifs_inode(host)->xattr_cnt < ubifs_xattr_max_cnt(c))
return 0;
ubifs_warn(c, "inode %lu has too many xattrs, doing a non-atomic deletion",
host->i_ino);
lowest_xent_key(c, &key, host->i_ino);
while (1) {
xent = ubifs_tnc_next_ent(c, &key, &nm);
if (IS_ERR(xent)) {
err = PTR_ERR(xent);
break;
}
fname_name(&nm) = xent->name;
fname_len(&nm) = le16_to_cpu(xent->nlen);
xino = ubifs_iget(c->vfs_sb, xent->inum);
if (IS_ERR(xino)) {
err = PTR_ERR(xino);
ubifs_err(c, "dead directory entry '%s', error %d",
xent->name, err);
ubifs_ro_mode(c, err);
kfree(pxent);
return err;
}
ubifs_assert(c, ubifs_inode(xino)->xattr);
clear_nlink(xino);
err = remove_xattr(c, host, xino, &nm);
if (err) {
kfree(pxent);
iput(xino);
ubifs_err(c, "cannot remove xattr, error %d", err);
return err;
}
iput(xino);
kfree(pxent);
pxent = xent;
key_read(c, &xent->key, &key);
}
kfree(pxent);
if (err != -ENOENT) {
ubifs_err(c, "cannot find next direntry, error %d", err);
return err;
}
return 0;
}
/**
* ubifs_evict_xattr_inode - Evict an xattr inode.
* @c: UBIFS file-system description object
......
......@@ -247,6 +247,11 @@ extern int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
extern const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
unsigned int max_size,
struct delayed_call *done);
static inline void fscrypt_set_ops(struct super_block *sb,
const struct fscrypt_operations *s_cop)
{
sb->s_cop = s_cop;
}
#else /* !CONFIG_FS_ENCRYPTION */
static inline bool fscrypt_has_encryption_key(const struct inode *inode)
......@@ -471,6 +476,12 @@ static inline const char *fscrypt_get_symlink(struct inode *inode,
{
return ERR_PTR(-EOPNOTSUPP);
}
static inline void fscrypt_set_ops(struct super_block *sb,
const struct fscrypt_operations *s_cop)
{
}
#endif /* !CONFIG_FS_ENCRYPTION */
/**
......
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