From a5969cabbb4660eab42b6ef0412cbbd1200cf14d Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Sat, 12 Oct 2024 07:10:09 +0000 Subject: [PATCH] 修改led为gpio --- kernel/fs/ubifs/tnc.c | 225 +++++++++++++++++++++++++++++++++++-------------------- 1 files changed, 142 insertions(+), 83 deletions(-) diff --git a/kernel/fs/ubifs/tnc.c b/kernel/fs/ubifs/tnc.c index f15ac37..2313c71 100644 --- a/kernel/fs/ubifs/tnc.c +++ b/kernel/fs/ubifs/tnc.c @@ -1,20 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * This file is part of UBIFS. * * Copyright (C) 2006-2008 Nokia Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Adrian Hunter * Artem Bityutskiy (Битюцкий Артём) @@ -35,7 +23,7 @@ #include "ubifs.h" static int try_read_node(const struct ubifs_info *c, void *buf, int type, - int len, int lnum, int offs); + struct ubifs_zbranch *zbr); static int fallible_read_node(struct ubifs_info *c, const union ubifs_key *key, struct ubifs_zbranch *zbr, void *node); @@ -55,6 +43,33 @@ NAME_GREATER = 2, 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. @@ -81,35 +96,15 @@ */ 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; } @@ -211,23 +206,6 @@ __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; } @@ -243,6 +221,42 @@ { c->calc_idx_sz -= ALIGN(dirt, 8); 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); } /** @@ -277,21 +291,32 @@ 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); + } - if (unlikely(err)) - return ERR_PTR(err); + replace_znode(c, zn, znode, zbr); + return zn; + +out: + kfree(zn); + return ERR_PTR(err); } /** @@ -372,7 +397,6 @@ /** * lnc_free - remove a leaf node from the leaf node cache. * @zbr: zbranch of leaf node - * @node: leaf node */ static void lnc_free(struct ubifs_zbranch *zbr) { @@ -433,9 +457,7 @@ * @c: UBIFS file-system description object * @buf: buffer to read to * @type: node type - * @len: node length (not aligned) - * @lnum: LEB number of node to read - * @offs: offset of node to read + * @zbr: the zbranch describing the node to read * * This function tries to read a node of known type and length, checks it and * stores it in @buf. This function returns %1 if a node is present and %0 if @@ -453,8 +475,11 @@ * journal nodes may potentially be corrupted, so checking is required. */ static int try_read_node(const struct ubifs_info *c, void *buf, int type, - int len, int lnum, int offs) + struct ubifs_zbranch *zbr) { + int len = zbr->len; + int lnum = zbr->lnum; + int offs = zbr->offs; int err, node_len; struct ubifs_ch *ch = buf; uint32_t crc, node_crc; @@ -478,14 +503,19 @@ if (node_len != len) return 0; - if (type == UBIFS_DATA_NODE && c->no_chk_data_crc && !c->mounting && - !c->remounting_rw) - return 1; + if (type != UBIFS_DATA_NODE || !c->no_chk_data_crc || c->mounting || + c->remounting_rw) { + crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8); + node_crc = le32_to_cpu(ch->crc); + if (crc != node_crc) + return 0; + } - crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8); - node_crc = le32_to_cpu(ch->crc); - if (crc != node_crc) + err = ubifs_node_check_hash(c, buf, zbr->hash); + if (err) { + ubifs_bad_hash(c, buf, zbr->hash, lnum, offs); return 0; + } return 1; } @@ -507,8 +537,7 @@ dbg_tnck(key, "LEB %d:%d, key ", zbr->lnum, zbr->offs); - ret = try_read_node(c, node, key_type(c, key), zbr->len, zbr->lnum, - zbr->offs); + ret = try_read_node(c, node, key_type(c, key), zbr); if (ret == 1) { union ubifs_key node_key; struct ubifs_dent_node *dent = node; @@ -899,7 +928,7 @@ int adding) { struct ubifs_znode *o_znode = NULL, *znode = *zn; - int uninitialized_var(o_n), err, cmp, unsure = 0, nn = *n; + int o_n, err, cmp, unsure = 0, nn = *n; cmp = fallible_matches_name(c, &znode->zbranch[nn], nm); if (unlikely(cmp < 0)) @@ -1521,8 +1550,8 @@ */ int ubifs_tnc_get_bu_keys(struct ubifs_info *c, struct bu_info *bu) { - int n, err = 0, lnum = -1, uninitialized_var(offs); - int uninitialized_var(len); + int n, err = 0, lnum = -1, offs; + int len; unsigned int block = key_block(c, &bu->key); struct ubifs_znode *znode; @@ -1711,6 +1740,12 @@ if (err) { ubifs_err(c, "expected node type %d", UBIFS_DATA_NODE); goto out; + } + + err = ubifs_node_check_hash(c, buf, zbr->hash); + if (err) { + ubifs_bad_hash(c, buf, zbr->hash, zbr->lnum, zbr->offs); + return err; } len = le32_to_cpu(ch->len); @@ -2266,13 +2301,14 @@ * @lnum: LEB number of node * @offs: node offset * @len: node length + * @hash: The hash over the node * * This function adds a node with key @key to TNC. The node may be new or it may * obsolete some existing one. Returns %0 on success or negative error code on * failure. */ int ubifs_tnc_add(struct ubifs_info *c, const union ubifs_key *key, int lnum, - int offs, int len) + int offs, int len, const u8 *hash) { int found, n, err = 0; struct ubifs_znode *znode; @@ -2287,6 +2323,7 @@ zbr.lnum = lnum; zbr.offs = offs; zbr.len = len; + ubifs_copy_hash(c, hash, zbr.hash); key_copy(c, key, &zbr.key); err = tnc_insert(c, znode, &zbr, n + 1); } else if (found == 1) { @@ -2297,6 +2334,7 @@ zbr->lnum = lnum; zbr->offs = offs; zbr->len = len; + ubifs_copy_hash(c, hash, zbr->hash); } else err = found; if (!err) @@ -2398,13 +2436,14 @@ * @lnum: LEB number of node * @offs: node offset * @len: node length + * @hash: The hash over the node * @nm: node name * * This is the same as 'ubifs_tnc_add()' but it should be used with keys which * may have collisions, like directory entry keys. */ int ubifs_tnc_add_nm(struct ubifs_info *c, const union ubifs_key *key, - int lnum, int offs, int len, + int lnum, int offs, int len, const u8 *hash, const struct fscrypt_name *nm) { int found, n, err = 0; @@ -2447,6 +2486,7 @@ zbr->lnum = lnum; zbr->offs = offs; zbr->len = len; + ubifs_copy_hash(c, hash, zbr->hash); goto out_unlock; } } @@ -2458,6 +2498,7 @@ zbr.lnum = lnum; zbr.offs = offs; zbr.len = len; + ubifs_copy_hash(c, hash, zbr.hash); key_copy(c, key, &zbr.key); err = tnc_insert(c, znode, &zbr, n + 1); if (err) @@ -2880,6 +2921,7 @@ err = PTR_ERR(xent); if (err == -ENOENT) break; + kfree(pxent); return err; } @@ -2893,6 +2935,7 @@ fname_len(&nm) = le16_to_cpu(xent->nlen); err = ubifs_tnc_remove_nm(c, &key1, &nm); if (err) { + kfree(pxent); kfree(xent); return err; } @@ -2901,6 +2944,7 @@ highest_ino_key(c, &key2, xattr_inum); err = ubifs_tnc_remove_range(c, &key1, &key2); if (err) { + kfree(pxent); kfree(xent); return err; } @@ -3046,6 +3090,21 @@ 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); } @@ -3461,7 +3520,7 @@ /** * dbg_check_inode_size - check if inode size is correct. * @c: UBIFS file-system description object - * @inum: inode number + * @inode: inode to check * @size: inode size * * This function makes sure that the inode size (@size) is correct and it does -- Gitblit v1.6.2