/** *structscan_data-dataprovidedtoscancallbackfunctions *@min_space:minimumnumberofbytesforwhichtoscan *@pick_free:whetheritisOKtoscanforemptyLEBs *@lnum:LEBnumberfoundisreturnedhere *@exclude_index:whethertoexcludeindexLEBs
*/ struct scan_data { int min_space; int pick_free; int lnum; int exclude_index;
};
/* Exclude LEBs that are currently in use */ if (lprops->flags & LPROPS_TAKEN) return LPT_SCAN_CONTINUE; /* Determine whether to add these LEB properties to the tree */ if (!in_tree && valuable(c, lprops))
ret |= LPT_SCAN_ADD; /* Exclude LEBs with too little space */ if (lprops->free + lprops->dirty < data->min_space) return ret; /* If specified, exclude index LEBs */ if (data->exclude_index && lprops->flags & LPROPS_INDEX) return ret; /* If specified, exclude empty or freeable LEBs */ if (lprops->free + lprops->dirty == c->leb_size) { if (!data->pick_free) return ret; /* Exclude LEBs with too little dirty space (unless it is empty) */
} elseif (lprops->dirty < c->dead_wm) return ret; /* Finally we found space */
data->lnum = lprops->lnum; return LPT_SCAN_ADD | LPT_SCAN_STOP;
}
/** *scan_for_dirty-findadataLEBwithfreespace. *@c:theUBIFSfile-systemdescriptionobject *@min_space:minimumamountfreeplusdirtyspacethereturnedLEBhasto *have *@pick_free:ifitisOKtoreturnafreeorfreeableLEB *@exclude_index:whethertoexcludeindexLEBs * *ThisfunctionreturnsapointertotheLEBpropertiesfoundoranegative *errorcode.
*/ staticconststruct ubifs_lprops *scan_for_dirty(struct ubifs_info *c, int min_space, int pick_free, int exclude_index)
{ conststruct ubifs_lprops *lprops; struct ubifs_lpt_heap *heap; struct scan_data data; int err, i;
/* There may be an LEB with enough dirty space on the free heap */
heap = &c->lpt_heap[LPROPS_FREE - 1]; for (i = 0; i < heap->cnt; i++) {
lprops = heap->arr[i]; if (lprops->free + lprops->dirty < min_space) continue; if (lprops->dirty < c->dead_wm) continue; return lprops;
} /* *ALEBmayhavefallenoffofthebottomofthedirtyheap,andended *upasuncategorizedeventhoughithasenoughdirtyspaceforusnow, *sochecktheuncategorizedlist.N.B.neitheremptynorfreeableLEBs *canendupasuncategorizedbecausetheyarekeptonlistsnot *finite-sizedheaps.
*/
list_for_each_entry(lprops, &c->uncat_list, list) { if (lprops->flags & LPROPS_TAKEN) continue; if (lprops->free + lprops->dirty < min_space) continue; if (exclude_index && (lprops->flags & LPROPS_INDEX)) continue; if (lprops->dirty < c->dead_wm) continue; return lprops;
} /* We have looked everywhere in main memory, now scan the flash */ if (c->pnodes_have >= c->pnode_cnt) /* All pnodes are in memory, so skip scan */ return ERR_PTR(-ENOSPC);
data.min_space = min_space;
data.pick_free = pick_free;
data.lnum = -1;
data.exclude_index = exclude_index;
err = ubifs_lpt_scan_nolock(c, -1, c->lscan_lnum, scan_for_dirty_cb,
&data); if (err) return ERR_PTR(err);
ubifs_assert(c, data.lnum >= c->main_first && data.lnum < c->leb_cnt);
c->lscan_lnum = data.lnum;
lprops = ubifs_lpt_lookup_dirty(c, data.lnum); if (IS_ERR(lprops)) return lprops;
ubifs_assert(c, lprops->lnum == data.lnum);
ubifs_assert(c, lprops->free + lprops->dirty >= min_space);
ubifs_assert(c, lprops->dirty >= c->dead_wm ||
(pick_free &&
lprops->free + lprops->dirty == c->leb_size));
ubifs_assert(c, !(lprops->flags & LPROPS_TAKEN));
ubifs_assert(c, !exclude_index || !(lprops->flags & LPROPS_INDEX)); return lprops;
}
/* Check if there are enough free LEBs for the index */ if (rsvd_idx_lebs < lebs) { /* OK, try to find an empty LEB */
lp = ubifs_fast_find_empty(c); if (lp) goto found;
/* Did not find a dirty LEB on the dirty heaps, have to scan */
dbg_find("scanning LPT for a dirty LEB");
lp = scan_for_dirty(c, min_space, pick_free, exclude_index); if (IS_ERR(lp)) {
err = PTR_ERR(lp); goto out;
}
ubifs_assert(c, lp->dirty >= c->dead_wm ||
(pick_free && lp->free + lp->dirty == c->leb_size));
/* Exclude LEBs that are currently in use */ if (lprops->flags & LPROPS_TAKEN) return LPT_SCAN_CONTINUE; /* Determine whether to add these LEB properties to the tree */ if (!in_tree && valuable(c, lprops))
ret |= LPT_SCAN_ADD; /* Exclude index LEBs */ if (lprops->flags & LPROPS_INDEX) return ret; /* Exclude LEBs with too little space */ if (lprops->free < data->min_space) return ret; /* If specified, exclude empty LEBs */ if (!data->pick_free && lprops->free == c->leb_size) return ret; /* *LEBsthathaveonlyfreeanddirtyspacemustnotbeallocated *becausetheymayhavebeenunmappedalreadyortheymayhavedata *thatisobsoleteonlybecauseofnodesthatarestillsittingina *wbuf.
*/ if (lprops->free + lprops->dirty == c->leb_size && lprops->dirty > 0) return ret; /* Finally we found space */
data->lnum = lprops->lnum; return LPT_SCAN_ADD | LPT_SCAN_STOP;
}
/** *do_find_free_space-findadataLEBwithfreespace. *@c:theUBIFSfile-systemdescriptionobject *@min_space:minimumamountoffreespacerequired *@pick_free:whetheritisOKtoscanforemptyLEBs *@squeeze:whethertotrytofindspaceinanon-emptyLEBfirst * *ThisfunctionreturnsapointertotheLEBpropertiesfoundoranegative *errorcode.
*/ static conststruct ubifs_lprops *do_find_free_space(struct ubifs_info *c, int min_space, int pick_free, int squeeze)
{ conststruct ubifs_lprops *lprops; struct ubifs_lpt_heap *heap; struct scan_data data; int err, i;
if (squeeze) {
lprops = ubifs_fast_find_free(c); if (lprops && lprops->free >= min_space) return lprops;
} if (pick_free) {
lprops = ubifs_fast_find_empty(c); if (lprops) return lprops;
} if (!squeeze) {
lprops = ubifs_fast_find_free(c); if (lprops && lprops->free >= min_space) return lprops;
} /* There may be an LEB with enough free space on the dirty heap */
heap = &c->lpt_heap[LPROPS_DIRTY - 1]; for (i = 0; i < heap->cnt; i++) {
lprops = heap->arr[i]; if (lprops->free >= min_space) return lprops;
} /* *ALEBmayhavefallenoffofthebottomofthefreeheap,andended *upasuncategorizedeventhoughithasenoughfreespaceforusnow, *sochecktheuncategorizedlist.N.B.neitheremptynorfreeableLEBs *canendupasuncategorizedbecausetheyarekeptonlistsnot *finite-sizedheaps.
*/
list_for_each_entry(lprops, &c->uncat_list, list) { if (lprops->flags & LPROPS_TAKEN) continue; if (lprops->flags & LPROPS_INDEX) continue; if (lprops->free >= min_space) return lprops;
} /* We have looked everywhere in main memory, now scan the flash */ if (c->pnodes_have >= c->pnode_cnt) /* All pnodes are in memory, so skip scan */ return ERR_PTR(-ENOSPC);
data.min_space = min_space;
data.pick_free = pick_free;
data.lnum = -1;
err = ubifs_lpt_scan_nolock(c, -1, c->lscan_lnum,
scan_for_free_cb,
&data); if (err) return ERR_PTR(err);
ubifs_assert(c, data.lnum >= c->main_first && data.lnum < c->leb_cnt);
c->lscan_lnum = data.lnum;
lprops = ubifs_lpt_lookup_dirty(c, data.lnum); if (IS_ERR(lprops)) return lprops;
ubifs_assert(c, lprops->lnum == data.lnum);
ubifs_assert(c, lprops->free >= min_space);
ubifs_assert(c, !(lprops->flags & LPROPS_TAKEN));
ubifs_assert(c, !(lprops->flags & LPROPS_INDEX)); return lprops;
}
/** *ubifs_find_free_space-findadataLEBwithfreespace. *@c:theUBIFSfile-systemdescriptionobject *@min_space:minimumamountofrequiredfreespace *@offs:containsoffsetofwherefreespacestartsonexit *@squeeze:whethertotrytofindspaceinanon-emptyLEBfirst * *ThisfunctionlooksforanLEBwithatleast@min_spacebytesoffreespace. *IttriestofindanemptyLEBifpossible.IfnoemptyLEBsareavailable, *thisfunctionsearchesforanon-emptydataLEB.ThereturnedLEBismarked *as"taken". * *ThisfunctionreturnsfoundLEBnumberincaseofsuccess,%-ENOSPCifit *failedtofindaLEBwith@min_spacebytesoffreespaceandotheranegative *errorcodesincaseoffailure.
*/ int ubifs_find_free_space(struct ubifs_info *c, int min_space, int *offs, int squeeze)
{ conststruct ubifs_lprops *lprops; int lebs, rsvd_idx_lebs, pick_free = 0, err, lnum, flags;
/* Exclude LEBs that are currently in use */ if (lprops->flags & LPROPS_TAKEN) return LPT_SCAN_CONTINUE; /* Determine whether to add these LEB properties to the tree */ if (!in_tree && valuable(c, lprops))
ret |= LPT_SCAN_ADD; /* Exclude index LEBS */ if (lprops->flags & LPROPS_INDEX) return ret; /* Exclude LEBs that cannot be made empty */ if (lprops->free + lprops->dirty != c->leb_size) return ret; /* *WeareallocatingfortheindexsoitissafetoallocateLEBswith *onlyfreeanddirtyspace,becausewritebuffersaresync'datcommit *start.
*/
data->lnum = lprops->lnum; return LPT_SCAN_ADD | LPT_SCAN_STOP;
}
/** *ubifs_save_dirty_idx_lnums-saveanarrayofthemostdirtyindexLEBnos. *@c:theUBIFSfile-systemdescriptionobject * *ThisfunctioniscalledeachcommittocreateanarrayofLEBnumbersof *dirtyindexLEBssortedinorderofdirtyandfreespace.Thisisusedby *thein-the-gapsmethodofTNCcommit.
*/ int ubifs_save_dirty_idx_lnums(struct ubifs_info *c)
{ int i;
ubifs_get_lprops(c); /* Copy the LPROPS_DIRTY_IDX heap */
c->dirty_idx.cnt = c->lpt_heap[LPROPS_DIRTY_IDX - 1].cnt;
memcpy(c->dirty_idx.arr, c->lpt_heap[LPROPS_DIRTY_IDX - 1].arr, sizeof(void *) * c->dirty_idx.cnt); /* Sort it so that the dirtiest is now at the end */
sort(c->dirty_idx.arr, c->dirty_idx.cnt, sizeof(void *),
cmp_dirty_idx, NULL);
dbg_find("found %d dirty index LEBs", c->dirty_idx.cnt); if (c->dirty_idx.cnt)
dbg_find("dirtiest index LEB is %d with dirty %d and free %d",
c->dirty_idx.arr[c->dirty_idx.cnt - 1]->lnum,
c->dirty_idx.arr[c->dirty_idx.cnt - 1]->dirty,
c->dirty_idx.arr[c->dirty_idx.cnt - 1]->free); /* Replace the lprops pointers with LEB numbers */ for (i = 0; i < c->dirty_idx.cnt; i++)
c->dirty_idx.arr[i] = (void *)(size_t)c->dirty_idx.arr[i]->lnum;
ubifs_release_lprops(c); return0;
}
/* Exclude LEBs that are currently in use */ if (lprops->flags & LPROPS_TAKEN) return LPT_SCAN_CONTINUE; /* Determine whether to add these LEB properties to the tree */ if (!in_tree && valuable(c, lprops))
ret |= LPT_SCAN_ADD; /* Exclude non-index LEBs */ if (!(lprops->flags & LPROPS_INDEX)) return ret; /* Exclude LEBs with too little space */ if (lprops->free + lprops->dirty < c->min_idx_node_sz) return ret; /* Finally we found space */
data->lnum = lprops->lnum; return LPT_SCAN_ADD | LPT_SCAN_STOP;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.