Skip to content

Commit b975dee

Browse files
committed
Merge branch 'linux-next' of git://git.infradead.org/~dedekind/ubifs-2.6
* 'linux-next' of git://git.infradead.org/~dedekind/ubifs-2.6: UBIFS: make minimum fanout 3 UBIFS: fix division by zero UBIFS: amend f_fsid UBIFS: fill f_fsid UBIFS: improve statfs reporting even more UBIFS: introduce LEB overhead UBIFS: add forgotten gc_idx_lebs component UBIFS: fix assertion UBIFS: improve statfs reporting UBIFS: remove incorrect index space check UBIFS: push empty flash hack down UBIFS: do not update min_idx_lebs in stafs UBIFS: allow for racing between GC and TNC UBIFS: always read hashed-key nodes under TNC mutex UBIFS: fix zero-length truncations
2 parents deac93d + a5cb562 commit b975dee

File tree

10 files changed

+221
-141
lines changed

10 files changed

+221
-141
lines changed

fs/ubifs/budget.c

Lines changed: 87 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -302,18 +302,6 @@ long long ubifs_calc_available(const struct ubifs_info *c, int min_idx_lebs)
302302
int subtract_lebs;
303303
long long available;
304304

305-
/*
306-
* Force the amount available to the total size reported if the used
307-
* space is zero.
308-
*/
309-
if (c->lst.total_used <= UBIFS_INO_NODE_SZ &&
310-
c->budg_data_growth + c->budg_dd_growth == 0) {
311-
/* Do the same calculation as for c->block_cnt */
312-
available = c->main_lebs - 2;
313-
available *= c->leb_size - c->dark_wm;
314-
return available;
315-
}
316-
317305
available = c->main_bytes - c->lst.total_used;
318306

319307
/*
@@ -714,34 +702,106 @@ void ubifs_release_dirty_inode_budget(struct ubifs_info *c,
714702
}
715703

716704
/**
717-
* ubifs_budg_get_free_space - return amount of free space.
705+
* ubifs_reported_space - calculate reported free space.
706+
* @c: the UBIFS file-system description object
707+
* @free: amount of free space
708+
*
709+
* This function calculates amount of free space which will be reported to
710+
* user-space. User-space application tend to expect that if the file-system
711+
* (e.g., via the 'statfs()' call) reports that it has N bytes available, they
712+
* are able to write a file of size N. UBIFS attaches node headers to each data
713+
* node and it has to write indexind nodes as well. This introduces additional
714+
* overhead, and UBIFS it has to report sligtly less free space to meet the
715+
* above expectetion.
716+
*
717+
* This function assumes free space is made up of uncompressed data nodes and
718+
* full index nodes (one per data node, tripled because we always allow enough
719+
* space to write the index thrice).
720+
*
721+
* Note, the calculation is pessimistic, which means that most of the time
722+
* UBIFS reports less space than it actually has.
723+
*/
724+
long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free)
725+
{
726+
int divisor, factor, f;
727+
728+
/*
729+
* Reported space size is @free * X, where X is UBIFS block size
730+
* divided by UBIFS block size + all overhead one data block
731+
* introduces. The overhead is the node header + indexing overhead.
732+
*
733+
* Indexing overhead calculations are based on the following formula:
734+
* I = N/(f - 1) + 1, where I - number of indexing nodes, N - number
735+
* of data nodes, f - fanout. Because effective UBIFS fanout is twice
736+
* as less than maximum fanout, we assume that each data node
737+
* introduces 3 * @c->max_idx_node_sz / (@c->fanout/2 - 1) bytes.
738+
* Note, the multiplier 3 is because UBIFS reseves thrice as more space
739+
* for the index.
740+
*/
741+
f = c->fanout > 3 ? c->fanout >> 1 : 2;
742+
factor = UBIFS_BLOCK_SIZE;
743+
divisor = UBIFS_MAX_DATA_NODE_SZ;
744+
divisor += (c->max_idx_node_sz * 3) / (f - 1);
745+
free *= factor;
746+
do_div(free, divisor);
747+
return free;
748+
}
749+
750+
/**
751+
* ubifs_get_free_space - return amount of free space.
718752
* @c: UBIFS file-system description object
719753
*
720-
* This function returns amount of free space on the file-system.
754+
* This function calculates amount of free space to report to user-space.
755+
*
756+
* Because UBIFS may introduce substantial overhead (the index, node headers,
757+
* alighment, wastage at the end of eraseblocks, etc), it cannot report real
758+
* amount of free flash space it has (well, because not all dirty space is
759+
* reclamable, UBIFS does not actually know the real amount). If UBIFS did so,
760+
* it would bread user expectetion about what free space is. Users seem to
761+
* accustomed to assume that if the file-system reports N bytes of free space,
762+
* they would be able to fit a file of N bytes to the FS. This almost works for
763+
* traditional file-systems, because they have way less overhead than UBIFS.
764+
* So, to keep users happy, UBIFS tries to take the overhead into account.
721765
*/
722-
long long ubifs_budg_get_free_space(struct ubifs_info *c)
766+
long long ubifs_get_free_space(struct ubifs_info *c)
723767
{
724-
int min_idx_lebs, rsvd_idx_lebs;
768+
int min_idx_lebs, rsvd_idx_lebs, lebs;
725769
long long available, outstanding, free;
726770

727-
/* Do exactly the same calculations as in 'do_budget_space()' */
728771
spin_lock(&c->space_lock);
729772
min_idx_lebs = ubifs_calc_min_idx_lebs(c);
773+
outstanding = c->budg_data_growth + c->budg_dd_growth;
730774

731-
if (min_idx_lebs > c->lst.idx_lebs)
732-
rsvd_idx_lebs = min_idx_lebs - c->lst.idx_lebs;
733-
else
734-
rsvd_idx_lebs = 0;
735-
736-
if (rsvd_idx_lebs > c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt
737-
- c->lst.taken_empty_lebs) {
775+
/*
776+
* Force the amount available to the total size reported if the used
777+
* space is zero.
778+
*/
779+
if (c->lst.total_used <= UBIFS_INO_NODE_SZ && !outstanding) {
738780
spin_unlock(&c->space_lock);
739-
return 0;
781+
return (long long)c->block_cnt << UBIFS_BLOCK_SHIFT;
740782
}
741783

742784
available = ubifs_calc_available(c, min_idx_lebs);
743-
outstanding = c->budg_data_growth + c->budg_dd_growth;
744-
c->min_idx_lebs = min_idx_lebs;
785+
786+
/*
787+
* When reporting free space to user-space, UBIFS guarantees that it is
788+
* possible to write a file of free space size. This means that for
789+
* empty LEBs we may use more precise calculations than
790+
* 'ubifs_calc_available()' is using. Namely, we know that in empty
791+
* LEBs we would waste only @c->leb_overhead bytes, not @c->dark_wm.
792+
* Thus, amend the available space.
793+
*
794+
* Note, the calculations below are similar to what we have in
795+
* 'do_budget_space()', so refer there for comments.
796+
*/
797+
if (min_idx_lebs > c->lst.idx_lebs)
798+
rsvd_idx_lebs = min_idx_lebs - c->lst.idx_lebs;
799+
else
800+
rsvd_idx_lebs = 0;
801+
lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt -
802+
c->lst.taken_empty_lebs;
803+
lebs -= rsvd_idx_lebs;
804+
available += lebs * (c->dark_wm - c->leb_overhead);
745805
spin_unlock(&c->space_lock);
746806

747807
if (available > outstanding)

fs/ubifs/dir.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,6 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
587587
if (err) {
588588
if (err != -ENOSPC)
589589
return err;
590-
err = 0;
591590
budgeted = 0;
592591
}
593592

fs/ubifs/file.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,7 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode,
793793
int err;
794794
struct ubifs_budget_req req;
795795
loff_t old_size = inode->i_size, new_size = attr->ia_size;
796-
int offset = new_size & (UBIFS_BLOCK_SIZE - 1);
796+
int offset = new_size & (UBIFS_BLOCK_SIZE - 1), budgeted = 1;
797797
struct ubifs_inode *ui = ubifs_inode(inode);
798798

799799
dbg_gen("ino %lu, size %lld -> %lld", inode->i_ino, old_size, new_size);
@@ -811,8 +811,15 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode,
811811
/* A funny way to budget for truncation node */
812812
req.dirtied_ino_d = UBIFS_TRUN_NODE_SZ;
813813
err = ubifs_budget_space(c, &req);
814-
if (err)
815-
return err;
814+
if (err) {
815+
/*
816+
* Treat truncations to zero as deletion and always allow them,
817+
* just like we do for '->unlink()'.
818+
*/
819+
if (new_size || err != -ENOSPC)
820+
return err;
821+
budgeted = 0;
822+
}
816823

817824
err = vmtruncate(inode, new_size);
818825
if (err)
@@ -869,7 +876,12 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode,
869876
err = ubifs_jnl_truncate(c, inode, old_size, new_size);
870877
mutex_unlock(&ui->ui_mutex);
871878
out_budg:
872-
ubifs_release_budget(c, &req);
879+
if (budgeted)
880+
ubifs_release_budget(c, &req);
881+
else {
882+
c->nospace = c->nospace_rp = 0;
883+
smp_wmb();
884+
}
873885
return err;
874886
}
875887

fs/ubifs/find.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -211,14 +211,8 @@ static const struct ubifs_lprops *scan_for_dirty(struct ubifs_info *c,
211211
* dirty index heap, and it falls-back to LPT scanning if the heaps are empty
212212
* or do not have an LEB which satisfies the @min_space criteria.
213213
*
214-
* Note:
215-
* o LEBs which have less than dead watermark of dirty space are never picked
216-
* by this function;
217-
*
218-
* Returns zero and the LEB properties of
219-
* found dirty LEB in case of success, %-ENOSPC if no dirty LEB was found and a
220-
* negative error code in case of other failures. The returned LEB is marked as
221-
* "taken".
214+
* Note, LEBs which have less than dead watermark of free + dirty space are
215+
* never picked by this function.
222216
*
223217
* The additional @pick_free argument controls if this function has to return a
224218
* free or freeable LEB if one is present. For example, GC must to set it to %1,
@@ -231,6 +225,10 @@ static const struct ubifs_lprops *scan_for_dirty(struct ubifs_info *c,
231225
*
232226
* In addition @pick_free is set to %2 by the recovery process in order to
233227
* recover gc_lnum in which case an index LEB must not be returned.
228+
*
229+
* This function returns zero and the LEB properties of found dirty LEB in case
230+
* of success, %-ENOSPC if no dirty LEB was found and a negative error code in
231+
* case of other failures. The returned LEB is marked as "taken".
234232
*/
235233
int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp,
236234
int min_space, int pick_free)
@@ -245,7 +243,7 @@ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp,
245243
int lebs, rsvd_idx_lebs = 0;
246244

247245
spin_lock(&c->space_lock);
248-
lebs = c->lst.empty_lebs;
246+
lebs = c->lst.empty_lebs + c->idx_gc_cnt;
249247
lebs += c->freeable_cnt - c->lst.taken_empty_lebs;
250248

251249
/*
@@ -317,7 +315,7 @@ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp,
317315
lp = idx_lp;
318316

319317
if (lp) {
320-
ubifs_assert(lp->dirty >= c->dead_wm);
318+
ubifs_assert(lp->free + lp->dirty >= c->dead_wm);
321319
goto found;
322320
}
323321

fs/ubifs/gc.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,12 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp)
344344
if (err)
345345
goto out;
346346

347+
/* Allow for races with TNC */
348+
c->gced_lnum = lnum;
349+
smp_wmb();
350+
c->gc_seq += 1;
351+
smp_wmb();
352+
347353
if (c->gc_lnum == -1) {
348354
c->gc_lnum = lnum;
349355
err = LEB_RETAINED;

fs/ubifs/misc.h

Lines changed: 17 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -283,38 +283,6 @@ static inline void *ubifs_idx_key(const struct ubifs_info *c,
283283
return (void *)((struct ubifs_branch *)idx->branches)->key;
284284
}
285285

286-
/**
287-
* ubifs_reported_space - calculate reported free space.
288-
* @c: the UBIFS file-system description object
289-
* @free: amount of free space
290-
*
291-
* This function calculates amount of free space which will be reported to
292-
* user-space. User-space application tend to expect that if the file-system
293-
* (e.g., via the 'statfs()' call) reports that it has N bytes available, they
294-
* are able to write a file of size N. UBIFS attaches node headers to each data
295-
* node and it has to write indexind nodes as well. This introduces additional
296-
* overhead, and UBIFS it has to report sligtly less free space to meet the
297-
* above expectetion.
298-
*
299-
* This function assumes free space is made up of uncompressed data nodes and
300-
* full index nodes (one per data node, doubled because we always allow enough
301-
* space to write the index twice).
302-
*
303-
* Note, the calculation is pessimistic, which means that most of the time
304-
* UBIFS reports less space than it actually has.
305-
*/
306-
static inline long long ubifs_reported_space(const struct ubifs_info *c,
307-
uint64_t free)
308-
{
309-
int divisor, factor;
310-
311-
divisor = UBIFS_MAX_DATA_NODE_SZ + (c->max_idx_node_sz * 3);
312-
factor = UBIFS_MAX_DATA_NODE_SZ - UBIFS_DATA_NODE_SZ;
313-
do_div(free, divisor);
314-
315-
return free * factor;
316-
}
317-
318286
/**
319287
* ubifs_current_time - round current time to time granularity.
320288
* @inode: inode
@@ -325,4 +293,21 @@ static inline struct timespec ubifs_current_time(struct inode *inode)
325293
current_fs_time(inode->i_sb) : CURRENT_TIME_SEC;
326294
}
327295

296+
/**
297+
* ubifs_tnc_lookup - look up a file-system node.
298+
* @c: UBIFS file-system description object
299+
* @key: node key to lookup
300+
* @node: the node is returned here
301+
*
302+
* This function look up and reads node with key @key. The caller has to make
303+
* sure the @node buffer is large enough to fit the node. Returns zero in case
304+
* of success, %-ENOENT if the node was not found, and a negative error code in
305+
* case of failure.
306+
*/
307+
static inline int ubifs_tnc_lookup(struct ubifs_info *c,
308+
const union ubifs_key *key, void *node)
309+
{
310+
return ubifs_tnc_locate(c, key, node, NULL, NULL);
311+
}
312+
328313
#endif /* __UBIFS_MISC_H__ */

fs/ubifs/super.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -370,8 +370,9 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf)
370370
{
371371
struct ubifs_info *c = dentry->d_sb->s_fs_info;
372372
unsigned long long free;
373+
__le32 *uuid = (__le32 *)c->uuid;
373374

374-
free = ubifs_budg_get_free_space(c);
375+
free = ubifs_get_free_space(c);
375376
dbg_gen("free space %lld bytes (%lld blocks)",
376377
free, free >> UBIFS_BLOCK_SHIFT);
377378

@@ -386,7 +387,8 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf)
386387
buf->f_files = 0;
387388
buf->f_ffree = 0;
388389
buf->f_namelen = UBIFS_MAX_NLEN;
389-
390+
buf->f_fsid.val[0] = le32_to_cpu(uuid[0]) ^ le32_to_cpu(uuid[2]);
391+
buf->f_fsid.val[1] = le32_to_cpu(uuid[1]) ^ le32_to_cpu(uuid[3]);
390392
return 0;
391393
}
392394

@@ -530,6 +532,12 @@ static int init_constants_early(struct ubifs_info *c)
530532
c->dead_wm = ALIGN(MIN_WRITE_SZ, c->min_io_size);
531533
c->dark_wm = ALIGN(UBIFS_MAX_NODE_SZ, c->min_io_size);
532534

535+
/*
536+
* Calculate how many bytes would be wasted at the end of LEB if it was
537+
* fully filled with data nodes of maximum size. This is used in
538+
* calculations when reporting free space.
539+
*/
540+
c->leb_overhead = c->leb_size % UBIFS_MAX_DATA_NODE_SZ;
533541
return 0;
534542
}
535543

@@ -647,13 +655,11 @@ static int init_constants_late(struct ubifs_info *c)
647655
* internally because it does not make much sense for UBIFS, but it is
648656
* necessary to report something for the 'statfs()' call.
649657
*
650-
* Subtract the LEB reserved for GC and the LEB which is reserved for
651-
* deletions.
652-
*
653-
* Review 'ubifs_calc_available()' if changing this calculation.
658+
* Subtract the LEB reserved for GC, the LEB which is reserved for
659+
* deletions, and assume only one journal head is available.
654660
*/
655-
tmp64 = c->main_lebs - 2;
656-
tmp64 *= (uint64_t)c->leb_size - c->dark_wm;
661+
tmp64 = c->main_lebs - 2 - c->jhead_cnt + 1;
662+
tmp64 *= (uint64_t)c->leb_size - c->leb_overhead;
657663
tmp64 = ubifs_reported_space(c, tmp64);
658664
c->block_cnt = tmp64 >> UBIFS_BLOCK_SHIFT;
659665

0 commit comments

Comments
 (0)