/* add new name into a directory. If it exists in a directory - do nothing */ int reiserfs_add_entry (reiserfs_filsys_t fs, struct key * dir, char * name, struct key * key, int fsck_need) { struct item_head entry_ih = {{0,}, }; char * entry; int retval; INITIALIZE_PATH(path); int gen_counter; int item_len; __u32 hash; if (reiserfs_find_entry (fs, dir, name, &gen_counter)) return 0; /* compose entry key to look for its place in the tree */ entry_ih.ih_key.k_dir_id = cpu_to_le32 (dir->k_dir_id); entry_ih.ih_key.k_objectid = cpu_to_le32 (dir->k_objectid); hash = hash_value (fs, name) + gen_counter; if (!strcmp (name, ".")) hash = DOT_OFFSET; if (!strcmp (name, "..")) hash = DOT_DOT_OFFSET; set_type_and_offset (KEY_FORMAT_1, &(entry_ih.ih_key), hash, TYPE_DIRENTRY); set_ih_key_format (&entry_ih, KEY_FORMAT_1); set_entry_count (&entry_ih, 1); if (SB_VERSION (fs) == REISERFS_VERSION_2) item_len = DEH_SIZE + ROUND_UP (strlen (name)); else item_len = DEH_SIZE + strlen (name); set_ih_item_len (&entry_ih, item_len); /* fsck may need to insert item which was not reached yet */ set_ih_fsck_need( &entry_ih, fsck_need ); entry = make_entry (0, name, key, get_offset (&(entry_ih.ih_key))); retval = _search_by_entry_key (fs, &(entry_ih.ih_key), &path); switch (retval) { case POSITION_NOT_FOUND: reiserfs_paste_into_item (fs, &path, entry, item_len); break; case DIRECTORY_NOT_FOUND: set_deh_location( (struct reiserfs_de_head *)entry, DEH_SIZE ); reiserfs_insert_item (fs, &path, &entry_ih, entry); break; default: reiserfs_panic ("reiserfs_add_entry: looking for %k (inserting name \"%s\") " "search_by_entry_key returned %d", &(entry_ih.ih_key), name, retval); } freemem (entry); return item_len; }
static int reiserfs_add_entry(struct reiserfs_transaction_handle *th, struct inode *dir, const char *name, int namelen, struct inode *inode, int visible) { struct cpu_key entry_key; struct reiserfs_de_head *deh; INITIALIZE_PATH(path); struct reiserfs_dir_entry de; DECLARE_BITMAP(bit_string, MAX_GENERATION_NUMBER + 1); int gen_number; char small_buf[32 + DEH_SIZE]; /* 48 bytes now and we avoid kmalloc if we create file with short name */ char *buffer; int buflen, paste_size; int retval; BUG_ON(!th->t_trans_id); /* cannot allow items to be added into a busy deleted directory */ if (!namelen) return -EINVAL; if (namelen > REISERFS_MAX_NAME(dir->i_sb->s_blocksize)) return -ENAMETOOLONG; /* each entry has unique key. compose it */ make_cpu_key(&entry_key, dir, get_third_component(dir->i_sb, name, namelen), TYPE_DIRENTRY, 3); /* get memory for composing the entry */ buflen = DEH_SIZE + ROUND_UP(namelen); if (buflen > sizeof(small_buf)) { buffer = kmalloc(buflen, GFP_NOFS); if (!buffer) return -ENOMEM; } else buffer = small_buf; paste_size = (get_inode_sd_version(dir) == STAT_DATA_V1) ? (DEH_SIZE + namelen) : buflen; /* fill buffer : directory entry head, name[, dir objectid | , stat data | ,stat data, dir objectid ] */ deh = (struct reiserfs_de_head *)buffer; deh->deh_location = 0; /* JDM Endian safe if 0 */ put_deh_offset(deh, cpu_key_k_offset(&entry_key)); deh->deh_state = 0; /* JDM Endian safe if 0 */ /* put key (ino analog) to de */ deh->deh_dir_id = INODE_PKEY(inode)->k_dir_id; /* safe: k_dir_id is le */ deh->deh_objectid = INODE_PKEY(inode)->k_objectid; /* safe: k_objectid is le */ /* copy name */ memcpy((char *)(deh + 1), name, namelen); /* padd by 0s to the 4 byte boundary */ padd_item((char *)(deh + 1), ROUND_UP(namelen), namelen); /* entry is ready to be pasted into tree, set 'visibility' and 'stat data in entry' attributes */ mark_de_without_sd(deh); visible ? mark_de_visible(deh) : mark_de_hidden(deh); /* find the proper place for the new entry */ memset(bit_string, 0, sizeof(bit_string)); de.de_gen_number_bit_string = bit_string; retval = reiserfs_find_entry(dir, name, namelen, &path, &de); if (retval != NAME_NOT_FOUND) { if (buffer != small_buf) kfree(buffer); pathrelse(&path); if (retval == IO_ERROR) { return -EIO; } if (retval != NAME_FOUND) { reiserfs_error(dir->i_sb, "zam-7002", "reiserfs_find_entry() returned " "unexpected value (%d)", retval); } return -EEXIST; } gen_number = find_first_zero_bit(bit_string, MAX_GENERATION_NUMBER + 1); if (gen_number > MAX_GENERATION_NUMBER) { /* there is no free generation number */ reiserfs_warning(dir->i_sb, "reiserfs-7010", "Congratulations! we have got hash function " "screwed up"); if (buffer != small_buf) kfree(buffer); pathrelse(&path); return -EBUSY; } /* adjust offset of directory enrty */ put_deh_offset(deh, SET_GENERATION_NUMBER(deh_offset(deh), gen_number)); set_cpu_key_k_offset(&entry_key, deh_offset(deh)); /* update max-hash-collisions counter in reiserfs_sb_info */ PROC_INFO_MAX(th->t_super, max_hash_collisions, gen_number); if (gen_number != 0) { /* we need to re-search for the insertion point */ if (search_by_entry_key(dir->i_sb, &entry_key, &path, &de) != NAME_NOT_FOUND) { reiserfs_warning(dir->i_sb, "vs-7032", "entry with this key (%K) already " "exists", &entry_key); if (buffer != small_buf) kfree(buffer); pathrelse(&path); return -EBUSY; } } /* perform the insertion of the entry that we have prepared */ retval = reiserfs_paste_into_item(th, &path, &entry_key, dir, buffer, paste_size); if (buffer != small_buf) kfree(buffer); if (retval) { reiserfs_check_path(&path); return retval; } dir->i_size += paste_size; dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; if (!S_ISDIR(inode->i_mode) && visible) // reiserfs_mkdir or reiserfs_rename will do that by itself reiserfs_update_sd(th, dir); reiserfs_check_path(&path); return 0; }
/* add entry to the directory (entry can be hidden). Does not mark dir inode dirty, do it after successesfull call to it */ static int reiserfs_add_entry (struct reiserfs_transaction_handle *th, struct inode * dir, const char * name, int namelen, struct key * object_key, struct reiserfs_dir_entry * de, int visible ) { struct key entry_key; char * buffer; int buflen; struct reiserfs_de_head * deh; struct path path; char bit_string [MAX_GEN_NUMBER / 8 + 1]; int gen_number; int repeat; #ifdef REISERFS_ALIGNED int aligned_namelen = (namelen+3) & ~3; #endif init_path (&path); if (!dir || !dir->i_sb) return -ENOENT; if ((unsigned int)namelen > REISERFS_MAX_NAME_LEN (dir->i_sb->s_blocksize)) return -ENAMETOOLONG; /* each entry has unique key. compose it */ copy_key (&entry_key, INODE_PKEY(dir)); entry_key.k_offset = get_third_component (name, namelen); entry_key.k_uniqueness = DIRENTRY_UNIQUENESS; /* get memory for composing the entry */ #ifdef REISERFS_ALIGNED buflen = DEH_SIZE + aligned_namelen; #else buflen = DEH_SIZE + namelen; #endif buffer = reiserfs_kmalloc (buflen, GFP_KERNEL, dir->i_sb); if (buffer == 0) return -ENOMEM; /* fill buffer : directory entry head, name[, dir objectid | , stat data | ,stat data, dir objectid ] */ deh = (struct reiserfs_de_head *)buffer; deh->deh_location = 0; deh->deh_offset = entry_key.k_offset; deh->deh_state = 0; /* put key (ino analog) to de */ deh->deh_dir_id = object_key->k_dir_id; deh->deh_objectid = object_key->k_objectid; /* copy name */ #ifdef REISERFS_ALIGNED memset( (char*)(deh+1), '\0', aligned_namelen ); #endif memcpy ((char *)(deh + 1), name, namelen); /* entry is ready to be pasted into tree, set 'visibility' and 'stat data in entry' attributes */ mark_de_without_sd (deh); visible ? mark_de_visible (deh) : mark_de_hidden (deh); /* find the proper place for the new entry */ memset (bit_string, 0, sizeof (bit_string)); de->de_gen_number_bit_string = bit_string; if (reiserfs_find_entry (dir, name, namelen, &path, de) == POSITION_FOUND) { reiserfs_panic (dir->i_sb, "vs-7030: reiserfs_add_entry: entry with this key %k already exists", &entry_key); } if (find_first_nonzero_bit (bit_string, MAX_GEN_NUMBER + 1) < MAX_GEN_NUMBER + 1) { /* there are few names with given hash value */ gen_number = find_first_zero_bit (bit_string, MAX_GEN_NUMBER + 1); if (gen_number > MAX_GEN_NUMBER) { /* there is no free generation number */ reiserfs_kfree (buffer, buflen, dir->i_sb); pathrelse (&path); return -EHASHCOLLISION; } /* adjust offset of directory enrty */ deh->deh_offset = SET_GENERATION_NUMBER (deh->deh_offset, gen_number); entry_key.k_offset = deh->deh_offset; /* find place for new entry */ if (search_by_entry_key (dir->i_sb, &entry_key, &path, &(de->de_entry_num), &repeat)) { reiserfs_panic (dir->i_sb, "reiserfs_add_entry: 7032: entry with this key (%k) already exists", &entry_key); } } else { deh->deh_offset = SET_GENERATION_NUMBER (deh->deh_offset, 0); entry_key.k_offset = deh->deh_offset; } /* perform the insertion of the entry that we have prepared */ if (reiserfs_paste_into_item (th, dir->i_sb, &path, &(de->de_entry_num), &entry_key, buffer, buflen, REISERFS_KERNEL_MEM, 0) == -1) { reiserfs_kfree (buffer, buflen, dir->i_sb); return -ENOSPC; } reiserfs_kfree (buffer, buflen, dir->i_sb); dir->i_size += buflen; dir->i_mtime = dir->i_ctime = CURRENT_TIME; return 0; }
/* path points to first direct item of the file regarless of how many of them are there */ int direct2indirect (struct reiserfs_transaction_handle *th, struct inode * inode, struct path * path, struct buffer_head * unbh, loff_t tail_offset) { struct super_block * sb = inode->i_sb; struct buffer_head *up_to_date_bh ; struct item_head * p_le_ih = PATH_PITEM_HEAD (path); unsigned long total_tail = 0 ; struct cpu_key end_key; /* Key to search for the last byte of the converted item. */ struct item_head ind_ih; /* new indirect item to be inserted or key of unfm pointer to be pasted */ int n_blk_size, n_retval; /* returned value for reiserfs_insert_item and clones */ struct unfm_nodeinfo unfm_ptr; /* Handle on an unformatted node that will be inserted in the tree. */ sb->u.reiserfs_sb.s_direct2indirect ++; n_blk_size = sb->s_blocksize; /* and key to search for append or insert pointer to the new unformatted node. */ copy_item_head (&ind_ih, p_le_ih); set_le_ih_k_offset (&ind_ih, tail_offset); set_le_ih_k_type (&ind_ih, TYPE_INDIRECT); /* Set the key to search for the place for new unfm pointer */ make_cpu_key (&end_key, inode, tail_offset, TYPE_INDIRECT, 4); // FIXME: we could avoid this if ( search_for_position_by_key (sb, &end_key, path) == POSITION_FOUND ) { reiserfs_warning ("PAP-14030: direct2indirect: " "pasted or inserted byte exists in the tree %K. " "Use fsck to repair.\n", &end_key); pathrelse(path); return -EIO; } p_le_ih = PATH_PITEM_HEAD (path); unfm_ptr.unfm_nodenum = cpu_to_le32 (unbh->b_blocknr); unfm_ptr.unfm_freespace = 0; // ??? if ( is_statdata_le_ih (p_le_ih) ) { /* Insert new indirect item. */ set_ih_free_space (&ind_ih, 0); /* delete at nearest future */ put_ih_item_len( &ind_ih, UNFM_P_SIZE ); PATH_LAST_POSITION (path)++; n_retval = reiserfs_insert_item (th, path, &end_key, &ind_ih, (char *)&unfm_ptr); } else { /* Paste into last indirect item of an object. */ n_retval = reiserfs_paste_into_item(th, path, &end_key, (char *)&unfm_ptr, UNFM_P_SIZE); } if ( n_retval ) { return n_retval; } // note: from here there are two keys which have matching first // three key components. They only differ by the fourth one. /* Set the key to search for the direct items of the file */ make_cpu_key (&end_key, inode, max_reiserfs_offset (inode), TYPE_DIRECT, 4); /* Move bytes from the direct items to the new unformatted node and delete them. */ while (1) { int tail_size; /* end_key.k_offset is set so, that we will always have found last item of the file */ if ( search_for_position_by_key (sb, &end_key, path) == POSITION_FOUND ) reiserfs_panic (sb, "PAP-14050: direct2indirect: " "direct item (%K) not found", &end_key); p_le_ih = PATH_PITEM_HEAD (path); RFALSE( !is_direct_le_ih (p_le_ih), "vs-14055: direct item expected(%K), found %h", &end_key, p_le_ih); tail_size = (le_ih_k_offset (p_le_ih) & (n_blk_size - 1)) + ih_item_len(p_le_ih) - 1; /* we only send the unbh pointer if the buffer is not up to date. ** this avoids overwriting good data from writepage() with old data ** from the disk or buffer cache ** Special case: unbh->b_page will be NULL if we are coming through ** DIRECT_IO handler here. */ if ( !unbh->b_page || buffer_uptodate(unbh) || Page_Uptodate(unbh->b_page)) { up_to_date_bh = NULL ; } else { up_to_date_bh = unbh ; } n_retval = reiserfs_delete_item (th, path, &end_key, inode, up_to_date_bh) ; total_tail += n_retval ; if (tail_size == n_retval) // done: file does not have direct items anymore break; } /* if we've copied bytes from disk into the page, we need to zero ** out the unused part of the block (it was not up to date before) ** the page is still kmapped (by whoever called reiserfs_get_block) */ if (up_to_date_bh) { unsigned pgoff = (tail_offset + total_tail - 1) & (PAGE_CACHE_SIZE - 1); memset(page_address(unbh->b_page) + pgoff, 0, n_blk_size - total_tail) ; } inode->u.reiserfs_i.i_first_direct_byte = U32_MAX; reiserfs_update_tail_transaction(inode); return 0; }
int direct2indirect(struct reiserfs_transaction_handle *th, struct inode *inode, struct treepath *path, struct buffer_head *unbh, loff_t tail_offset) { struct super_block *sb = inode->i_sb; struct buffer_head *up_to_date_bh; struct item_head *p_le_ih = PATH_PITEM_HEAD(path); unsigned long total_tail = 0; struct cpu_key end_key; struct item_head ind_ih; int blk_size, retval; unp_t unfm_ptr; BUG_ON(!th->t_trans_id); REISERFS_SB(sb)->s_direct2indirect++; blk_size = sb->s_blocksize; copy_item_head(&ind_ih, p_le_ih); set_le_ih_k_offset(&ind_ih, tail_offset); set_le_ih_k_type(&ind_ih, TYPE_INDIRECT); make_cpu_key(&end_key, inode, tail_offset, TYPE_INDIRECT, 4); if (search_for_position_by_key(sb, &end_key, path) == POSITION_FOUND) { reiserfs_error(sb, "PAP-14030", "pasted or inserted byte exists in " "the tree %K. Use fsck to repair.", &end_key); pathrelse(path); return -EIO; } p_le_ih = PATH_PITEM_HEAD(path); unfm_ptr = cpu_to_le32(unbh->b_blocknr); if (is_statdata_le_ih(p_le_ih)) { set_ih_free_space(&ind_ih, 0); put_ih_item_len(&ind_ih, UNFM_P_SIZE); PATH_LAST_POSITION(path)++; retval = reiserfs_insert_item(th, path, &end_key, &ind_ih, inode, (char *)&unfm_ptr); } else { retval = reiserfs_paste_into_item(th, path, &end_key, inode, (char *)&unfm_ptr, UNFM_P_SIZE); } if (retval) { return retval; } make_cpu_key(&end_key, inode, max_reiserfs_offset(inode), TYPE_DIRECT, 4); while (1) { int tail_size; if (search_for_position_by_key(sb, &end_key, path) == POSITION_FOUND) reiserfs_panic(sb, "PAP-14050", "direct item (%K) not found", &end_key); p_le_ih = PATH_PITEM_HEAD(path); RFALSE(!is_direct_le_ih(p_le_ih), "vs-14055: direct item expected(%K), found %h", &end_key, p_le_ih); tail_size = (le_ih_k_offset(p_le_ih) & (blk_size - 1)) + ih_item_len(p_le_ih) - 1; if (!unbh->b_page || buffer_uptodate(unbh) || PageUptodate(unbh->b_page)) { up_to_date_bh = NULL; } else { up_to_date_bh = unbh; } retval = reiserfs_delete_item(th, path, &end_key, inode, up_to_date_bh); total_tail += retval; if (tail_size == retval) break; } if (up_to_date_bh) { unsigned pgoff = (tail_offset + total_tail - 1) & (PAGE_CACHE_SIZE - 1); char *kaddr = kmap_atomic(up_to_date_bh->b_page); memset(kaddr + pgoff, 0, blk_size - total_tail); kunmap_atomic(kaddr); } REISERFS_I(inode)->i_first_direct_byte = U32_MAX; return 0; }
/* * path points to first direct item of the file regardless of how many of * them are there */ int direct2indirect(struct reiserfs_transaction_handle *th, struct inode *inode, struct treepath *path, struct buffer_head *unbh, loff_t tail_offset) { struct super_block *sb = inode->i_sb; struct buffer_head *up_to_date_bh; struct item_head *p_le_ih = tp_item_head(path); unsigned long total_tail = 0; /* Key to search for the last byte of the converted item. */ struct cpu_key end_key; /* * new indirect item to be inserted or key * of unfm pointer to be pasted */ struct item_head ind_ih; int blk_size; /* returned value for reiserfs_insert_item and clones */ int retval; /* Handle on an unformatted node that will be inserted in the tree. */ unp_t unfm_ptr; BUG_ON(!th->t_trans_id); REISERFS_SB(sb)->s_direct2indirect++; blk_size = sb->s_blocksize; /* * and key to search for append or insert pointer to the new * unformatted node. */ copy_item_head(&ind_ih, p_le_ih); set_le_ih_k_offset(&ind_ih, tail_offset); set_le_ih_k_type(&ind_ih, TYPE_INDIRECT); /* Set the key to search for the place for new unfm pointer */ make_cpu_key(&end_key, inode, tail_offset, TYPE_INDIRECT, 4); /* FIXME: we could avoid this */ if (search_for_position_by_key(sb, &end_key, path) == POSITION_FOUND) { reiserfs_error(sb, "PAP-14030", "pasted or inserted byte exists in " "the tree %K. Use fsck to repair.", &end_key); pathrelse(path); return -EIO; } p_le_ih = tp_item_head(path); unfm_ptr = cpu_to_le32(unbh->b_blocknr); if (is_statdata_le_ih(p_le_ih)) { /* Insert new indirect item. */ set_ih_free_space(&ind_ih, 0); /* delete at nearest future */ put_ih_item_len(&ind_ih, UNFM_P_SIZE); PATH_LAST_POSITION(path)++; retval = reiserfs_insert_item(th, path, &end_key, &ind_ih, inode, (char *)&unfm_ptr); } else { /* Paste into last indirect item of an object. */ retval = reiserfs_paste_into_item(th, path, &end_key, inode, (char *)&unfm_ptr, UNFM_P_SIZE); } if (retval) { return retval; } /* * note: from here there are two keys which have matching first * three key components. They only differ by the fourth one. */ /* Set the key to search for the direct items of the file */ make_cpu_key(&end_key, inode, max_reiserfs_offset(inode), TYPE_DIRECT, 4); /* * Move bytes from the direct items to the new unformatted node * and delete them. */ while (1) { int tail_size; /* * end_key.k_offset is set so, that we will always have found * last item of the file */ if (search_for_position_by_key(sb, &end_key, path) == POSITION_FOUND) reiserfs_panic(sb, "PAP-14050", "direct item (%K) not found", &end_key); p_le_ih = tp_item_head(path); RFALSE(!is_direct_le_ih(p_le_ih), "vs-14055: direct item expected(%K), found %h", &end_key, p_le_ih); tail_size = (le_ih_k_offset(p_le_ih) & (blk_size - 1)) + ih_item_len(p_le_ih) - 1; /* * we only send the unbh pointer if the buffer is not * up to date. this avoids overwriting good data from * writepage() with old data from the disk or buffer cache * Special case: unbh->b_page will be NULL if we are coming * through DIRECT_IO handler here. */ if (!unbh->b_page || buffer_uptodate(unbh) || PageUptodate(unbh->b_page)) { up_to_date_bh = NULL; } else { up_to_date_bh = unbh; } retval = reiserfs_delete_item(th, path, &end_key, inode, up_to_date_bh); total_tail += retval; /* done: file does not have direct items anymore */ if (tail_size == retval) break; } /* * if we've copied bytes from disk into the page, we need to zero * out the unused part of the block (it was not up to date before) */ if (up_to_date_bh) { unsigned pgoff = (tail_offset + total_tail - 1) & (PAGE_SIZE - 1); char *kaddr = kmap_atomic(up_to_date_bh->b_page); memset(kaddr + pgoff, 0, blk_size - total_tail); kunmap_atomic(kaddr); } REISERFS_I(inode)->i_first_direct_byte = U32_MAX; return 0; }