Skip to content

Commit

Permalink
Merge tag 'upstream-4.4-rc1' of git://git.infradead.org/linux-ubifs
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Linus Torvalds committed Nov 11, 2015
2 parents 4bde961 + 8c1c5f2 commit 01504f5
Show file tree
Hide file tree
Showing 17 changed files with 142 additions and 42 deletions.
4 changes: 1 addition & 3 deletions drivers/mtd/ubi/attach.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/mtd/ubi/cdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion drivers/mtd/ubi/eba.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
29 changes: 29 additions & 0 deletions drivers/mtd/ubi/fastmap-wl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -213,6 +237,11 @@ int ubi_wl_get_peb(struct ubi_device *ubi)
}
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;
}

Expand Down
4 changes: 2 additions & 2 deletions drivers/mtd/ubi/fastmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion drivers/mtd/ubi/ubi-media.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
15 changes: 15 additions & 0 deletions fs/ubifs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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'
8 changes: 4 additions & 4 deletions fs/ubifs/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down
11 changes: 6 additions & 5 deletions fs/ubifs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 = {
Expand Down
50 changes: 50 additions & 0 deletions fs/ubifs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}

Expand All @@ -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 = {
Expand All @@ -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 = {
Expand Down
6 changes: 2 additions & 4 deletions fs/ubifs/lpt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
9 changes: 2 additions & 7 deletions fs/ubifs/misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/**
Expand Down
8 changes: 3 additions & 5 deletions fs/ubifs/recovery.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
}
}

Expand Down
12 changes: 10 additions & 2 deletions fs/ubifs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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 */
Expand Down
3 changes: 1 addition & 2 deletions fs/ubifs/tnc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 01504f5

Please sign in to comment.