/* returns 1 if it finds an indirect item and gets valid hint info * from it, otherwise 0 */ static int get_left_neighbor(reiserfs_blocknr_hint_t *hint) { struct path * path; struct buffer_head * bh; struct item_head * ih; int pos_in_item; __u32 * item; int ret = 0; if (!hint->path) /* reiserfs code can call this function w/o pointer to path * structure supplied; then we rely on supplied search_start */ return 0; path = hint->path; bh = get_last_bh(path); RFALSE( !bh, "green-4002: Illegal path specified to get_left_neighbor"); ih = get_ih(path); pos_in_item = path->pos_in_item; item = get_item (path); hint->search_start = bh->b_blocknr; if (!hint->formatted_node && is_indirect_le_ih (ih)) { /* for indirect item: go to left and look for the first non-hole entry in the indirect item */ if (pos_in_item == I_UNFM_NUM (ih)) pos_in_item--; // pos_in_item = I_UNFM_NUM (ih) - 1; while (pos_in_item >= 0) { int t=get_block_num(item,pos_in_item); if (t) { hint->search_start = t; ret = 1; break; } pos_in_item --; } } /* does result value fit into specified region? */ return ret; }
/* The function is NOT SCHEDULE-SAFE! */ int search_for_position_by_key(struct reiserfs_sb_info *p_s_sbi, const struct cpu_key *p_cpu_key, /* Key to search (cpu variable) */ struct path *p_s_search_path) /* Filled up by this function. */ { int retval, n_blk_size; off_t item_offset, offset; struct item_head *p_le_ih; /* Pointer to on-disk structure */ struct reiserfs_dir_entry de; /* If searching for directory entry. */ if (is_direntry_cpu_key(p_cpu_key)) return (search_by_entry_key(p_s_sbi, p_cpu_key, p_s_search_path, &de)); /* If not searching for directory entry. */ /* If item is found. */ retval = search_item(p_s_sbi, p_cpu_key, p_s_search_path); if (retval == IO_ERROR) return (retval); if (retval == ITEM_FOUND) { if (ih_item_len(B_N_PITEM_HEAD( PATH_PLAST_BUFFER(p_s_search_path), PATH_LAST_POSITION(p_s_search_path))) == 0) { reiserfs_log(LOG_WARNING, "item length equals zero\n"); } pos_in_item(p_s_search_path) = 0; return (POSITION_FOUND); } if (PATH_LAST_POSITION(p_s_search_path) == 0) { reiserfs_log(LOG_WARNING, "position equals zero\n"); } /* Item is not found. Set path to the previous item. */ p_le_ih = B_N_PITEM_HEAD(PATH_PLAST_BUFFER(p_s_search_path), --PATH_LAST_POSITION(p_s_search_path)); n_blk_size = p_s_sbi->s_blocksize; if (comp_short_keys(&(p_le_ih->ih_key), p_cpu_key)) { return (FILE_NOT_FOUND); } item_offset = le_ih_k_offset(p_le_ih); offset = cpu_key_k_offset(p_cpu_key); /* Needed byte is contained in the item pointed to by the path.*/ if (item_offset <= offset && item_offset + op_bytes_number(p_le_ih, n_blk_size) > offset) { pos_in_item(p_s_search_path) = offset - item_offset; if (is_indirect_le_ih(p_le_ih)) { pos_in_item(p_s_search_path) /= n_blk_size; } return (POSITION_FOUND); } /* Needed byte is not contained in the item pointed to by the * path. Set pos_in_item out of the item. */ if (is_indirect_le_ih(p_le_ih)) pos_in_item(p_s_search_path) = ih_item_len(p_le_ih) / UNFM_P_SIZE; else pos_in_item(p_s_search_path) = ih_item_len(p_le_ih); return (POSITION_NOT_FOUND); }
/* 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); }