mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-20 21:51:05 +00:00
This pull request contains the following changes for UBI/UBIFS
- fscrypt framework usage updates - One huge fix for xattr unlink - Cleanup of fscrypt ifdefs - Fix for our new UBIFS auth feature -----BEGIN PGP SIGNATURE----- iQJKBAABCAA0FiEEdgfidid8lnn52cLTZvlZhesYu8EFAlzYkIgWHHJpY2hhcmRA c2lnbWEtc3Rhci5hdAAKCRBm+VmF6xi7wTRrD/99iBd4f8F0jF1wmB8/9kDAnz5s KaK+VtC0RVRijRijYzo+/2kDXpXEbmPycg6AVl5EfKxXCVFw1K7pQvuBX43qyv4o BINRv1av8FEBA9eTjvBgZJUrjB1AuvV37716/OeM2bnvuCsp1escnvTEh6S3VFYw oWDBgZJd+DE10CYtZjuLoyDPcYdNrzebbmu3Xbfl2XsPwZFUJIrymMd6NE8Xdk3I EQbZ3guEM5Djui+nrko3iKzfoZ4eK7WguO3DOEjUHpwea4ZfnZtnlH345aYOAqRE N5qrDCzXOsWs6Zs+clODMQgg+aTN3kGBNV534culcpMAbUp7WXynUQ1DDqtOJNJO pGFjhAfGi4E6YgB3UwqxMbXxI4Tg/X2ckc77hWZlC7h/1Y/i89nacT6Ij5rPNOn1 mby1mFxWHI04uSEICWyocFK4m/J2b17Tmte2Mc5ZOigQqREUB7J8wiT4NWm6GhV1 nTb5DA8MepC3zopbsL/iAiKPhSkH1h6AkabBw1ADTksacgNUfhjzALkxqa64tIqv C43QG3n/HqsNZJ4aLdizLLb8KIt4pWsIaqHOeDGSfr3I1GEBrpfKiR72P/h3fSF9 9GIFJU5HiV+3zeAC2024muaV7KjcimZ6t/hPFTCFH9pMGNk2Mtn/gZFfmqnjLKbj TDxUTrZF9Lujonrbwg== =ymCJ -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
d7a02fa0a8
16 changed files with 349 additions and 182 deletions
|
@ -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 ubi_bitflip_check(struct ubi_device *ubi, int pnum, int force)
|
||||||
{
|
{
|
||||||
int err;
|
int err = 0;
|
||||||
struct ubi_wl_entry *e;
|
struct ubi_wl_entry *e;
|
||||||
|
|
||||||
if (pnum < 0 || pnum >= ubi->peb_count) {
|
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,
|
int ubifs_prepare_auth_node(struct ubifs_info *c, void *node,
|
||||||
struct shash_desc *inhash)
|
struct shash_desc *inhash)
|
||||||
{
|
{
|
||||||
SHASH_DESC_ON_STACK(hash_desc, c->hash_tfm);
|
|
||||||
struct ubifs_auth_node *auth = node;
|
struct ubifs_auth_node *auth = node;
|
||||||
u8 *hash;
|
u8 *hash;
|
||||||
int err;
|
int err;
|
||||||
|
@ -85,12 +84,16 @@ int ubifs_prepare_auth_node(struct ubifs_info *c, void *node,
|
||||||
if (!hash)
|
if (!hash)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
hash_desc->tfm = c->hash_tfm;
|
{
|
||||||
ubifs_shash_copy_state(c, inhash, hash_desc);
|
SHASH_DESC_ON_STACK(hash_desc, c->hash_tfm);
|
||||||
|
|
||||||
err = crypto_shash_final(hash_desc, hash);
|
hash_desc->tfm = c->hash_tfm;
|
||||||
if (err)
|
ubifs_shash_copy_state(c, inhash, hash_desc);
|
||||||
goto out;
|
|
||||||
|
err = crypto_shash_final(hash_desc, hash);
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
err = ubifs_hash_calc_hmac(c, hash, auth->hmac);
|
err = ubifs_hash_calc_hmac(c, hash, auth->hmac);
|
||||||
if (err)
|
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);
|
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
|
* ubifs_bad_hash - Report hash mismatches
|
||||||
* @c: UBIFS file-system description object
|
* @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);
|
err = PTR_ERR(child);
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
zbr->znode = child;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
znode = child;
|
znode = child;
|
||||||
|
|
|
@ -790,16 +790,14 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
|
||||||
dentry, inode->i_ino,
|
dentry, inode->i_ino,
|
||||||
inode->i_nlink, dir->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);
|
err = fscrypt_setup_filename(dir, &dentry->d_name, 1, &nm);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
err = ubifs_purge_xattrs(inode);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
sz_change = CALC_DENT_SIZE(fname_len(&nm));
|
sz_change = CALC_DENT_SIZE(fname_len(&nm));
|
||||||
|
|
||||||
ubifs_assert(c, inode_is_locked(dir));
|
ubifs_assert(c, inode_is_locked(dir));
|
||||||
|
@ -900,16 +898,14 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry)
|
||||||
if (err)
|
if (err)
|
||||||
return 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);
|
err = fscrypt_setup_filename(dir, &dentry->d_name, 1, &nm);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
err = ubifs_purge_xattrs(inode);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
sz_change = CALC_DENT_SIZE(fname_len(&nm));
|
sz_change = CALC_DENT_SIZE(fname_len(&nm));
|
||||||
|
|
||||||
err = ubifs_budget_space(c, &req);
|
err = ubifs_budget_space(c, &req);
|
||||||
|
@ -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,
|
old_dentry, old_inode->i_ino, old_dir->i_ino,
|
||||||
new_dentry, new_dir->i_ino, flags);
|
new_dentry, new_dir->i_ino, flags);
|
||||||
|
|
||||||
if (unlink)
|
if (unlink) {
|
||||||
ubifs_assert(c, inode_is_locked(new_inode));
|
ubifs_assert(c, inode_is_locked(new_inode));
|
||||||
|
|
||||||
|
err = ubifs_purge_xattrs(new_inode);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
if (unlink && is_dir) {
|
if (unlink && is_dir) {
|
||||||
err = ubifs_check_dir_empty(new_inode);
|
err = ubifs_check_dir_empty(new_inode);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -1650,9 +1651,7 @@ const struct inode_operations ubifs_dir_inode_operations = {
|
||||||
#ifdef CONFIG_UBIFS_FS_XATTR
|
#ifdef CONFIG_UBIFS_FS_XATTR
|
||||||
.listxattr = ubifs_listxattr,
|
.listxattr = ubifs_listxattr,
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
|
|
||||||
.update_time = ubifs_update_time,
|
.update_time = ubifs_update_time,
|
||||||
#endif
|
|
||||||
.tmpfile = ubifs_tmpfile,
|
.tmpfile = ubifs_tmpfile,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1375,7 +1375,6 @@ static inline int mctime_update_needed(const struct inode *inode,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
|
|
||||||
/**
|
/**
|
||||||
* ubifs_update_time - update time of inode.
|
* ubifs_update_time - update time of inode.
|
||||||
* @inode: inode to update
|
* @inode: inode to update
|
||||||
|
@ -1392,6 +1391,9 @@ int ubifs_update_time(struct inode *inode, struct timespec64 *time,
|
||||||
int iflags = I_DIRTY_TIME;
|
int iflags = I_DIRTY_TIME;
|
||||||
int err, release;
|
int err, release;
|
||||||
|
|
||||||
|
if (!IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT))
|
||||||
|
return generic_update_time(inode, time, flags);
|
||||||
|
|
||||||
err = ubifs_budget_space(c, &req);
|
err = ubifs_budget_space(c, &req);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
@ -1414,7 +1416,6 @@ int ubifs_update_time(struct inode *inode, struct timespec64 *time,
|
||||||
ubifs_release_budget(c, &req);
|
ubifs_release_budget(c, &req);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* update_mctime - update mtime and ctime of an inode.
|
* 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)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
vma->vm_ops = &ubifs_file_vm_ops;
|
vma->vm_ops = &ubifs_file_vm_ops;
|
||||||
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
|
|
||||||
file_accessed(file);
|
if (IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT))
|
||||||
#endif
|
file_accessed(file);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1663,9 +1665,7 @@ const struct inode_operations ubifs_file_inode_operations = {
|
||||||
#ifdef CONFIG_UBIFS_FS_XATTR
|
#ifdef CONFIG_UBIFS_FS_XATTR
|
||||||
.listxattr = ubifs_listxattr,
|
.listxattr = ubifs_listxattr,
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
|
|
||||||
.update_time = ubifs_update_time,
|
.update_time = ubifs_update_time,
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct inode_operations ubifs_symlink_inode_operations = {
|
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
|
#ifdef CONFIG_UBIFS_FS_XATTR
|
||||||
.listxattr = ubifs_listxattr,
|
.listxattr = ubifs_listxattr,
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
|
|
||||||
.update_time = ubifs_update_time,
|
.update_time = ubifs_update_time,
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct file_operations ubifs_file_operations = {
|
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;
|
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.
|
* ubifs_save_dirty_idx_lnums - save an array of the most dirty index LEB nos.
|
||||||
* @c: the UBIFS file-system description object
|
* @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);
|
sizeof(void *) * c->dirty_idx.cnt);
|
||||||
/* Sort it so that the dirtiest is now at the end */
|
/* Sort it so that the dirtiest is now at the end */
|
||||||
sort(c->dirty_idx.arr, c->dirty_idx.cnt, sizeof(void *),
|
sort(c->dirty_idx.arr, c->dirty_idx.cnt, sizeof(void *),
|
||||||
(int (*)(const void *, const void *))cmp_dirty_idx,
|
(int (*)(const void *, const void *))cmp_dirty_idx, NULL);
|
||||||
(void (*)(void *, void *, int))swap_dirty_idx);
|
|
||||||
dbg_find("found %d dirty index LEBs", c->dirty_idx.cnt);
|
dbg_find("found %d dirty index LEBs", c->dirty_idx.cnt);
|
||||||
if (c->dirty_idx.cnt)
|
if (c->dirty_idx.cnt)
|
||||||
dbg_find("dirtiest index LEB is %d with dirty %d and free %d",
|
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;
|
return err;
|
||||||
}
|
}
|
||||||
case FS_IOC_SET_ENCRYPTION_POLICY: {
|
case FS_IOC_SET_ENCRYPTION_POLICY: {
|
||||||
#ifdef CONFIG_FS_ENCRYPTION
|
|
||||||
struct ubifs_info *c = inode->i_sb->s_fs_info;
|
struct ubifs_info *c = inode->i_sb->s_fs_info;
|
||||||
|
|
||||||
err = ubifs_enable_encryption(c);
|
err = ubifs_enable_encryption(c);
|
||||||
|
@ -201,17 +200,9 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
return fscrypt_ioctl_set_policy(file, (const void __user *)arg);
|
return fscrypt_ioctl_set_policy(file, (const void __user *)arg);
|
||||||
#else
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
case FS_IOC_GET_ENCRYPTION_POLICY: {
|
case FS_IOC_GET_ENCRYPTION_POLICY:
|
||||||
#ifdef CONFIG_FS_ENCRYPTION
|
|
||||||
return fscrypt_ioctl_get_policy(file, (void __user *)arg);
|
return fscrypt_ioctl_get_policy(file, (void __user *)arg);
|
||||||
#else
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return -ENOTTY;
|
return -ENOTTY;
|
||||||
|
|
|
@ -852,10 +852,11 @@ out_free:
|
||||||
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)
|
||||||
{
|
{
|
||||||
int err, lnum, offs;
|
int err, lnum, offs;
|
||||||
struct ubifs_ino_node *ino;
|
struct ubifs_ino_node *ino, *ino_start;
|
||||||
struct ubifs_inode *ui = ubifs_inode(inode);
|
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 last_reference = !inode->i_nlink;
|
||||||
|
int kill_xattrs = ui->xattr_cnt && last_reference;
|
||||||
u8 hash[UBIFS_HASH_ARR_SZ];
|
u8 hash[UBIFS_HASH_ARR_SZ];
|
||||||
|
|
||||||
dbg_jnl("ino %lu, nlink %u", inode->i_ino, inode->i_nlink);
|
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) {
|
if (!last_reference) {
|
||||||
ilen += ui->data_len;
|
ilen += ui->data_len;
|
||||||
sync = IS_SYNC(inode);
|
sync = IS_SYNC(inode);
|
||||||
|
} else if (kill_xattrs) {
|
||||||
|
write_len += UBIFS_INO_NODE_SZ * ui->xattr_cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ubifs_authenticated(c))
|
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
|
else
|
||||||
write_len = ilen;
|
write_len += ilen;
|
||||||
|
|
||||||
ino = kmalloc(write_len, GFP_NOFS);
|
ino_start = ino = kmalloc(write_len, GFP_NOFS);
|
||||||
if (!ino)
|
if (!ino)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -883,12 +886,59 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)
|
||||||
if (err)
|
if (err)
|
||||||
goto out_free;
|
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);
|
pack_inode(c, ino, inode, 1);
|
||||||
err = ubifs_node_calc_hash(c, ino, hash);
|
err = ubifs_node_calc_hash(c, ino, hash);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_release;
|
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)
|
if (err)
|
||||||
goto out_release;
|
goto out_release;
|
||||||
if (!sync)
|
if (!sync)
|
||||||
|
@ -903,7 +953,7 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)
|
||||||
if (err)
|
if (err)
|
||||||
goto out_ro;
|
goto out_ro;
|
||||||
ubifs_delete_orphan(c, inode->i_ino);
|
ubifs_delete_orphan(c, inode->i_ino);
|
||||||
err = ubifs_add_dirt(c, lnum, ilen);
|
err = ubifs_add_dirt(c, lnum, write_len);
|
||||||
} else {
|
} else {
|
||||||
union ubifs_key key;
|
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);
|
spin_lock(&ui->ui_lock);
|
||||||
ui->synced_i_size = ui->ui_size;
|
ui->synced_i_size = ui->ui_size;
|
||||||
spin_unlock(&ui->ui_lock);
|
spin_unlock(&ui->ui_lock);
|
||||||
kfree(ino);
|
kfree(ino_start);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_release:
|
out_release:
|
||||||
|
@ -926,7 +976,7 @@ out_ro:
|
||||||
ubifs_ro_mode(c, err);
|
ubifs_ro_mode(c, err);
|
||||||
finish_reservation(c);
|
finish_reservation(c);
|
||||||
out_free:
|
out_free:
|
||||||
kfree(ino);
|
kfree(ino_start);
|
||||||
return err;
|
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);
|
ubifs_assert(c, inode->i_nlink == 0);
|
||||||
|
|
||||||
if (ui->del_cmtno != c->cmt_no)
|
if (ui->xattr_cnt || ui->del_cmtno != c->cmt_no)
|
||||||
/* A commit happened for sure */
|
/* A commit happened for sure or inode hosts xattrs */
|
||||||
return ubifs_jnl_write_inode(c, inode);
|
return ubifs_jnl_write_inode(c, inode);
|
||||||
|
|
||||||
down_read(&c->commit_sem);
|
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;
|
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);
|
const char *ubifs_assert_action_name(struct ubifs_info *c);
|
||||||
|
|
||||||
#endif /* __UBIFS_MISC_H__ */
|
#endif /* __UBIFS_MISC_H__ */
|
||||||
|
|
|
@ -54,30 +54,24 @@
|
||||||
|
|
||||||
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,
|
||||||
* ubifs_add_orphan - add an orphan.
|
struct ubifs_orphan *parent_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 -ENOMEM;
|
return ERR_PTR(-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 -ENFILE;
|
return ERR_PTR(-ENFILE);
|
||||||
}
|
}
|
||||||
p = &c->orph_tree.rb_node;
|
p = &c->orph_tree.rb_node;
|
||||||
while (*p) {
|
while (*p) {
|
||||||
|
@ -91,7 +85,7 @@ int ubifs_add_orphan(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 0;
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c->tot_orphans += 1;
|
c->tot_orphans += 1;
|
||||||
|
@ -100,8 +94,135 @@ int ubifs_add_orphan(struct ubifs_info *c, ino_t inum)
|
||||||
rb_insert_color(&orphan->rb, &c->orph_tree);
|
rb_insert_color(&orphan->rb, &c->orph_tree);
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ubifs_orphan *lookup_orphan(struct ubifs_info *c, ino_t inum)
|
||||||
|
{
|
||||||
|
struct ubifs_orphan *o;
|
||||||
|
struct rb_node *p;
|
||||||
|
|
||||||
|
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 {
|
||||||
|
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 (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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,49 +235,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 *o;
|
orphan_delete(c, inum);
|
||||||
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);
|
|
||||||
if (inum < o->inum)
|
|
||||||
p = p->rb_left;
|
|
||||||
else if (inum > o->inum)
|
|
||||||
p = p->rb_right;
|
|
||||||
else {
|
|
||||||
if (o->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;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
spin_unlock(&c->orphan_lock);
|
|
||||||
kfree(o);
|
|
||||||
dbg_gen("inum %lu", (unsigned long)inum);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spin_unlock(&c->orphan_lock);
|
|
||||||
ubifs_err(c, "missing orphan ino %lu", (unsigned long)inum);
|
|
||||||
dump_stack();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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;
|
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;
|
||||||
|
|
||||||
inum = le64_to_cpu(orph->inos[i]);
|
inum = le64_to_cpu(orph->inos[i]);
|
||||||
dbg_rcvry("deleting orphaned inode %lu",
|
dbg_rcvry("deleting orphaned inode %lu",
|
||||||
(unsigned long)inum);
|
(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)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
err = insert_dead_orphan(c, inum);
|
err = insert_dead_orphan(c, inum);
|
||||||
|
@ -744,26 +829,15 @@ struct check_info {
|
||||||
struct rb_root root;
|
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;
|
bool found = false;
|
||||||
struct rb_node *p;
|
|
||||||
|
|
||||||
spin_lock(&c->orphan_lock);
|
spin_lock(&c->orphan_lock);
|
||||||
p = c->orph_tree.rb_node;
|
found = !!lookup_orphan(c, inum);
|
||||||
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 {
|
|
||||||
spin_unlock(&c->orphan_lock);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spin_unlock(&c->orphan_lock);
|
spin_unlock(&c->orphan_lock);
|
||||||
return 0;
|
|
||||||
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dbg_ins_check_orphan(struct rb_root *root, ino_t inum)
|
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;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_FS_ENCRYPTION
|
if (!IS_ENABLED(CONFIG_UBIFS_FS_ENCRYPTION) && c->encrypted) {
|
||||||
if (c->encrypted) {
|
|
||||||
ubifs_err(c, "file system contains encrypted files but UBIFS"
|
ubifs_err(c, "file system contains encrypted files but UBIFS"
|
||||||
" was built without crypto support.");
|
" was built without crypto support.");
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Automatically increase file system size to the maximum size */
|
/* Automatically increase file system size to the maximum size */
|
||||||
c->old_leb_cnt = c->leb_cnt;
|
c->old_leb_cnt = c->leb_cnt;
|
||||||
|
@ -943,6 +941,9 @@ int ubifs_enable_encryption(struct ubifs_info *c)
|
||||||
int err;
|
int err;
|
||||||
struct ubifs_sb_node *sup = c->sup_node;
|
struct ubifs_sb_node *sup = c->sup_node;
|
||||||
|
|
||||||
|
if (!IS_ENABLED(CONFIG_UBIFS_FS_ENCRYPTION))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (c->encrypted)
|
if (c->encrypted)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -129,9 +129,10 @@ struct inode *ubifs_iget(struct super_block *sb, unsigned long inum)
|
||||||
goto out_ino;
|
goto out_ino;
|
||||||
|
|
||||||
inode->i_flags |= S_NOCMTIME;
|
inode->i_flags |= S_NOCMTIME;
|
||||||
#ifndef CONFIG_UBIFS_ATIME_SUPPORT
|
|
||||||
inode->i_flags |= S_NOATIME;
|
if (!IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT))
|
||||||
#endif
|
inode->i_flags |= S_NOATIME;
|
||||||
|
|
||||||
set_nlink(inode, le32_to_cpu(ino->nlink));
|
set_nlink(inode, le32_to_cpu(ino->nlink));
|
||||||
i_uid_write(inode, le32_to_cpu(ino->uid));
|
i_uid_write(inode, le32_to_cpu(ino->uid));
|
||||||
i_gid_write(inode, le32_to_cpu(ino->gid));
|
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);
|
c->bud_bytes, c->bud_bytes >> 10, c->bud_bytes >> 20);
|
||||||
dbg_gen("max. seq. number: %llu", c->max_sqnum);
|
dbg_gen("max. seq. number: %llu", c->max_sqnum);
|
||||||
dbg_gen("commit number: %llu", c->cmt_no);
|
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;
|
return 0;
|
||||||
|
|
||||||
|
@ -2141,9 +2144,7 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
#ifdef CONFIG_UBIFS_FS_XATTR
|
#ifdef CONFIG_UBIFS_FS_XATTR
|
||||||
sb->s_xattr = ubifs_xattr_handlers;
|
sb->s_xattr = ubifs_xattr_handlers;
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_FS_ENCRYPTION
|
fscrypt_set_ops(sb, &ubifs_crypt_operations);
|
||||||
sb->s_cop = &ubifs_crypt_operations;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
mutex_lock(&c->umount_mutex);
|
mutex_lock(&c->umount_mutex);
|
||||||
err = mount_ubifs(c);
|
err = mount_ubifs(c);
|
||||||
|
@ -2245,11 +2246,10 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags,
|
||||||
goto out_deact;
|
goto out_deact;
|
||||||
/* We do not support atime */
|
/* We do not support atime */
|
||||||
sb->s_flags |= SB_ACTIVE;
|
sb->s_flags |= SB_ACTIVE;
|
||||||
#ifndef CONFIG_UBIFS_ATIME_SUPPORT
|
if (IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT))
|
||||||
sb->s_flags |= SB_NOATIME;
|
ubifs_msg(c, "full atime support is enabled.");
|
||||||
#else
|
else
|
||||||
ubifs_msg(c, "full atime support is enabled.");
|
sb->s_flags |= SB_NOATIME;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 'fill_super()' opens ubi again so we must close it here */
|
/* '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)
|
if (node_len != len)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (type == UBIFS_DATA_NODE && c->no_chk_data_crc && !c->mounting &&
|
if (type != UBIFS_DATA_NODE || !c->no_chk_data_crc || c->mounting ||
|
||||||
!c->remounting_rw)
|
c->remounting_rw) {
|
||||||
return 1;
|
crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8);
|
||||||
|
node_crc = le32_to_cpu(ch->crc);
|
||||||
crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8);
|
if (crc != node_crc)
|
||||||
node_crc = le32_to_cpu(ch->crc);
|
return 0;
|
||||||
if (crc != node_crc)
|
}
|
||||||
return 0;
|
|
||||||
|
|
||||||
err = ubifs_node_check_hash(c, buf, zbr->hash);
|
err = ubifs_node_check_hash(c, buf, zbr->hash);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
|
@ -924,6 +924,8 @@ 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 childs 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
|
||||||
|
@ -935,6 +937,7 @@ 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;
|
||||||
|
@ -1996,9 +1999,7 @@ int ubifs_calc_dark(const struct ubifs_info *c, int spc);
|
||||||
/* file.c */
|
/* file.c */
|
||||||
int ubifs_fsync(struct file *file, loff_t start, loff_t end, int datasync);
|
int ubifs_fsync(struct file *file, loff_t start, loff_t end, int datasync);
|
||||||
int ubifs_setattr(struct dentry *dentry, struct iattr *attr);
|
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);
|
int ubifs_update_time(struct inode *inode, struct timespec64 *time, int flags);
|
||||||
#endif
|
|
||||||
|
|
||||||
/* dir.c */
|
/* dir.c */
|
||||||
struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir,
|
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);
|
size_t size, int flags, bool check_lock);
|
||||||
ssize_t ubifs_xattr_get(struct inode *host, const char *name, void *buf,
|
ssize_t ubifs_xattr_get(struct inode *host, const char *name, void *buf,
|
||||||
size_t size);
|
size_t size);
|
||||||
|
int ubifs_purge_xattrs(struct inode *host);
|
||||||
|
|
||||||
#ifdef CONFIG_UBIFS_FS_XATTR
|
#ifdef CONFIG_UBIFS_FS_XATTR
|
||||||
void ubifs_evict_xattr_inode(struct ubifs_info *c, ino_t xattr_inum);
|
void ubifs_evict_xattr_inode(struct ubifs_info *c, ino_t xattr_inum);
|
||||||
|
|
|
@ -60,12 +60,6 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/xattr.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.
|
* 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,
|
.new_ino_d = ALIGN(size, 8), .dirtied_ino = 1,
|
||||||
.dirtied_ino_d = ALIGN(host_ui->data_len, 8) };
|
.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",
|
ubifs_err(c, "inode %lu already has too many xattrs (%d), cannot create more",
|
||||||
host->i_ino, host_ui->xattr_cnt);
|
host->i_ino, host_ui->xattr_cnt);
|
||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
|
@ -507,6 +501,69 @@ out_cancel:
|
||||||
return err;
|
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.
|
* ubifs_evict_xattr_inode - Evict an xattr inode.
|
||||||
* @c: UBIFS file-system description object
|
* @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,
|
extern const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
|
||||||
unsigned int max_size,
|
unsigned int max_size,
|
||||||
struct delayed_call *done);
|
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 */
|
#else /* !CONFIG_FS_ENCRYPTION */
|
||||||
|
|
||||||
static inline bool fscrypt_has_encryption_key(const struct inode *inode)
|
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);
|
return ERR_PTR(-EOPNOTSUPP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void fscrypt_set_ops(struct super_block *sb,
|
||||||
|
const struct fscrypt_operations *s_cop)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* !CONFIG_FS_ENCRYPTION */
|
#endif /* !CONFIG_FS_ENCRYPTION */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue