Commit f96c08e8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'linux-next' of git://git.infradead.org/ubifs-2.6

* 'linux-next' of git://git.infradead.org/ubifs-2.6:
  UBIFS: remove fast unmounting
  UBIFS: return sensible error codes
  UBIFS: remount ro fixes
  UBIFS: spelling fix 'date' -> 'data'
  UBIFS: sync wbufs after syncing inodes and pages
  UBIFS: fix LPT out-of-space bug (again)
  UBIFS: fix no_chk_data_crc
  UBIFS: fix assertions
  UBIFS: ensure orphan area head is initialized
  UBIFS: always clean up GC LEB space
  UBIFS: add re-mount debugging checks
  UBIFS: fix LEB list freeing
  UBIFS: simplify locking
  UBIFS: document dark_wm and dead_wm better
  UBIFS: do not treat all data as short term
  UBIFS: constify operations
  UBIFS: do not commit twice
parents 7420b73d 27ad2799
......@@ -79,13 +79,6 @@ Mount options
(*) == default.
norm_unmount (*) commit on unmount; the journal is committed
when the file-system is unmounted so that the
next mount does not have to replay the journal
and it becomes very fast;
fast_unmount do not commit on unmount; this option makes
unmount faster, but the next mount slower
because of the need to replay the journal.
bulk_read read more in one go to take advantage of flash
media that read faster sequentially
no_bulk_read (*) do not bulk-read
......
......@@ -689,7 +689,7 @@ long long ubifs_reported_space(const struct ubifs_info *c, long long free)
}
/**
* ubifs_get_free_space - return amount of free space.
* ubifs_get_free_space_nolock - return amount of free space.
* @c: UBIFS file-system description object
*
* This function calculates amount of free space to report to user-space.
......@@ -704,16 +704,14 @@ long long ubifs_reported_space(const struct ubifs_info *c, long long free)
* traditional file-systems, because they have way less overhead than UBIFS.
* So, to keep users happy, UBIFS tries to take the overhead into account.
*/
long long ubifs_get_free_space(struct ubifs_info *c)
long long ubifs_get_free_space_nolock(struct ubifs_info *c)
{
int min_idx_lebs, rsvd_idx_lebs, lebs;
int rsvd_idx_lebs, lebs;
long long available, outstanding, free;
spin_lock(&c->space_lock);
min_idx_lebs = c->min_idx_lebs;
ubifs_assert(min_idx_lebs == ubifs_calc_min_idx_lebs(c));
ubifs_assert(c->min_idx_lebs == ubifs_calc_min_idx_lebs(c));
outstanding = c->budg_data_growth + c->budg_dd_growth;
available = ubifs_calc_available(c, min_idx_lebs);
available = ubifs_calc_available(c, c->min_idx_lebs);
/*
* When reporting free space to user-space, UBIFS guarantees that it is
......@@ -726,15 +724,14 @@ long long ubifs_get_free_space(struct ubifs_info *c)
* Note, the calculations below are similar to what we have in
* 'do_budget_space()', so refer there for comments.
*/
if (min_idx_lebs > c->lst.idx_lebs)
rsvd_idx_lebs = min_idx_lebs - c->lst.idx_lebs;
if (c->min_idx_lebs > c->lst.idx_lebs)
rsvd_idx_lebs = c->min_idx_lebs - c->lst.idx_lebs;
else
rsvd_idx_lebs = 0;
lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt -
c->lst.taken_empty_lebs;
lebs -= rsvd_idx_lebs;
available += lebs * (c->dark_wm - c->leb_overhead);
spin_unlock(&c->space_lock);
if (available > outstanding)
free = ubifs_reported_space(c, available - outstanding);
......@@ -742,3 +739,21 @@ long long ubifs_get_free_space(struct ubifs_info *c)
free = 0;
return free;
}
/**
* ubifs_get_free_space - return amount of free space.
* @c: UBIFS file-system description object
*
* This function calculates and retuns amount of free space to report to
* user-space.
*/
long long ubifs_get_free_space(struct ubifs_info *c)
{
long long free;
spin_lock(&c->space_lock);
free = ubifs_get_free_space_nolock(c);
spin_unlock(&c->space_lock);
return free;
}
......@@ -620,9 +620,11 @@ void dbg_dump_budg(struct ubifs_info *c)
c->dark_wm, c->dead_wm, c->max_idx_node_sz);
printk(KERN_DEBUG "\tgc_lnum %d, ihead_lnum %d\n",
c->gc_lnum, c->ihead_lnum);
for (i = 0; i < c->jhead_cnt; i++)
printk(KERN_DEBUG "\tjhead %d\t LEB %d\n",
c->jheads[i].wbuf.jhead, c->jheads[i].wbuf.lnum);
/* If we are in R/O mode, journal heads do not exist */
if (c->jheads)
for (i = 0; i < c->jhead_cnt; i++)
printk(KERN_DEBUG "\tjhead %d\t LEB %d\n",
c->jheads[i].wbuf.jhead, c->jheads[i].wbuf.lnum);
for (rb = rb_first(&c->buds); rb; rb = rb_next(rb)) {
bud = rb_entry(rb, struct ubifs_bud, rb);
printk(KERN_DEBUG "\tbud LEB %d\n", bud->lnum);
......@@ -637,10 +639,7 @@ void dbg_dump_budg(struct ubifs_info *c)
/* Print budgeting predictions */
available = ubifs_calc_available(c, c->min_idx_lebs);
outstanding = c->budg_data_growth + c->budg_dd_growth;
if (available > outstanding)
free = ubifs_reported_space(c, available - outstanding);
else
free = 0;
free = ubifs_get_free_space_nolock(c);
printk(KERN_DEBUG "Budgeting predictions:\n");
printk(KERN_DEBUG "\tavailable: %lld, outstanding %lld, free %lld\n",
available, outstanding, free);
......@@ -860,6 +859,65 @@ void dbg_dump_index(struct ubifs_info *c)
dbg_walk_index(c, NULL, dump_znode, NULL);
}
/**
* dbg_save_space_info - save information about flash space.
* @c: UBIFS file-system description object
*
* This function saves information about UBIFS free space, dirty space, etc, in
* order to check it later.
*/
void dbg_save_space_info(struct ubifs_info *c)
{
struct ubifs_debug_info *d = c->dbg;
ubifs_get_lp_stats(c, &d->saved_lst);
spin_lock(&c->space_lock);
d->saved_free = ubifs_get_free_space_nolock(c);
spin_unlock(&c->space_lock);
}
/**
* dbg_check_space_info - check flash space information.
* @c: UBIFS file-system description object
*
* This function compares current flash space information with the information
* which was saved when the 'dbg_save_space_info()' function was called.
* Returns zero if the information has not changed, and %-EINVAL it it has
* changed.
*/
int dbg_check_space_info(struct ubifs_info *c)
{
struct ubifs_debug_info *d = c->dbg;
struct ubifs_lp_stats lst;
long long avail, free;
spin_lock(&c->space_lock);
avail = ubifs_calc_available(c, c->min_idx_lebs);
spin_unlock(&c->space_lock);
free = ubifs_get_free_space(c);
if (free != d->saved_free) {
ubifs_err("free space changed from %lld to %lld",
d->saved_free, free);
goto out;
}
return 0;
out:
ubifs_msg("saved lprops statistics dump");
dbg_dump_lstats(&d->saved_lst);
ubifs_get_lp_stats(c, &lst);
ubifs_msg("current lprops statistics dump");
dbg_dump_lstats(&d->saved_lst);
spin_lock(&c->space_lock);
dbg_dump_budg(c);
spin_unlock(&c->space_lock);
dump_stack();
return -EINVAL;
}
/**
* dbg_check_synced_i_size - check synchronized inode size.
* @inode: inode to check
......@@ -1349,7 +1407,7 @@ int dbg_check_tnc(struct ubifs_info *c, int extra)
* @c: UBIFS file-system description object
* @leaf_cb: called for each leaf node
* @znode_cb: called for each indexing node
* @priv: private date which is passed to callbacks
* @priv: private data which is passed to callbacks
*
* This function walks the UBIFS index and calls the @leaf_cb for each leaf
* node and @znode_cb for each indexing node. Returns zero in case of success
......@@ -2409,7 +2467,7 @@ void ubifs_debugging_exit(struct ubifs_info *c)
* Root directory for UBIFS stuff in debugfs. Contains sub-directories which
* contain the stuff specific to particular file-system mounts.
*/
static struct dentry *debugfs_rootdir;
static struct dentry *dfs_rootdir;
/**
* dbg_debugfs_init - initialize debugfs file-system.
......@@ -2421,9 +2479,9 @@ static struct dentry *debugfs_rootdir;
*/
int dbg_debugfs_init(void)
{
debugfs_rootdir = debugfs_create_dir("ubifs", NULL);
if (IS_ERR(debugfs_rootdir)) {
int err = PTR_ERR(debugfs_rootdir);
dfs_rootdir = debugfs_create_dir("ubifs", NULL);
if (IS_ERR(dfs_rootdir)) {
int err = PTR_ERR(dfs_rootdir);
ubifs_err("cannot create \"ubifs\" debugfs directory, "
"error %d\n", err);
return err;
......@@ -2437,7 +2495,7 @@ int dbg_debugfs_init(void)
*/
void dbg_debugfs_exit(void)
{
debugfs_remove(debugfs_rootdir);
debugfs_remove(dfs_rootdir);
}
static int open_debugfs_file(struct inode *inode, struct file *file)
......@@ -2452,13 +2510,13 @@ static ssize_t write_debugfs_file(struct file *file, const char __user *buf,
struct ubifs_info *c = file->private_data;
struct ubifs_debug_info *d = c->dbg;
if (file->f_path.dentry == d->dump_lprops)
if (file->f_path.dentry == d->dfs_dump_lprops)
dbg_dump_lprops(c);
else if (file->f_path.dentry == d->dump_budg) {
else if (file->f_path.dentry == d->dfs_dump_budg) {
spin_lock(&c->space_lock);
dbg_dump_budg(c);
spin_unlock(&c->space_lock);
} else if (file->f_path.dentry == d->dump_tnc) {
} else if (file->f_path.dentry == d->dfs_dump_tnc) {
mutex_lock(&c->tnc_mutex);
dbg_dump_tnc(c);
mutex_unlock(&c->tnc_mutex);
......@@ -2469,7 +2527,7 @@ static ssize_t write_debugfs_file(struct file *file, const char __user *buf,
return count;
}
static const struct file_operations debugfs_fops = {
static const struct file_operations dfs_fops = {
.open = open_debugfs_file,
.write = write_debugfs_file,
.owner = THIS_MODULE,
......@@ -2494,36 +2552,32 @@ int dbg_debugfs_init_fs(struct ubifs_info *c)
struct dentry *dent;
struct ubifs_debug_info *d = c->dbg;
sprintf(d->debugfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id);
d->debugfs_dir = debugfs_create_dir(d->debugfs_dir_name,
debugfs_rootdir);
if (IS_ERR(d->debugfs_dir)) {
err = PTR_ERR(d->debugfs_dir);
sprintf(d->dfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id);
d->dfs_dir = debugfs_create_dir(d->dfs_dir_name, dfs_rootdir);
if (IS_ERR(d->dfs_dir)) {
err = PTR_ERR(d->dfs_dir);
ubifs_err("cannot create \"%s\" debugfs directory, error %d\n",
d->debugfs_dir_name, err);
d->dfs_dir_name, err);
goto out;
}
fname = "dump_lprops";
dent = debugfs_create_file(fname, S_IWUGO, d->debugfs_dir, c,
&debugfs_fops);
dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops);
if (IS_ERR(dent))
goto out_remove;
d->dump_lprops = dent;
d->dfs_dump_lprops = dent;
fname = "dump_budg";
dent = debugfs_create_file(fname, S_IWUGO, d->debugfs_dir, c,
&debugfs_fops);
dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops);
if (IS_ERR(dent))
goto out_remove;
d->dump_budg = dent;
d->dfs_dump_budg = dent;
fname = "dump_tnc";
dent = debugfs_create_file(fname, S_IWUGO, d->debugfs_dir, c,
&debugfs_fops);
dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops);
if (IS_ERR(dent))
goto out_remove;
d->dump_tnc = dent;
d->dfs_dump_tnc = dent;
return 0;
......@@ -2531,7 +2585,7 @@ int dbg_debugfs_init_fs(struct ubifs_info *c)
err = PTR_ERR(dent);
ubifs_err("cannot create \"%s\" debugfs directory, error %d\n",
fname, err);
debugfs_remove_recursive(d->debugfs_dir);
debugfs_remove_recursive(d->dfs_dir);
out:
return err;
}
......@@ -2542,7 +2596,7 @@ int dbg_debugfs_init_fs(struct ubifs_info *c)
*/
void dbg_debugfs_exit_fs(struct ubifs_info *c)
{
debugfs_remove_recursive(c->dbg->debugfs_dir);
debugfs_remove_recursive(c->dbg->dfs_dir);
}
#endif /* CONFIG_UBIFS_FS_DEBUG */
......@@ -41,15 +41,17 @@
* @chk_lpt_wastage: used by LPT tree size checker
* @chk_lpt_lebs: used by LPT tree size checker
* @new_nhead_offs: used by LPT tree size checker
* @new_ihead_lnum: used by debugging to check ihead_lnum
* @new_ihead_offs: used by debugging to check ihead_offs
* @new_ihead_lnum: used by debugging to check @c->ihead_lnum
* @new_ihead_offs: used by debugging to check @c->ihead_offs
*
* debugfs_dir_name: name of debugfs directory containing this file-system's
* files
* debugfs_dir: direntry object of the file-system debugfs directory
* dump_lprops: "dump lprops" debugfs knob
* dump_budg: "dump budgeting information" debugfs knob
* dump_tnc: "dump TNC" debugfs knob
* @saved_lst: saved lprops statistics (used by 'dbg_save_space_info()')
* @saved_free: saved free space (used by 'dbg_save_space_info()')
*
* dfs_dir_name: name of debugfs directory containing this file-system's files
* dfs_dir: direntry object of the file-system debugfs directory
* dfs_dump_lprops: "dump lprops" debugfs knob
* dfs_dump_budg: "dump budgeting information" debugfs knob
* dfs_dump_tnc: "dump TNC" debugfs knob
*/
struct ubifs_debug_info {
void *buf;
......@@ -69,11 +71,14 @@ struct ubifs_debug_info {
int new_ihead_lnum;
int new_ihead_offs;
char debugfs_dir_name[100];
struct dentry *debugfs_dir;
struct dentry *dump_lprops;
struct dentry *dump_budg;
struct dentry *dump_tnc;
struct ubifs_lp_stats saved_lst;
long long saved_free;
char dfs_dir_name[100];
struct dentry *dfs_dir;
struct dentry *dfs_dump_lprops;
struct dentry *dfs_dump_budg;
struct dentry *dfs_dump_tnc;
};
#define ubifs_assert(expr) do { \
......@@ -297,7 +302,8 @@ int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb,
dbg_znode_callback znode_cb, void *priv);
/* Checking functions */
void dbg_save_space_info(struct ubifs_info *c);
int dbg_check_space_info(struct ubifs_info *c);
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);
......@@ -439,6 +445,8 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c);
#define dbg_walk_index(c, leaf_cb, znode_cb, priv) 0
#define dbg_old_index_check_init(c, zroot) 0
#define dbg_save_space_info(c) ({})
#define dbg_check_space_info(c) 0
#define dbg_check_old_index(c, zroot) 0
#define dbg_check_cats(c) 0
#define dbg_check_ltab(c) 0
......
......@@ -482,30 +482,29 @@ static int ubifs_dir_release(struct inode *dir, struct file *file)
}
/**
* lock_2_inodes - lock two UBIFS inodes.
* lock_2_inodes - a wrapper for locking two UBIFS inodes.
* @inode1: first inode
* @inode2: second inode
*
* We do not implement any tricks to guarantee strict lock ordering, because
* VFS has already done it for us on the @i_mutex. So this is just a simple
* wrapper function.
*/
static void lock_2_inodes(struct inode *inode1, struct inode *inode2)
{
if (inode1->i_ino < inode2->i_ino) {
mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_2);
mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_3);
} else {
mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2);
mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_3);
}
mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1);
mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2);
}
/**
* unlock_2_inodes - unlock two UBIFS inodes inodes.
* unlock_2_inodes - a wrapper for unlocking two UBIFS inodes.
* @inode1: first inode
* @inode2: second inode
*/
static void unlock_2_inodes(struct inode *inode1, struct inode *inode2)
{
mutex_unlock(&ubifs_inode(inode1)->ui_mutex);
mutex_unlock(&ubifs_inode(inode2)->ui_mutex);
mutex_unlock(&ubifs_inode(inode1)->ui_mutex);
}
static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
......@@ -527,6 +526,8 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
dbg_gen("dent '%.*s' to ino %lu (nlink %d) in dir ino %lu",
dentry->d_name.len, dentry->d_name.name, inode->i_ino,
inode->i_nlink, dir->i_ino);
ubifs_assert(mutex_is_locked(&dir->i_mutex));
ubifs_assert(mutex_is_locked(&inode->i_mutex));
err = dbg_check_synced_i_size(inode);
if (err)
return err;
......@@ -580,6 +581,8 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
dbg_gen("dent '%.*s' from ino %lu (nlink %d) in dir ino %lu",
dentry->d_name.len, dentry->d_name.name, inode->i_ino,
inode->i_nlink, dir->i_ino);
ubifs_assert(mutex_is_locked(&dir->i_mutex));
ubifs_assert(mutex_is_locked(&inode->i_mutex));
err = dbg_check_synced_i_size(inode);
if (err)
return err;
......@@ -667,7 +670,8 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry)
dbg_gen("directory '%.*s', ino %lu in dir ino %lu", dentry->d_name.len,
dentry->d_name.name, inode->i_ino, dir->i_ino);
ubifs_assert(mutex_is_locked(&dir->i_mutex));
ubifs_assert(mutex_is_locked(&inode->i_mutex));
err = check_dir_empty(c, dentry->d_inode);
if (err)
return err;
......@@ -922,59 +926,30 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
}
/**
* lock_3_inodes - lock three UBIFS inodes for rename.
* lock_3_inodes - a wrapper for locking three UBIFS inodes.
* @inode1: first inode
* @inode2: second inode
* @inode3: third inode
*
* For 'ubifs_rename()', @inode1 may be the same as @inode2 whereas @inode3 may
* be null.
* This function is used for 'ubifs_rename()' and @inode1 may be the same as
* @inode2 whereas @inode3 may be %NULL.
*
* We do not implement any tricks to guarantee strict lock ordering, because
* VFS has already done it for us on the @i_mutex. So this is just a simple
* wrapper function.
*/
static void lock_3_inodes(struct inode *inode1, struct inode *inode2,
struct inode *inode3)
{
struct inode *i1, *i2, *i3;
if (!inode3) {
if (inode1 != inode2) {
lock_2_inodes(inode1, inode2);
return;
}
mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1);
return;
}
if (inode1 == inode2) {
lock_2_inodes(inode1, inode3);
return;
}
/* 3 different inodes */
if (inode1 < inode2) {
i3 = inode2;
if (inode1 < inode3) {
i1 = inode1;
i2 = inode3;
} else {
i1 = inode3;
i2 = inode1;
}
} else {
i3 = inode1;
if (inode2 < inode3) {
i1 = inode2;
i2 = inode3;
} else {
i1 = inode3;
i2 = inode2;
}
}
mutex_lock_nested(&ubifs_inode(i1)->ui_mutex, WB_MUTEX_1);
lock_2_inodes(i2, i3);
mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1);
if (inode2 != inode1)
mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2);
if (inode3)
mutex_lock_nested(&ubifs_inode(inode3)->ui_mutex, WB_MUTEX_3);
}
/**
* unlock_3_inodes - unlock three UBIFS inodes for rename.
* unlock_3_inodes - a wrapper for unlocking three UBIFS inodes for rename.
* @inode1: first inode
* @inode2: second inode
* @inode3: third inode
......@@ -982,11 +957,11 @@ static void lock_3_inodes(struct inode *inode1, struct inode *inode2,
static void unlock_3_inodes(struct inode *inode1, struct inode *inode2,
struct inode *inode3)
{
mutex_unlock(&ubifs_inode(inode1)->ui_mutex);
if (inode1 != inode2)
mutex_unlock(&ubifs_inode(inode2)->ui_mutex);
if (inode3)
mutex_unlock(&ubifs_inode(inode3)->ui_mutex);
if (inode1 != inode2)
mutex_unlock(&ubifs_inode(inode2)->ui_mutex);
mutex_unlock(&ubifs_inode(inode1)->ui_mutex);
}
static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
......@@ -1020,6 +995,11 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
"dir ino %lu", old_dentry->d_name.len, old_dentry->d_name.name,
old_inode->i_ino, old_dir->i_ino, new_dentry->d_name.len,
new_dentry->d_name.name, new_dir->i_ino);
ubifs_assert(mutex_is_locked(&old_dir->i_mutex));
ubifs_assert(mutex_is_locked(&new_dir->i_mutex));
if (unlink)
ubifs_assert(mutex_is_locked(&new_inode->i_mutex));
if (unlink && is_dir) {
err = check_dir_empty(c, new_inode);
......@@ -1199,7 +1179,7 @@ int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
return 0;
}
struct inode_operations ubifs_dir_inode_operations = {
const struct inode_operations ubifs_dir_inode_operations = {
.lookup = ubifs_lookup,
.create = ubifs_create,
.link = ubifs_link,
......@@ -1219,7 +1199,7 @@ struct inode_operations ubifs_dir_inode_operations = {
#endif
};
struct file_operations ubifs_dir_operations = {
const struct file_operations ubifs_dir_operations = {
.llseek = ubifs_dir_llseek,
.release = ubifs_dir_release,
.read = generic_read_dir,
......
......@@ -432,7 +432,6 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping,
int uninitialized_var(err), appending = !!(pos + len > inode->i_size);
struct page *page;
ubifs_assert(ubifs_inode(inode)->ui_size == inode->i_size);
if (unlikely(c->ro_media))
......@@ -1541,7 +1540,7 @@ static int ubifs_file_mmap(struct file *file, struct vm_area_struct *vma)
return 0;
}
struct address_space_operations ubifs_file_address_operations = {
const struct address_space_operations ubifs_file_address_operations = {
.readpage = ubifs_readpage,
.writepage = ubifs_writepage,
.write_begin = ubifs_write_begin,
......@@ -1551,7 +1550,7 @@ struct address_space_operations ubifs_file_address_operations = {
.releasepage = ubifs_releasepage,
};
struct inode_operations ubifs_file_inode_operations = {
const struct inode_operations ubifs_file_inode_operations = {
.setattr = ubifs_setattr,
.getattr = ubifs_getattr,
#ifdef CONFIG_UBIFS_FS_XATTR
......@@ -1562,14 +1561,14 @@ struct inode_operations ubifs_file_inode_operations = {
#endif
};
struct inode_operations ubifs_symlink_inode_operations = {
const struct inode_operations ubifs_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = ubifs_follow_link,
.setattr = ubifs_setattr,
.getattr = ubifs_getattr,
};
struct file_operations ubifs_file_operations = {
const struct file_operations ubifs_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
......
<
......@@ -31,6 +31,26 @@
* to be reused. Garbage collection will cause the number of dirty index nodes
* to grow, however sufficient space is reserved for the index to ensure the
* commit will never run out of space.
*
* Notes about dead watermark. At current UBIFS implementation we assume that
* LEBs which have less than @c->dead_wm bytes of free + dirty space are full
* and not worth garbage-collecting. The dead watermark is one min. I/O unit
* size, or min. UBIFS node size, depending on what is greater. Indeed, UBIFS
* Garbage Collector has to synchronize the GC head's write buffer before
* returning, so this is about wasting one min. I/O unit. However, UBIFS GC can
* actually reclaim even very small pieces of dirty space by garbage collecting
* enough dirty LEBs, but we do not bother doing this at this implementation.
*
* Notes about dark watermark. The results of GC work depends on how big are
* the UBIFS nodes GC deals with. Large nodes make GC waste more space. Indeed,
* if GC move data from LEB A to LEB B and nodes in LEB A are large, GC would
* have to waste large pieces of free space at the end of LEB B, because nodes
* from LEB A would not fit. And the worst situation is when all nodes are of
* maximum size. So dark watermark is the amount of free + dirty space in LEB
* which are guaranteed to be reclaimable. If LEB has less space, the GC migh
* be unable to reclaim it. So, LEBs with free + dirty greater than dark
* watermark are "good" LEBs from GC's point of few. The other LEBs are not so
* good, and GC takes extra care when moving them.
*/
#include <linux/pagemap.h>
......@@ -381,7 +401,7 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp)
/*
* Don't release the LEB until after the next commit, because
* it may contain date which is needed for recovery. So
* it may contain data which is needed for recovery. So
* although we freed this LEB, it will become usable only after
* the commit.
*/
......@@ -810,8 +830,9 @@ int ubifs_gc_end_commit(struct ubifs_info *c)
* ubifs_destroy_idx_gc - destroy idx_gc list.
* @c: UBIFS file-system description object
*