- /* Iterate through the objects in each hash entry,
- * looking at each object.
- * Make sure it is rooted.
- */
-
- for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
- ylist_for_each_safe(lh, n, &dev->obj_bucket[i].list) {
- if (lh) {
- obj = ylist_entry(lh, yaffs_obj_t, hash_link);
- parent= obj->parent;
-
- if(yaffs_has_null_parent(dev,obj)){
- /* These directories are not hanging */
- hanging = 0;
- }
- else if(!parent || parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY)
- hanging = 1;
- else if(yaffs_has_null_parent(dev,parent))
- hanging = 0;
- else {
- /*
- * Need to follow the parent chain to see if it is hanging.
- */
- hanging = 0;
- depth_limit=100;
-
- while(parent != dev->root_dir &&
- parent->parent &&
- parent->parent->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY &&
- depth_limit > 0){
- parent = parent->parent;
- depth_limit--;
- }
- if(parent != dev->root_dir)
- hanging = 1;
- }
- if(hanging){
- T(YAFFS_TRACE_SCAN,
- (TSTR("Hanging object %d moved to lost and found" TENDSTR),
- obj->obj_id));
- yaffs_add_obj_to_dir(dev->lost_n_found,obj);
- }
- }
- }
- }
-}
-
-
-/*
- * Delete directory contents for cleaning up lost and found.
- */
-static void yaffs_del_dir_contents(yaffs_obj_t *dir)
-{
- yaffs_obj_t *obj;
- struct ylist_head *lh;
- struct ylist_head *n;
-
- if(dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY)
- YBUG();
-
- ylist_for_each_safe(lh, n, &dir->variant.dir_variant.children) {
- if (lh) {
- obj = ylist_entry(lh, yaffs_obj_t, siblings);
- if(obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY)
- yaffs_del_dir_contents(obj);
-
- T(YAFFS_TRACE_SCAN,
- (TSTR("Deleting lost_found object %d" TENDSTR),
- obj->obj_id));
-
- /* Need to use UnlinkObject since Delete would not handle
- * hardlinked objects correctly.
- */
- yaffs_unlink_obj(obj);
- }
- }
-
-}
-
-static void yaffs_empty_l_n_f(yaffs_dev_t *dev)
-{
- yaffs_del_dir_contents(dev->lost_n_found);
-}
-
-static void yaffs_check_obj_details_loaded(yaffs_obj_t *in)
-{
- __u8 *chunk_data;
- yaffs_obj_header *oh;
- yaffs_dev_t *dev;
- yaffs_ext_tags tags;
- int result;
- int alloc_failed = 0;
-
- if (!in)
- return;
-
- dev = in->my_dev;
-
-#if 0
- T(YAFFS_TRACE_SCAN, (TSTR("details for object %d %s loaded" TENDSTR),
- in->obj_id,
- in->lazy_loaded ? "not yet" : "already"));
-#endif
-
- if (in->lazy_loaded && in->hdr_chunk > 0) {
- in->lazy_loaded = 0;
- chunk_data = yaffs_get_temp_buffer(dev, __LINE__);
-
- result = yaffs_rd_chunk_tags_nand(dev, in->hdr_chunk, chunk_data, &tags);
- oh = (yaffs_obj_header *) chunk_data;
-
- in->yst_mode = oh->yst_mode;
-#ifdef CONFIG_YAFFS_WINCE
- in->win_atime[0] = oh->win_atime[0];
- in->win_ctime[0] = oh->win_ctime[0];
- in->win_mtime[0] = oh->win_mtime[0];
- in->win_atime[1] = oh->win_atime[1];
- in->win_ctime[1] = oh->win_ctime[1];
- in->win_mtime[1] = oh->win_mtime[1];
-#else
- in->yst_uid = oh->yst_uid;
- in->yst_gid = oh->yst_gid;
- in->yst_atime = oh->yst_atime;
- in->yst_mtime = oh->yst_mtime;
- in->yst_ctime = oh->yst_ctime;
- in->yst_rdev = oh->yst_rdev;
-
-#endif
- yaffs_set_obj_name_from_oh(in, oh);
-
- if (in->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) {
- in->variant.symlink_variant.alias =
- yaffs_clone_str(oh->alias);
- if (!in->variant.symlink_variant.alias)
- alloc_failed = 1; /* Not returned to caller */
- }
-
- yaffs_release_temp_buffer(dev, chunk_data, __LINE__);
- }
-}
-
-/*------------------------------ Directory Functions ----------------------------- */
-
-/*
- *yaffs_update_parent() handles fixing a directories mtime and ctime when a new
- * link (ie. name) is created or deleted in the directory.
- *
- * ie.
- * create dir/a : update dir's mtime/ctime
- * rm dir/a: update dir's mtime/ctime
- * modify dir/a: don't update dir's mtimme/ctime
- *
- * This can be handled immediately or defered. Defering helps reduce the number
- * of updates when many files in a directory are changed within a brief period.
- *
- * If the directory updating is defered then yaffs_update_dirty_dirs must be
- * called periodically.
- */
-
-static void yaffs_update_parent(yaffs_obj_t *obj)
-{
- yaffs_dev_t *dev;
- if(!obj)
- return;
-#ifndef CONFIG_YAFFS_WINCE
-
- dev = obj->my_dev;
- obj->dirty = 1;
- obj->yst_mtime = obj->yst_ctime = Y_CURRENT_TIME;
- if(dev->param.defered_dir_update){
- struct ylist_head *link = &obj->variant.dir_variant.dirty;
-
- if(ylist_empty(link)){
- ylist_add(link,&dev->dirty_dirs);
- T(YAFFS_TRACE_BACKGROUND, (TSTR("Added object %d to dirty directories" TENDSTR),obj->obj_id));
- }
-
- } else
- yaffs_update_oh(obj, NULL, 0, 0, 0, NULL);
-#endif
-}
-
-void yaffs_update_dirty_dirs(yaffs_dev_t *dev)
-{
- struct ylist_head *link;
- yaffs_obj_t *obj;
- yaffs_dir_s *d_s;
- yaffs_obj_variant *o_v;
-
- T(YAFFS_TRACE_BACKGROUND, (TSTR("Update dirty directories" TENDSTR)));
-
- while(!ylist_empty(&dev->dirty_dirs)){
- link = dev->dirty_dirs.next;
- ylist_del_init(link);
-
- d_s=ylist_entry(link,yaffs_dir_s,dirty);
- o_v = ylist_entry(d_s,yaffs_obj_variant,dir_variant);
- obj = ylist_entry(o_v,yaffs_obj_t,variant);
-
- T(YAFFS_TRACE_BACKGROUND, (TSTR("Update directory %d" TENDSTR), obj->obj_id));
-
- if(obj->dirty)
- yaffs_update_oh(obj, NULL, 0, 0, 0, NULL);
- }
-}
-
-static void yaffs_remove_obj_from_dir(yaffs_obj_t *obj)
-{
- yaffs_dev_t *dev = obj->my_dev;
- yaffs_obj_t *parent;
-
- yaffs_verify_obj_in_dir(obj);
- parent = obj->parent;
-
- yaffs_verify_dir(parent);
-
- if (dev && dev->param.remove_obj_fn)
- dev->param.remove_obj_fn(obj);
-
-
- ylist_del_init(&obj->siblings);
- obj->parent = NULL;
-
- yaffs_verify_dir(parent);
-}
-
-void yaffs_add_obj_to_dir(yaffs_obj_t *directory,
- yaffs_obj_t *obj)
-{
- if (!directory) {
- T(YAFFS_TRACE_ALWAYS,
- (TSTR
- ("tragedy: Trying to add an object to a null pointer directory"
- TENDSTR)));
- YBUG();
- return;
- }
- if (directory->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
- T(YAFFS_TRACE_ALWAYS,
- (TSTR
- ("tragedy: Trying to add an object to a non-directory"
- TENDSTR)));
- YBUG();
- }
-
- if (obj->siblings.prev == NULL) {
- /* Not initialised */
- YBUG();
- }
-
-
- yaffs_verify_dir(directory);