This pull request includes the following UBI/UBIFS changes:
* access time support for UBIFS by Dongsheng Yang * random cleanups and bug fixes all over the place -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABAgAGBQJWQmnVAAoJEEtJtSqsAOnWpnkP/0pUN+Cx58QJoJXxaSgClH/l QwYGznz4Fv3QuSafXJZy8CPzsTasaOOtoVKJPfPTvP8Drrl3FFbtdhqlqdx1YKqw DuKeViwmE/HF49a5pxgtR8032l35s3zZUWwd2yKA3B6SVEIsjAoWlIutyzKA/DiR R4mGVsfRevfzq1+l2YXGGZ8PJXMtRKnFTjzmIUJY0OeT3xCvl/uUFCid2x693aut GpJ6AMKGYcU+BuQJmb89wvdRYCHPdYEJr7TWq+GBxU3gDPlLY9302IhPq9ftv8Lp ClA0X3GZqVPR921XR+aA4ysRbfENT+UBewiBt2OEwQLnI6jxEn9EqsgErATxpOYy PEduYuU56mqc67EE4r7+YHfkidMSa8KrR9s+GpzR6JStW9HNGFDfGfCAK7BcdvWT +TuHfNk787Gbl4TO41iFI87s6zNQszYOpxBTEFYHx0FQWLNxD5c79UkisL+biqvJ bX8+7pClJQXcY0CXqe56GVQLC5v4HbvMmnstiNk52ihxEB0NT6htzWe/GPb/+UZ1 K+kOAT54DPeag3FK4J1WZ57cYyJHdbyASB5vKvb+A1IwzrYFo8P35GekoWNK7eAJ Od5mb++7pTEFSH7oSwsprPOmrHLRmXgRG8yhLRfqX1ZwFeyFdqGQxjce9O/QB1jo jr4dxAY6Gnjdo1q07QSI =9n2S -----END PGP SIGNATURE----- Merge tag 'upstream-4.4-rc1' of git://git.infradead.org/linux-ubifs Pull UBI/UBIFS updates from Richard Weinberger: - access time support for UBIFS by Dongsheng Yang - random cleanups and bug fixes all over the place * tag 'upstream-4.4-rc1' of git://git.infradead.org/linux-ubifs: ubifs: introduce UBIFS_ATIME_SUPPORT to ubifs ubifs: make ubifs_[get|set]xattr atomic UBIFS: Delete unnecessary checks before the function call "iput" UBI: Remove in vain semicolon UBI: Fastmap: Fix PEB array type UBIFS: Fix possible memory leak in ubifs_readdir() fs/ubifs: remove unnecessary new_valid_dev check ubi: fastmap: Implement produce_free_peb() UBIFS: print verbose message when rescanning a corrupted node UBIFS: call dbg_is_power_cut() instead of reading c->dbg->pc_happened UBI: drop null test before destroy functions UBI: Update comments to reflect UBI_METAONLY flag UBI: Fix debug message UBI: Fix typo in comment UBI: Fastmap: Simplify expression UBIFS: fix a typo in comment of ubifs_budget_req UBIFS: use kmemdup rather than duplicating its implementation
This commit is contained in:
commit
01504f5e9e
|
@ -1209,9 +1209,7 @@ static void destroy_ai(struct ubi_attach_info *ai)
|
|||
}
|
||||
}
|
||||
|
||||
if (ai->aeb_slab_cache)
|
||||
kmem_cache_destroy(ai->aeb_slab_cache);
|
||||
|
||||
kmem_cache_destroy(ai->aeb_slab_cache);
|
||||
kfree(ai);
|
||||
}
|
||||
|
||||
|
|
|
@ -949,7 +949,7 @@ static long ubi_cdev_ioctl(struct file *file, unsigned int cmd,
|
|||
if (!req) {
|
||||
err = -ENOMEM;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
err = copy_from_user(req, argp, sizeof(struct ubi_rnvol_req));
|
||||
if (err) {
|
||||
|
|
|
@ -1358,7 +1358,7 @@ int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap,
|
|||
continue;
|
||||
|
||||
ubi_err(ubi, "LEB:%i:%i is PEB:%i instead of %i!",
|
||||
vol->vol_id, i, fm_eba[i][j],
|
||||
vol->vol_id, j, fm_eba[i][j],
|
||||
scan_eba[i][j]);
|
||||
ubi_assert(0);
|
||||
}
|
||||
|
|
|
@ -171,6 +171,30 @@ void ubi_refill_pools(struct ubi_device *ubi)
|
|||
spin_unlock(&ubi->wl_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* produce_free_peb - produce a free physical eraseblock.
|
||||
* @ubi: UBI device description object
|
||||
*
|
||||
* This function tries to make a free PEB by means of synchronous execution of
|
||||
* pending works. This may be needed if, for example the background thread is
|
||||
* disabled. Returns zero in case of success and a negative error code in case
|
||||
* of failure.
|
||||
*/
|
||||
static int produce_free_peb(struct ubi_device *ubi)
|
||||
{
|
||||
int err;
|
||||
|
||||
while (!ubi->free.rb_node && ubi->works_count) {
|
||||
dbg_wl("do one work synchronously");
|
||||
err = do_work(ubi);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubi_wl_get_peb - get a physical eraseblock.
|
||||
* @ubi: UBI device description object
|
||||
|
@ -213,6 +237,11 @@ again:
|
|||
}
|
||||
retried = 1;
|
||||
up_read(&ubi->fm_eba_sem);
|
||||
ret = produce_free_peb(ubi);
|
||||
if (ret < 0) {
|
||||
down_read(&ubi->fm_eba_sem);
|
||||
goto out;
|
||||
}
|
||||
goto again;
|
||||
}
|
||||
|
||||
|
|
|
@ -450,7 +450,7 @@ static void unmap_peb(struct ubi_attach_info *ai, int pnum)
|
|||
* < 0 indicates an internal error.
|
||||
*/
|
||||
static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai,
|
||||
int *pebs, int pool_size, unsigned long long *max_sqnum,
|
||||
__be32 *pebs, int pool_size, unsigned long long *max_sqnum,
|
||||
struct list_head *free)
|
||||
{
|
||||
struct ubi_vid_hdr *vh;
|
||||
|
@ -775,7 +775,7 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
|
|||
for (j = 0; j < be32_to_cpu(fm_eba->reserved_pebs); j++) {
|
||||
int pnum = be32_to_cpu(fm_eba->pnum[j]);
|
||||
|
||||
if ((int)be32_to_cpu(fm_eba->pnum[j]) < 0)
|
||||
if (pnum < 0)
|
||||
continue;
|
||||
|
||||
aeb = NULL;
|
||||
|
|
|
@ -500,7 +500,7 @@ struct ubi_fm_volhdr {
|
|||
/* struct ubi_fm_volhdr is followed by one struct ubi_fm_eba records */
|
||||
|
||||
/**
|
||||
* struct ubi_fm_eba - denotes an association beween a PEB and LEB
|
||||
* struct ubi_fm_eba - denotes an association between a PEB and LEB
|
||||
* @magic: EBA table magic number
|
||||
* @reserved_pebs: number of table entries
|
||||
* @pnum: PEB number of LEB (LEB is the index)
|
||||
|
|
|
@ -35,3 +35,18 @@ config UBIFS_FS_ZLIB
|
|||
default y
|
||||
help
|
||||
Zlib compresses better than LZO but it is slower. Say 'Y' if unsure.
|
||||
|
||||
config UBIFS_ATIME_SUPPORT
|
||||
bool "Access time support" if UBIFS_FS
|
||||
depends on UBIFS_FS
|
||||
default n
|
||||
help
|
||||
Originally UBIFS did not support atime, because it looked like a bad idea due
|
||||
increased flash wear. This option adds atime support and it is disabled by default
|
||||
to preserve the old behavior. If you enable this option, UBIFS starts updating atime,
|
||||
which means that file-system read operations will cause writes (inode atime
|
||||
updates). This may affect file-system performance and increase flash device wear,
|
||||
so be careful. How often atime is updated depends on the selected strategy:
|
||||
strictatime is the "heavy", relatime is "lighter", etc.
|
||||
|
||||
If unsure, say 'N'
|
||||
|
|
|
@ -2573,7 +2573,7 @@ int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf,
|
|||
{
|
||||
int err, failing;
|
||||
|
||||
if (c->dbg->pc_happened)
|
||||
if (dbg_is_power_cut(c))
|
||||
return -EROFS;
|
||||
|
||||
failing = power_cut_emulated(c, lnum, 1);
|
||||
|
@ -2595,7 +2595,7 @@ int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf,
|
|||
{
|
||||
int err;
|
||||
|
||||
if (c->dbg->pc_happened)
|
||||
if (dbg_is_power_cut(c))
|
||||
return -EROFS;
|
||||
if (power_cut_emulated(c, lnum, 1))
|
||||
return -EROFS;
|
||||
|
@ -2611,7 +2611,7 @@ int dbg_leb_unmap(struct ubifs_info *c, int lnum)
|
|||
{
|
||||
int err;
|
||||
|
||||
if (c->dbg->pc_happened)
|
||||
if (dbg_is_power_cut(c))
|
||||
return -EROFS;
|
||||
if (power_cut_emulated(c, lnum, 0))
|
||||
return -EROFS;
|
||||
|
@ -2627,7 +2627,7 @@ int dbg_leb_map(struct ubifs_info *c, int lnum)
|
|||
{
|
||||
int err;
|
||||
|
||||
if (c->dbg->pc_happened)
|
||||
if (dbg_is_power_cut(c))
|
||||
return -EROFS;
|
||||
if (power_cut_emulated(c, lnum, 0))
|
||||
return -EROFS;
|
||||
|
|
|
@ -449,13 +449,14 @@ static int ubifs_readdir(struct file *file, struct dir_context *ctx)
|
|||
}
|
||||
|
||||
out:
|
||||
kfree(file->private_data);
|
||||
file->private_data = NULL;
|
||||
|
||||
if (err != -ENOENT) {
|
||||
ubifs_err(c, "cannot find next direntry, error %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
kfree(file->private_data);
|
||||
file->private_data = NULL;
|
||||
/* 2 is a special value indicating that there are no more direntries */
|
||||
ctx->pos = 2;
|
||||
return 0;
|
||||
|
@ -787,9 +788,6 @@ static int ubifs_mknod(struct inode *dir, struct dentry *dentry,
|
|||
|
||||
dbg_gen("dent '%pd' in dir ino %lu", dentry, dir->i_ino);
|
||||
|
||||
if (!new_valid_dev(rdev))
|
||||
return -EINVAL;
|
||||
|
||||
if (S_ISBLK(mode) || S_ISCHR(mode)) {
|
||||
dev = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS);
|
||||
if (!dev)
|
||||
|
@ -1188,6 +1186,9 @@ const struct inode_operations ubifs_dir_inode_operations = {
|
|||
.getxattr = ubifs_getxattr,
|
||||
.listxattr = ubifs_listxattr,
|
||||
.removexattr = ubifs_removexattr,
|
||||
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
|
||||
.update_time = ubifs_update_time,
|
||||
#endif
|
||||
};
|
||||
|
||||
const struct file_operations ubifs_dir_operations = {
|
||||
|
|
|
@ -1354,6 +1354,47 @@ 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
|
||||
*
|
||||
* This function updates time of the inode.
|
||||
*/
|
||||
int ubifs_update_time(struct inode *inode, struct timespec *time,
|
||||
int flags)
|
||||
{
|
||||
struct ubifs_inode *ui = ubifs_inode(inode);
|
||||
struct ubifs_info *c = inode->i_sb->s_fs_info;
|
||||
struct ubifs_budget_req req = { .dirtied_ino = 1,
|
||||
.dirtied_ino_d = ALIGN(ui->data_len, 8) };
|
||||
int iflags = I_DIRTY_TIME;
|
||||
int err, release;
|
||||
|
||||
err = ubifs_budget_space(c, &req);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mutex_lock(&ui->ui_mutex);
|
||||
if (flags & S_ATIME)
|
||||
inode->i_atime = *time;
|
||||
if (flags & S_CTIME)
|
||||
inode->i_ctime = *time;
|
||||
if (flags & S_MTIME)
|
||||
inode->i_mtime = *time;
|
||||
|
||||
if (!(inode->i_sb->s_flags & MS_LAZYTIME))
|
||||
iflags |= I_DIRTY_SYNC;
|
||||
|
||||
release = ui->dirty;
|
||||
__mark_inode_dirty(inode, iflags);
|
||||
mutex_unlock(&ui->ui_mutex);
|
||||
if (release)
|
||||
ubifs_release_budget(c, &req);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* update_ctime - update mtime and ctime of an inode.
|
||||
* @inode: inode to update
|
||||
|
@ -1537,6 +1578,9 @@ 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
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1557,6 +1601,9 @@ const struct inode_operations ubifs_file_inode_operations = {
|
|||
.getxattr = ubifs_getxattr,
|
||||
.listxattr = ubifs_listxattr,
|
||||
.removexattr = ubifs_removexattr,
|
||||
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
|
||||
.update_time = ubifs_update_time,
|
||||
#endif
|
||||
};
|
||||
|
||||
const struct inode_operations ubifs_symlink_inode_operations = {
|
||||
|
@ -1568,6 +1615,9 @@ const struct inode_operations ubifs_symlink_inode_operations = {
|
|||
.getxattr = ubifs_getxattr,
|
||||
.listxattr = ubifs_listxattr,
|
||||
.removexattr = ubifs_removexattr,
|
||||
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
|
||||
.update_time = ubifs_update_time,
|
||||
#endif
|
||||
};
|
||||
|
||||
const struct file_operations ubifs_file_operations = {
|
||||
|
|
|
@ -1498,11 +1498,10 @@ static struct ubifs_nnode *dirty_cow_nnode(struct ubifs_info *c,
|
|||
}
|
||||
|
||||
/* nnode is being committed, so copy it */
|
||||
n = kmalloc(sizeof(struct ubifs_nnode), GFP_NOFS);
|
||||
n = kmemdup(nnode, sizeof(struct ubifs_nnode), GFP_NOFS);
|
||||
if (unlikely(!n))
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
memcpy(n, nnode, sizeof(struct ubifs_nnode));
|
||||
n->cnext = NULL;
|
||||
__set_bit(DIRTY_CNODE, &n->flags);
|
||||
__clear_bit(COW_CNODE, &n->flags);
|
||||
|
@ -1549,11 +1548,10 @@ static struct ubifs_pnode *dirty_cow_pnode(struct ubifs_info *c,
|
|||
}
|
||||
|
||||
/* pnode is being committed, so copy it */
|
||||
p = kmalloc(sizeof(struct ubifs_pnode), GFP_NOFS);
|
||||
p = kmemdup(pnode, sizeof(struct ubifs_pnode), GFP_NOFS);
|
||||
if (unlikely(!p))
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
memcpy(p, pnode, sizeof(struct ubifs_pnode));
|
||||
p->cnext = NULL;
|
||||
__set_bit(DIRTY_CNODE, &p->flags);
|
||||
__clear_bit(COW_CNODE, &p->flags);
|
||||
|
|
|
@ -155,13 +155,8 @@ static inline int ubifs_wbuf_sync(struct ubifs_wbuf *wbuf)
|
|||
*/
|
||||
static inline int ubifs_encode_dev(union ubifs_dev_desc *dev, dev_t rdev)
|
||||
{
|
||||
if (new_valid_dev(rdev)) {
|
||||
dev->new = cpu_to_le32(new_encode_dev(rdev));
|
||||
return sizeof(dev->new);
|
||||
} else {
|
||||
dev->huge = cpu_to_le64(huge_encode_dev(rdev));
|
||||
return sizeof(dev->huge);
|
||||
}
|
||||
dev->new = cpu_to_le32(new_encode_dev(rdev));
|
||||
return sizeof(dev->new);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -789,7 +789,7 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
|
|||
corrupted_rescan:
|
||||
/* Re-scan the corrupted data with verbose messages */
|
||||
ubifs_err(c, "corruption %d", ret);
|
||||
ubifs_scan_a_node(c, buf, len, lnum, offs, 1);
|
||||
ubifs_scan_a_node(c, buf, len, lnum, offs, 0);
|
||||
corrupted:
|
||||
ubifs_scanned_corruption(c, lnum, offs, buf);
|
||||
err = -EUCLEAN;
|
||||
|
@ -1331,8 +1331,7 @@ void ubifs_destroy_size_tree(struct ubifs_info *c)
|
|||
struct size_entry *e, *n;
|
||||
|
||||
rbtree_postorder_for_each_entry_safe(e, n, &c->size_tree, rb) {
|
||||
if (e->inode)
|
||||
iput(e->inode);
|
||||
iput(e->inode);
|
||||
kfree(e);
|
||||
}
|
||||
|
||||
|
@ -1533,8 +1532,7 @@ int ubifs_recover_size(struct ubifs_info *c)
|
|||
err = fix_size_in_place(c, e);
|
||||
if (err)
|
||||
return err;
|
||||
if (e->inode)
|
||||
iput(e->inode);
|
||||
iput(e->inode);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -128,7 +128,10 @@ struct inode *ubifs_iget(struct super_block *sb, unsigned long inum)
|
|||
if (err)
|
||||
goto out_ino;
|
||||
|
||||
inode->i_flags |= (S_NOCMTIME | S_NOATIME);
|
||||
inode->i_flags |= S_NOCMTIME;
|
||||
#ifndef 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));
|
||||
|
@ -2139,7 +2142,12 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags,
|
|||
if (err)
|
||||
goto out_deact;
|
||||
/* We do not support atime */
|
||||
sb->s_flags |= MS_ACTIVE | MS_NOATIME;
|
||||
sb->s_flags |= MS_ACTIVE;
|
||||
#ifndef CONFIG_UBIFS_ATIME_SUPPORT
|
||||
sb->s_flags |= MS_NOATIME;
|
||||
#else
|
||||
ubifs_msg(c, "full atime support is enabled.");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 'fill_super()' opens ubi again so we must close it here */
|
||||
|
|
|
@ -198,11 +198,10 @@ static struct ubifs_znode *copy_znode(struct ubifs_info *c,
|
|||
{
|
||||
struct ubifs_znode *zn;
|
||||
|
||||
zn = kmalloc(c->max_znode_sz, GFP_NOFS);
|
||||
zn = kmemdup(znode, c->max_znode_sz, GFP_NOFS);
|
||||
if (unlikely(!zn))
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
memcpy(zn, znode, c->max_znode_sz);
|
||||
zn->cnext = NULL;
|
||||
__set_bit(DIRTY_ZNODE, &zn->flags);
|
||||
__clear_bit(COW_ZNODE, &zn->flags);
|
||||
|
|
|
@ -858,9 +858,9 @@ struct ubifs_compressor {
|
|||
* @mod_dent: non-zero if the operation removes or modifies an existing
|
||||
* directory entry
|
||||
* @new_ino: non-zero if the operation adds a new inode
|
||||
* @new_ino_d: now much data newly created inode contains
|
||||
* @new_ino_d: how much data newly created inode contains
|
||||
* @dirtied_ino: how many inodes the operation makes dirty
|
||||
* @dirtied_ino_d: now much data dirtied inode contains
|
||||
* @dirtied_ino_d: how much data dirtied inode contains
|
||||
* @idx_growth: how much the index will supposedly grow
|
||||
* @data_growth: how much new data the operation will supposedly add
|
||||
* @dd_growth: how much data that makes other data dirty the operation will
|
||||
|
@ -1746,6 +1746,9 @@ 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 timespec *time, int flags);
|
||||
#endif
|
||||
|
||||
/* dir.c */
|
||||
struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir,
|
||||
|
|
|
@ -200,6 +200,7 @@ static int change_xattr(struct ubifs_info *c, struct inode *host,
|
|||
int err;
|
||||
struct ubifs_inode *host_ui = ubifs_inode(host);
|
||||
struct ubifs_inode *ui = ubifs_inode(inode);
|
||||
void *buf = NULL;
|
||||
struct ubifs_budget_req req = { .dirtied_ino = 2,
|
||||
.dirtied_ino_d = ALIGN(size, 8) + ALIGN(host_ui->data_len, 8) };
|
||||
|
||||
|
@ -208,14 +209,17 @@ static int change_xattr(struct ubifs_info *c, struct inode *host,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
kfree(ui->data);
|
||||
ui->data = kmemdup(value, size, GFP_NOFS);
|
||||
if (!ui->data) {
|
||||
buf = kmemdup(value, size, GFP_NOFS);
|
||||
if (!buf) {
|
||||
err = -ENOMEM;
|
||||
goto out_free;
|
||||
}
|
||||
mutex_lock(&ui->ui_mutex);
|
||||
kfree(ui->data);
|
||||
ui->data = buf;
|
||||
inode->i_size = ui->ui_size = size;
|
||||
ui->data_len = size;
|
||||
mutex_unlock(&ui->ui_mutex);
|
||||
|
||||
mutex_lock(&host_ui->ui_mutex);
|
||||
host->i_ctime = ubifs_current_time(host);
|
||||
|
@ -409,6 +413,7 @@ ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf,
|
|||
ubifs_assert(inode->i_size == ui->data_len);
|
||||
ubifs_assert(ubifs_inode(host)->xattr_size > ui->data_len);
|
||||
|
||||
mutex_lock(&ui->ui_mutex);
|
||||
if (buf) {
|
||||
/* If @buf is %NULL we are supposed to return the length */
|
||||
if (ui->data_len > size) {
|
||||
|
@ -423,6 +428,7 @@ ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf,
|
|||
err = ui->data_len;
|
||||
|
||||
out_iput:
|
||||
mutex_unlock(&ui->ui_mutex);
|
||||
iput(inode);
|
||||
out_unlock:
|
||||
kfree(xent);
|
||||
|
|
Loading…
Reference in a new issue