static int reiserfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { int retval; struct inode *inode = d_inode(old_dentry); struct reiserfs_transaction_handle th; /* * We need blocks for transaction + update of quotas for * the owners of the directory */ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb); retval = dquot_initialize(dir); if (retval) return retval; reiserfs_write_lock(dir->i_sb); if (inode->i_nlink >= REISERFS_LINK_MAX) { /* FIXME: sd_nlink is 32 bit for new files */ reiserfs_write_unlock(dir->i_sb); return -EMLINK; } /* inc before scheduling so reiserfs_unlink knows we are here */ inc_nlink(inode); retval = journal_begin(&th, dir->i_sb, jbegin_count); if (retval) { drop_nlink(inode); reiserfs_write_unlock(dir->i_sb); return retval; } /* create new entry */ retval = reiserfs_add_entry(&th, dir, dentry->d_name.name, dentry->d_name.len, inode, 1 /*visible */ ); reiserfs_update_inode_transaction(inode); reiserfs_update_inode_transaction(dir); if (retval) { int err; drop_nlink(inode); err = journal_end(&th); reiserfs_write_unlock(dir->i_sb); return err ? err : retval; } inode->i_ctime = current_time(inode); reiserfs_update_sd(&th, inode); ihold(inode); d_instantiate(dentry, inode); retval = journal_end(&th); reiserfs_write_unlock(dir->i_sb); return retval; }
static int reiserfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { int retval; struct inode *inode = old_dentry->d_inode; struct reiserfs_transaction_handle th; /* We need blocks for transaction + update of quotas for the owners of the directory */ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb); reiserfs_write_lock(dir->i_sb); if (inode->i_nlink >= REISERFS_LINK_MAX) { //FIXME: sd_nlink is 32 bit for new files reiserfs_write_unlock(dir->i_sb); return -EMLINK; } if (inode->i_nlink == 0) { reiserfs_write_unlock(dir->i_sb); return -ENOENT; } /* inc before scheduling so reiserfs_unlink knows we are here */ inode->i_nlink++; retval = journal_begin(&th, dir->i_sb, jbegin_count); if (retval) { inode->i_nlink--; reiserfs_write_unlock(dir->i_sb); return retval; } /* create new entry */ retval = reiserfs_add_entry(&th, dir, dentry->d_name.name, dentry->d_name.len, inode, 1 /*visible */ ); reiserfs_update_inode_transaction(inode); reiserfs_update_inode_transaction(dir); if (retval) { int err; inode->i_nlink--; err = journal_end(&th, dir->i_sb, jbegin_count); reiserfs_write_unlock(dir->i_sb); return err ? err : retval; } inode->i_ctime = CURRENT_TIME_SEC; reiserfs_update_sd(&th, inode); atomic_inc(&inode->i_count); d_instantiate(dentry, inode); retval = journal_end(&th, dir->i_sb, jbegin_count); reiserfs_write_unlock(dir->i_sb); return retval; }
static int reiserfs_create (struct inode * dir, struct dentry *dentry, int mode, struct nameidata *nd) { int retval; struct inode * inode; int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 ; struct reiserfs_transaction_handle th ; int locked; if (!(inode = new_inode(dir->i_sb))) { return -ENOMEM ; } retval = new_inode_init(inode, dir, mode); if (retval) return retval; locked = reiserfs_cache_default_acl (dir); reiserfs_write_lock(dir->i_sb); if (locked) reiserfs_write_lock_xattrs (dir->i_sb); journal_begin(&th, dir->i_sb, jbegin_count) ; retval = reiserfs_new_inode (&th, dir, mode, 0, 0/*i_size*/, dentry, inode); if (locked) reiserfs_write_unlock_xattrs (dir->i_sb); if (retval) { goto out_failed; } inode->i_op = &reiserfs_file_inode_operations; inode->i_fop = &reiserfs_file_operations; inode->i_mapping->a_ops = &reiserfs_address_space_operations ; retval = reiserfs_add_entry (&th, dir, dentry->d_name.name, dentry->d_name.len, inode, 1/*visible*/); if (retval) { inode->i_nlink--; reiserfs_update_sd (&th, inode); journal_end(&th, dir->i_sb, jbegin_count) ; iput (inode); goto out_failed; } reiserfs_update_inode_transaction(inode) ; reiserfs_update_inode_transaction(dir) ; d_instantiate(dentry, inode); journal_end(&th, dir->i_sb, jbegin_count) ; out_failed: reiserfs_write_unlock(dir->i_sb); return retval; }
/* we don't mark inodes dirty, we just log them */ static void reiserfs_dirty_inode (struct inode * inode) { struct reiserfs_transaction_handle th ; if (inode->i_sb->s_flags & MS_RDONLY) { reiserfs_warning("clm-6006: writing inode %lu on readonly FS\n", inode->i_ino) ; return ; } lock_kernel() ; /* this is really only used for atime updates, so they don't have ** to be included in O_SYNC or fsync */ journal_begin(&th, inode->i_sb, 1) ; reiserfs_update_sd (&th, inode); journal_end(&th, inode->i_sb, 1) ; unlock_kernel() ; }
static void __discard_prealloc (struct reiserfs_transaction_handle * th, struct reiserfs_inode_info *ei) { unsigned long save = ei->i_prealloc_block ; int dirty = 0; struct inode *inode = &ei->vfs_inode; BUG_ON (!th->t_trans_id); #ifdef CONFIG_REISERFS_CHECK if (ei->i_prealloc_count < 0) reiserfs_warning (th->t_super, "zam-4001:%s: inode has negative prealloc blocks count.", __FUNCTION__ ); #endif while (ei->i_prealloc_count > 0) { reiserfs_free_prealloc_block(th, inode, ei->i_prealloc_block); ei->i_prealloc_block++; ei->i_prealloc_count --; dirty = 1; } if (dirty) reiserfs_update_sd(th, inode); ei->i_prealloc_block = save; list_del_init(&(ei->i_prealloc_list)); }
static int reiserfs_rmdir(struct inode *dir, struct dentry *dentry) { int retval, err; struct inode *inode; struct reiserfs_transaction_handle th; int jbegin_count; INITIALIZE_PATH(path); struct reiserfs_dir_entry de; /* we will be doing 2 balancings and update 2 stat data, we change quotas * of the owner of the directory and of the owner of the parent directory. * The quota structure is possibly deleted only on last iput => outside * of this transaction */ jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb); dquot_initialize(dir); reiserfs_write_lock(dir->i_sb); retval = journal_begin(&th, dir->i_sb, jbegin_count); if (retval) goto out_rmdir; de.de_gen_number_bit_string = NULL; if ((retval = reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &path, &de)) == NAME_NOT_FOUND) { retval = -ENOENT; goto end_rmdir; } else if (retval == IO_ERROR) { retval = -EIO; goto end_rmdir; } inode = dentry->d_inode; reiserfs_update_inode_transaction(inode); reiserfs_update_inode_transaction(dir); if (de.de_objectid != inode->i_ino) { // FIXME: compare key of an object and a key found in the // entry retval = -EIO; goto end_rmdir; } if (!reiserfs_empty_dir(inode)) { retval = -ENOTEMPTY; goto end_rmdir; } /* cut entry from dir directory */ retval = reiserfs_cut_from_item(&th, &path, &(de.de_entry_key), dir, NULL, /* page */ 0 /*new file size - not used here */ ); if (retval < 0) goto end_rmdir; if (inode->i_nlink != 2 && inode->i_nlink != 1) reiserfs_error(inode->i_sb, "reiserfs-7040", "empty directory has nlink != 2 (%d)", inode->i_nlink); clear_nlink(inode); inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; reiserfs_update_sd(&th, inode); DEC_DIR_INODE_NLINK(dir) dir->i_size -= (DEH_SIZE + de.de_entrylen); reiserfs_update_sd(&th, dir); /* prevent empty directory from getting lost */ add_save_link(&th, inode, 0 /* not truncate */ ); retval = journal_end(&th, dir->i_sb, jbegin_count); reiserfs_check_path(&path); out_rmdir: reiserfs_write_unlock(dir->i_sb); return retval; end_rmdir: /* we must release path, because we did not call reiserfs_cut_from_item, or reiserfs_cut_from_item does not release path if operation was not complete */ pathrelse(&path); err = journal_end(&th, dir->i_sb, jbegin_count); reiserfs_write_unlock(dir->i_sb); return err ? err : retval; }
static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) { int retval; struct inode *inode; struct reiserfs_transaction_handle th; struct reiserfs_security_handle security; int lock_depth; /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) + REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb)); dquot_initialize(dir); #ifdef DISPLACE_NEW_PACKING_LOCALITIES /* set flag that new packing locality created and new blocks for the content * of that directory are not displaced yet */ REISERFS_I(dir)->new_packing_locality = 1; #endif mode = S_IFDIR | mode; if (!(inode = new_inode(dir->i_sb))) { return -ENOMEM; } new_inode_init(inode, dir, mode); jbegin_count += reiserfs_cache_default_acl(dir); retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security); if (retval < 0) { drop_new_inode(inode); return retval; } jbegin_count += retval; lock_depth = reiserfs_write_lock_once(dir->i_sb); retval = journal_begin(&th, dir->i_sb, jbegin_count); if (retval) { drop_new_inode(inode); goto out_failed; } /* inc the link count now, so another writer doesn't overflow it while ** we sleep later on. */ INC_DIR_INODE_NLINK(dir) retval = reiserfs_new_inode(&th, dir, mode, NULL /*symlink */ , old_format_only(dir->i_sb) ? EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE, dentry, inode, &security); if (retval) { DEC_DIR_INODE_NLINK(dir) goto out_failed; } reiserfs_update_inode_transaction(inode); reiserfs_update_inode_transaction(dir); inode->i_op = &reiserfs_dir_inode_operations; inode->i_fop = &reiserfs_dir_operations; // note, _this_ add_entry will not update dir's stat data retval = reiserfs_add_entry(&th, dir, dentry->d_name.name, dentry->d_name.len, inode, 1 /*visible */ ); if (retval) { int err; clear_nlink(inode); DEC_DIR_INODE_NLINK(dir); reiserfs_update_sd(&th, inode); err = journal_end(&th, dir->i_sb, jbegin_count); if (err) retval = err; unlock_new_inode(inode); iput(inode); goto out_failed; } // the above add_entry did not update dir's stat data reiserfs_update_sd(&th, dir); unlock_new_inode(inode); d_instantiate(dentry, inode); retval = journal_end(&th, dir->i_sb, jbegin_count); out_failed: reiserfs_write_unlock_once(dir->i_sb, lock_depth); return retval; }
static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev) { int retval; struct inode *inode; struct reiserfs_transaction_handle th; struct reiserfs_security_handle security; /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) + REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb)); if (!new_valid_dev(rdev)) return -EINVAL; dquot_initialize(dir); if (!(inode = new_inode(dir->i_sb))) { return -ENOMEM; } new_inode_init(inode, dir, mode); jbegin_count += reiserfs_cache_default_acl(dir); retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security); if (retval < 0) { drop_new_inode(inode); return retval; } jbegin_count += retval; reiserfs_write_lock(dir->i_sb); retval = journal_begin(&th, dir->i_sb, jbegin_count); if (retval) { drop_new_inode(inode); goto out_failed; } retval = reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry, inode, &security); if (retval) { goto out_failed; } inode->i_op = &reiserfs_special_inode_operations; init_special_inode(inode, inode->i_mode, rdev); //FIXME: needed for block and char devices only reiserfs_update_sd(&th, inode); reiserfs_update_inode_transaction(inode); reiserfs_update_inode_transaction(dir); retval = reiserfs_add_entry(&th, dir, dentry->d_name.name, dentry->d_name.len, inode, 1 /*visible */ ); if (retval) { int err; drop_nlink(inode); reiserfs_update_sd(&th, inode); err = journal_end(&th, dir->i_sb, jbegin_count); if (err) retval = err; unlock_new_inode(inode); iput(inode); goto out_failed; } unlock_new_inode(inode); d_instantiate(dentry, inode); retval = journal_end(&th, dir->i_sb, jbegin_count); out_failed: reiserfs_write_unlock(dir->i_sb); return retval; }
static int reiserfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd) { int retval; struct inode *inode; /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) + REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb)); struct reiserfs_transaction_handle th; struct reiserfs_security_handle security; dquot_initialize(dir); if (!(inode = new_inode(dir->i_sb))) { return -ENOMEM; } new_inode_init(inode, dir, mode); jbegin_count += reiserfs_cache_default_acl(dir); retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security); if (retval < 0) { drop_new_inode(inode); return retval; } jbegin_count += retval; reiserfs_write_lock(dir->i_sb); retval = journal_begin(&th, dir->i_sb, jbegin_count); if (retval) { drop_new_inode(inode); goto out_failed; } retval = reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry, inode, &security); if (retval) goto out_failed; inode->i_op = &reiserfs_file_inode_operations; inode->i_fop = &reiserfs_file_operations; inode->i_mapping->a_ops = &reiserfs_address_space_operations; retval = reiserfs_add_entry(&th, dir, dentry->d_name.name, dentry->d_name.len, inode, 1 /*visible */ ); if (retval) { int err; drop_nlink(inode); reiserfs_update_sd(&th, inode); err = journal_end(&th, dir->i_sb, jbegin_count); if (err) retval = err; unlock_new_inode(inode); iput(inode); goto out_failed; } reiserfs_update_inode_transaction(inode); reiserfs_update_inode_transaction(dir); unlock_new_inode(inode); d_instantiate(dentry, inode); retval = journal_end(&th, dir->i_sb, jbegin_count); out_failed: reiserfs_write_unlock(dir->i_sb); return retval; }
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; }
/* * process, that is going to call fix_nodes/do_balance must hold only * one path. If it holds 2 or more, it can get into endless waiting in * get_empty_nodes or its clones */ static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) { int retval; INITIALIZE_PATH(old_entry_path); INITIALIZE_PATH(new_entry_path); INITIALIZE_PATH(dot_dot_entry_path); struct item_head new_entry_ih, old_entry_ih, dot_dot_ih; struct reiserfs_dir_entry old_de, new_de, dot_dot_de; struct inode *old_inode, *new_dentry_inode; struct reiserfs_transaction_handle th; int jbegin_count; umode_t old_inode_mode; unsigned long savelink = 1; struct timespec ctime; /* three balancings: (1) old name removal, (2) new name insertion and (3) maybe "save" link insertion stat data updates: (1) old directory, (2) new directory and (3) maybe old object stat data (when it is directory) and (4) maybe stat data of object to which new entry pointed initially and (5) maybe block containing ".." of renamed directory quota updates: two parent directories */ jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 5 + 4 * REISERFS_QUOTA_TRANS_BLOCKS(old_dir->i_sb); dquot_initialize(old_dir); dquot_initialize(new_dir); old_inode = old_dentry->d_inode; new_dentry_inode = new_dentry->d_inode; // make sure, that oldname still exists and points to an object we // are going to rename old_de.de_gen_number_bit_string = NULL; reiserfs_write_lock(old_dir->i_sb); retval = reiserfs_find_entry(old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_entry_path, &old_de); pathrelse(&old_entry_path); if (retval == IO_ERROR) { reiserfs_write_unlock(old_dir->i_sb); return -EIO; } if (retval != NAME_FOUND || old_de.de_objectid != old_inode->i_ino) { reiserfs_write_unlock(old_dir->i_sb); return -ENOENT; } old_inode_mode = old_inode->i_mode; if (S_ISDIR(old_inode_mode)) { // make sure, that directory being renamed has correct ".." // and that its new parent directory has not too many links // already if (new_dentry_inode) { if (!reiserfs_empty_dir(new_dentry_inode)) { reiserfs_write_unlock(old_dir->i_sb); return -ENOTEMPTY; } } /* directory is renamed, its parent directory will be changed, ** so find ".." entry */ dot_dot_de.de_gen_number_bit_string = NULL; retval = reiserfs_find_entry(old_inode, "..", 2, &dot_dot_entry_path, &dot_dot_de); pathrelse(&dot_dot_entry_path); if (retval != NAME_FOUND) { reiserfs_write_unlock(old_dir->i_sb); return -EIO; } /* inode number of .. must equal old_dir->i_ino */ if (dot_dot_de.de_objectid != old_dir->i_ino) { reiserfs_write_unlock(old_dir->i_sb); return -EIO; } } retval = journal_begin(&th, old_dir->i_sb, jbegin_count); if (retval) { reiserfs_write_unlock(old_dir->i_sb); return retval; } /* add new entry (or find the existing one) */ retval = reiserfs_add_entry(&th, new_dir, new_dentry->d_name.name, new_dentry->d_name.len, old_inode, 0); if (retval == -EEXIST) { if (!new_dentry_inode) { reiserfs_panic(old_dir->i_sb, "vs-7050", "new entry is found, new inode == 0"); } } else if (retval) { int err = journal_end(&th, old_dir->i_sb, jbegin_count); reiserfs_write_unlock(old_dir->i_sb); return err ? err : retval; } reiserfs_update_inode_transaction(old_dir); reiserfs_update_inode_transaction(new_dir); /* this makes it so an fsync on an open fd for the old name will ** commit the rename operation */ reiserfs_update_inode_transaction(old_inode); if (new_dentry_inode) reiserfs_update_inode_transaction(new_dentry_inode); while (1) { // look for old name using corresponding entry key (found by reiserfs_find_entry) if ((retval = search_by_entry_key(new_dir->i_sb, &old_de.de_entry_key, &old_entry_path, &old_de)) != NAME_FOUND) { pathrelse(&old_entry_path); journal_end(&th, old_dir->i_sb, jbegin_count); reiserfs_write_unlock(old_dir->i_sb); return -EIO; } copy_item_head(&old_entry_ih, get_ih(&old_entry_path)); reiserfs_prepare_for_journal(old_inode->i_sb, old_de.de_bh, 1); // look for new name by reiserfs_find_entry new_de.de_gen_number_bit_string = NULL; retval = reiserfs_find_entry(new_dir, new_dentry->d_name.name, new_dentry->d_name.len, &new_entry_path, &new_de); // reiserfs_add_entry should not return IO_ERROR, because it is called with essentially same parameters from // reiserfs_add_entry above, and we'll catch any i/o errors before we get here. if (retval != NAME_FOUND_INVISIBLE && retval != NAME_FOUND) { pathrelse(&new_entry_path); pathrelse(&old_entry_path); journal_end(&th, old_dir->i_sb, jbegin_count); reiserfs_write_unlock(old_dir->i_sb); return -EIO; } copy_item_head(&new_entry_ih, get_ih(&new_entry_path)); reiserfs_prepare_for_journal(old_inode->i_sb, new_de.de_bh, 1); if (S_ISDIR(old_inode->i_mode)) { if ((retval = search_by_entry_key(new_dir->i_sb, &dot_dot_de.de_entry_key, &dot_dot_entry_path, &dot_dot_de)) != NAME_FOUND) { pathrelse(&dot_dot_entry_path); pathrelse(&new_entry_path); pathrelse(&old_entry_path); journal_end(&th, old_dir->i_sb, jbegin_count); reiserfs_write_unlock(old_dir->i_sb); return -EIO; } copy_item_head(&dot_dot_ih, get_ih(&dot_dot_entry_path)); // node containing ".." gets into transaction reiserfs_prepare_for_journal(old_inode->i_sb, dot_dot_de.de_bh, 1); } /* we should check seals here, not do this stuff, yes? Then, having gathered everything into RAM we should lock the buffers, yes? -Hans */ /* probably. our rename needs to hold more ** than one path at once. The seals would ** have to be written to deal with multi-path ** issues -chris */ /* sanity checking before doing the rename - avoid races many ** of the above checks could have scheduled. We have to be ** sure our items haven't been shifted by another process. */ if (item_moved(&new_entry_ih, &new_entry_path) || !entry_points_to_object(new_dentry->d_name.name, new_dentry->d_name.len, &new_de, new_dentry_inode) || item_moved(&old_entry_ih, &old_entry_path) || !entry_points_to_object(old_dentry->d_name.name, old_dentry->d_name.len, &old_de, old_inode)) { reiserfs_restore_prepared_buffer(old_inode->i_sb, new_de.de_bh); reiserfs_restore_prepared_buffer(old_inode->i_sb, old_de.de_bh); if (S_ISDIR(old_inode_mode)) reiserfs_restore_prepared_buffer(old_inode-> i_sb, dot_dot_de. de_bh); continue; } if (S_ISDIR(old_inode_mode)) { if (item_moved(&dot_dot_ih, &dot_dot_entry_path) || !entry_points_to_object("..", 2, &dot_dot_de, old_dir)) { reiserfs_restore_prepared_buffer(old_inode-> i_sb, old_de.de_bh); reiserfs_restore_prepared_buffer(old_inode-> i_sb, new_de.de_bh); reiserfs_restore_prepared_buffer(old_inode-> i_sb, dot_dot_de. de_bh); continue; } } RFALSE(S_ISDIR(old_inode_mode) && !buffer_journal_prepared(dot_dot_de.de_bh), ""); break; } /* ok, all the changes can be done in one fell swoop when we have claimed all the buffers needed. */ mark_de_visible(new_de.de_deh + new_de.de_entry_num); set_ino_in_dir_entry(&new_de, INODE_PKEY(old_inode)); journal_mark_dirty(&th, old_dir->i_sb, new_de.de_bh); mark_de_hidden(old_de.de_deh + old_de.de_entry_num); journal_mark_dirty(&th, old_dir->i_sb, old_de.de_bh); ctime = CURRENT_TIME_SEC; old_dir->i_ctime = old_dir->i_mtime = ctime; new_dir->i_ctime = new_dir->i_mtime = ctime; /* thanks to Alex Adriaanse <*****@*****.**> for patch which adds ctime update of renamed object */ old_inode->i_ctime = ctime; if (new_dentry_inode) { // adjust link number of the victim if (S_ISDIR(new_dentry_inode->i_mode)) { clear_nlink(new_dentry_inode); } else { drop_nlink(new_dentry_inode); } new_dentry_inode->i_ctime = ctime; savelink = new_dentry_inode->i_nlink; } if (S_ISDIR(old_inode_mode)) { /* adjust ".." of renamed directory */ set_ino_in_dir_entry(&dot_dot_de, INODE_PKEY(new_dir)); journal_mark_dirty(&th, new_dir->i_sb, dot_dot_de.de_bh); if (!new_dentry_inode) /* there (in new_dir) was no directory, so it got new link (".." of renamed directory) */ INC_DIR_INODE_NLINK(new_dir); /* old directory lost one link - ".. " of renamed directory */ DEC_DIR_INODE_NLINK(old_dir); } // looks like in 2.3.99pre3 brelse is atomic. so we can use pathrelse pathrelse(&new_entry_path); pathrelse(&dot_dot_entry_path); // FIXME: this reiserfs_cut_from_item's return value may screw up // anybody, but it will panic if will not be able to find the // entry. This needs one more clean up if (reiserfs_cut_from_item (&th, &old_entry_path, &(old_de.de_entry_key), old_dir, NULL, 0) < 0) reiserfs_error(old_dir->i_sb, "vs-7060", "couldn't not cut old name. Fsck later?"); old_dir->i_size -= DEH_SIZE + old_de.de_entrylen; reiserfs_update_sd(&th, old_dir); reiserfs_update_sd(&th, new_dir); reiserfs_update_sd(&th, old_inode); if (new_dentry_inode) { if (savelink == 0) add_save_link(&th, new_dentry_inode, 0 /* not truncate */ ); reiserfs_update_sd(&th, new_dentry_inode); } retval = journal_end(&th, old_dir->i_sb, jbegin_count); reiserfs_write_unlock(old_dir->i_sb); return retval; }
static int reiserfs_mkdir (struct inode * dir, struct dentry *dentry, int mode) { int retval; struct inode * inode; struct reiserfs_transaction_handle th ; int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; int locked; #ifdef DISPLACE_NEW_PACKING_LOCALITIES /* set flag that new packing locality created and new blocks for the content * of that directory are not displaced yet */ REISERFS_I(dir)->new_packing_locality = 1; #endif mode = S_IFDIR | mode; if (!(inode = new_inode(dir->i_sb))) { return -ENOMEM ; } retval = new_inode_init(inode, dir, mode); if (retval) return retval; locked = reiserfs_cache_default_acl (dir); reiserfs_write_lock(dir->i_sb); if (locked) reiserfs_write_lock_xattrs (dir->i_sb); journal_begin(&th, dir->i_sb, jbegin_count) ; /* inc the link count now, so another writer doesn't overflow it while ** we sleep later on. */ INC_DIR_INODE_NLINK(dir) retval = reiserfs_new_inode (&th, dir, mode, 0/*symlink*/, old_format_only (dir->i_sb) ? EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE, dentry, inode); if (locked) reiserfs_write_unlock_xattrs (dir->i_sb); if (retval) { dir->i_nlink-- ; goto out_failed; } reiserfs_update_inode_transaction(inode) ; reiserfs_update_inode_transaction(dir) ; inode->i_op = &reiserfs_dir_inode_operations; inode->i_fop = &reiserfs_dir_operations; // note, _this_ add_entry will not update dir's stat data retval = reiserfs_add_entry (&th, dir, dentry->d_name.name, dentry->d_name.len, inode, 1/*visible*/); if (retval) { inode->i_nlink = 0; DEC_DIR_INODE_NLINK(dir); reiserfs_update_sd (&th, inode); journal_end(&th, dir->i_sb, jbegin_count) ; iput (inode); goto out_failed; } // the above add_entry did not update dir's stat data reiserfs_update_sd (&th, dir); d_instantiate(dentry, inode); journal_end(&th, dir->i_sb, jbegin_count) ; out_failed: reiserfs_write_unlock(dir->i_sb); return retval; }
int indirect2direct(struct reiserfs_transaction_handle *th, struct inode *inode, struct page *page, struct treepath *path, const struct cpu_key *item_key, loff_t n_new_file_size, char *mode) { struct super_block *sb = inode->i_sb; struct item_head s_ih; unsigned long block_size = sb->s_blocksize; char *tail; int tail_len, round_tail_len; loff_t pos, pos1; struct cpu_key key; BUG_ON(!th->t_trans_id); REISERFS_SB(sb)->s_indirect2direct++; *mode = M_SKIP_BALANCING; copy_item_head(&s_ih, PATH_PITEM_HEAD(path)); tail_len = (n_new_file_size & (block_size - 1)); if (get_inode_sd_version(inode) == STAT_DATA_V2) round_tail_len = ROUND_UP(tail_len); else round_tail_len = tail_len; pos = le_ih_k_offset(&s_ih) - 1 + (ih_item_len(&s_ih) / UNFM_P_SIZE - 1) * sb->s_blocksize; pos1 = pos; tail = (char *)kmap(page); if (path_changed(&s_ih, path)) { if (search_for_position_by_key(sb, item_key, path) == POSITION_NOT_FOUND) reiserfs_panic(sb, "PAP-5520", "item to be converted %K does not exist", item_key); copy_item_head(&s_ih, PATH_PITEM_HEAD(path)); #ifdef CONFIG_REISERFS_CHECK pos = le_ih_k_offset(&s_ih) - 1 + (ih_item_len(&s_ih) / UNFM_P_SIZE - 1) * sb->s_blocksize; if (pos != pos1) reiserfs_panic(sb, "vs-5530", "tail position " "changed while we were reading it"); #endif } make_le_item_head(&s_ih, NULL, get_inode_item_key_version(inode), pos1 + 1, TYPE_DIRECT, round_tail_len, 0xffff ); tail = tail + (pos & (PAGE_CACHE_SIZE - 1)); PATH_LAST_POSITION(path)++; key = *item_key; set_cpu_key_k_type(&key, TYPE_DIRECT); key.key_length = 4; if (reiserfs_insert_item(th, path, &key, &s_ih, inode, tail ? tail : NULL) < 0) { kunmap(page); return block_size - round_tail_len; } kunmap(page); reiserfs_update_sd(th, inode); *mode = M_CUT; REISERFS_I(inode)->i_first_direct_byte = pos1 + 1; return block_size - round_tail_len; }
/* this first locks inode (neither reads nor sync are permitted), reads tail through page cache, insert direct item. When direct item inserted successfully inode is left locked. Return value is always what we expect from it (number of cut bytes). But when tail remains in the unformatted node, we set mode to SKIP_BALANCING and unlock inode */ int indirect2direct (struct reiserfs_transaction_handle *th, struct inode * p_s_inode, struct page *page, struct path * p_s_path, /* path to the indirect item. */ const struct cpu_key * p_s_item_key, /* Key to look for unformatted node pointer to be cut. */ loff_t n_new_file_size, /* New file size. */ char * p_c_mode) { struct super_block * p_s_sb = p_s_inode->i_sb; struct item_head s_ih; unsigned long n_block_size = p_s_sb->s_blocksize; char * tail; int tail_len, round_tail_len; loff_t pos, pos1; /* position of first byte of the tail */ struct cpu_key key; REISERFS_SB(p_s_sb)->s_indirect2direct ++; *p_c_mode = M_SKIP_BALANCING; /* store item head path points to. */ copy_item_head (&s_ih, PATH_PITEM_HEAD(p_s_path)); tail_len = (n_new_file_size & (n_block_size - 1)); if (get_inode_sd_version (p_s_inode) == STAT_DATA_V2) round_tail_len = ROUND_UP (tail_len); else round_tail_len = tail_len; pos = le_ih_k_offset (&s_ih) - 1 + (ih_item_len(&s_ih) / UNFM_P_SIZE - 1) * p_s_sb->s_blocksize; pos1 = pos; // we are protected by i_sem. The tail can not disapper, not // append can be done either // we are in truncate or packing tail in file_release tail = (char *)kmap(page) ; /* this can schedule */ if (path_changed (&s_ih, p_s_path)) { /* re-search indirect item */ if ( search_for_position_by_key (p_s_sb, p_s_item_key, p_s_path) == POSITION_NOT_FOUND ) reiserfs_panic(p_s_sb, "PAP-5520: indirect2direct: " "item to be converted %K does not exist", p_s_item_key); copy_item_head(&s_ih, PATH_PITEM_HEAD(p_s_path)); #ifdef CONFIG_REISERFS_CHECK pos = le_ih_k_offset (&s_ih) - 1 + (ih_item_len(&s_ih) / UNFM_P_SIZE - 1) * p_s_sb->s_blocksize; if (pos != pos1) reiserfs_panic (p_s_sb, "vs-5530: indirect2direct: " "tail position changed while we were reading it"); #endif } /* Set direct item header to insert. */ make_le_item_head (&s_ih, NULL, get_inode_item_key_version (p_s_inode), pos1 + 1, TYPE_DIRECT, round_tail_len, 0xffff/*ih_free_space*/); /* we want a pointer to the first byte of the tail in the page. ** the page was locked and this part of the page was up to date when ** indirect2direct was called, so we know the bytes are still valid */ tail = tail + (pos & (PAGE_CACHE_SIZE - 1)) ; PATH_LAST_POSITION(p_s_path)++; key = *p_s_item_key; set_cpu_key_k_type (&key, TYPE_DIRECT); key.key_length = 4; /* Insert tail as new direct item in the tree */ if ( reiserfs_insert_item(th, p_s_path, &key, &s_ih, p_s_inode, tail ? tail : NULL) < 0 ) { /* No disk memory. So we can not convert last unformatted node to the direct item. In this case we used to adjust indirect items's ih_free_space. Now ih_free_space is not used, it would be ideal to write zeros to corresponding unformatted node. For now i_size is considered as guard for going out of file size */ kunmap(page) ; return n_block_size - round_tail_len; } kunmap(page) ; /* make sure to get the i_blocks changes from reiserfs_insert_item */ reiserfs_update_sd(th, p_s_inode); // note: we have now the same as in above direct2indirect // conversion: there are two keys which have matching first three // key components. They only differ by the fouhth one. /* We have inserted new direct item and must remove last unformatted node. */ *p_c_mode = M_CUT; /* we store position of first direct item in the in-core inode */ //mark_file_with_tail (p_s_inode, pos1 + 1); REISERFS_I(p_s_inode)->i_first_direct_byte = pos1 + 1; return n_block_size - round_tail_len; }
static int reiserfs_symlink (struct inode * parent_dir, struct dentry * dentry, const char * symname) { int retval; struct inode * inode; char * name; int item_len; struct reiserfs_transaction_handle th ; int mode = S_IFLNK | S_IRWXUGO; int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; if (!(inode = new_inode(parent_dir->i_sb))) { return -ENOMEM ; } retval = new_inode_init(inode, parent_dir, mode); if (retval) { return retval; } reiserfs_write_lock(parent_dir->i_sb); item_len = ROUND_UP (strlen (symname)); if (item_len > MAX_DIRECT_ITEM_LEN (parent_dir->i_sb->s_blocksize)) { retval = -ENAMETOOLONG; drop_new_inode(inode); goto out_failed; } name = reiserfs_kmalloc (item_len, GFP_NOFS, parent_dir->i_sb); if (!name) { drop_new_inode(inode); retval = -ENOMEM; goto out_failed; } memcpy (name, symname, strlen (symname)); padd_item (name, item_len, strlen (symname)); /* We would inherit the default ACL here, but symlinks don't get ACLs */ journal_begin(&th, parent_dir->i_sb, jbegin_count) ; retval = reiserfs_new_inode (&th, parent_dir, mode, name, strlen (symname), dentry, inode); reiserfs_kfree (name, item_len, parent_dir->i_sb); if (retval) { /* reiserfs_new_inode iputs for us */ goto out_failed; } reiserfs_update_inode_transaction(inode) ; reiserfs_update_inode_transaction(parent_dir) ; inode->i_op = &reiserfs_symlink_inode_operations; inode->i_mapping->a_ops = &reiserfs_address_space_operations; // must be sure this inode is written with this transaction // //reiserfs_update_sd (&th, inode, READ_BLOCKS); retval = reiserfs_add_entry (&th, parent_dir, dentry->d_name.name, dentry->d_name.len, inode, 1/*visible*/); if (retval) { inode->i_nlink--; reiserfs_update_sd (&th, inode); journal_end(&th, parent_dir->i_sb, jbegin_count) ; iput (inode); goto out_failed; } d_instantiate(dentry, inode); journal_end(&th, parent_dir->i_sb, jbegin_count) ; out_failed: reiserfs_write_unlock(parent_dir->i_sb); return retval; }
static int reiserfs_unlink (struct inode * dir, struct dentry *dentry) { int retval; struct inode * inode; struct reiserfs_dir_entry de; INITIALIZE_PATH (path); struct reiserfs_transaction_handle th ; int jbegin_count; unsigned long savelink; inode = dentry->d_inode; /* in this transaction we can be doing at max two balancings and update two stat datas */ jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2; reiserfs_write_lock(dir->i_sb); journal_begin(&th, dir->i_sb, jbegin_count) ; de.de_gen_number_bit_string = 0; if ( (retval = reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path, &de)) == NAME_NOT_FOUND) { retval = -ENOENT; goto end_unlink; } else if (retval == IO_ERROR) { retval = -EIO; goto end_unlink; } reiserfs_update_inode_transaction(inode) ; reiserfs_update_inode_transaction(dir) ; if (de.de_objectid != inode->i_ino) { // FIXME: compare key of an object and a key found in the // entry retval = -EIO; goto end_unlink; } if (!inode->i_nlink) { reiserfs_warning (inode->i_sb, "%s: deleting nonexistent file " "(%s:%lu), %d", __FUNCTION__, reiserfs_bdevname (inode->i_sb), inode->i_ino, inode->i_nlink); inode->i_nlink = 1; } inode->i_nlink--; /* * we schedule before doing the add_save_link call, save the link * count so we don't race */ savelink = inode->i_nlink; retval = reiserfs_cut_from_item (&th, &path, &(de.de_entry_key), dir, NULL, 0); if (retval < 0) { inode->i_nlink++; goto end_unlink; } inode->i_ctime = CURRENT_TIME; reiserfs_update_sd (&th, inode); dir->i_size -= (de.de_entrylen + DEH_SIZE); dir->i_ctime = dir->i_mtime = CURRENT_TIME; reiserfs_update_sd (&th, dir); if (!savelink) /* prevent file from getting lost */ add_save_link (&th, inode, 0/* not truncate */); journal_end(&th, dir->i_sb, jbegin_count) ; reiserfs_check_path(&path) ; reiserfs_write_unlock(dir->i_sb); return 0; end_unlink: pathrelse (&path); journal_end(&th, dir->i_sb, jbegin_count) ; reiserfs_check_path(&path) ; reiserfs_write_unlock(dir->i_sb); return retval; }
static int reiserfs_rmdir (struct inode * dir, struct dentry *dentry) { int retval; struct inode * inode; struct reiserfs_transaction_handle th ; int jbegin_count; INITIALIZE_PATH (path); struct reiserfs_dir_entry de; /* we will be doing 2 balancings and update 2 stat data */ jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2; reiserfs_write_lock(dir->i_sb); journal_begin(&th, dir->i_sb, jbegin_count) ; de.de_gen_number_bit_string = 0; if ( (retval = reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path, &de)) == NAME_NOT_FOUND) { retval = -ENOENT; goto end_rmdir; } else if ( retval == IO_ERROR) { retval = -EIO; goto end_rmdir; } inode = dentry->d_inode; reiserfs_update_inode_transaction(inode) ; reiserfs_update_inode_transaction(dir) ; if (de.de_objectid != inode->i_ino) { // FIXME: compare key of an object and a key found in the // entry retval = -EIO; goto end_rmdir; } if (!reiserfs_empty_dir(inode)) { retval = -ENOTEMPTY; goto end_rmdir; } /* cut entry from dir directory */ retval = reiserfs_cut_from_item (&th, &path, &(de.de_entry_key), dir, NULL, /* page */ 0/*new file size - not used here*/); if (retval < 0) goto end_rmdir; if ( inode->i_nlink != 2 && inode->i_nlink != 1 ) reiserfs_warning (inode->i_sb, "%s: empty directory has nlink " "!= 2 (%d)", __FUNCTION__, inode->i_nlink); inode->i_nlink = 0; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; reiserfs_update_sd (&th, inode); DEC_DIR_INODE_NLINK(dir) dir->i_size -= (DEH_SIZE + de.de_entrylen); reiserfs_update_sd (&th, dir); /* prevent empty directory from getting lost */ add_save_link (&th, inode, 0/* not truncate */); journal_end(&th, dir->i_sb, jbegin_count) ; reiserfs_check_path(&path) ; reiserfs_write_unlock(dir->i_sb); return 0; end_rmdir: /* we must release path, because we did not call reiserfs_cut_from_item, or reiserfs_cut_from_item does not release path if operation was not complete */ pathrelse (&path); journal_end(&th, dir->i_sb, jbegin_count) ; reiserfs_write_unlock(dir->i_sb); return retval; }
static int reiserfs_unlink(struct inode *dir, struct dentry *dentry) { int retval, err; struct inode *inode; struct reiserfs_dir_entry de; INITIALIZE_PATH(path); struct reiserfs_transaction_handle th; int jbegin_count; unsigned long savelink; int depth; dquot_initialize(dir); inode = dentry->d_inode; /* in this transaction we can be doing at max two balancings and update * two stat datas, we change quotas of the owner of the directory and of * the owner of the parent directory. The quota structure is possibly * deleted only on iput => outside of this transaction */ jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb); depth = reiserfs_write_lock_once(dir->i_sb); retval = journal_begin(&th, dir->i_sb, jbegin_count); if (retval) goto out_unlink; de.de_gen_number_bit_string = NULL; if ((retval = reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &path, &de)) == NAME_NOT_FOUND) { retval = -ENOENT; goto end_unlink; } else if (retval == IO_ERROR) { retval = -EIO; goto end_unlink; } reiserfs_update_inode_transaction(inode); reiserfs_update_inode_transaction(dir); if (de.de_objectid != inode->i_ino) { // FIXME: compare key of an object and a key found in the // entry retval = -EIO; goto end_unlink; } if (!inode->i_nlink) { reiserfs_warning(inode->i_sb, "reiserfs-7042", "deleting nonexistent file (%lu), %d", inode->i_ino, inode->i_nlink); set_nlink(inode, 1); } drop_nlink(inode); /* * we schedule before doing the add_save_link call, save the link * count so we don't race */ savelink = inode->i_nlink; retval = reiserfs_cut_from_item(&th, &path, &(de.de_entry_key), dir, NULL, 0); if (retval < 0) { inc_nlink(inode); goto end_unlink; } inode->i_ctime = CURRENT_TIME_SEC; reiserfs_update_sd(&th, inode); dir->i_size -= (de.de_entrylen + DEH_SIZE); dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; reiserfs_update_sd(&th, dir); if (!savelink) /* prevent file from getting lost */ add_save_link(&th, inode, 0 /* not truncate */ ); retval = journal_end(&th, dir->i_sb, jbegin_count); reiserfs_check_path(&path); reiserfs_write_unlock_once(dir->i_sb, depth); return retval; end_unlink: pathrelse(&path); err = journal_end(&th, dir->i_sb, jbegin_count); reiserfs_check_path(&path); if (err) retval = err; out_unlink: reiserfs_write_unlock_once(dir->i_sb, depth); return retval; }
static int reiserfs_symlink(struct inode *parent_dir, struct dentry *dentry, const char *symname) { int retval; struct inode *inode; char *name; int item_len; struct reiserfs_transaction_handle th; struct reiserfs_security_handle security; int mode = S_IFLNK | S_IRWXUGO; /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(parent_dir->i_sb) + REISERFS_QUOTA_TRANS_BLOCKS(parent_dir->i_sb)); dquot_initialize(parent_dir); if (!(inode = new_inode(parent_dir->i_sb))) { return -ENOMEM; } new_inode_init(inode, parent_dir, mode); retval = reiserfs_security_init(parent_dir, inode, &dentry->d_name, &security); if (retval < 0) { drop_new_inode(inode); return retval; } jbegin_count += retval; reiserfs_write_lock(parent_dir->i_sb); item_len = ROUND_UP(strlen(symname)); if (item_len > MAX_DIRECT_ITEM_LEN(parent_dir->i_sb->s_blocksize)) { retval = -ENAMETOOLONG; drop_new_inode(inode); goto out_failed; } name = kmalloc(item_len, GFP_NOFS); if (!name) { drop_new_inode(inode); retval = -ENOMEM; goto out_failed; } memcpy(name, symname, strlen(symname)); padd_item(name, item_len, strlen(symname)); retval = journal_begin(&th, parent_dir->i_sb, jbegin_count); if (retval) { drop_new_inode(inode); kfree(name); goto out_failed; } retval = reiserfs_new_inode(&th, parent_dir, mode, name, strlen(symname), dentry, inode, &security); kfree(name); if (retval) { /* reiserfs_new_inode iputs for us */ goto out_failed; } reiserfs_update_inode_transaction(inode); reiserfs_update_inode_transaction(parent_dir); inode->i_op = &reiserfs_symlink_inode_operations; inode->i_mapping->a_ops = &reiserfs_address_space_operations; // must be sure this inode is written with this transaction // //reiserfs_update_sd (&th, inode, READ_BLOCKS); retval = reiserfs_add_entry(&th, parent_dir, dentry->d_name.name, dentry->d_name.len, inode, 1 /*visible */ ); if (retval) { int err; drop_nlink(inode); reiserfs_update_sd(&th, inode); err = journal_end(&th, parent_dir->i_sb, jbegin_count); if (err) retval = err; unlock_new_inode(inode); iput(inode); goto out_failed; } unlock_new_inode(inode); d_instantiate(dentry, inode); retval = journal_end(&th, parent_dir->i_sb, jbegin_count); out_failed: reiserfs_write_unlock(parent_dir->i_sb); return retval; }
static int reiserfs_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t rdev) { int retval; struct inode * inode; struct reiserfs_transaction_handle th ; int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; int locked; if (!new_valid_dev(rdev)) return -EINVAL; if (!(inode = new_inode(dir->i_sb))) { return -ENOMEM ; } retval = new_inode_init(inode, dir, mode); if (retval) return retval; locked = reiserfs_cache_default_acl (dir); reiserfs_write_lock(dir->i_sb); if (locked) reiserfs_write_lock_xattrs (dir->i_sb); journal_begin(&th, dir->i_sb, jbegin_count) ; retval = reiserfs_new_inode (&th, dir, mode, 0, 0/*i_size*/, dentry, inode); if (locked) reiserfs_write_unlock_xattrs (dir->i_sb); if (retval) { goto out_failed; } inode->i_op = &reiserfs_special_inode_operations; init_special_inode(inode, inode->i_mode, rdev) ; //FIXME: needed for block and char devices only reiserfs_update_sd (&th, inode); reiserfs_update_inode_transaction(inode) ; reiserfs_update_inode_transaction(dir) ; retval = reiserfs_add_entry (&th, dir, dentry->d_name.name, dentry->d_name.len, inode, 1/*visible*/); if (retval) { inode->i_nlink--; reiserfs_update_sd (&th, inode); journal_end(&th, dir->i_sb, jbegin_count) ; iput (inode); goto out_failed; } d_instantiate(dentry, inode); journal_end(&th, dir->i_sb, jbegin_count) ; out_failed: reiserfs_write_unlock(dir->i_sb); return retval; }