Ejemplo n.º 1
0
/* look for uncompleted unlinks and truncates and complete them */
static void finish_unfinished (struct super_block * s)
{
    INITIALIZE_PATH (path);
    struct cpu_key max_cpu_key, obj_key;
    struct key save_link_key;
    int retval;
    struct item_head * ih;
    struct buffer_head * bh;
    int item_pos;
    char * item;
    int done;
    struct inode * inode;
    int truncate;
 
 
    /* compose key to look for "save" links */
    max_cpu_key.version = KEY_FORMAT_3_5;
    max_cpu_key.on_disk_key = MAX_KEY;
    max_cpu_key.key_length = 3;
 
    done = 0;
    s -> u.reiserfs_sb.s_is_unlinked_ok = 1;
    while (1) {
        retval = search_item (s, &max_cpu_key, &path);
        if (retval != ITEM_NOT_FOUND) {
            reiserfs_warning ("vs-2140: finish_unfinished: search_by_key returned %d\n",
                              retval);
            break;
        }
        
        bh = get_last_bh (&path);
        item_pos = get_item_pos (&path);
        if (item_pos != B_NR_ITEMS (bh)) {
            reiserfs_warning ("vs-2060: finish_unfinished: wrong position found\n");
            break;
        }
        item_pos --;
        ih = B_N_PITEM_HEAD (bh, item_pos);
 
        if (le32_to_cpu (ih->ih_key.k_dir_id) != MAX_KEY_OBJECTID)
            /* there are no "save" links anymore */
            break;
 
        save_link_key = ih->ih_key;
        if (is_indirect_le_ih (ih))
            truncate = 1;
        else
            truncate = 0;
 
        /* reiserfs_iget needs k_dirid and k_objectid only */
        item = B_I_PITEM (bh, ih);
        obj_key.on_disk_key.k_dir_id = le32_to_cpu (*(__u32 *)item);
        obj_key.on_disk_key.k_objectid = le32_to_cpu (ih->ih_key.k_objectid);
	obj_key.on_disk_key.u.k_offset_v1.k_offset = 0;
	obj_key.on_disk_key.u.k_offset_v1.k_uniqueness = 0;
	
        pathrelse (&path);
 
        inode = reiserfs_iget (s, &obj_key);
        if (!inode) {
            /* the unlink almost completed, it just did not manage to remove
	       "save" link and release objectid */
            reiserfs_warning ("vs-2180: finish_unfinished: iget failed for %K\n",
                              &obj_key);
            remove_save_link_only (s, &save_link_key, 1);
            continue;
        }

	if (!truncate && inode->i_nlink) {
	    /* file is not unlinked */
            reiserfs_warning ("vs-2185: finish_unfinished: file %K is not unlinked\n",
                              &obj_key);
            remove_save_link_only (s, &save_link_key, 0);
            continue;
	}

	if (truncate && S_ISDIR (inode->i_mode) ) {
	    /* We got a truncate request for a dir which is impossible.
	       The only imaginable way is to execute unfinished truncate request
	       then boot into old kernel, remove the file and create dir with
	       the same key. */
	    reiserfs_warning("green-2101: impossible truncate on a directory %k. Please report\n", INODE_PKEY (inode));
	    remove_save_link_only (s, &save_link_key, 0);
	    truncate = 0;
	    iput (inode); 
	    continue;
	}
 
        if (truncate) {
            inode -> u.reiserfs_i.i_flags |= i_link_saved_truncate_mask;
            /* not completed truncate found. New size was committed together
	       with "save" link */
            reiserfs_warning ("Truncating %k to %Ld ..",
                              INODE_PKEY (inode), inode->i_size);
            reiserfs_truncate_file (inode, 0/*don't update modification time*/);
            remove_save_link (inode, truncate);
        } else {
            inode -> u.reiserfs_i.i_flags |= i_link_saved_unlink_mask;
            /* not completed unlink (rmdir) found */
            reiserfs_warning ("Removing %k..", INODE_PKEY (inode));
            /* removal gets completed in iput */
        }
 
        iput (inode);
        printk ("done\n");
        done ++;
    }
    s -> u.reiserfs_sb.s_is_unlinked_ok = 0;
     
    pathrelse (&path);
    if (done)
        reiserfs_warning ("There were %d uncompleted unlinks/truncates. "
                          "Completed\n", done);
}
Ejemplo n.º 2
0
/* NOTE: this only should be used to look for keys who exists */
int _search_by_entry_key (reiserfs_filsys_t fs, struct key * key, 
			  struct path * path)
{
    struct buffer_head * bh;
    int item_pos;
    struct item_head * ih;
    struct key tmpkey;

    if (_search_by_key (fs, key, path) == ITEM_FOUND) {
        path->pos_in_item = 0;
        return POSITION_FOUND;
    }

    bh = get_bh (path);
    item_pos = get_item_pos (path);
    ih = get_ih (path);

    if (item_pos == 0) {
	/* key is less than the smallest key in the tree */
	if (not_of_one_file (&(ih->ih_key), key))
	    /* there are no items of that directory */
	    return DIRECTORY_NOT_FOUND;

	if (!is_direntry_ih (ih))
	    reiserfs_panic ("_search_by_entry_key: found item is not of directory type %H",
			    ih);

	/* key we looked for should be here */
        path->pos_in_item = 0;
	return POSITION_NOT_FOUND;
    }

    /* take previous item */
    item_pos --;
    ih --;
    PATH_LAST_POSITION (path) --;

    if (not_of_one_file (&(ih->ih_key), key) || !is_direntry_ih (ih)) {
        /* previous item belongs to another object or is stat data, check next
           item */

	item_pos ++;
	PATH_LAST_POSITION (path) ++;

        if (item_pos < B_NR_ITEMS (bh)) {
	    /* next item is in the same node */
	    ih ++;
            if (not_of_one_file (&(ih->ih_key), key)) {
		/* there are no items of that directory */
                path->pos_in_item = 0;
                return DIRECTORY_NOT_FOUND;
            }

            if (!is_direntry_ih (ih))
		reiserfs_panic ("_search_by_entry_key: %k is not a directory",
				key);
        } else {
	    /* next item is in right neighboring node */
            struct key * next_key = _get_rkey (path);

            if (next_key == 0 || not_of_one_file (next_key, key)) {
                /* there are no items of that directory */
                path->pos_in_item = 0;
                return DIRECTORY_NOT_FOUND;
            }

            if (!is_direntry_key (next_key))
		reiserfs_panic ("_search_by_entry_key: %k is not a directory",
				key);

            /* we got right delimiting key - search for it - the entry will be
	       pasted in position 0 */
            copy_key (&tmpkey, next_key);
            pathrelse (path);
            if (_search_by_key (fs, &tmpkey, path) != ITEM_FOUND || PATH_LAST_POSITION (path) != 0)
                reiserfs_panic ("_search_by_entry_key: item corresponding to delimiting key %k not found",
				&tmpkey);
        }

        /* next item is the part of this directory */
        path->pos_in_item = 0;
        return POSITION_NOT_FOUND;
    }


    /* previous item is part of desired directory */
    if (_bin_search (&(key->u.k_offset_v1.k_offset), B_I_DEH (bh, ih), ih_entry_count (ih),
		     DEH_SIZE, &(path->pos_in_item), comp_dir_entries) == ITEM_FOUND)
	return POSITION_FOUND;

    return POSITION_NOT_FOUND;
}