Merge branch 'linux-next' of git://git.infradead.org/~dedekind/ubifs-2.6
* 'linux-next' of git://git.infradead.org/~dedekind/ubifs-2.6: (29 commits) UBIFS: xattr bugfixes UBIFS: remove unneeded check UBIFS: few commentary fixes UBIFS: fix budgeting request alignment in xattr code UBIFS: improve arguments checking in debugging messages UBIFS: always set i_generation to 0 UBIFS: correct spelling of "thrice". UBIFS: support splice_write UBIFS: minor tweaks in commit UBIFS: reserve more space for index UBIFS: print pid in dump function UBIFS: align inode data to eight UBIFS: improve budgeting checks UBIFS: correct orphan deletion order UBIFS: fix typos in comments UBIFS: do not union creat_sqnum and del_cmtno UBIFS: optimize deletions UBIFS: increment commit number earlier UBIFS: remove another unneeded function parameter UBIFS: remove unneeded function parameter ...
This commit is contained in:
Коммит
21d3bdb160
|
@ -57,7 +57,7 @@ Similarly to JFFS2, UBIFS supports on-the-flight compression which makes
|
|||
it possible to fit quite a lot of data to the flash.
|
||||
|
||||
Similarly to JFFS2, UBIFS is tolerant of unclean reboots and power-cuts.
|
||||
It does not need stuff like ckfs.ext2. UBIFS automatically replays its
|
||||
It does not need stuff like fsck.ext2. UBIFS automatically replays its
|
||||
journal and recovers from crashes, ensuring that the on-flash data
|
||||
structures are consistent.
|
||||
|
||||
|
|
|
@ -263,8 +263,8 @@ int ubifs_calc_min_idx_lebs(struct ubifs_info *c)
|
|||
|
||||
idx_size = c->old_idx_sz + c->budg_idx_growth + c->budg_uncommitted_idx;
|
||||
|
||||
/* And make sure we have twice the index size of space reserved */
|
||||
idx_size <<= 1;
|
||||
/* And make sure we have thrice the index size of space reserved */
|
||||
idx_size = idx_size + (idx_size << 1);
|
||||
|
||||
/*
|
||||
* We do not maintain 'old_idx_size' as 'old_idx_lebs'/'old_idx_bytes'
|
||||
|
@ -388,11 +388,11 @@ static int can_use_rp(struct ubifs_info *c)
|
|||
* This function makes sure UBIFS has enough free eraseblocks for index growth
|
||||
* and data.
|
||||
*
|
||||
* When budgeting index space, UBIFS reserves twice as more LEBs as the index
|
||||
* When budgeting index space, UBIFS reserves thrice as many LEBs as the index
|
||||
* would take if it was consolidated and written to the flash. This guarantees
|
||||
* that the "in-the-gaps" commit method always succeeds and UBIFS will always
|
||||
* be able to commit dirty index. So this function basically adds amount of
|
||||
* budgeted index space to the size of the current index, multiplies this by 2,
|
||||
* budgeted index space to the size of the current index, multiplies this by 3,
|
||||
* and makes sure this does not exceed the amount of free eraseblocks.
|
||||
*
|
||||
* Notes about @c->min_idx_lebs and @c->lst.idx_lebs variables:
|
||||
|
@ -543,8 +543,16 @@ int ubifs_budget_space(struct ubifs_info *c, struct ubifs_budget_req *req)
|
|||
int err, idx_growth, data_growth, dd_growth;
|
||||
struct retries_info ri;
|
||||
|
||||
ubifs_assert(req->new_page <= 1);
|
||||
ubifs_assert(req->dirtied_page <= 1);
|
||||
ubifs_assert(req->new_dent <= 1);
|
||||
ubifs_assert(req->mod_dent <= 1);
|
||||
ubifs_assert(req->new_ino <= 1);
|
||||
ubifs_assert(req->new_ino_d <= UBIFS_MAX_INO_DATA);
|
||||
ubifs_assert(req->dirtied_ino <= 4);
|
||||
ubifs_assert(req->dirtied_ino_d <= UBIFS_MAX_INO_DATA * 4);
|
||||
ubifs_assert(!(req->new_ino_d & 7));
|
||||
ubifs_assert(!(req->dirtied_ino_d & 7));
|
||||
|
||||
data_growth = calc_data_growth(c, req);
|
||||
dd_growth = calc_dd_growth(c, req);
|
||||
|
@ -618,8 +626,16 @@ again:
|
|||
*/
|
||||
void ubifs_release_budget(struct ubifs_info *c, struct ubifs_budget_req *req)
|
||||
{
|
||||
ubifs_assert(req->new_page <= 1);
|
||||
ubifs_assert(req->dirtied_page <= 1);
|
||||
ubifs_assert(req->new_dent <= 1);
|
||||
ubifs_assert(req->mod_dent <= 1);
|
||||
ubifs_assert(req->new_ino <= 1);
|
||||
ubifs_assert(req->new_ino_d <= UBIFS_MAX_INO_DATA);
|
||||
ubifs_assert(req->dirtied_ino <= 4);
|
||||
ubifs_assert(req->dirtied_ino_d <= UBIFS_MAX_INO_DATA * 4);
|
||||
ubifs_assert(!(req->new_ino_d & 7));
|
||||
ubifs_assert(!(req->dirtied_ino_d & 7));
|
||||
if (!req->recalculate) {
|
||||
ubifs_assert(req->idx_growth >= 0);
|
||||
ubifs_assert(req->data_growth >= 0);
|
||||
|
@ -647,7 +663,11 @@ void ubifs_release_budget(struct ubifs_info *c, struct ubifs_budget_req *req)
|
|||
|
||||
ubifs_assert(c->budg_idx_growth >= 0);
|
||||
ubifs_assert(c->budg_data_growth >= 0);
|
||||
ubifs_assert(c->budg_dd_growth >= 0);
|
||||
ubifs_assert(c->min_idx_lebs < c->main_lebs);
|
||||
ubifs_assert(!(c->budg_idx_growth & 7));
|
||||
ubifs_assert(!(c->budg_data_growth & 7));
|
||||
ubifs_assert(!(c->budg_dd_growth & 7));
|
||||
spin_unlock(&c->space_lock);
|
||||
}
|
||||
|
||||
|
@ -686,9 +706,10 @@ void ubifs_convert_page_budget(struct ubifs_info *c)
|
|||
void ubifs_release_dirty_inode_budget(struct ubifs_info *c,
|
||||
struct ubifs_inode *ui)
|
||||
{
|
||||
struct ubifs_budget_req req = {.dd_growth = c->inode_budget,
|
||||
.dirtied_ino_d = ui->data_len};
|
||||
struct ubifs_budget_req req;
|
||||
|
||||
memset(&req, 0, sizeof(struct ubifs_budget_req));
|
||||
req.dd_growth = c->inode_budget + ALIGN(ui->data_len, 8);
|
||||
ubifs_release_budget(c, &req);
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ static int do_commit(struct ubifs_info *c)
|
|||
goto out_up;
|
||||
}
|
||||
|
||||
c->cmt_no += 1;
|
||||
err = ubifs_gc_start_commit(c);
|
||||
if (err)
|
||||
goto out_up;
|
||||
|
@ -115,7 +116,7 @@ static int do_commit(struct ubifs_info *c)
|
|||
goto out;
|
||||
|
||||
mutex_lock(&c->mst_mutex);
|
||||
c->mst_node->cmt_no = cpu_to_le64(++c->cmt_no);
|
||||
c->mst_node->cmt_no = cpu_to_le64(c->cmt_no);
|
||||
c->mst_node->log_lnum = cpu_to_le32(new_ltail_lnum);
|
||||
c->mst_node->root_lnum = cpu_to_le32(zroot.lnum);
|
||||
c->mst_node->root_offs = cpu_to_le32(zroot.offs);
|
||||
|
|
|
@ -568,8 +568,8 @@ void dbg_dump_budget_req(const struct ubifs_budget_req *req)
|
|||
void dbg_dump_lstats(const struct ubifs_lp_stats *lst)
|
||||
{
|
||||
spin_lock(&dbg_lock);
|
||||
printk(KERN_DEBUG "Lprops statistics: empty_lebs %d, idx_lebs %d\n",
|
||||
lst->empty_lebs, lst->idx_lebs);
|
||||
printk(KERN_DEBUG "(pid %d) Lprops statistics: empty_lebs %d, "
|
||||
"idx_lebs %d\n", current->pid, lst->empty_lebs, lst->idx_lebs);
|
||||
printk(KERN_DEBUG "\ttaken_empty_lebs %d, total_free %lld, "
|
||||
"total_dirty %lld\n", lst->taken_empty_lebs, lst->total_free,
|
||||
lst->total_dirty);
|
||||
|
@ -587,8 +587,8 @@ void dbg_dump_budg(struct ubifs_info *c)
|
|||
struct ubifs_gced_idx_leb *idx_gc;
|
||||
|
||||
spin_lock(&dbg_lock);
|
||||
printk(KERN_DEBUG "Budgeting info: budg_data_growth %lld, "
|
||||
"budg_dd_growth %lld, budg_idx_growth %lld\n",
|
||||
printk(KERN_DEBUG "(pid %d) Budgeting info: budg_data_growth %lld, "
|
||||
"budg_dd_growth %lld, budg_idx_growth %lld\n", current->pid,
|
||||
c->budg_data_growth, c->budg_dd_growth, c->budg_idx_growth);
|
||||
printk(KERN_DEBUG "\tdata budget sum %lld, total budget sum %lld, "
|
||||
"freeable_cnt %d\n", c->budg_data_growth + c->budg_dd_growth,
|
||||
|
@ -634,7 +634,7 @@ void dbg_dump_lprops(struct ubifs_info *c)
|
|||
struct ubifs_lprops lp;
|
||||
struct ubifs_lp_stats lst;
|
||||
|
||||
printk(KERN_DEBUG "Dumping LEB properties\n");
|
||||
printk(KERN_DEBUG "(pid %d) Dumping LEB properties\n", current->pid);
|
||||
ubifs_get_lp_stats(c, &lst);
|
||||
dbg_dump_lstats(&lst);
|
||||
|
||||
|
@ -655,7 +655,7 @@ void dbg_dump_leb(const struct ubifs_info *c, int lnum)
|
|||
if (dbg_failure_mode)
|
||||
return;
|
||||
|
||||
printk(KERN_DEBUG "Dumping LEB %d\n", lnum);
|
||||
printk(KERN_DEBUG "(pid %d) Dumping LEB %d\n", current->pid, lnum);
|
||||
|
||||
sleb = ubifs_scan(c, lnum, 0, c->dbg_buf);
|
||||
if (IS_ERR(sleb)) {
|
||||
|
@ -720,8 +720,8 @@ void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat)
|
|||
{
|
||||
int i;
|
||||
|
||||
printk(KERN_DEBUG "Dumping heap cat %d (%d elements)\n",
|
||||
cat, heap->cnt);
|
||||
printk(KERN_DEBUG "(pid %d) Dumping heap cat %d (%d elements)\n",
|
||||
current->pid, cat, heap->cnt);
|
||||
for (i = 0; i < heap->cnt; i++) {
|
||||
struct ubifs_lprops *lprops = heap->arr[i];
|
||||
|
||||
|
@ -736,7 +736,7 @@ void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
|
|||
{
|
||||
int i;
|
||||
|
||||
printk(KERN_DEBUG "Dumping pnode:\n");
|
||||
printk(KERN_DEBUG "(pid %d) Dumping pnode:\n", current->pid);
|
||||
printk(KERN_DEBUG "\taddress %zx parent %zx cnext %zx\n",
|
||||
(size_t)pnode, (size_t)parent, (size_t)pnode->cnext);
|
||||
printk(KERN_DEBUG "\tflags %lu iip %d level %d num %d\n",
|
||||
|
@ -755,7 +755,7 @@ void dbg_dump_tnc(struct ubifs_info *c)
|
|||
int level;
|
||||
|
||||
printk(KERN_DEBUG "\n");
|
||||
printk(KERN_DEBUG "Dumping the TNC tree\n");
|
||||
printk(KERN_DEBUG "(pid %d) Dumping the TNC tree\n", current->pid);
|
||||
znode = ubifs_tnc_levelorder_next(c->zroot.znode, NULL);
|
||||
level = znode->level;
|
||||
printk(KERN_DEBUG "== Level %d ==\n", level);
|
||||
|
@ -2208,16 +2208,17 @@ int dbg_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
|
|||
int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
|
||||
int offset, int len, int dtype)
|
||||
{
|
||||
int err;
|
||||
int err, failing;
|
||||
|
||||
if (in_failure_mode(desc))
|
||||
return -EIO;
|
||||
if (do_fail(desc, lnum, 1))
|
||||
failing = do_fail(desc, lnum, 1);
|
||||
if (failing)
|
||||
cut_data(buf, len);
|
||||
err = ubi_leb_write(desc, lnum, buf, offset, len, dtype);
|
||||
if (err)
|
||||
return err;
|
||||
if (in_failure_mode(desc))
|
||||
if (failing)
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
|
139
fs/ubifs/debug.h
139
fs/ubifs/debug.h
|
@ -27,7 +27,7 @@
|
|||
|
||||
#define UBIFS_DBG(op) op
|
||||
|
||||
#define ubifs_assert(expr) do { \
|
||||
#define ubifs_assert(expr) do { \
|
||||
if (unlikely(!(expr))) { \
|
||||
printk(KERN_CRIT "UBIFS assert failed in %s at %u (pid %d)\n", \
|
||||
__func__, __LINE__, current->pid); \
|
||||
|
@ -73,50 +73,50 @@ const char *dbg_key_str1(const struct ubifs_info *c,
|
|||
const union ubifs_key *key);
|
||||
|
||||
/*
|
||||
* DBGKEY macros require dbg_lock to be held, which it is in the dbg message
|
||||
* DBGKEY macros require @dbg_lock to be held, which it is in the dbg message
|
||||
* macros.
|
||||
*/
|
||||
#define DBGKEY(key) dbg_key_str0(c, (key))
|
||||
#define DBGKEY1(key) dbg_key_str1(c, (key))
|
||||
|
||||
/* General messages */
|
||||
#define dbg_gen(fmt, ...) dbg_do_msg(UBIFS_MSG_GEN, fmt, ##__VA_ARGS__)
|
||||
#define dbg_gen(fmt, ...) dbg_do_msg(UBIFS_MSG_GEN, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional journal messages */
|
||||
#define dbg_jnl(fmt, ...) dbg_do_msg(UBIFS_MSG_JNL, fmt, ##__VA_ARGS__)
|
||||
#define dbg_jnl(fmt, ...) dbg_do_msg(UBIFS_MSG_JNL, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional TNC messages */
|
||||
#define dbg_tnc(fmt, ...) dbg_do_msg(UBIFS_MSG_TNC, fmt, ##__VA_ARGS__)
|
||||
#define dbg_tnc(fmt, ...) dbg_do_msg(UBIFS_MSG_TNC, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional lprops messages */
|
||||
#define dbg_lp(fmt, ...) dbg_do_msg(UBIFS_MSG_LP, fmt, ##__VA_ARGS__)
|
||||
#define dbg_lp(fmt, ...) dbg_do_msg(UBIFS_MSG_LP, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional LEB find messages */
|
||||
#define dbg_find(fmt, ...) dbg_do_msg(UBIFS_MSG_FIND, fmt, ##__VA_ARGS__)
|
||||
#define dbg_find(fmt, ...) dbg_do_msg(UBIFS_MSG_FIND, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional mount messages */
|
||||
#define dbg_mnt(fmt, ...) dbg_do_msg(UBIFS_MSG_MNT, fmt, ##__VA_ARGS__)
|
||||
#define dbg_mnt(fmt, ...) dbg_do_msg(UBIFS_MSG_MNT, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional I/O messages */
|
||||
#define dbg_io(fmt, ...) dbg_do_msg(UBIFS_MSG_IO, fmt, ##__VA_ARGS__)
|
||||
#define dbg_io(fmt, ...) dbg_do_msg(UBIFS_MSG_IO, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional commit messages */
|
||||
#define dbg_cmt(fmt, ...) dbg_do_msg(UBIFS_MSG_CMT, fmt, ##__VA_ARGS__)
|
||||
#define dbg_cmt(fmt, ...) dbg_do_msg(UBIFS_MSG_CMT, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional budgeting messages */
|
||||
#define dbg_budg(fmt, ...) dbg_do_msg(UBIFS_MSG_BUDG, fmt, ##__VA_ARGS__)
|
||||
#define dbg_budg(fmt, ...) dbg_do_msg(UBIFS_MSG_BUDG, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional log messages */
|
||||
#define dbg_log(fmt, ...) dbg_do_msg(UBIFS_MSG_LOG, fmt, ##__VA_ARGS__)
|
||||
#define dbg_log(fmt, ...) dbg_do_msg(UBIFS_MSG_LOG, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional gc messages */
|
||||
#define dbg_gc(fmt, ...) dbg_do_msg(UBIFS_MSG_GC, fmt, ##__VA_ARGS__)
|
||||
#define dbg_gc(fmt, ...) dbg_do_msg(UBIFS_MSG_GC, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional scan messages */
|
||||
#define dbg_scan(fmt, ...) dbg_do_msg(UBIFS_MSG_SCAN, fmt, ##__VA_ARGS__)
|
||||
#define dbg_scan(fmt, ...) dbg_do_msg(UBIFS_MSG_SCAN, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional recovery messages */
|
||||
#define dbg_rcvry(fmt, ...) dbg_do_msg(UBIFS_MSG_RCVRY, fmt, ##__VA_ARGS__)
|
||||
#define dbg_rcvry(fmt, ...) dbg_do_msg(UBIFS_MSG_RCVRY, fmt, ##__VA_ARGS__)
|
||||
|
||||
/*
|
||||
* Debugging message type flags (must match msg_type_names in debug.c).
|
||||
|
@ -239,34 +239,23 @@ typedef int (*dbg_leaf_callback)(struct ubifs_info *c,
|
|||
struct ubifs_zbranch *zbr, void *priv);
|
||||
typedef int (*dbg_znode_callback)(struct ubifs_info *c,
|
||||
struct ubifs_znode *znode, void *priv);
|
||||
|
||||
int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb,
|
||||
dbg_znode_callback znode_cb, void *priv);
|
||||
|
||||
/* Checking functions */
|
||||
|
||||
int dbg_check_lprops(struct ubifs_info *c);
|
||||
|
||||
int dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot);
|
||||
int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot);
|
||||
|
||||
int dbg_check_cats(struct ubifs_info *c);
|
||||
|
||||
int dbg_check_ltab(struct ubifs_info *c);
|
||||
|
||||
int dbg_check_synced_i_size(struct inode *inode);
|
||||
|
||||
int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir);
|
||||
|
||||
int dbg_check_tnc(struct ubifs_info *c, int extra);
|
||||
|
||||
int dbg_check_idx_size(struct ubifs_info *c, long long idx_size);
|
||||
|
||||
int dbg_check_filesystem(struct ubifs_info *c);
|
||||
|
||||
void dbg_check_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat,
|
||||
int add_pos);
|
||||
|
||||
int dbg_check_lprops(struct ubifs_info *c);
|
||||
int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode,
|
||||
int row, int col);
|
||||
|
@ -329,71 +318,77 @@ static inline int dbg_change(struct ubi_volume_desc *desc, int lnum,
|
|||
#else /* !CONFIG_UBIFS_FS_DEBUG */
|
||||
|
||||
#define UBIFS_DBG(op)
|
||||
#define ubifs_assert(expr) ({})
|
||||
#define ubifs_assert_cmt_locked(c)
|
||||
|
||||
/* Use "if (0)" to make compiler check arguments even if debugging is off */
|
||||
#define ubifs_assert(expr) do { \
|
||||
if (0 && (expr)) \
|
||||
printk(KERN_CRIT "UBIFS assert failed in %s at %u (pid %d)\n", \
|
||||
__func__, __LINE__, current->pid); \
|
||||
} while (0)
|
||||
|
||||
#define dbg_err(fmt, ...) do { \
|
||||
if (0) \
|
||||
ubifs_err(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define dbg_msg(fmt, ...) do { \
|
||||
if (0) \
|
||||
printk(KERN_DEBUG "UBIFS DBG (pid %d): %s: " fmt "\n", \
|
||||
current->pid, __func__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define dbg_dump_stack()
|
||||
#define dbg_err(fmt, ...) ({})
|
||||
#define dbg_msg(fmt, ...) ({})
|
||||
#define dbg_key(c, key, fmt, ...) ({})
|
||||
#define ubifs_assert_cmt_locked(c)
|
||||
|
||||
#define dbg_gen(fmt, ...) ({})
|
||||
#define dbg_jnl(fmt, ...) ({})
|
||||
#define dbg_tnc(fmt, ...) ({})
|
||||
#define dbg_lp(fmt, ...) ({})
|
||||
#define dbg_find(fmt, ...) ({})
|
||||
#define dbg_mnt(fmt, ...) ({})
|
||||
#define dbg_io(fmt, ...) ({})
|
||||
#define dbg_cmt(fmt, ...) ({})
|
||||
#define dbg_budg(fmt, ...) ({})
|
||||
#define dbg_log(fmt, ...) ({})
|
||||
#define dbg_gc(fmt, ...) ({})
|
||||
#define dbg_scan(fmt, ...) ({})
|
||||
#define dbg_rcvry(fmt, ...) ({})
|
||||
#define dbg_gen(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_jnl(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_tnc(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_lp(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_find(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_mnt(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_io(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_cmt(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_budg(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_log(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_gc(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_scan(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
|
||||
#define dbg_rcvry(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
|
||||
|
||||
#define dbg_ntype(type) ""
|
||||
#define dbg_cstate(cmt_state) ""
|
||||
#define dbg_get_key_dump(c, key) ({})
|
||||
#define dbg_dump_inode(c, inode) ({})
|
||||
#define dbg_dump_node(c, node) ({})
|
||||
#define dbg_dump_budget_req(req) ({})
|
||||
#define dbg_dump_lstats(lst) ({})
|
||||
#define dbg_dump_budg(c) ({})
|
||||
#define dbg_dump_lprop(c, lp) ({})
|
||||
#define dbg_dump_lprops(c) ({})
|
||||
#define dbg_dump_leb(c, lnum) ({})
|
||||
#define dbg_dump_znode(c, znode) ({})
|
||||
#define dbg_dump_heap(c, heap, cat) ({})
|
||||
#define dbg_dump_pnode(c, pnode, parent, iip) ({})
|
||||
#define dbg_dump_tnc(c) ({})
|
||||
#define dbg_dump_index(c) ({})
|
||||
#define DBGKEY(key) ((char *)(key))
|
||||
#define DBGKEY1(key) ((char *)(key))
|
||||
|
||||
#define dbg_ntype(type) ""
|
||||
#define dbg_cstate(cmt_state) ""
|
||||
#define dbg_get_key_dump(c, key) ({})
|
||||
#define dbg_dump_inode(c, inode) ({})
|
||||
#define dbg_dump_node(c, node) ({})
|
||||
#define dbg_dump_budget_req(req) ({})
|
||||
#define dbg_dump_lstats(lst) ({})
|
||||
#define dbg_dump_budg(c) ({})
|
||||
#define dbg_dump_lprop(c, lp) ({})
|
||||
#define dbg_dump_lprops(c) ({})
|
||||
#define dbg_dump_leb(c, lnum) ({})
|
||||
#define dbg_dump_znode(c, znode) ({})
|
||||
#define dbg_dump_heap(c, heap, cat) ({})
|
||||
#define dbg_dump_pnode(c, pnode, parent, iip) ({})
|
||||
#define dbg_dump_tnc(c) ({})
|
||||
#define dbg_dump_index(c) ({})
|
||||
|
||||
#define dbg_walk_index(c, leaf_cb, znode_cb, priv) 0
|
||||
|
||||
#define dbg_old_index_check_init(c, zroot) 0
|
||||
#define dbg_check_old_index(c, zroot) 0
|
||||
|
||||
#define dbg_check_cats(c) 0
|
||||
|
||||
#define dbg_check_ltab(c) 0
|
||||
|
||||
#define dbg_check_synced_i_size(inode) 0
|
||||
|
||||
#define dbg_check_dir_size(c, dir) 0
|
||||
|
||||
#define dbg_check_tnc(c, x) 0
|
||||
|
||||
#define dbg_check_idx_size(c, idx_size) 0
|
||||
|
||||
#define dbg_check_filesystem(c) 0
|
||||
|
||||
#define dbg_check_heap(c, heap, cat, add_pos) ({})
|
||||
|
||||
#define dbg_check_lprops(c) 0
|
||||
#define dbg_check_lpt_nodes(c, cnode, row, col) 0
|
||||
|
||||
#define dbg_force_in_the_gaps_enabled 0
|
||||
#define dbg_force_in_the_gaps() 0
|
||||
|
||||
#define dbg_failure_mode 0
|
||||
#define dbg_failure_mode_registration(c) ({})
|
||||
#define dbg_failure_mode_deregistration(c) ({})
|
||||
|
|
|
@ -165,7 +165,6 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir,
|
|||
}
|
||||
|
||||
inode->i_ino = ++c->highest_inum;
|
||||
inode->i_generation = ++c->vfs_gen;
|
||||
/*
|
||||
* The creation sequence number remains with this inode for its
|
||||
* lifetime. All nodes for this inode have a greater sequence number,
|
||||
|
@ -220,15 +219,7 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
|
|||
|
||||
err = ubifs_tnc_lookup_nm(c, &key, dent, &dentry->d_name);
|
||||
if (err) {
|
||||
/*
|
||||
* Do not hash the direntry if parent 'i_nlink' is zero, because
|
||||
* this has side-effects - '->delete_inode()' call will not be
|
||||
* called for the parent orphan inode, because 'd_count' of its
|
||||
* direntry will stay 1 (it'll be negative direntry I guess)
|
||||
* and prevent 'iput_final()' until the dentry is destroyed due
|
||||
* to unmount or memory pressure.
|
||||
*/
|
||||
if (err == -ENOENT && dir->i_nlink != 0) {
|
||||
if (err == -ENOENT) {
|
||||
dbg_gen("not found");
|
||||
goto done;
|
||||
}
|
||||
|
@ -525,7 +516,7 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
|
|||
struct ubifs_inode *dir_ui = ubifs_inode(dir);
|
||||
int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len);
|
||||
struct ubifs_budget_req req = { .new_dent = 1, .dirtied_ino = 2,
|
||||
.dirtied_ino_d = ui->data_len };
|
||||
.dirtied_ino_d = ALIGN(ui->data_len, 8) };
|
||||
|
||||
/*
|
||||
* Budget request settings: new direntry, changing the target inode,
|
||||
|
@ -727,8 +718,7 @@ static int ubifs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
|
|||
struct ubifs_inode *dir_ui = ubifs_inode(dir);
|
||||
struct ubifs_info *c = dir->i_sb->s_fs_info;
|
||||
int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len);
|
||||
struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
|
||||
.dirtied_ino_d = 1 };
|
||||
struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1 };
|
||||
|
||||
/*
|
||||
* Budget request settings: new inode, new direntry and changing parent
|
||||
|
@ -789,7 +779,8 @@ static int ubifs_mknod(struct inode *dir, struct dentry *dentry,
|
|||
int sz_change = CALC_DENT_SIZE(dentry->d_name.len);
|
||||
int err, devlen = 0;
|
||||
struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
|
||||
.new_ino_d = devlen, .dirtied_ino = 1 };
|
||||
.new_ino_d = ALIGN(devlen, 8),
|
||||
.dirtied_ino = 1 };
|
||||
|
||||
/*
|
||||
* Budget request settings: new inode, new direntry and changing parent
|
||||
|
@ -863,7 +854,8 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
|
|||
int err, len = strlen(symname);
|
||||
int sz_change = CALC_DENT_SIZE(dentry->d_name.len);
|
||||
struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
|
||||
.new_ino_d = len, .dirtied_ino = 1 };
|
||||
.new_ino_d = ALIGN(len, 8),
|
||||
.dirtied_ino = 1 };
|
||||
|
||||
/*
|
||||
* Budget request settings: new inode, new direntry and changing parent
|
||||
|
@ -1012,7 +1004,7 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||
struct ubifs_budget_req req = { .new_dent = 1, .mod_dent = 1,
|
||||
.dirtied_ino = 3 };
|
||||
struct ubifs_budget_req ino_req = { .dirtied_ino = 1,
|
||||
.dirtied_ino_d = old_inode_ui->data_len };
|
||||
.dirtied_ino_d = ALIGN(old_inode_ui->data_len, 8) };
|
||||
struct timespec time;
|
||||
|
||||
/*
|
||||
|
|
|
@ -890,7 +890,7 @@ static int do_setattr(struct ubifs_info *c, struct inode *inode,
|
|||
loff_t new_size = attr->ia_size;
|
||||
struct ubifs_inode *ui = ubifs_inode(inode);
|
||||
struct ubifs_budget_req req = { .dirtied_ino = 1,
|
||||
.dirtied_ino_d = ui->data_len };
|
||||
.dirtied_ino_d = ALIGN(ui->data_len, 8) };
|
||||
|
||||
err = ubifs_budget_space(c, &req);
|
||||
if (err)
|
||||
|
@ -941,7 +941,8 @@ int ubifs_setattr(struct dentry *dentry, struct iattr *attr)
|
|||
struct inode *inode = dentry->d_inode;
|
||||
struct ubifs_info *c = inode->i_sb->s_fs_info;
|
||||
|
||||
dbg_gen("ino %lu, ia_valid %#x", inode->i_ino, attr->ia_valid);
|
||||
dbg_gen("ino %lu, mode %#x, ia_valid %#x",
|
||||
inode->i_ino, inode->i_mode, attr->ia_valid);
|
||||
err = inode_change_ok(inode, attr);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -1051,7 +1052,7 @@ static int update_mctime(struct ubifs_info *c, struct inode *inode)
|
|||
if (mctime_update_needed(inode, &now)) {
|
||||
int err, release;
|
||||
struct ubifs_budget_req req = { .dirtied_ino = 1,
|
||||
.dirtied_ino_d = ui->data_len };
|
||||
.dirtied_ino_d = ALIGN(ui->data_len, 8) };
|
||||
|
||||
err = ubifs_budget_space(c, &req);
|
||||
if (err)
|
||||
|
@ -1270,6 +1271,7 @@ struct file_operations ubifs_file_operations = {
|
|||
.fsync = ubifs_fsync,
|
||||
.unlocked_ioctl = ubifs_ioctl,
|
||||
.splice_read = generic_file_splice_read,
|
||||
.splice_write = generic_file_splice_write,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = ubifs_compat_ioctl,
|
||||
#endif
|
||||
|
|
|
@ -290,9 +290,14 @@ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp,
|
|||
idx_lp = idx_heap->arr[0];
|
||||
sum = idx_lp->free + idx_lp->dirty;
|
||||
/*
|
||||
* Since we reserve twice as more space for the index than it
|
||||
* Since we reserve thrice as much space for the index than it
|
||||
* actually takes, it does not make sense to pick indexing LEBs
|
||||
* with less than half LEB of dirty space.
|
||||
* with less than, say, half LEB of dirty space. May be half is
|
||||
* not the optimal boundary - this should be tested and
|
||||
* checked. This boundary should determine how much we use
|
||||
* in-the-gaps to consolidate the index comparing to how much
|
||||
* we use garbage collector to consolidate it. The "half"
|
||||
* criteria just feels to be fine.
|
||||
*/
|
||||
if (sum < min_space || sum < c->half_leb_size)
|
||||
idx_lp = NULL;
|
||||
|
|
|
@ -53,6 +53,20 @@
|
|||
#include <linux/crc32.h>
|
||||
#include "ubifs.h"
|
||||
|
||||
/**
|
||||
* ubifs_ro_mode - switch UBIFS to read read-only mode.
|
||||
* @c: UBIFS file-system description object
|
||||
* @err: error code which is the reason of switching to R/O mode
|
||||
*/
|
||||
void ubifs_ro_mode(struct ubifs_info *c, int err)
|
||||
{
|
||||
if (!c->ro_media) {
|
||||
c->ro_media = 1;
|
||||
ubifs_warn("switched to read-only mode, error %d", err);
|
||||
dbg_dump_stack();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_check_node - check node.
|
||||
* @c: UBIFS file-system description object
|
||||
|
|
|
@ -447,13 +447,11 @@ static int get_dent_type(int mode)
|
|||
* @ino: buffer in which to pack inode node
|
||||
* @inode: inode to pack
|
||||
* @last: indicates the last node of the group
|
||||
* @last_reference: non-zero if this is a deletion inode
|
||||
*/
|
||||
static void pack_inode(struct ubifs_info *c, struct ubifs_ino_node *ino,
|
||||
const struct inode *inode, int last,
|
||||
int last_reference)
|
||||
const struct inode *inode, int last)
|
||||
{
|
||||
int data_len = 0;
|
||||
int data_len = 0, last_reference = !inode->i_nlink;
|
||||
struct ubifs_inode *ui = ubifs_inode(inode);
|
||||
|
||||
ino->ch.node_type = UBIFS_INO_NODE;
|
||||
|
@ -596,9 +594,9 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
|
|||
ubifs_prep_grp_node(c, dent, dlen, 0);
|
||||
|
||||
ino = (void *)dent + aligned_dlen;
|
||||
pack_inode(c, ino, inode, 0, last_reference);
|
||||
pack_inode(c, ino, inode, 0);
|
||||
ino = (void *)ino + aligned_ilen;
|
||||
pack_inode(c, ino, dir, 1, 0);
|
||||
pack_inode(c, ino, dir, 1);
|
||||
|
||||
if (last_reference) {
|
||||
err = ubifs_add_orphan(c, inode->i_ino);
|
||||
|
@ -606,6 +604,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
|
|||
release_head(c, BASEHD);
|
||||
goto out_finish;
|
||||
}
|
||||
ui->del_cmtno = c->cmt_no;
|
||||
}
|
||||
|
||||
err = write_head(c, BASEHD, dent, len, &lnum, &dent_offs, sync);
|
||||
|
@ -750,30 +749,25 @@ out_free:
|
|||
* ubifs_jnl_write_inode - flush inode to the journal.
|
||||
* @c: UBIFS file-system description object
|
||||
* @inode: inode to flush
|
||||
* @deletion: inode has been deleted
|
||||
*
|
||||
* This function writes inode @inode to the journal. If the inode is
|
||||
* synchronous, it also synchronizes the write-buffer. Returns zero in case of
|
||||
* success and a negative error code in case of failure.
|
||||
*/
|
||||
int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode,
|
||||
int deletion)
|
||||
int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)
|
||||
{
|
||||
int err, len, lnum, offs, sync = 0;
|
||||
int err, lnum, offs;
|
||||
struct ubifs_ino_node *ino;
|
||||
struct ubifs_inode *ui = ubifs_inode(inode);
|
||||
int sync = 0, len = UBIFS_INO_NODE_SZ, last_reference = !inode->i_nlink;
|
||||
|
||||
dbg_jnl("ino %lu%s", inode->i_ino,
|
||||
deletion ? " (last reference)" : "");
|
||||
if (deletion)
|
||||
ubifs_assert(inode->i_nlink == 0);
|
||||
dbg_jnl("ino %lu, nlink %u", inode->i_ino, inode->i_nlink);
|
||||
|
||||
len = UBIFS_INO_NODE_SZ;
|
||||
/*
|
||||
* If the inode is being deleted, do not write the attached data. No
|
||||
* need to synchronize the write-buffer either.
|
||||
*/
|
||||
if (!deletion) {
|
||||
if (!last_reference) {
|
||||
len += ui->data_len;
|
||||
sync = IS_SYNC(inode);
|
||||
}
|
||||
|
@ -786,7 +780,7 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode,
|
|||
if (err)
|
||||
goto out_free;
|
||||
|
||||
pack_inode(c, ino, inode, 1, deletion);
|
||||
pack_inode(c, ino, inode, 1);
|
||||
err = write_head(c, BASEHD, ino, len, &lnum, &offs, sync);
|
||||
if (err)
|
||||
goto out_release;
|
||||
|
@ -795,7 +789,7 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode,
|
|||
inode->i_ino);
|
||||
release_head(c, BASEHD);
|
||||
|
||||
if (deletion) {
|
||||
if (last_reference) {
|
||||
err = ubifs_tnc_remove_ino(c, inode->i_ino);
|
||||
if (err)
|
||||
goto out_ro;
|
||||
|
@ -827,6 +821,65 @@ out_free:
|
|||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_jnl_delete_inode - delete an inode.
|
||||
* @c: UBIFS file-system description object
|
||||
* @inode: inode to delete
|
||||
*
|
||||
* This function deletes inode @inode which includes removing it from orphans,
|
||||
* deleting it from TNC and, in some cases, writing a deletion inode to the
|
||||
* journal.
|
||||
*
|
||||
* When regular file inodes are unlinked or a directory inode is removed, the
|
||||
* 'ubifs_jnl_update()' function writes a corresponding deletion inode and
|
||||
* direntry to the media, and adds the inode to orphans. After this, when the
|
||||
* last reference to this inode has been dropped, this function is called. In
|
||||
* general, it has to write one more deletion inode to the media, because if
|
||||
* a commit happened between 'ubifs_jnl_update()' and
|
||||
* 'ubifs_jnl_delete_inode()', the deletion inode is not in the journal
|
||||
* anymore, and in fact it might not be on the flash anymore, because it might
|
||||
* have been garbage-collected already. And for optimization reasons UBIFS does
|
||||
* not read the orphan area if it has been unmounted cleanly, so it would have
|
||||
* no indication in the journal that there is a deleted inode which has to be
|
||||
* removed from TNC.
|
||||
*
|
||||
* However, if there was no commit between 'ubifs_jnl_update()' and
|
||||
* 'ubifs_jnl_delete_inode()', then there is no need to write the deletion
|
||||
* inode to the media for the second time. And this is quite a typical case.
|
||||
*
|
||||
* This function returns zero in case of success and a negative error code in
|
||||
* case of failure.
|
||||
*/
|
||||
int ubifs_jnl_delete_inode(struct ubifs_info *c, const struct inode *inode)
|
||||
{
|
||||
int err;
|
||||
struct ubifs_inode *ui = ubifs_inode(inode);
|
||||
|
||||
ubifs_assert(inode->i_nlink == 0);
|
||||
|
||||
if (ui->del_cmtno != c->cmt_no)
|
||||
/* A commit happened for sure */
|
||||
return ubifs_jnl_write_inode(c, inode);
|
||||
|
||||
down_read(&c->commit_sem);
|
||||
/*
|
||||
* Check commit number again, because the first test has been done
|
||||
* without @c->commit_sem, so a commit might have happened.
|
||||
*/
|
||||
if (ui->del_cmtno != c->cmt_no) {
|
||||
up_read(&c->commit_sem);
|
||||
return ubifs_jnl_write_inode(c, inode);
|
||||
}
|
||||
|
||||
err = ubifs_tnc_remove_ino(c, inode->i_ino);
|
||||
if (err)
|
||||
ubifs_ro_mode(c, err);
|
||||
else
|
||||
ubifs_delete_orphan(c, inode->i_ino);
|
||||
up_read(&c->commit_sem);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_jnl_rename - rename a directory entry.
|
||||
* @c: UBIFS file-system description object
|
||||
|
@ -917,16 +970,16 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
|
|||
|
||||
p = (void *)dent2 + aligned_dlen2;
|
||||
if (new_inode) {
|
||||
pack_inode(c, p, new_inode, 0, last_reference);
|
||||
pack_inode(c, p, new_inode, 0);
|
||||
p += ALIGN(ilen, 8);
|
||||
}
|
||||
|
||||
if (!move)
|
||||
pack_inode(c, p, old_dir, 1, 0);
|
||||
pack_inode(c, p, old_dir, 1);
|
||||
else {
|
||||
pack_inode(c, p, old_dir, 0, 0);
|
||||
pack_inode(c, p, old_dir, 0);
|
||||
p += ALIGN(plen, 8);
|
||||
pack_inode(c, p, new_dir, 1, 0);
|
||||
pack_inode(c, p, new_dir, 1);
|
||||
}
|
||||
|
||||
if (last_reference) {
|
||||
|
@ -935,6 +988,7 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
|
|||
release_head(c, BASEHD);
|
||||
goto out_finish;
|
||||
}
|
||||
new_ui->del_cmtno = c->cmt_no;
|
||||
}
|
||||
|
||||
err = write_head(c, BASEHD, dent, len, &lnum, &offs, sync);
|
||||
|
@ -1131,7 +1185,7 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode,
|
|||
if (err)
|
||||
goto out_free;
|
||||
|
||||
pack_inode(c, ino, inode, 0, 0);
|
||||
pack_inode(c, ino, inode, 0);
|
||||
ubifs_prep_grp_node(c, trun, UBIFS_TRUN_NODE_SZ, dlen ? 0 : 1);
|
||||
if (dlen)
|
||||
ubifs_prep_grp_node(c, dn, dlen, 1);
|
||||
|
@ -1251,9 +1305,9 @@ int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host,
|
|||
ubifs_prep_grp_node(c, xent, xlen, 0);
|
||||
|
||||
ino = (void *)xent + aligned_xlen;
|
||||
pack_inode(c, ino, inode, 0, 1);
|
||||
pack_inode(c, ino, inode, 0);
|
||||
ino = (void *)ino + UBIFS_INO_NODE_SZ;
|
||||
pack_inode(c, ino, host, 1, 0);
|
||||
pack_inode(c, ino, host, 1);
|
||||
|
||||
err = write_head(c, BASEHD, xent, len, &lnum, &xent_offs, sync);
|
||||
if (!sync && !err)
|
||||
|
@ -1320,7 +1374,7 @@ int ubifs_jnl_change_xattr(struct ubifs_info *c, const struct inode *inode,
|
|||
const struct inode *host)
|
||||
{
|
||||
int err, len1, len2, aligned_len, aligned_len1, lnum, offs;
|
||||
struct ubifs_inode *host_ui = ubifs_inode(inode);
|
||||
struct ubifs_inode *host_ui = ubifs_inode(host);
|
||||
struct ubifs_ino_node *ino;
|
||||
union ubifs_key key;
|
||||
int sync = IS_DIRSYNC(host);
|
||||
|
@ -1344,8 +1398,8 @@ int ubifs_jnl_change_xattr(struct ubifs_info *c, const struct inode *inode,
|
|||
if (err)
|
||||
goto out_free;
|
||||
|
||||
pack_inode(c, ino, host, 0, 0);
|
||||
pack_inode(c, (void *)ino + aligned_len1, inode, 1, 0);
|
||||
pack_inode(c, ino, host, 0);
|
||||
pack_inode(c, (void *)ino + aligned_len1, inode, 1);
|
||||
|
||||
err = write_head(c, BASEHD, ino, aligned_len, &lnum, &offs, 0);
|
||||
if (!sync && !err) {
|
||||
|
|
|
@ -317,6 +317,8 @@ int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs)
|
|||
return 0;
|
||||
|
||||
out_unlock:
|
||||
if (err != -EAGAIN)
|
||||
ubifs_ro_mode(c, err);
|
||||
mutex_unlock(&c->log_mutex);
|
||||
kfree(ref);
|
||||
kfree(bud);
|
||||
|
@ -410,7 +412,7 @@ int ubifs_log_start_commit(struct ubifs_info *c, int *ltail_lnum)
|
|||
return -ENOMEM;
|
||||
|
||||
cs->ch.node_type = UBIFS_CS_NODE;
|
||||
cs->cmt_no = cpu_to_le64(c->cmt_no + 1);
|
||||
cs->cmt_no = cpu_to_le64(c->cmt_no);
|
||||
ubifs_prepare_node(c, cs, UBIFS_CS_NODE_SZ, 0);
|
||||
|
||||
/*
|
||||
|
|
|
@ -79,20 +79,6 @@ static inline struct ubifs_inode *ubifs_inode(const struct inode *inode)
|
|||
return container_of(inode, struct ubifs_inode, vfs_inode);
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_ro_mode - switch UBIFS to read read-only mode.
|
||||
* @c: UBIFS file-system description object
|
||||
* @err: error code which is the reason of switching to R/O mode
|
||||
*/
|
||||
static inline void ubifs_ro_mode(struct ubifs_info *c, int err)
|
||||
{
|
||||
if (!c->ro_media) {
|
||||
c->ro_media = 1;
|
||||
ubifs_warn("switched to read-only mode, error %d", err);
|
||||
dbg_dump_stack();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_compr_present - check if compressor was compiled in.
|
||||
* @compr_type: compressor type to check
|
||||
|
@ -322,7 +308,7 @@ static inline long long ubifs_reported_space(const struct ubifs_info *c,
|
|||
{
|
||||
int divisor, factor;
|
||||
|
||||
divisor = UBIFS_MAX_DATA_NODE_SZ + (c->max_idx_node_sz << 1);
|
||||
divisor = UBIFS_MAX_DATA_NODE_SZ + (c->max_idx_node_sz * 3);
|
||||
factor = UBIFS_MAX_DATA_NODE_SZ - UBIFS_DATA_NODE_SZ;
|
||||
do_div(free, divisor);
|
||||
|
||||
|
|
|
@ -310,10 +310,10 @@ static int write_orph_node(struct ubifs_info *c, int atomic)
|
|||
c->cmt_orphans -= cnt;
|
||||
spin_unlock(&c->orphan_lock);
|
||||
if (c->cmt_orphans)
|
||||
orph->cmt_no = cpu_to_le64(c->cmt_no + 1);
|
||||
orph->cmt_no = cpu_to_le64(c->cmt_no);
|
||||
else
|
||||
/* Mark the last node of the commit */
|
||||
orph->cmt_no = cpu_to_le64((c->cmt_no + 1) | (1ULL << 63));
|
||||
orph->cmt_no = cpu_to_le64((c->cmt_no) | (1ULL << 63));
|
||||
ubifs_assert(c->ohead_offs + len <= c->leb_size);
|
||||
ubifs_assert(c->ohead_lnum >= c->orph_first);
|
||||
ubifs_assert(c->ohead_lnum <= c->orph_last);
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/parser.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
@ -149,7 +148,7 @@ struct inode *ubifs_iget(struct super_block *sb, unsigned long inum)
|
|||
if (err)
|
||||
goto out_invalid;
|
||||
|
||||
/* Disable readahead */
|
||||
/* Disable read-ahead */
|
||||
inode->i_mapping->backing_dev_info = &c->bdi;
|
||||
|
||||
switch (inode->i_mode & S_IFMT) {
|
||||
|
@ -278,7 +277,7 @@ static void ubifs_destroy_inode(struct inode *inode)
|
|||
*/
|
||||
static int ubifs_write_inode(struct inode *inode, int wait)
|
||||
{
|
||||
int err;
|
||||
int err = 0;
|
||||
struct ubifs_info *c = inode->i_sb->s_fs_info;
|
||||
struct ubifs_inode *ui = ubifs_inode(inode);
|
||||
|
||||
|
@ -299,10 +298,18 @@ static int ubifs_write_inode(struct inode *inode, int wait)
|
|||
return 0;
|
||||
}
|
||||
|
||||
dbg_gen("inode %lu", inode->i_ino);
|
||||
err = ubifs_jnl_write_inode(c, inode, 0);
|
||||
if (err)
|
||||
ubifs_err("can't write inode %lu, error %d", inode->i_ino, err);
|
||||
/*
|
||||
* As an optimization, do not write orphan inodes to the media just
|
||||
* because this is not needed.
|
||||
*/
|
||||
dbg_gen("inode %lu, mode %#x, nlink %u",
|
||||
inode->i_ino, (int)inode->i_mode, inode->i_nlink);
|
||||
if (inode->i_nlink) {
|
||||
err = ubifs_jnl_write_inode(c, inode);
|
||||
if (err)
|
||||
ubifs_err("can't write inode %lu, error %d",
|
||||
inode->i_ino, err);
|
||||
}
|
||||
|
||||
ui->dirty = 0;
|
||||
mutex_unlock(&ui->ui_mutex);
|
||||
|
@ -314,8 +321,9 @@ static void ubifs_delete_inode(struct inode *inode)
|
|||
{
|
||||
int err;
|
||||
struct ubifs_info *c = inode->i_sb->s_fs_info;
|
||||
struct ubifs_inode *ui = ubifs_inode(inode);
|
||||
|
||||
if (ubifs_inode(inode)->xattr)
|
||||
if (ui->xattr)
|
||||
/*
|
||||
* Extended attribute inode deletions are fully handled in
|
||||
* 'ubifs_removexattr()'. These inodes are special and have
|
||||
|
@ -323,7 +331,7 @@ static void ubifs_delete_inode(struct inode *inode)
|
|||
*/
|
||||
goto out;
|
||||
|
||||
dbg_gen("inode %lu", inode->i_ino);
|
||||
dbg_gen("inode %lu, mode %#x", inode->i_ino, (int)inode->i_mode);
|
||||
ubifs_assert(!atomic_read(&inode->i_count));
|
||||
ubifs_assert(inode->i_nlink == 0);
|
||||
|
||||
|
@ -331,15 +339,19 @@ static void ubifs_delete_inode(struct inode *inode)
|
|||
if (is_bad_inode(inode))
|
||||
goto out;
|
||||
|
||||
ubifs_inode(inode)->ui_size = inode->i_size = 0;
|
||||
err = ubifs_jnl_write_inode(c, inode, 1);
|
||||
ui->ui_size = inode->i_size = 0;
|
||||
err = ubifs_jnl_delete_inode(c, inode);
|
||||
if (err)
|
||||
/*
|
||||
* Worst case we have a lost orphan inode wasting space, so a
|
||||
* simple error message is ok here.
|
||||
* simple error message is OK here.
|
||||
*/
|
||||
ubifs_err("can't write inode %lu, error %d", inode->i_ino, err);
|
||||
ubifs_err("can't delete inode %lu, error %d",
|
||||
inode->i_ino, err);
|
||||
|
||||
out:
|
||||
if (ui->dirty)
|
||||
ubifs_release_dirty_inode_budget(c, ui);
|
||||
clear_inode(inode);
|
||||
}
|
||||
|
||||
|
@ -1122,8 +1134,8 @@ static int mount_ubifs(struct ubifs_info *c)
|
|||
if (err)
|
||||
goto out_infos;
|
||||
|
||||
ubifs_msg("mounted UBI device %d, volume %d", c->vi.ubi_num,
|
||||
c->vi.vol_id);
|
||||
ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"",
|
||||
c->vi.ubi_num, c->vi.vol_id, c->vi.name);
|
||||
if (mounted_read_only)
|
||||
ubifs_msg("mounted read-only");
|
||||
x = (long long)c->main_lebs * c->leb_size;
|
||||
|
@ -1469,6 +1481,7 @@ static void ubifs_put_super(struct super_block *sb)
|
|||
*/
|
||||
ubifs_assert(atomic_long_read(&c->dirty_pg_cnt) == 0);
|
||||
ubifs_assert(c->budg_idx_growth == 0);
|
||||
ubifs_assert(c->budg_dd_growth == 0);
|
||||
ubifs_assert(c->budg_data_growth == 0);
|
||||
|
||||
/*
|
||||
|
@ -1657,7 +1670,6 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
|
|||
INIT_LIST_HEAD(&c->orph_new);
|
||||
|
||||
c->highest_inum = UBIFS_FIRST_INO;
|
||||
get_random_bytes(&c->vfs_gen, sizeof(int));
|
||||
c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM;
|
||||
|
||||
ubi_get_volume_info(ubi, &c->vi);
|
||||
|
@ -1671,10 +1683,10 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
|
|||
}
|
||||
|
||||
/*
|
||||
* UBIFS provids 'backing_dev_info' in order to disable readahead. For
|
||||
* UBIFS provides 'backing_dev_info' in order to disable read-ahead. For
|
||||
* UBIFS, I/O is not deferred, it is done immediately in readpage,
|
||||
* which means the user would have to wait not just for their own I/O
|
||||
* but the readahead I/O as well i.e. completely pointless.
|
||||
* but the read-ahead I/O as well i.e. completely pointless.
|
||||
*
|
||||
* Read-ahead will be disabled because @c->bdi.ra_pages is 0.
|
||||
*/
|
||||
|
|
|
@ -372,26 +372,25 @@ static int layout_in_gaps(struct ubifs_info *c, int cnt)
|
|||
written = layout_leb_in_gaps(c, p);
|
||||
if (written < 0) {
|
||||
err = written;
|
||||
if (err == -ENOSPC) {
|
||||
if (!dbg_force_in_the_gaps_enabled) {
|
||||
/*
|
||||
* Do not print scary warnings if the
|
||||
* debugging option which forces
|
||||
* in-the-gaps is enabled.
|
||||
*/
|
||||
ubifs_err("out of space");
|
||||
spin_lock(&c->space_lock);
|
||||
dbg_dump_budg(c);
|
||||
spin_unlock(&c->space_lock);
|
||||
dbg_dump_lprops(c);
|
||||
}
|
||||
/* Try to commit anyway */
|
||||
err = 0;
|
||||
break;
|
||||
if (err != -ENOSPC) {
|
||||
kfree(c->gap_lebs);
|
||||
c->gap_lebs = NULL;
|
||||
return err;
|
||||
}
|
||||
kfree(c->gap_lebs);
|
||||
c->gap_lebs = NULL;
|
||||
return err;
|
||||
if (!dbg_force_in_the_gaps_enabled) {
|
||||
/*
|
||||
* Do not print scary warnings if the debugging
|
||||
* option which forces in-the-gaps is enabled.
|
||||
*/
|
||||
ubifs_err("out of space");
|
||||
spin_lock(&c->space_lock);
|
||||
dbg_dump_budg(c);
|
||||
spin_unlock(&c->space_lock);
|
||||
dbg_dump_lprops(c);
|
||||
}
|
||||
/* Try to commit anyway */
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
cnt -= written;
|
||||
|
|
|
@ -228,10 +228,10 @@ enum {
|
|||
/* Minimum number of orphan area logical eraseblocks */
|
||||
#define UBIFS_MIN_ORPH_LEBS 1
|
||||
/*
|
||||
* Minimum number of main area logical eraseblocks (buds, 2 for the index, 1
|
||||
* Minimum number of main area logical eraseblocks (buds, 3 for the index, 1
|
||||
* for GC, 1 for deletions, and at least 1 for committed data).
|
||||
*/
|
||||
#define UBIFS_MIN_MAIN_LEBS (UBIFS_MIN_BUD_LEBS + 5)
|
||||
#define UBIFS_MIN_MAIN_LEBS (UBIFS_MIN_BUD_LEBS + 6)
|
||||
|
||||
/* Minimum number of logical eraseblocks */
|
||||
#define UBIFS_MIN_LEB_CNT (UBIFS_SB_LEBS + UBIFS_MST_LEBS + \
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
* Adrian Hunter
|
||||
*/
|
||||
|
||||
/* Implementation version 0.7 */
|
||||
|
||||
#ifndef __UBIFS_H__
|
||||
#define __UBIFS_H__
|
||||
|
||||
|
@ -322,6 +320,8 @@ struct ubifs_gced_idx_leb {
|
|||
* struct ubifs_inode - UBIFS in-memory inode description.
|
||||
* @vfs_inode: VFS inode description object
|
||||
* @creat_sqnum: sequence number at time of creation
|
||||
* @del_cmtno: commit number corresponding to the time the inode was deleted,
|
||||
* protected by @c->commit_sem;
|
||||
* @xattr_size: summarized size of all extended attributes in bytes
|
||||
* @xattr_cnt: count of extended attributes this inode has
|
||||
* @xattr_names: sum of lengths of all extended attribute names belonging to
|
||||
|
@ -373,6 +373,7 @@ struct ubifs_gced_idx_leb {
|
|||
struct ubifs_inode {
|
||||
struct inode vfs_inode;
|
||||
unsigned long long creat_sqnum;
|
||||
unsigned long long del_cmtno;
|
||||
unsigned int xattr_size;
|
||||
unsigned int xattr_cnt;
|
||||
unsigned int xattr_names;
|
||||
|
@ -779,7 +780,7 @@ struct ubifs_compressor {
|
|||
/**
|
||||
* struct ubifs_budget_req - budget requirements of an operation.
|
||||
*
|
||||
* @fast: non-zero if the budgeting should try to aquire budget quickly and
|
||||
* @fast: non-zero if the budgeting should try to acquire budget quickly and
|
||||
* should not try to call write-back
|
||||
* @recalculate: non-zero if @idx_growth, @data_growth, and @dd_growth fields
|
||||
* have to be re-calculated
|
||||
|
@ -805,21 +806,31 @@ struct ubifs_compressor {
|
|||
* An inode may contain 4KiB of data at max., thus the widths of @new_ino_d
|
||||
* is 13 bits, and @dirtied_ino_d - 15, because up to 4 inodes may be made
|
||||
* dirty by the re-name operation.
|
||||
*
|
||||
* Note, UBIFS aligns node lengths to 8-bytes boundary, so the requester has to
|
||||
* make sure the amount of inode data which contribute to @new_ino_d and
|
||||
* @dirtied_ino_d fields are aligned.
|
||||
*/
|
||||
struct ubifs_budget_req {
|
||||
unsigned int fast:1;
|
||||
unsigned int recalculate:1;
|
||||
#ifndef UBIFS_DEBUG
|
||||
unsigned int new_page:1;
|
||||
unsigned int dirtied_page:1;
|
||||
unsigned int new_dent:1;
|
||||
unsigned int mod_dent:1;
|
||||
unsigned int new_ino:1;
|
||||
unsigned int new_ino_d:13;
|
||||
#ifndef UBIFS_DEBUG
|
||||
unsigned int dirtied_ino:4;
|
||||
unsigned int dirtied_ino_d:15;
|
||||
#else
|
||||
/* Not bit-fields to check for overflows */
|
||||
unsigned int new_page;
|
||||
unsigned int dirtied_page;
|
||||
unsigned int new_dent;
|
||||
unsigned int mod_dent;
|
||||
unsigned int new_ino;
|
||||
unsigned int new_ino_d;
|
||||
unsigned int dirtied_ino;
|
||||
unsigned int dirtied_ino_d;
|
||||
#endif
|
||||
|
@ -860,13 +871,13 @@ struct ubifs_mount_opts {
|
|||
* struct ubifs_info - UBIFS file-system description data structure
|
||||
* (per-superblock).
|
||||
* @vfs_sb: VFS @struct super_block object
|
||||
* @bdi: backing device info object to make VFS happy and disable readahead
|
||||
* @bdi: backing device info object to make VFS happy and disable read-ahead
|
||||
*
|
||||
* @highest_inum: highest used inode number
|
||||
* @vfs_gen: VFS inode generation counter
|
||||
* @max_sqnum: current global sequence number
|
||||
* @cmt_no: commit number (last successfully completed commit)
|
||||
* @cnt_lock: protects @highest_inum, @vfs_gen, and @max_sqnum counters
|
||||
* @cmt_no: commit number of the last successfully completed commit, protected
|
||||
* by @commit_sem
|
||||
* @cnt_lock: protects @highest_inum and @max_sqnum counters
|
||||
* @fmt_version: UBIFS on-flash format version
|
||||
* @uuid: UUID from super block
|
||||
*
|
||||
|
@ -1103,7 +1114,6 @@ struct ubifs_info {
|
|||
struct backing_dev_info bdi;
|
||||
|
||||
ino_t highest_inum;
|
||||
unsigned int vfs_gen;
|
||||
unsigned long long max_sqnum;
|
||||
unsigned long long cmt_no;
|
||||
spinlock_t cnt_lock;
|
||||
|
@ -1346,6 +1356,7 @@ extern struct backing_dev_info ubifs_backing_dev_info;
|
|||
extern struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
|
||||
|
||||
/* io.c */
|
||||
void ubifs_ro_mode(struct ubifs_info *c, int err);
|
||||
int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len);
|
||||
int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs,
|
||||
int dtype);
|
||||
|
@ -1399,8 +1410,8 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
|
|||
int deletion, int xent);
|
||||
int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
|
||||
const union ubifs_key *key, const void *buf, int len);
|
||||
int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode,
|
||||
int last_reference);
|
||||
int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode);
|
||||
int ubifs_jnl_delete_inode(struct ubifs_info *c, const struct inode *inode);
|
||||
int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
|
||||
const struct dentry *old_dentry,
|
||||
const struct inode *new_dir,
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
|
||||
/*
|
||||
* Limit the number of extended attributes per inode so that the total size
|
||||
* (xattr_size) is guaranteeded to fit in an 'unsigned int'.
|
||||
* (@xattr_size) is guaranteeded to fit in an 'unsigned int'.
|
||||
*/
|
||||
#define MAX_XATTRS_PER_INODE 65535
|
||||
|
||||
|
@ -103,14 +103,14 @@ static int create_xattr(struct ubifs_info *c, struct inode *host,
|
|||
struct inode *inode;
|
||||
struct ubifs_inode *ui, *host_ui = ubifs_inode(host);
|
||||
struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
|
||||
.new_ino_d = size, .dirtied_ino = 1,
|
||||
.dirtied_ino_d = host_ui->data_len};
|
||||
.new_ino_d = ALIGN(size, 8), .dirtied_ino = 1,
|
||||
.dirtied_ino_d = ALIGN(host_ui->data_len, 8) };
|
||||
|
||||
if (host_ui->xattr_cnt >= MAX_XATTRS_PER_INODE)
|
||||
return -ENOSPC;
|
||||
/*
|
||||
* Linux limits the maximum size of the extended attribute names list
|
||||
* to %XATTR_LIST_MAX. This means we should not allow creating more*
|
||||
* to %XATTR_LIST_MAX. This means we should not allow creating more
|
||||
* extended attributes if the name list becomes larger. This limitation
|
||||
* is artificial for UBIFS, though.
|
||||
*/
|
||||
|
@ -128,7 +128,6 @@ static int create_xattr(struct ubifs_info *c, struct inode *host,
|
|||
goto out_budg;
|
||||
}
|
||||
|
||||
mutex_lock(&host_ui->ui_mutex);
|
||||
/* Re-define all operations to be "nothing" */
|
||||
inode->i_mapping->a_ops = &none_address_operations;
|
||||
inode->i_op = &none_inode_operations;
|
||||
|
@ -141,23 +140,19 @@ static int create_xattr(struct ubifs_info *c, struct inode *host,
|
|||
ui->data = kmalloc(size, GFP_NOFS);
|
||||
if (!ui->data) {
|
||||
err = -ENOMEM;
|
||||
goto out_unlock;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
memcpy(ui->data, value, size);
|
||||
inode->i_size = ui->ui_size = size;
|
||||
ui->data_len = size;
|
||||
|
||||
mutex_lock(&host_ui->ui_mutex);
|
||||
host->i_ctime = ubifs_current_time(host);
|
||||
host_ui->xattr_cnt += 1;
|
||||
host_ui->xattr_size += CALC_DENT_SIZE(nm->len);
|
||||
host_ui->xattr_size += CALC_XATTR_BYTES(size);
|
||||
host_ui->xattr_names += nm->len;
|
||||
|
||||
/*
|
||||
* We do not use i_size_write() because nobody can race with us as we
|
||||
* are holding host @host->i_mutex - every xattr operation for this
|
||||
* inode is serialized by it.
|
||||
*/
|
||||
inode->i_size = ui->ui_size = size;
|
||||
ui->data_len = size;
|
||||
err = ubifs_jnl_update(c, host, nm, inode, 0, 1);
|
||||
if (err)
|
||||
goto out_cancel;
|
||||
|
@ -172,8 +167,8 @@ out_cancel:
|
|||
host_ui->xattr_cnt -= 1;
|
||||
host_ui->xattr_size -= CALC_DENT_SIZE(nm->len);
|
||||
host_ui->xattr_size -= CALC_XATTR_BYTES(size);
|
||||
out_unlock:
|
||||
mutex_unlock(&host_ui->ui_mutex);
|
||||
out_free:
|
||||
make_bad_inode(inode);
|
||||
iput(inode);
|
||||
out_budg:
|
||||
|
@ -200,29 +195,28 @@ static int change_xattr(struct ubifs_info *c, struct inode *host,
|
|||
struct ubifs_inode *host_ui = ubifs_inode(host);
|
||||
struct ubifs_inode *ui = ubifs_inode(inode);
|
||||
struct ubifs_budget_req req = { .dirtied_ino = 2,
|
||||
.dirtied_ino_d = size + host_ui->data_len };
|
||||
.dirtied_ino_d = ALIGN(size, 8) + ALIGN(host_ui->data_len, 8) };
|
||||
|
||||
ubifs_assert(ui->data_len == inode->i_size);
|
||||
err = ubifs_budget_space(c, &req);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mutex_lock(&host_ui->ui_mutex);
|
||||
host->i_ctime = ubifs_current_time(host);
|
||||
host_ui->xattr_size -= CALC_XATTR_BYTES(ui->data_len);
|
||||
host_ui->xattr_size += CALC_XATTR_BYTES(size);
|
||||
|
||||
kfree(ui->data);
|
||||
ui->data = kmalloc(size, GFP_NOFS);
|
||||
if (!ui->data) {
|
||||
err = -ENOMEM;
|
||||
goto out_unlock;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
memcpy(ui->data, value, size);
|
||||
inode->i_size = ui->ui_size = size;
|
||||
ui->data_len = size;
|
||||
|
||||
mutex_lock(&host_ui->ui_mutex);
|
||||
host->i_ctime = ubifs_current_time(host);
|
||||
host_ui->xattr_size -= CALC_XATTR_BYTES(ui->data_len);
|
||||
host_ui->xattr_size += CALC_XATTR_BYTES(size);
|
||||
|
||||
/*
|
||||
* It is important to write the host inode after the xattr inode
|
||||
* because if the host inode gets synchronized (via 'fsync()'), then
|
||||
|
@ -240,9 +234,9 @@ static int change_xattr(struct ubifs_info *c, struct inode *host,
|
|||
out_cancel:
|
||||
host_ui->xattr_size -= CALC_XATTR_BYTES(size);
|
||||
host_ui->xattr_size += CALC_XATTR_BYTES(ui->data_len);
|
||||
make_bad_inode(inode);
|
||||
out_unlock:
|
||||
mutex_unlock(&host_ui->ui_mutex);
|
||||
make_bad_inode(inode);
|
||||
out_free:
|
||||
ubifs_release_budget(c, &req);
|
||||
return err;
|
||||
}
|
||||
|
@ -312,6 +306,7 @@ int ubifs_setxattr(struct dentry *dentry, const char *name,
|
|||
|
||||
dbg_gen("xattr '%s', host ino %lu ('%.*s'), size %zd", name,
|
||||
host->i_ino, dentry->d_name.len, dentry->d_name.name, size);
|
||||
ubifs_assert(mutex_is_locked(&host->i_mutex));
|
||||
|
||||
if (size > UBIFS_MAX_INO_DATA)
|
||||
return -ERANGE;
|
||||
|
@ -384,7 +379,6 @@ ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf,
|
|||
if (!xent)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&host->i_mutex);
|
||||
xent_key_init(c, &key, host->i_ino, &nm);
|
||||
err = ubifs_tnc_lookup_nm(c, &key, xent, &nm);
|
||||
if (err) {
|
||||
|
@ -419,7 +413,6 @@ ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf,
|
|||
out_iput:
|
||||
iput(inode);
|
||||
out_unlock:
|
||||
mutex_unlock(&host->i_mutex);
|
||||
kfree(xent);
|
||||
return err;
|
||||
}
|
||||
|
@ -449,8 +442,6 @@ ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
|||
return -ERANGE;
|
||||
|
||||
lowest_xent_key(c, &key, host->i_ino);
|
||||
|
||||
mutex_lock(&host->i_mutex);
|
||||
while (1) {
|
||||
int type;
|
||||
|
||||
|
@ -479,7 +470,6 @@ ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
|||
pxent = xent;
|
||||
key_read(c, &xent->key, &key);
|
||||
}
|
||||
mutex_unlock(&host->i_mutex);
|
||||
|
||||
kfree(pxent);
|
||||
if (err != -ENOENT) {
|
||||
|
@ -497,8 +487,8 @@ static int remove_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);
|
||||
struct ubifs_budget_req req = { .dirtied_ino = 1, .mod_dent = 1,
|
||||
.dirtied_ino_d = host_ui->data_len };
|
||||
struct ubifs_budget_req req = { .dirtied_ino = 2, .mod_dent = 1,
|
||||
.dirtied_ino_d = ALIGN(host_ui->data_len, 8) };
|
||||
|
||||
ubifs_assert(ui->data_len == inode->i_size);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче