From c64cda8a99135c584a1c61074e225aacdf31060f Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 15 Mar 2019 13:54:32 -0700 Subject: ubifs: remove unnecessary calls to set up directory key In ubifs_unlink() and ubifs_rmdir(), remove the call to fscrypt_get_encryption_info() that precedes fscrypt_setup_filename(). This call was unnecessary, because fscrypt_setup_filename() already tries to set up the directory's encryption key. Signed-off-by: Eric Biggers Signed-off-by: Richard Weinberger --- fs/ubifs/dir.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'fs/ubifs/dir.c') diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 5767b373a8ff..c3311ea68fe5 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -792,12 +792,6 @@ 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) - return err; - } - err = fscrypt_setup_filename(dir, &dentry->d_name, 1, &nm); if (err) return err; @@ -902,12 +896,6 @@ 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) - return err; - } - err = fscrypt_setup_filename(dir, &dentry->d_name, 1, &nm); if (err) return err; -- cgit v1.2.3 From 9ca2d732644484488db31123ecd3bf122b551566 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Fri, 5 Apr 2019 00:34:38 +0200 Subject: ubifs: Limit number of xattrs per inode Since we have to write one deletion inode per xattr into the journal, limit the max number of xattrs. In theory UBIFS supported up to 65535 xattrs per inode. But this never worked correctly, expect no powercuts happened. Now we support only as many xattrs as we can store in 50% of a LEB. Even for tiny flashes this allows dozens of xattrs per inode, which is for an embedded filesystem still fine. In case someone has existing inodes with much more xattrs, it is still possible to delete them. UBIFS will fall back to an non-atomic deletion mode. Reported-by: Stefan Agner Fixes: 1e51764a3c2ac ("UBIFS: add new flash file system") Signed-off-by: Richard Weinberger --- fs/ubifs/dir.c | 15 +++++++++++- fs/ubifs/journal.c | 12 +++++++++ fs/ubifs/misc.h | 8 ++++++ fs/ubifs/super.c | 2 ++ fs/ubifs/ubifs.h | 1 + fs/ubifs/xattr.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++------ 6 files changed, 101 insertions(+), 8 deletions(-) (limited to 'fs/ubifs/dir.c') diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index c3311ea68fe5..d2f5a50f5d83 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -796,6 +796,10 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry) if (err) return err; + err = ubifs_purge_xattrs(inode); + if (err) + return err; + sz_change = CALC_DENT_SIZE(fname_len(&nm)); ubifs_assert(c, inode_is_locked(dir)); @@ -900,6 +904,10 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry) if (err) return err; + err = ubifs_purge_xattrs(inode); + if (err) + return err; + sz_change = CALC_DENT_SIZE(fname_len(&nm)); err = ubifs_budget_space(c, &req); @@ -1282,9 +1290,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) diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index 4f74d443ca44..74a7306978d0 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -892,6 +892,11 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode) 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); @@ -907,6 +912,13 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode) 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); diff --git a/fs/ubifs/misc.h b/fs/ubifs/misc.h index 6f87237fdbf4..78a6e97f846e 100644 --- a/fs/ubifs/misc.h +++ b/fs/ubifs/misc.h @@ -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__ */ diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 12628184772c..300458a4f518 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1548,6 +1548,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; diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index d28102829f6c..cf4b10f24b6d 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -2017,6 +2017,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); diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c index f5ad1ede7990..acab3181ab35 100644 --- a/fs/ubifs/xattr.c +++ b/fs/ubifs/xattr.c @@ -60,12 +60,6 @@ #include #include -/* - * 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 @@ out_cancel: 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 -- cgit v1.2.3 From e3d73dead4988f3eb8483b28087f3ec0ff9d1398 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 26 Mar 2019 08:52:32 +0100 Subject: ubifs: Remove ifdefs around CONFIG_UBIFS_ATIME_SUPPORT ifdefs reduce readability and compile coverage. This removes the ifdefs around CONFIG_UBIFS_ATIME_SUPPORT by replacing them with IS_ENABLED() where applicable. The fs layer would fall back to generic_update_time() when .update_time doesn't exist. We do this fallback explicitly now. Signed-off-by: Sascha Hauer Signed-off-by: Richard Weinberger --- fs/ubifs/dir.c | 2 -- fs/ubifs/file.c | 16 +++++++--------- fs/ubifs/super.c | 16 ++++++++-------- fs/ubifs/ubifs.h | 2 -- 4 files changed, 15 insertions(+), 21 deletions(-) (limited to 'fs/ubifs/dir.c') diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index d2f5a50f5d83..80c062c03857 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -1653,9 +1653,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, }; diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 5d2ffb1a45fc..512e7d9c60cd 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -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 - file_accessed(file); -#endif + + if (IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT)) + file_accessed(file); + 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 = { diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index d0c1228635f0..ed026ad6f455 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -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 - inode->i_flags |= S_NOATIME; -#endif + + if (!IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT)) + inode->i_flags |= S_NOATIME; + 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)); @@ -2248,11 +2249,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 - ubifs_msg(c, "full atime support is enabled."); -#endif + if (IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT)) + ubifs_msg(c, "full atime support is enabled."); + else + sb->s_flags |= SB_NOATIME; } /* 'fill_super()' opens ubi again so we must close it here */ diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index cf4b10f24b6d..379b9f791ff6 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1999,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, -- cgit v1.2.3