1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
| void yaffs_update_dirty_dirs(struct yaffs_dev *dev) { ........ while (!list_empty(&dev->dirty_dirs)) { link = dev->dirty_dirs.next; list_del_init(link);
d_s = list_entry(link, struct yaffs_dir_var, dirty); o_v = list_entry(d_s, union yaffs_obj_var, dir_variant); obj = list_entry(o_v, struct yaffs_obj, variant); if (obj->dirty)
yaffs_update_oh(obj, NULL, 0, 0, 0, NULL); } } int yaffs_update_oh(struct yaffs_obj \*in, const YCHAR \*name, int force,int is_shrink, int shadows, struct yaffs_xattr_mod *xmod) { strcpy(old_name, _Y("silly old name"));
if (in->fake && in != dev->root_dir && !force && !xmod) return ret_val;
yaffs_check_gc(dev, 0); yaffs_check_obj_details_loaded(in); buffer = yaffs_get_temp_buffer(in->my_dev); oh = (struct yaffs_obj_hdr *)buffer; prev_chunk_id = in->hdr_chunk;
if (prev_chunk_id > 0) {
result = yaffs_rd_chunk_tags_nand(dev, prev_chunk_id,buffer, &old_tags); if (result == YAFFS_OK) {
yaffs_verify_oh(in, oh, &old_tags, 0); memcpy(old_name, oh->name, sizeof(oh->name)); memset(oh, 0xff, sizeof(*oh)); } } else { memset(buffer, 0xff, dev->data_bytes_per_chunk); }
oh->type = in->variant_type; oh->yst_mode = in->yst_mode; oh->shadows_obj = oh->inband_shadowed_obj_id = shadows;
yaffs_load_attribs_oh(oh, in);
if (in->parent) oh->parent_obj_id = in->parent->obj_id; else oh->parent_obj_id = 0;
if (name && *name) { memset(oh->name, 0, sizeof(oh->name)); yaffs_load_oh_from_name(dev, oh->name, name); } else if (prev_chunk_id > 0) { memcpy(oh->name, old_name, sizeof(oh->name)); } else { memset(oh->name, 0, sizeof(oh->name)); } oh->is_shrink = is_shrink; switch (in->variant_type) { case YAFFS_OBJECT_TYPE_UNKNOWN: break; case YAFFS_OBJECT_TYPE_FILE: if (oh->parent_obj_id != YAFFS_OBJECTID_DELETED && oh->parent_obj_id != YAFFS_OBJECTID_UNLINKED) file_size = in->variant.file_variant.stored_size; yaffs_oh_size_load(dev, oh, file_size, 0); break; case YAFFS_OBJECT_TYPE_HARDLINK: oh->equiv_id = in->variant.hardlink_variant.equiv_id; break; case YAFFS_OBJECT_TYPE_SPECIAL: /\* Do nothing */ break; case YAFFS_OBJECT_TYPE_DIRECTORY: /\* Do nothing */ break; case YAFFS_OBJECT_TYPE_SYMLINK: alias = in->variant.symlink_variant.alias; if (!alias) alias = _Y("no alias"); strncpy(oh->alias, alias, YAFFS_MAX_ALIAS_LENGTH); oh->alias[YAFFS_MAX_ALIAS_LENGTH] = 0; break; }
if (xmod) yaffs_apply_xattrib_mod(in, (char *)buffer, xmod); memset(&new_tags, 0, sizeof(new_tags)); in->serial++; new_tags.chunk_id = 0; new_tags.obj_id = in->obj_id; new_tags.serial_number = in->serial; new_tags.extra_available = 1; new_tags.extra_parent_id = oh->parent_obj_id; new_tags.extra_file_size = file_size; new_tags.extra_is_shrink = oh->is_shrink; new_tags.extra_equiv_id = oh->equiv_id; new_tags.extra_shadows = (oh->shadows_obj > 0) ? 1 : 0; new_tags.extra_obj_type = in->variant_type; yaffs_do_endian_oh(dev, oh);
yaffs_verify_oh(in, oh, &new_tags, 1); new_chunk_id = yaffs_write_new_chunk(dev, buffer, &new_tags,(prev_chunk_id > 0) ? 1 : 0);
if (buffer) yaffs_release_temp_buffer(dev, buffer);
if (new_chunk_id < 0) return new_chunk_id;
in->hdr_chunk = new_chunk_id;
if (prev_chunk_id > 0) yaffs_chunk_del(dev, prev_chunk_id, 1, __LINE__); if (!yaffs_obj_cache_dirty(in)) in->dirty = 0; if (is_shrink) { bi = yaffs_get_block_info(in->my_dev, new_chunk_id / in->my_dev->param.chunks_per_block); bi->has_shrink_hdr = 1; } return new_chunk_id; }
紧急程度计算方法见yaffs_bg_gc_urgency函数如下:
static unsigned yaffs_bg_gc_urgency(struct yaffs_dev *dev) { unsigned erased_chunks = dev->n_erased_blocks * dev->param.chunks_per_block; struct yaffs_linux_context *context = yaffs_dev_to_lc(dev); unsigned scattered = 0;
if (erased_chunks < dev->n_free_chunks) scattered = (dev->n_free_chunks - erased_chunks);
if (!context->bg_running) return 0;
else if (scattered < (dev->param.chunks_per_block * 2)) return 0;
else if (erased_chunks > dev->n_free_chunks / 2) return 0; else if (erased_chunks > dev->n_free_chunks / 4) return 1; else return 2; }
|