未验证 提交 f6a50de1 编写于 作者: O openeuler-ci-bot 提交者: Gitee

!400 Backport fs and block bugfixes

Merge Pull Request from: @zhangjialin11 
 
Pull fs bugfixes from Zhihao Cheng and ZhaoLong Wang
block bugfix from Yu Kuai 
 
Link:https://gitee.com/openeuler/kernel/pulls/400 

Reviewed-by: Zheng Zengkai <zhengzengkai@huawei.com> 
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com> 
......@@ -321,14 +321,12 @@ struct bfq_group *bfqq_group(struct bfq_queue *bfqq)
static void bfqg_get(struct bfq_group *bfqg)
{
bfqg->ref++;
refcount_inc(&bfqg->ref);
}
static void bfqg_put(struct bfq_group *bfqg)
{
bfqg->ref--;
if (bfqg->ref == 0)
if (refcount_dec_and_test(&bfqg->ref))
kfree(bfqg);
}
......@@ -535,7 +533,7 @@ static struct blkg_policy_data *bfq_pd_alloc(gfp_t gfp, struct request_queue *q,
}
/* see comments in bfq_bic_update_cgroup for why refcounting */
bfqg_get(bfqg);
refcount_set(&bfqg->ref, 1);
return &bfqg->pd;
}
......
......@@ -900,7 +900,7 @@ struct bfq_group {
char blkg_path[128];
/* reference counter (see comments in bfq_bic_update_cgroup) */
int ref;
refcount_t ref;
/* Is bfq_group still online? */
bool online;
......
......@@ -146,13 +146,15 @@ void ubi_refill_pools(struct ubi_device *ubi)
if (ubi->fm_anchor) {
wl_tree_add(ubi->fm_anchor, &ubi->free);
ubi->free_count++;
ubi->fm_anchor = NULL;
}
/*
* All available PEBs are in ubi->free, now is the time to get
* the best anchor PEBs.
*/
ubi->fm_anchor = ubi_wl_get_fm_peb(ubi, 1);
if (!ubi->fm_disabled)
/*
* All available PEBs are in ubi->free, now is the time to get
* the best anchor PEBs.
*/
ubi->fm_anchor = ubi_wl_get_fm_peb(ubi, 1);
for (;;) {
enough = 0;
......
......@@ -885,8 +885,11 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
err = do_sync_erase(ubi, e1, vol_id, lnum, 0);
if (err) {
if (e2)
if (e2) {
spin_lock(&ubi->wl_lock);
wl_entry_destroy(ubi, e2);
spin_unlock(&ubi->wl_lock);
}
goto out_ro;
}
......@@ -1121,14 +1124,18 @@ static int __erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk)
/* Re-schedule the LEB for erasure */
err1 = schedule_erase(ubi, e, vol_id, lnum, 0, false);
if (err1) {
spin_lock(&ubi->wl_lock);
wl_entry_destroy(ubi, e);
spin_unlock(&ubi->wl_lock);
err = err1;
goto out_ro;
}
return err;
}
spin_lock(&ubi->wl_lock);
wl_entry_destroy(ubi, e);
spin_unlock(&ubi->wl_lock);
if (err != -EIO)
/*
* If this is not %-EIO, we have no idea what to do. Scheduling
......
......@@ -1316,6 +1316,42 @@ static int get_option_gid(substring_t args[], kgid_t *result)
return 0;
}
/*
* Remove duplicate path delimiters. Windows is supposed to do that
* but there are some bugs that prevent rename from working if there are
* multiple delimiters.
*
* Returns a sanitized duplicate of @path. The caller is responsible for
* cleaning up the original.
*/
#define IS_DELIM(c) ((c) == '/' || (c) == '\\')
static char *sanitize_path(char *path)
{
char *cursor1 = path, *cursor2 = path;
/* skip all prepended delimiters */
while (IS_DELIM(*cursor1))
cursor1++;
/* copy the first letter */
*cursor2 = *cursor1;
/* copy the remainder... */
while (*(cursor1++)) {
/* ... skipping all duplicated delimiters */
if (IS_DELIM(*cursor1) && IS_DELIM(*cursor2))
continue;
*(++cursor2) = *cursor1;
}
/* if the last character is a delimiter, skip it */
if (IS_DELIM(*(cursor2 - 1)))
cursor2--;
*(cursor2) = '\0';
return kstrdup(path, GFP_KERNEL);
}
/*
* Parse a devname into substrings and populate the vol->UNC and vol->prepath
* fields with the result. Returns 0 on success and an error otherwise.
......@@ -1364,7 +1400,7 @@ cifs_parse_devname(const char *devname, struct smb_vol *vol)
if (!*pos)
return 0;
vol->prepath = kstrdup(pos, GFP_KERNEL);
vol->prepath = sanitize_path(pos);
if (!vol->prepath)
return -ENOMEM;
......
......@@ -44,6 +44,33 @@ enum {
NOT_ON_MEDIA = 3,
};
static void do_insert_old_idx(struct ubifs_info *c,
struct ubifs_old_idx *old_idx)
{
struct ubifs_old_idx *o;
struct rb_node **p, *parent = NULL;
p = &c->old_idx.rb_node;
while (*p) {
parent = *p;
o = rb_entry(parent, struct ubifs_old_idx, rb);
if (old_idx->lnum < o->lnum)
p = &(*p)->rb_left;
else if (old_idx->lnum > o->lnum)
p = &(*p)->rb_right;
else if (old_idx->offs < o->offs)
p = &(*p)->rb_left;
else if (old_idx->offs > o->offs)
p = &(*p)->rb_right;
else {
ubifs_err(c, "old idx added twice!");
kfree(old_idx);
}
}
rb_link_node(&old_idx->rb, parent, p);
rb_insert_color(&old_idx->rb, &c->old_idx);
}
/**
* insert_old_idx - record an index node obsoleted since the last commit start.
* @c: UBIFS file-system description object
......@@ -69,35 +96,15 @@ enum {
*/
static int insert_old_idx(struct ubifs_info *c, int lnum, int offs)
{
struct ubifs_old_idx *old_idx, *o;
struct rb_node **p, *parent = NULL;
struct ubifs_old_idx *old_idx;
old_idx = kmalloc(sizeof(struct ubifs_old_idx), GFP_NOFS);
if (unlikely(!old_idx))
return -ENOMEM;
old_idx->lnum = lnum;
old_idx->offs = offs;
do_insert_old_idx(c, old_idx);
p = &c->old_idx.rb_node;
while (*p) {
parent = *p;
o = rb_entry(parent, struct ubifs_old_idx, rb);
if (lnum < o->lnum)
p = &(*p)->rb_left;
else if (lnum > o->lnum)
p = &(*p)->rb_right;
else if (offs < o->offs)
p = &(*p)->rb_left;
else if (offs > o->offs)
p = &(*p)->rb_right;
else {
ubifs_err(c, "old idx added twice!");
kfree(old_idx);
return 0;
}
}
rb_link_node(&old_idx->rb, parent, p);
rb_insert_color(&old_idx->rb, &c->old_idx);
return 0;
}
......@@ -199,23 +206,6 @@ static struct ubifs_znode *copy_znode(struct ubifs_info *c,
__set_bit(DIRTY_ZNODE, &zn->flags);
__clear_bit(COW_ZNODE, &zn->flags);
ubifs_assert(c, !ubifs_zn_obsolete(znode));
__set_bit(OBSOLETE_ZNODE, &znode->flags);
if (znode->level != 0) {
int i;
const int n = zn->child_cnt;
/* The children now have new parent */
for (i = 0; i < n; i++) {
struct ubifs_zbranch *zbr = &zn->zbranch[i];
if (zbr->znode)
zbr->znode->parent = zn;
}
}
atomic_long_inc(&c->dirty_zn_cnt);
return zn;
}
......@@ -233,6 +223,42 @@ static int add_idx_dirt(struct ubifs_info *c, int lnum, int dirt)
return ubifs_add_dirt(c, lnum, dirt);
}
/**
* replace_znode - replace old znode with new znode.
* @c: UBIFS file-system description object
* @new_zn: new znode
* @old_zn: old znode
* @zbr: the branch of parent znode
*
* Replace old znode with new znode in TNC.
*/
static void replace_znode(struct ubifs_info *c, struct ubifs_znode *new_zn,
struct ubifs_znode *old_zn, struct ubifs_zbranch *zbr)
{
ubifs_assert(c, !ubifs_zn_obsolete(old_zn));
__set_bit(OBSOLETE_ZNODE, &old_zn->flags);
if (old_zn->level != 0) {
int i;
const int n = new_zn->child_cnt;
/* The children now have new parent */
for (i = 0; i < n; i++) {
struct ubifs_zbranch *child = &new_zn->zbranch[i];
if (child->znode)
child->znode->parent = new_zn;
}
}
zbr->znode = new_zn;
zbr->lnum = 0;
zbr->offs = 0;
zbr->len = 0;
atomic_long_inc(&c->dirty_zn_cnt);
}
/**
* dirty_cow_znode - ensure a znode is not being committed.
* @c: UBIFS file-system description object
......@@ -265,21 +291,32 @@ static struct ubifs_znode *dirty_cow_znode(struct ubifs_info *c,
return zn;
if (zbr->len) {
err = insert_old_idx(c, zbr->lnum, zbr->offs);
if (unlikely(err))
return ERR_PTR(err);
struct ubifs_old_idx *old_idx;
old_idx = kmalloc(sizeof(struct ubifs_old_idx), GFP_NOFS);
if (unlikely(!old_idx)) {
err = -ENOMEM;
goto out;
}
old_idx->lnum = zbr->lnum;
old_idx->offs = zbr->offs;
err = add_idx_dirt(c, zbr->lnum, zbr->len);
} else
err = 0;
if (err) {
kfree(old_idx);
goto out;
}
zbr->znode = zn;
zbr->lnum = 0;
zbr->offs = 0;
zbr->len = 0;
do_insert_old_idx(c, old_idx);
}
replace_znode(c, zn, znode, zbr);
if (unlikely(err))
return ERR_PTR(err);
return zn;
out:
kfree(zn);
return ERR_PTR(err);
}
/**
......@@ -3053,6 +3090,21 @@ static void tnc_destroy_cnext(struct ubifs_info *c)
cnext = cnext->cnext;
if (ubifs_zn_obsolete(znode))
kfree(znode);
else if (!ubifs_zn_cow(znode)) {
/*
* Don't forget to update clean znode count after
* committing failed, because ubifs will check this
* count while closing tnc. Non-obsolete znode could
* be re-dirtied during committing process, so dirty
* flag is untrustable. The flag 'COW_ZNODE' is set
* for each dirty znode before committing, and it is
* cleared as long as the znode become clean, so we
* can statistic clean znode count according to this
* flag.
*/
atomic_long_inc(&c->clean_zn_cnt);
atomic_long_inc(&ubifs_clean_zn_cnt);
}
} while (cnext && cnext != c->cnext);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册