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:
Linus Torvalds 2008-08-15 10:33:07 -07:00
commit 21d3bdb160
18 changed files with 327 additions and 242 deletions

View File

@ -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.

View File

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

View File

@ -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);

View File

@ -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;
}

View File

@ -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) ({})

View File

@ -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;
/*

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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) {

View File

@ -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);
/*

View File

@ -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);

View File

@ -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);

View File

@ -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.
*/

View File

@ -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;

View File

@ -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 + \

View File

@ -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,

View File

@ -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);