18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Trivial changes by Alan Cox to remove EHASHCOLLISION for compatibility
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Trivial Changes:
78c2ecf20Sopenharmony_ci * Rights granted to Hans Reiser to redistribute under other terms providing
88c2ecf20Sopenharmony_ci * he accepts all liability including but not limited to patent, fitness
98c2ecf20Sopenharmony_ci * for purpose, and direct or indirect claims arising from failure to perform.
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * NO WARRANTY
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <linux/time.h>
158c2ecf20Sopenharmony_ci#include <linux/bitops.h>
168c2ecf20Sopenharmony_ci#include <linux/slab.h>
178c2ecf20Sopenharmony_ci#include "reiserfs.h"
188c2ecf20Sopenharmony_ci#include "acl.h"
198c2ecf20Sopenharmony_ci#include "xattr.h"
208c2ecf20Sopenharmony_ci#include <linux/quotaops.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#define INC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) { inc_nlink(i); if (i->i_nlink >= REISERFS_LINK_MAX) set_nlink(i, 1); }
238c2ecf20Sopenharmony_ci#define DEC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) drop_nlink(i);
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci/*
268c2ecf20Sopenharmony_ci * directory item contains array of entry headers. This performs
278c2ecf20Sopenharmony_ci * binary search through that array
288c2ecf20Sopenharmony_ci */
298c2ecf20Sopenharmony_cistatic int bin_search_in_dir_item(struct reiserfs_dir_entry *de, loff_t off)
308c2ecf20Sopenharmony_ci{
318c2ecf20Sopenharmony_ci	struct item_head *ih = de->de_ih;
328c2ecf20Sopenharmony_ci	struct reiserfs_de_head *deh = de->de_deh;
338c2ecf20Sopenharmony_ci	int rbound, lbound, j;
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	lbound = 0;
368c2ecf20Sopenharmony_ci	rbound = ih_entry_count(ih) - 1;
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	for (j = (rbound + lbound) / 2; lbound <= rbound;
398c2ecf20Sopenharmony_ci	     j = (rbound + lbound) / 2) {
408c2ecf20Sopenharmony_ci		if (off < deh_offset(deh + j)) {
418c2ecf20Sopenharmony_ci			rbound = j - 1;
428c2ecf20Sopenharmony_ci			continue;
438c2ecf20Sopenharmony_ci		}
448c2ecf20Sopenharmony_ci		if (off > deh_offset(deh + j)) {
458c2ecf20Sopenharmony_ci			lbound = j + 1;
468c2ecf20Sopenharmony_ci			continue;
478c2ecf20Sopenharmony_ci		}
488c2ecf20Sopenharmony_ci		/* this is not name found, but matched third key component */
498c2ecf20Sopenharmony_ci		de->de_entry_num = j;
508c2ecf20Sopenharmony_ci		return NAME_FOUND;
518c2ecf20Sopenharmony_ci	}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	de->de_entry_num = lbound;
548c2ecf20Sopenharmony_ci	return NAME_NOT_FOUND;
558c2ecf20Sopenharmony_ci}
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci/*
588c2ecf20Sopenharmony_ci * comment?  maybe something like set de to point to what the path points to?
598c2ecf20Sopenharmony_ci */
608c2ecf20Sopenharmony_cistatic inline void set_de_item_location(struct reiserfs_dir_entry *de,
618c2ecf20Sopenharmony_ci					struct treepath *path)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	de->de_bh = get_last_bh(path);
648c2ecf20Sopenharmony_ci	de->de_ih = tp_item_head(path);
658c2ecf20Sopenharmony_ci	de->de_deh = B_I_DEH(de->de_bh, de->de_ih);
668c2ecf20Sopenharmony_ci	de->de_item_num = PATH_LAST_POSITION(path);
678c2ecf20Sopenharmony_ci}
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci/*
708c2ecf20Sopenharmony_ci * de_bh, de_ih, de_deh (points to first element of array), de_item_num is set
718c2ecf20Sopenharmony_ci */
728c2ecf20Sopenharmony_ciinline void set_de_name_and_namelen(struct reiserfs_dir_entry *de)
738c2ecf20Sopenharmony_ci{
748c2ecf20Sopenharmony_ci	struct reiserfs_de_head *deh = de->de_deh + de->de_entry_num;
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	BUG_ON(de->de_entry_num >= ih_entry_count(de->de_ih));
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	de->de_entrylen = entry_length(de->de_bh, de->de_ih, de->de_entry_num);
798c2ecf20Sopenharmony_ci	de->de_namelen = de->de_entrylen - (de_with_sd(deh) ? SD_SIZE : 0);
808c2ecf20Sopenharmony_ci	de->de_name = ih_item_body(de->de_bh, de->de_ih) + deh_location(deh);
818c2ecf20Sopenharmony_ci	if (de->de_name[de->de_namelen - 1] == 0)
828c2ecf20Sopenharmony_ci		de->de_namelen = strlen(de->de_name);
838c2ecf20Sopenharmony_ci}
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci/* what entry points to */
868c2ecf20Sopenharmony_cistatic inline void set_de_object_key(struct reiserfs_dir_entry *de)
878c2ecf20Sopenharmony_ci{
888c2ecf20Sopenharmony_ci	BUG_ON(de->de_entry_num >= ih_entry_count(de->de_ih));
898c2ecf20Sopenharmony_ci	de->de_dir_id = deh_dir_id(&de->de_deh[de->de_entry_num]);
908c2ecf20Sopenharmony_ci	de->de_objectid = deh_objectid(&de->de_deh[de->de_entry_num]);
918c2ecf20Sopenharmony_ci}
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_cistatic inline void store_de_entry_key(struct reiserfs_dir_entry *de)
948c2ecf20Sopenharmony_ci{
958c2ecf20Sopenharmony_ci	struct reiserfs_de_head *deh = de->de_deh + de->de_entry_num;
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	BUG_ON(de->de_entry_num >= ih_entry_count(de->de_ih));
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	/* store key of the found entry */
1008c2ecf20Sopenharmony_ci	de->de_entry_key.version = KEY_FORMAT_3_5;
1018c2ecf20Sopenharmony_ci	de->de_entry_key.on_disk_key.k_dir_id =
1028c2ecf20Sopenharmony_ci	    le32_to_cpu(de->de_ih->ih_key.k_dir_id);
1038c2ecf20Sopenharmony_ci	de->de_entry_key.on_disk_key.k_objectid =
1048c2ecf20Sopenharmony_ci	    le32_to_cpu(de->de_ih->ih_key.k_objectid);
1058c2ecf20Sopenharmony_ci	set_cpu_key_k_offset(&de->de_entry_key, deh_offset(deh));
1068c2ecf20Sopenharmony_ci	set_cpu_key_k_type(&de->de_entry_key, TYPE_DIRENTRY);
1078c2ecf20Sopenharmony_ci}
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci/*
1108c2ecf20Sopenharmony_ci * We assign a key to each directory item, and place multiple entries in a
1118c2ecf20Sopenharmony_ci * single directory item.  A directory item has a key equal to the key of
1128c2ecf20Sopenharmony_ci * the first directory entry in it.
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci * This function first calls search_by_key, then, if item whose first entry
1158c2ecf20Sopenharmony_ci * matches is not found it looks for the entry inside directory item found
1168c2ecf20Sopenharmony_ci * by search_by_key. Fills the path to the entry, and to the entry position
1178c2ecf20Sopenharmony_ci * in the item
1188c2ecf20Sopenharmony_ci */
1198c2ecf20Sopenharmony_ci/* The function is NOT SCHEDULE-SAFE! */
1208c2ecf20Sopenharmony_ciint search_by_entry_key(struct super_block *sb, const struct cpu_key *key,
1218c2ecf20Sopenharmony_ci			struct treepath *path, struct reiserfs_dir_entry *de)
1228c2ecf20Sopenharmony_ci{
1238c2ecf20Sopenharmony_ci	int retval;
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	retval = search_item(sb, key, path);
1268c2ecf20Sopenharmony_ci	switch (retval) {
1278c2ecf20Sopenharmony_ci	case ITEM_NOT_FOUND:
1288c2ecf20Sopenharmony_ci		if (!PATH_LAST_POSITION(path)) {
1298c2ecf20Sopenharmony_ci			reiserfs_error(sb, "vs-7000", "search_by_key "
1308c2ecf20Sopenharmony_ci				       "returned item position == 0");
1318c2ecf20Sopenharmony_ci			pathrelse(path);
1328c2ecf20Sopenharmony_ci			return IO_ERROR;
1338c2ecf20Sopenharmony_ci		}
1348c2ecf20Sopenharmony_ci		PATH_LAST_POSITION(path)--;
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	case ITEM_FOUND:
1378c2ecf20Sopenharmony_ci		break;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	case IO_ERROR:
1408c2ecf20Sopenharmony_ci		return retval;
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	default:
1438c2ecf20Sopenharmony_ci		pathrelse(path);
1448c2ecf20Sopenharmony_ci		reiserfs_error(sb, "vs-7002", "no path to here");
1458c2ecf20Sopenharmony_ci		return IO_ERROR;
1468c2ecf20Sopenharmony_ci	}
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	set_de_item_location(de, path);
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci#ifdef CONFIG_REISERFS_CHECK
1518c2ecf20Sopenharmony_ci	if (!is_direntry_le_ih(de->de_ih) ||
1528c2ecf20Sopenharmony_ci	    COMP_SHORT_KEYS(&de->de_ih->ih_key, key)) {
1538c2ecf20Sopenharmony_ci		print_block(de->de_bh, 0, -1, -1);
1548c2ecf20Sopenharmony_ci		reiserfs_panic(sb, "vs-7005", "found item %h is not directory "
1558c2ecf20Sopenharmony_ci			       "item or does not belong to the same directory "
1568c2ecf20Sopenharmony_ci			       "as key %K", de->de_ih, key);
1578c2ecf20Sopenharmony_ci	}
1588c2ecf20Sopenharmony_ci#endif				/* CONFIG_REISERFS_CHECK */
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	/*
1618c2ecf20Sopenharmony_ci	 * binary search in directory item by third component of the
1628c2ecf20Sopenharmony_ci	 * key. sets de->de_entry_num of de
1638c2ecf20Sopenharmony_ci	 */
1648c2ecf20Sopenharmony_ci	retval = bin_search_in_dir_item(de, cpu_key_k_offset(key));
1658c2ecf20Sopenharmony_ci	path->pos_in_item = de->de_entry_num;
1668c2ecf20Sopenharmony_ci	if (retval != NAME_NOT_FOUND) {
1678c2ecf20Sopenharmony_ci		/*
1688c2ecf20Sopenharmony_ci		 * ugly, but rename needs de_bh, de_deh, de_name,
1698c2ecf20Sopenharmony_ci		 * de_namelen, de_objectid set
1708c2ecf20Sopenharmony_ci		 */
1718c2ecf20Sopenharmony_ci		set_de_name_and_namelen(de);
1728c2ecf20Sopenharmony_ci		set_de_object_key(de);
1738c2ecf20Sopenharmony_ci	}
1748c2ecf20Sopenharmony_ci	return retval;
1758c2ecf20Sopenharmony_ci}
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci/* Keyed 32-bit hash function using TEA in a Davis-Meyer function */
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci/*
1808c2ecf20Sopenharmony_ci * The third component is hashed, and you can choose from more than
1818c2ecf20Sopenharmony_ci * one hash function.  Per directory hashes are not yet implemented
1828c2ecf20Sopenharmony_ci * but are thought about. This function should be moved to hashes.c
1838c2ecf20Sopenharmony_ci * Jedi, please do so.  -Hans
1848c2ecf20Sopenharmony_ci */
1858c2ecf20Sopenharmony_cistatic __u32 get_third_component(struct super_block *s,
1868c2ecf20Sopenharmony_ci				 const char *name, int len)
1878c2ecf20Sopenharmony_ci{
1888c2ecf20Sopenharmony_ci	__u32 res;
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	if (!len || (len == 1 && name[0] == '.'))
1918c2ecf20Sopenharmony_ci		return DOT_OFFSET;
1928c2ecf20Sopenharmony_ci	if (len == 2 && name[0] == '.' && name[1] == '.')
1938c2ecf20Sopenharmony_ci		return DOT_DOT_OFFSET;
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	res = REISERFS_SB(s)->s_hash_function(name, len);
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	/* take bits from 7-th to 30-th including both bounds */
1988c2ecf20Sopenharmony_ci	res = GET_HASH_VALUE(res);
1998c2ecf20Sopenharmony_ci	if (res == 0)
2008c2ecf20Sopenharmony_ci		/*
2018c2ecf20Sopenharmony_ci		 * needed to have no names before "." and ".." those have hash
2028c2ecf20Sopenharmony_ci		 * value == 0 and generation conters 1 and 2 accordingly
2038c2ecf20Sopenharmony_ci		 */
2048c2ecf20Sopenharmony_ci		res = 128;
2058c2ecf20Sopenharmony_ci	return res + MAX_GENERATION_NUMBER;
2068c2ecf20Sopenharmony_ci}
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_cistatic int reiserfs_match(struct reiserfs_dir_entry *de,
2098c2ecf20Sopenharmony_ci			  const char *name, int namelen)
2108c2ecf20Sopenharmony_ci{
2118c2ecf20Sopenharmony_ci	int retval = NAME_NOT_FOUND;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	if ((namelen == de->de_namelen) &&
2148c2ecf20Sopenharmony_ci	    !memcmp(de->de_name, name, de->de_namelen))
2158c2ecf20Sopenharmony_ci		retval =
2168c2ecf20Sopenharmony_ci		    (de_visible(de->de_deh + de->de_entry_num) ? NAME_FOUND :
2178c2ecf20Sopenharmony_ci		     NAME_FOUND_INVISIBLE);
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	return retval;
2208c2ecf20Sopenharmony_ci}
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci/* de's de_bh, de_ih, de_deh, de_item_num, de_entry_num are set already */
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci/* used when hash collisions exist */
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_cistatic int linear_search_in_dir_item(struct cpu_key *key,
2278c2ecf20Sopenharmony_ci				     struct reiserfs_dir_entry *de,
2288c2ecf20Sopenharmony_ci				     const char *name, int namelen)
2298c2ecf20Sopenharmony_ci{
2308c2ecf20Sopenharmony_ci	struct reiserfs_de_head *deh = de->de_deh;
2318c2ecf20Sopenharmony_ci	int retval;
2328c2ecf20Sopenharmony_ci	int i;
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	i = de->de_entry_num;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	if (i == ih_entry_count(de->de_ih) ||
2378c2ecf20Sopenharmony_ci	    GET_HASH_VALUE(deh_offset(deh + i)) !=
2388c2ecf20Sopenharmony_ci	    GET_HASH_VALUE(cpu_key_k_offset(key))) {
2398c2ecf20Sopenharmony_ci		i--;
2408c2ecf20Sopenharmony_ci	}
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	RFALSE(de->de_deh != B_I_DEH(de->de_bh, de->de_ih),
2438c2ecf20Sopenharmony_ci	       "vs-7010: array of entry headers not found");
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	deh += i;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	for (; i >= 0; i--, deh--) {
2488c2ecf20Sopenharmony_ci		/* hash value does not match, no need to check whole name */
2498c2ecf20Sopenharmony_ci		if (GET_HASH_VALUE(deh_offset(deh)) !=
2508c2ecf20Sopenharmony_ci		    GET_HASH_VALUE(cpu_key_k_offset(key))) {
2518c2ecf20Sopenharmony_ci			return NAME_NOT_FOUND;
2528c2ecf20Sopenharmony_ci		}
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci		/* mark that this generation number is used */
2558c2ecf20Sopenharmony_ci		if (de->de_gen_number_bit_string)
2568c2ecf20Sopenharmony_ci			set_bit(GET_GENERATION_NUMBER(deh_offset(deh)),
2578c2ecf20Sopenharmony_ci				de->de_gen_number_bit_string);
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci		/* calculate pointer to name and namelen */
2608c2ecf20Sopenharmony_ci		de->de_entry_num = i;
2618c2ecf20Sopenharmony_ci		set_de_name_and_namelen(de);
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci		/*
2648c2ecf20Sopenharmony_ci		 * de's de_name, de_namelen, de_recordlen are set.
2658c2ecf20Sopenharmony_ci		 * Fill the rest.
2668c2ecf20Sopenharmony_ci		 */
2678c2ecf20Sopenharmony_ci		if ((retval =
2688c2ecf20Sopenharmony_ci		     reiserfs_match(de, name, namelen)) != NAME_NOT_FOUND) {
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci			/* key of pointed object */
2718c2ecf20Sopenharmony_ci			set_de_object_key(de);
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci			store_de_entry_key(de);
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci			/* retval can be NAME_FOUND or NAME_FOUND_INVISIBLE */
2768c2ecf20Sopenharmony_ci			return retval;
2778c2ecf20Sopenharmony_ci		}
2788c2ecf20Sopenharmony_ci	}
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	if (GET_GENERATION_NUMBER(le_ih_k_offset(de->de_ih)) == 0)
2818c2ecf20Sopenharmony_ci		/*
2828c2ecf20Sopenharmony_ci		 * we have reached left most entry in the node. In common we
2838c2ecf20Sopenharmony_ci		 * have to go to the left neighbor, but if generation counter
2848c2ecf20Sopenharmony_ci		 * is 0 already, we know for sure, that there is no name with
2858c2ecf20Sopenharmony_ci		 * the same hash value
2868c2ecf20Sopenharmony_ci		 */
2878c2ecf20Sopenharmony_ci		/*
2888c2ecf20Sopenharmony_ci		 * FIXME: this work correctly only because hash value can not
2898c2ecf20Sopenharmony_ci		 *  be 0. Btw, in case of Yura's hash it is probably possible,
2908c2ecf20Sopenharmony_ci		 * so, this is a bug
2918c2ecf20Sopenharmony_ci		 */
2928c2ecf20Sopenharmony_ci		return NAME_NOT_FOUND;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	RFALSE(de->de_item_num,
2958c2ecf20Sopenharmony_ci	       "vs-7015: two diritems of the same directory in one node?");
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	return GOTO_PREVIOUS_ITEM;
2988c2ecf20Sopenharmony_ci}
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci/*
3018c2ecf20Sopenharmony_ci * may return NAME_FOUND, NAME_FOUND_INVISIBLE, NAME_NOT_FOUND
3028c2ecf20Sopenharmony_ci * FIXME: should add something like IOERROR
3038c2ecf20Sopenharmony_ci */
3048c2ecf20Sopenharmony_cistatic int reiserfs_find_entry(struct inode *dir, const char *name, int namelen,
3058c2ecf20Sopenharmony_ci			       struct treepath *path_to_entry,
3068c2ecf20Sopenharmony_ci			       struct reiserfs_dir_entry *de)
3078c2ecf20Sopenharmony_ci{
3088c2ecf20Sopenharmony_ci	struct cpu_key key_to_search;
3098c2ecf20Sopenharmony_ci	int retval;
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	if (namelen > REISERFS_MAX_NAME(dir->i_sb->s_blocksize))
3128c2ecf20Sopenharmony_ci		return NAME_NOT_FOUND;
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	/* we will search for this key in the tree */
3158c2ecf20Sopenharmony_ci	make_cpu_key(&key_to_search, dir,
3168c2ecf20Sopenharmony_ci		     get_third_component(dir->i_sb, name, namelen),
3178c2ecf20Sopenharmony_ci		     TYPE_DIRENTRY, 3);
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	while (1) {
3208c2ecf20Sopenharmony_ci		retval =
3218c2ecf20Sopenharmony_ci		    search_by_entry_key(dir->i_sb, &key_to_search,
3228c2ecf20Sopenharmony_ci					path_to_entry, de);
3238c2ecf20Sopenharmony_ci		if (retval == IO_ERROR) {
3248c2ecf20Sopenharmony_ci			reiserfs_error(dir->i_sb, "zam-7001", "io error");
3258c2ecf20Sopenharmony_ci			return IO_ERROR;
3268c2ecf20Sopenharmony_ci		}
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci		/* compare names for all entries having given hash value */
3298c2ecf20Sopenharmony_ci		retval =
3308c2ecf20Sopenharmony_ci		    linear_search_in_dir_item(&key_to_search, de, name,
3318c2ecf20Sopenharmony_ci					      namelen);
3328c2ecf20Sopenharmony_ci		/*
3338c2ecf20Sopenharmony_ci		 * there is no need to scan directory anymore.
3348c2ecf20Sopenharmony_ci		 * Given entry found or does not exist
3358c2ecf20Sopenharmony_ci		 */
3368c2ecf20Sopenharmony_ci		if (retval != GOTO_PREVIOUS_ITEM) {
3378c2ecf20Sopenharmony_ci			path_to_entry->pos_in_item = de->de_entry_num;
3388c2ecf20Sopenharmony_ci			return retval;
3398c2ecf20Sopenharmony_ci		}
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci		/*
3428c2ecf20Sopenharmony_ci		 * there is left neighboring item of this directory
3438c2ecf20Sopenharmony_ci		 * and given entry can be there
3448c2ecf20Sopenharmony_ci		 */
3458c2ecf20Sopenharmony_ci		set_cpu_key_k_offset(&key_to_search,
3468c2ecf20Sopenharmony_ci				     le_ih_k_offset(de->de_ih) - 1);
3478c2ecf20Sopenharmony_ci		pathrelse(path_to_entry);
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	}			/* while (1) */
3508c2ecf20Sopenharmony_ci}
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_cistatic struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
3538c2ecf20Sopenharmony_ci				      unsigned int flags)
3548c2ecf20Sopenharmony_ci{
3558c2ecf20Sopenharmony_ci	int retval;
3568c2ecf20Sopenharmony_ci	struct inode *inode = NULL;
3578c2ecf20Sopenharmony_ci	struct reiserfs_dir_entry de;
3588c2ecf20Sopenharmony_ci	INITIALIZE_PATH(path_to_entry);
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	if (REISERFS_MAX_NAME(dir->i_sb->s_blocksize) < dentry->d_name.len)
3618c2ecf20Sopenharmony_ci		return ERR_PTR(-ENAMETOOLONG);
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci	reiserfs_write_lock(dir->i_sb);
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	de.de_gen_number_bit_string = NULL;
3668c2ecf20Sopenharmony_ci	retval =
3678c2ecf20Sopenharmony_ci	    reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len,
3688c2ecf20Sopenharmony_ci				&path_to_entry, &de);
3698c2ecf20Sopenharmony_ci	pathrelse(&path_to_entry);
3708c2ecf20Sopenharmony_ci	if (retval == NAME_FOUND) {
3718c2ecf20Sopenharmony_ci		inode = reiserfs_iget(dir->i_sb,
3728c2ecf20Sopenharmony_ci				      (struct cpu_key *)&de.de_dir_id);
3738c2ecf20Sopenharmony_ci		if (!inode || IS_ERR(inode)) {
3748c2ecf20Sopenharmony_ci			reiserfs_write_unlock(dir->i_sb);
3758c2ecf20Sopenharmony_ci			return ERR_PTR(-EACCES);
3768c2ecf20Sopenharmony_ci		}
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci		/*
3798c2ecf20Sopenharmony_ci		 * Propagate the private flag so we know we're
3808c2ecf20Sopenharmony_ci		 * in the priv tree.  Also clear IOP_XATTR
3818c2ecf20Sopenharmony_ci		 * since we don't have xattrs on xattr files.
3828c2ecf20Sopenharmony_ci		 */
3838c2ecf20Sopenharmony_ci		if (IS_PRIVATE(dir)) {
3848c2ecf20Sopenharmony_ci			inode->i_flags |= S_PRIVATE;
3858c2ecf20Sopenharmony_ci			inode->i_opflags &= ~IOP_XATTR;
3868c2ecf20Sopenharmony_ci		}
3878c2ecf20Sopenharmony_ci	}
3888c2ecf20Sopenharmony_ci	reiserfs_write_unlock(dir->i_sb);
3898c2ecf20Sopenharmony_ci	if (retval == IO_ERROR) {
3908c2ecf20Sopenharmony_ci		return ERR_PTR(-EIO);
3918c2ecf20Sopenharmony_ci	}
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	return d_splice_alias(inode, dentry);
3948c2ecf20Sopenharmony_ci}
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci/*
3978c2ecf20Sopenharmony_ci * looks up the dentry of the parent directory for child.
3988c2ecf20Sopenharmony_ci * taken from ext2_get_parent
3998c2ecf20Sopenharmony_ci */
4008c2ecf20Sopenharmony_cistruct dentry *reiserfs_get_parent(struct dentry *child)
4018c2ecf20Sopenharmony_ci{
4028c2ecf20Sopenharmony_ci	int retval;
4038c2ecf20Sopenharmony_ci	struct inode *inode = NULL;
4048c2ecf20Sopenharmony_ci	struct reiserfs_dir_entry de;
4058c2ecf20Sopenharmony_ci	INITIALIZE_PATH(path_to_entry);
4068c2ecf20Sopenharmony_ci	struct inode *dir = d_inode(child);
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	if (dir->i_nlink == 0) {
4098c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOENT);
4108c2ecf20Sopenharmony_ci	}
4118c2ecf20Sopenharmony_ci	de.de_gen_number_bit_string = NULL;
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	reiserfs_write_lock(dir->i_sb);
4148c2ecf20Sopenharmony_ci	retval = reiserfs_find_entry(dir, "..", 2, &path_to_entry, &de);
4158c2ecf20Sopenharmony_ci	pathrelse(&path_to_entry);
4168c2ecf20Sopenharmony_ci	if (retval != NAME_FOUND) {
4178c2ecf20Sopenharmony_ci		reiserfs_write_unlock(dir->i_sb);
4188c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOENT);
4198c2ecf20Sopenharmony_ci	}
4208c2ecf20Sopenharmony_ci	inode = reiserfs_iget(dir->i_sb, (struct cpu_key *)&de.de_dir_id);
4218c2ecf20Sopenharmony_ci	reiserfs_write_unlock(dir->i_sb);
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci	return d_obtain_alias(inode);
4248c2ecf20Sopenharmony_ci}
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci/* add entry to the directory (entry can be hidden).
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ciinsert definition of when hidden directories are used here -Hans
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci Does not mark dir   inode dirty, do it after successesfull call to it */
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_cistatic int reiserfs_add_entry(struct reiserfs_transaction_handle *th,
4338c2ecf20Sopenharmony_ci			      struct inode *dir, const char *name, int namelen,
4348c2ecf20Sopenharmony_ci			      struct inode *inode, int visible)
4358c2ecf20Sopenharmony_ci{
4368c2ecf20Sopenharmony_ci	struct cpu_key entry_key;
4378c2ecf20Sopenharmony_ci	struct reiserfs_de_head *deh;
4388c2ecf20Sopenharmony_ci	INITIALIZE_PATH(path);
4398c2ecf20Sopenharmony_ci	struct reiserfs_dir_entry de;
4408c2ecf20Sopenharmony_ci	DECLARE_BITMAP(bit_string, MAX_GENERATION_NUMBER + 1);
4418c2ecf20Sopenharmony_ci	int gen_number;
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	/*
4448c2ecf20Sopenharmony_ci	 * 48 bytes now and we avoid kmalloc if we
4458c2ecf20Sopenharmony_ci	 * create file with short name
4468c2ecf20Sopenharmony_ci	 */
4478c2ecf20Sopenharmony_ci	char small_buf[32 + DEH_SIZE];
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci	char *buffer;
4508c2ecf20Sopenharmony_ci	int buflen, paste_size;
4518c2ecf20Sopenharmony_ci	int retval;
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	BUG_ON(!th->t_trans_id);
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci	/* cannot allow items to be added into a busy deleted directory */
4568c2ecf20Sopenharmony_ci	if (!namelen)
4578c2ecf20Sopenharmony_ci		return -EINVAL;
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci	if (namelen > REISERFS_MAX_NAME(dir->i_sb->s_blocksize))
4608c2ecf20Sopenharmony_ci		return -ENAMETOOLONG;
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	/* each entry has unique key. compose it */
4638c2ecf20Sopenharmony_ci	make_cpu_key(&entry_key, dir,
4648c2ecf20Sopenharmony_ci		     get_third_component(dir->i_sb, name, namelen),
4658c2ecf20Sopenharmony_ci		     TYPE_DIRENTRY, 3);
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	/* get memory for composing the entry */
4688c2ecf20Sopenharmony_ci	buflen = DEH_SIZE + ROUND_UP(namelen);
4698c2ecf20Sopenharmony_ci	if (buflen > sizeof(small_buf)) {
4708c2ecf20Sopenharmony_ci		buffer = kmalloc(buflen, GFP_NOFS);
4718c2ecf20Sopenharmony_ci		if (!buffer)
4728c2ecf20Sopenharmony_ci			return -ENOMEM;
4738c2ecf20Sopenharmony_ci	} else
4748c2ecf20Sopenharmony_ci		buffer = small_buf;
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_ci	paste_size =
4778c2ecf20Sopenharmony_ci	    (get_inode_sd_version(dir) ==
4788c2ecf20Sopenharmony_ci	     STAT_DATA_V1) ? (DEH_SIZE + namelen) : buflen;
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	/*
4818c2ecf20Sopenharmony_ci	 * fill buffer : directory entry head, name[, dir objectid | ,
4828c2ecf20Sopenharmony_ci	 * stat data | ,stat data, dir objectid ]
4838c2ecf20Sopenharmony_ci	 */
4848c2ecf20Sopenharmony_ci	deh = (struct reiserfs_de_head *)buffer;
4858c2ecf20Sopenharmony_ci	deh->deh_location = 0;	/* JDM Endian safe if 0 */
4868c2ecf20Sopenharmony_ci	put_deh_offset(deh, cpu_key_k_offset(&entry_key));
4878c2ecf20Sopenharmony_ci	deh->deh_state = 0;	/* JDM Endian safe if 0 */
4888c2ecf20Sopenharmony_ci	/* put key (ino analog) to de */
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	/* safe: k_dir_id is le */
4918c2ecf20Sopenharmony_ci	deh->deh_dir_id = INODE_PKEY(inode)->k_dir_id;
4928c2ecf20Sopenharmony_ci	/* safe: k_objectid is le */
4938c2ecf20Sopenharmony_ci	deh->deh_objectid = INODE_PKEY(inode)->k_objectid;
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci	/* copy name */
4968c2ecf20Sopenharmony_ci	memcpy((char *)(deh + 1), name, namelen);
4978c2ecf20Sopenharmony_ci	/* padd by 0s to the 4 byte boundary */
4988c2ecf20Sopenharmony_ci	padd_item((char *)(deh + 1), ROUND_UP(namelen), namelen);
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	/*
5018c2ecf20Sopenharmony_ci	 * entry is ready to be pasted into tree, set 'visibility'
5028c2ecf20Sopenharmony_ci	 * and 'stat data in entry' attributes
5038c2ecf20Sopenharmony_ci	 */
5048c2ecf20Sopenharmony_ci	mark_de_without_sd(deh);
5058c2ecf20Sopenharmony_ci	visible ? mark_de_visible(deh) : mark_de_hidden(deh);
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	/* find the proper place for the new entry */
5088c2ecf20Sopenharmony_ci	memset(bit_string, 0, sizeof(bit_string));
5098c2ecf20Sopenharmony_ci	de.de_gen_number_bit_string = bit_string;
5108c2ecf20Sopenharmony_ci	retval = reiserfs_find_entry(dir, name, namelen, &path, &de);
5118c2ecf20Sopenharmony_ci	if (retval != NAME_NOT_FOUND) {
5128c2ecf20Sopenharmony_ci		if (buffer != small_buf)
5138c2ecf20Sopenharmony_ci			kfree(buffer);
5148c2ecf20Sopenharmony_ci		pathrelse(&path);
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci		if (retval == IO_ERROR) {
5178c2ecf20Sopenharmony_ci			return -EIO;
5188c2ecf20Sopenharmony_ci		}
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci		if (retval != NAME_FOUND) {
5218c2ecf20Sopenharmony_ci			reiserfs_error(dir->i_sb, "zam-7002",
5228c2ecf20Sopenharmony_ci				       "reiserfs_find_entry() returned "
5238c2ecf20Sopenharmony_ci				       "unexpected value (%d)", retval);
5248c2ecf20Sopenharmony_ci		}
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci		return -EEXIST;
5278c2ecf20Sopenharmony_ci	}
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	gen_number =
5308c2ecf20Sopenharmony_ci	    find_first_zero_bit(bit_string,
5318c2ecf20Sopenharmony_ci				MAX_GENERATION_NUMBER + 1);
5328c2ecf20Sopenharmony_ci	if (gen_number > MAX_GENERATION_NUMBER) {
5338c2ecf20Sopenharmony_ci		/* there is no free generation number */
5348c2ecf20Sopenharmony_ci		reiserfs_warning(dir->i_sb, "reiserfs-7010",
5358c2ecf20Sopenharmony_ci				 "Congratulations! we have got hash function "
5368c2ecf20Sopenharmony_ci				 "screwed up");
5378c2ecf20Sopenharmony_ci		if (buffer != small_buf)
5388c2ecf20Sopenharmony_ci			kfree(buffer);
5398c2ecf20Sopenharmony_ci		pathrelse(&path);
5408c2ecf20Sopenharmony_ci		return -EBUSY;
5418c2ecf20Sopenharmony_ci	}
5428c2ecf20Sopenharmony_ci	/* adjust offset of directory enrty */
5438c2ecf20Sopenharmony_ci	put_deh_offset(deh, SET_GENERATION_NUMBER(deh_offset(deh), gen_number));
5448c2ecf20Sopenharmony_ci	set_cpu_key_k_offset(&entry_key, deh_offset(deh));
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci	/* update max-hash-collisions counter in reiserfs_sb_info */
5478c2ecf20Sopenharmony_ci	PROC_INFO_MAX(th->t_super, max_hash_collisions, gen_number);
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	/* we need to re-search for the insertion point */
5508c2ecf20Sopenharmony_ci	if (gen_number != 0) {
5518c2ecf20Sopenharmony_ci		if (search_by_entry_key(dir->i_sb, &entry_key, &path, &de) !=
5528c2ecf20Sopenharmony_ci		    NAME_NOT_FOUND) {
5538c2ecf20Sopenharmony_ci			reiserfs_warning(dir->i_sb, "vs-7032",
5548c2ecf20Sopenharmony_ci					 "entry with this key (%K) already "
5558c2ecf20Sopenharmony_ci					 "exists", &entry_key);
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci			if (buffer != small_buf)
5588c2ecf20Sopenharmony_ci				kfree(buffer);
5598c2ecf20Sopenharmony_ci			pathrelse(&path);
5608c2ecf20Sopenharmony_ci			return -EBUSY;
5618c2ecf20Sopenharmony_ci		}
5628c2ecf20Sopenharmony_ci	}
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	/* perform the insertion of the entry that we have prepared */
5658c2ecf20Sopenharmony_ci	retval =
5668c2ecf20Sopenharmony_ci	    reiserfs_paste_into_item(th, &path, &entry_key, dir, buffer,
5678c2ecf20Sopenharmony_ci				     paste_size);
5688c2ecf20Sopenharmony_ci	if (buffer != small_buf)
5698c2ecf20Sopenharmony_ci		kfree(buffer);
5708c2ecf20Sopenharmony_ci	if (retval) {
5718c2ecf20Sopenharmony_ci		reiserfs_check_path(&path);
5728c2ecf20Sopenharmony_ci		return retval;
5738c2ecf20Sopenharmony_ci	}
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	dir->i_size += paste_size;
5768c2ecf20Sopenharmony_ci	dir->i_mtime = dir->i_ctime = current_time(dir);
5778c2ecf20Sopenharmony_ci	if (!S_ISDIR(inode->i_mode) && visible)
5788c2ecf20Sopenharmony_ci		/* reiserfs_mkdir or reiserfs_rename will do that by itself */
5798c2ecf20Sopenharmony_ci		reiserfs_update_sd(th, dir);
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci	reiserfs_check_path(&path);
5828c2ecf20Sopenharmony_ci	return 0;
5838c2ecf20Sopenharmony_ci}
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci/*
5868c2ecf20Sopenharmony_ci * quota utility function, call if you've had to abort after calling
5878c2ecf20Sopenharmony_ci * new_inode_init, and have not called reiserfs_new_inode yet.
5888c2ecf20Sopenharmony_ci * This should only be called on inodes that do not have stat data
5898c2ecf20Sopenharmony_ci * inserted into the tree yet.
5908c2ecf20Sopenharmony_ci */
5918c2ecf20Sopenharmony_cistatic int drop_new_inode(struct inode *inode)
5928c2ecf20Sopenharmony_ci{
5938c2ecf20Sopenharmony_ci	dquot_drop(inode);
5948c2ecf20Sopenharmony_ci	make_bad_inode(inode);
5958c2ecf20Sopenharmony_ci	inode->i_flags |= S_NOQUOTA;
5968c2ecf20Sopenharmony_ci	iput(inode);
5978c2ecf20Sopenharmony_ci	return 0;
5988c2ecf20Sopenharmony_ci}
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci/*
6018c2ecf20Sopenharmony_ci * utility function that does setup for reiserfs_new_inode.
6028c2ecf20Sopenharmony_ci * dquot_initialize needs lots of credits so it's better to have it
6038c2ecf20Sopenharmony_ci * outside of a transaction, so we had to pull some bits of
6048c2ecf20Sopenharmony_ci * reiserfs_new_inode out into this func.
6058c2ecf20Sopenharmony_ci */
6068c2ecf20Sopenharmony_cistatic int new_inode_init(struct inode *inode, struct inode *dir, umode_t mode)
6078c2ecf20Sopenharmony_ci{
6088c2ecf20Sopenharmony_ci	/*
6098c2ecf20Sopenharmony_ci	 * Make inode invalid - just in case we are going to drop it before
6108c2ecf20Sopenharmony_ci	 * the initialization happens
6118c2ecf20Sopenharmony_ci	 */
6128c2ecf20Sopenharmony_ci	INODE_PKEY(inode)->k_objectid = 0;
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	/*
6158c2ecf20Sopenharmony_ci	 * the quota init calls have to know who to charge the quota to, so
6168c2ecf20Sopenharmony_ci	 * we have to set uid and gid here
6178c2ecf20Sopenharmony_ci	 */
6188c2ecf20Sopenharmony_ci	inode_init_owner(inode, dir, mode);
6198c2ecf20Sopenharmony_ci	return dquot_initialize(inode);
6208c2ecf20Sopenharmony_ci}
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_cistatic int reiserfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
6238c2ecf20Sopenharmony_ci			   bool excl)
6248c2ecf20Sopenharmony_ci{
6258c2ecf20Sopenharmony_ci	int retval;
6268c2ecf20Sopenharmony_ci	struct inode *inode;
6278c2ecf20Sopenharmony_ci	/*
6288c2ecf20Sopenharmony_ci	 * We need blocks for transaction + (user+group)*(quotas
6298c2ecf20Sopenharmony_ci	 * for new inode + update of quota for directory owner)
6308c2ecf20Sopenharmony_ci	 */
6318c2ecf20Sopenharmony_ci	int jbegin_count =
6328c2ecf20Sopenharmony_ci	    JOURNAL_PER_BALANCE_CNT * 2 +
6338c2ecf20Sopenharmony_ci	    2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
6348c2ecf20Sopenharmony_ci		 REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
6358c2ecf20Sopenharmony_ci	struct reiserfs_transaction_handle th;
6368c2ecf20Sopenharmony_ci	struct reiserfs_security_handle security;
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	retval = dquot_initialize(dir);
6398c2ecf20Sopenharmony_ci	if (retval)
6408c2ecf20Sopenharmony_ci		return retval;
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci	if (!(inode = new_inode(dir->i_sb))) {
6438c2ecf20Sopenharmony_ci		return -ENOMEM;
6448c2ecf20Sopenharmony_ci	}
6458c2ecf20Sopenharmony_ci	retval = new_inode_init(inode, dir, mode);
6468c2ecf20Sopenharmony_ci	if (retval) {
6478c2ecf20Sopenharmony_ci		drop_new_inode(inode);
6488c2ecf20Sopenharmony_ci		return retval;
6498c2ecf20Sopenharmony_ci	}
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	jbegin_count += reiserfs_cache_default_acl(dir);
6528c2ecf20Sopenharmony_ci	retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security);
6538c2ecf20Sopenharmony_ci	if (retval < 0) {
6548c2ecf20Sopenharmony_ci		drop_new_inode(inode);
6558c2ecf20Sopenharmony_ci		return retval;
6568c2ecf20Sopenharmony_ci	}
6578c2ecf20Sopenharmony_ci	jbegin_count += retval;
6588c2ecf20Sopenharmony_ci	reiserfs_write_lock(dir->i_sb);
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	retval = journal_begin(&th, dir->i_sb, jbegin_count);
6618c2ecf20Sopenharmony_ci	if (retval) {
6628c2ecf20Sopenharmony_ci		drop_new_inode(inode);
6638c2ecf20Sopenharmony_ci		goto out_failed;
6648c2ecf20Sopenharmony_ci	}
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	retval =
6678c2ecf20Sopenharmony_ci	    reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry,
6688c2ecf20Sopenharmony_ci			       inode, &security);
6698c2ecf20Sopenharmony_ci	if (retval)
6708c2ecf20Sopenharmony_ci		goto out_failed;
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci	inode->i_op = &reiserfs_file_inode_operations;
6738c2ecf20Sopenharmony_ci	inode->i_fop = &reiserfs_file_operations;
6748c2ecf20Sopenharmony_ci	inode->i_mapping->a_ops = &reiserfs_address_space_operations;
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_ci	retval =
6778c2ecf20Sopenharmony_ci	    reiserfs_add_entry(&th, dir, dentry->d_name.name,
6788c2ecf20Sopenharmony_ci			       dentry->d_name.len, inode, 1 /*visible */ );
6798c2ecf20Sopenharmony_ci	if (retval) {
6808c2ecf20Sopenharmony_ci		int err;
6818c2ecf20Sopenharmony_ci		drop_nlink(inode);
6828c2ecf20Sopenharmony_ci		reiserfs_update_sd(&th, inode);
6838c2ecf20Sopenharmony_ci		err = journal_end(&th);
6848c2ecf20Sopenharmony_ci		if (err)
6858c2ecf20Sopenharmony_ci			retval = err;
6868c2ecf20Sopenharmony_ci		unlock_new_inode(inode);
6878c2ecf20Sopenharmony_ci		iput(inode);
6888c2ecf20Sopenharmony_ci		goto out_failed;
6898c2ecf20Sopenharmony_ci	}
6908c2ecf20Sopenharmony_ci	reiserfs_update_inode_transaction(inode);
6918c2ecf20Sopenharmony_ci	reiserfs_update_inode_transaction(dir);
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_ci	d_instantiate_new(dentry, inode);
6948c2ecf20Sopenharmony_ci	retval = journal_end(&th);
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ciout_failed:
6978c2ecf20Sopenharmony_ci	reiserfs_write_unlock(dir->i_sb);
6988c2ecf20Sopenharmony_ci	reiserfs_security_free(&security);
6998c2ecf20Sopenharmony_ci	return retval;
7008c2ecf20Sopenharmony_ci}
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_cistatic int reiserfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
7038c2ecf20Sopenharmony_ci			  dev_t rdev)
7048c2ecf20Sopenharmony_ci{
7058c2ecf20Sopenharmony_ci	int retval;
7068c2ecf20Sopenharmony_ci	struct inode *inode;
7078c2ecf20Sopenharmony_ci	struct reiserfs_transaction_handle th;
7088c2ecf20Sopenharmony_ci	struct reiserfs_security_handle security;
7098c2ecf20Sopenharmony_ci	/*
7108c2ecf20Sopenharmony_ci	 * We need blocks for transaction + (user+group)*(quotas
7118c2ecf20Sopenharmony_ci	 * for new inode + update of quota for directory owner)
7128c2ecf20Sopenharmony_ci	 */
7138c2ecf20Sopenharmony_ci	int jbegin_count =
7148c2ecf20Sopenharmony_ci	    JOURNAL_PER_BALANCE_CNT * 3 +
7158c2ecf20Sopenharmony_ci	    2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
7168c2ecf20Sopenharmony_ci		 REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci	retval = dquot_initialize(dir);
7198c2ecf20Sopenharmony_ci	if (retval)
7208c2ecf20Sopenharmony_ci		return retval;
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci	if (!(inode = new_inode(dir->i_sb))) {
7238c2ecf20Sopenharmony_ci		return -ENOMEM;
7248c2ecf20Sopenharmony_ci	}
7258c2ecf20Sopenharmony_ci	retval = new_inode_init(inode, dir, mode);
7268c2ecf20Sopenharmony_ci	if (retval) {
7278c2ecf20Sopenharmony_ci		drop_new_inode(inode);
7288c2ecf20Sopenharmony_ci		return retval;
7298c2ecf20Sopenharmony_ci	}
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	jbegin_count += reiserfs_cache_default_acl(dir);
7328c2ecf20Sopenharmony_ci	retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security);
7338c2ecf20Sopenharmony_ci	if (retval < 0) {
7348c2ecf20Sopenharmony_ci		drop_new_inode(inode);
7358c2ecf20Sopenharmony_ci		return retval;
7368c2ecf20Sopenharmony_ci	}
7378c2ecf20Sopenharmony_ci	jbegin_count += retval;
7388c2ecf20Sopenharmony_ci	reiserfs_write_lock(dir->i_sb);
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci	retval = journal_begin(&th, dir->i_sb, jbegin_count);
7418c2ecf20Sopenharmony_ci	if (retval) {
7428c2ecf20Sopenharmony_ci		drop_new_inode(inode);
7438c2ecf20Sopenharmony_ci		goto out_failed;
7448c2ecf20Sopenharmony_ci	}
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	retval =
7478c2ecf20Sopenharmony_ci	    reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry,
7488c2ecf20Sopenharmony_ci			       inode, &security);
7498c2ecf20Sopenharmony_ci	if (retval) {
7508c2ecf20Sopenharmony_ci		goto out_failed;
7518c2ecf20Sopenharmony_ci	}
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci	inode->i_op = &reiserfs_special_inode_operations;
7548c2ecf20Sopenharmony_ci	init_special_inode(inode, inode->i_mode, rdev);
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci	/* FIXME: needed for block and char devices only */
7578c2ecf20Sopenharmony_ci	reiserfs_update_sd(&th, inode);
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ci	reiserfs_update_inode_transaction(inode);
7608c2ecf20Sopenharmony_ci	reiserfs_update_inode_transaction(dir);
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci	retval =
7638c2ecf20Sopenharmony_ci	    reiserfs_add_entry(&th, dir, dentry->d_name.name,
7648c2ecf20Sopenharmony_ci			       dentry->d_name.len, inode, 1 /*visible */ );
7658c2ecf20Sopenharmony_ci	if (retval) {
7668c2ecf20Sopenharmony_ci		int err;
7678c2ecf20Sopenharmony_ci		drop_nlink(inode);
7688c2ecf20Sopenharmony_ci		reiserfs_update_sd(&th, inode);
7698c2ecf20Sopenharmony_ci		err = journal_end(&th);
7708c2ecf20Sopenharmony_ci		if (err)
7718c2ecf20Sopenharmony_ci			retval = err;
7728c2ecf20Sopenharmony_ci		unlock_new_inode(inode);
7738c2ecf20Sopenharmony_ci		iput(inode);
7748c2ecf20Sopenharmony_ci		goto out_failed;
7758c2ecf20Sopenharmony_ci	}
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_ci	d_instantiate_new(dentry, inode);
7788c2ecf20Sopenharmony_ci	retval = journal_end(&th);
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ciout_failed:
7818c2ecf20Sopenharmony_ci	reiserfs_write_unlock(dir->i_sb);
7828c2ecf20Sopenharmony_ci	reiserfs_security_free(&security);
7838c2ecf20Sopenharmony_ci	return retval;
7848c2ecf20Sopenharmony_ci}
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_cistatic int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
7878c2ecf20Sopenharmony_ci{
7888c2ecf20Sopenharmony_ci	int retval;
7898c2ecf20Sopenharmony_ci	struct inode *inode;
7908c2ecf20Sopenharmony_ci	struct reiserfs_transaction_handle th;
7918c2ecf20Sopenharmony_ci	struct reiserfs_security_handle security;
7928c2ecf20Sopenharmony_ci	/*
7938c2ecf20Sopenharmony_ci	 * We need blocks for transaction + (user+group)*(quotas
7948c2ecf20Sopenharmony_ci	 * for new inode + update of quota for directory owner)
7958c2ecf20Sopenharmony_ci	 */
7968c2ecf20Sopenharmony_ci	int jbegin_count =
7978c2ecf20Sopenharmony_ci	    JOURNAL_PER_BALANCE_CNT * 3 +
7988c2ecf20Sopenharmony_ci	    2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
7998c2ecf20Sopenharmony_ci		 REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci	retval = dquot_initialize(dir);
8028c2ecf20Sopenharmony_ci	if (retval)
8038c2ecf20Sopenharmony_ci		return retval;
8048c2ecf20Sopenharmony_ci
8058c2ecf20Sopenharmony_ci#ifdef DISPLACE_NEW_PACKING_LOCALITIES
8068c2ecf20Sopenharmony_ci	/*
8078c2ecf20Sopenharmony_ci	 * set flag that new packing locality created and new blocks
8088c2ecf20Sopenharmony_ci	 * for the content of that directory are not displaced yet
8098c2ecf20Sopenharmony_ci	 */
8108c2ecf20Sopenharmony_ci	REISERFS_I(dir)->new_packing_locality = 1;
8118c2ecf20Sopenharmony_ci#endif
8128c2ecf20Sopenharmony_ci	mode = S_IFDIR | mode;
8138c2ecf20Sopenharmony_ci	if (!(inode = new_inode(dir->i_sb))) {
8148c2ecf20Sopenharmony_ci		return -ENOMEM;
8158c2ecf20Sopenharmony_ci	}
8168c2ecf20Sopenharmony_ci	retval = new_inode_init(inode, dir, mode);
8178c2ecf20Sopenharmony_ci	if (retval) {
8188c2ecf20Sopenharmony_ci		drop_new_inode(inode);
8198c2ecf20Sopenharmony_ci		return retval;
8208c2ecf20Sopenharmony_ci	}
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci	jbegin_count += reiserfs_cache_default_acl(dir);
8238c2ecf20Sopenharmony_ci	retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security);
8248c2ecf20Sopenharmony_ci	if (retval < 0) {
8258c2ecf20Sopenharmony_ci		drop_new_inode(inode);
8268c2ecf20Sopenharmony_ci		return retval;
8278c2ecf20Sopenharmony_ci	}
8288c2ecf20Sopenharmony_ci	jbegin_count += retval;
8298c2ecf20Sopenharmony_ci	reiserfs_write_lock(dir->i_sb);
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci	retval = journal_begin(&th, dir->i_sb, jbegin_count);
8328c2ecf20Sopenharmony_ci	if (retval) {
8338c2ecf20Sopenharmony_ci		drop_new_inode(inode);
8348c2ecf20Sopenharmony_ci		goto out_failed;
8358c2ecf20Sopenharmony_ci	}
8368c2ecf20Sopenharmony_ci
8378c2ecf20Sopenharmony_ci	/*
8388c2ecf20Sopenharmony_ci	 * inc the link count now, so another writer doesn't overflow
8398c2ecf20Sopenharmony_ci	 * it while we sleep later on.
8408c2ecf20Sopenharmony_ci	 */
8418c2ecf20Sopenharmony_ci	INC_DIR_INODE_NLINK(dir)
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci	retval = reiserfs_new_inode(&th, dir, mode, NULL /*symlink */,
8448c2ecf20Sopenharmony_ci				    old_format_only(dir->i_sb) ?
8458c2ecf20Sopenharmony_ci				    EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE,
8468c2ecf20Sopenharmony_ci				    dentry, inode, &security);
8478c2ecf20Sopenharmony_ci	if (retval) {
8488c2ecf20Sopenharmony_ci		DEC_DIR_INODE_NLINK(dir)
8498c2ecf20Sopenharmony_ci		goto out_failed;
8508c2ecf20Sopenharmony_ci	}
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	reiserfs_update_inode_transaction(inode);
8538c2ecf20Sopenharmony_ci	reiserfs_update_inode_transaction(dir);
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci	inode->i_op = &reiserfs_dir_inode_operations;
8568c2ecf20Sopenharmony_ci	inode->i_fop = &reiserfs_dir_operations;
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_ci	/* note, _this_ add_entry will not update dir's stat data */
8598c2ecf20Sopenharmony_ci	retval =
8608c2ecf20Sopenharmony_ci	    reiserfs_add_entry(&th, dir, dentry->d_name.name,
8618c2ecf20Sopenharmony_ci			       dentry->d_name.len, inode, 1 /*visible */ );
8628c2ecf20Sopenharmony_ci	if (retval) {
8638c2ecf20Sopenharmony_ci		int err;
8648c2ecf20Sopenharmony_ci		clear_nlink(inode);
8658c2ecf20Sopenharmony_ci		DEC_DIR_INODE_NLINK(dir);
8668c2ecf20Sopenharmony_ci		reiserfs_update_sd(&th, inode);
8678c2ecf20Sopenharmony_ci		err = journal_end(&th);
8688c2ecf20Sopenharmony_ci		if (err)
8698c2ecf20Sopenharmony_ci			retval = err;
8708c2ecf20Sopenharmony_ci		unlock_new_inode(inode);
8718c2ecf20Sopenharmony_ci		iput(inode);
8728c2ecf20Sopenharmony_ci		goto out_failed;
8738c2ecf20Sopenharmony_ci	}
8748c2ecf20Sopenharmony_ci	/* the above add_entry did not update dir's stat data */
8758c2ecf20Sopenharmony_ci	reiserfs_update_sd(&th, dir);
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci	d_instantiate_new(dentry, inode);
8788c2ecf20Sopenharmony_ci	retval = journal_end(&th);
8798c2ecf20Sopenharmony_ciout_failed:
8808c2ecf20Sopenharmony_ci	reiserfs_write_unlock(dir->i_sb);
8818c2ecf20Sopenharmony_ci	reiserfs_security_free(&security);
8828c2ecf20Sopenharmony_ci	return retval;
8838c2ecf20Sopenharmony_ci}
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_cistatic inline int reiserfs_empty_dir(struct inode *inode)
8868c2ecf20Sopenharmony_ci{
8878c2ecf20Sopenharmony_ci	/*
8888c2ecf20Sopenharmony_ci	 * we can cheat because an old format dir cannot have
8898c2ecf20Sopenharmony_ci	 * EMPTY_DIR_SIZE, and a new format dir cannot have
8908c2ecf20Sopenharmony_ci	 * EMPTY_DIR_SIZE_V1.  So, if the inode is either size,
8918c2ecf20Sopenharmony_ci	 * regardless of disk format version, the directory is empty.
8928c2ecf20Sopenharmony_ci	 */
8938c2ecf20Sopenharmony_ci	if (inode->i_size != EMPTY_DIR_SIZE &&
8948c2ecf20Sopenharmony_ci	    inode->i_size != EMPTY_DIR_SIZE_V1) {
8958c2ecf20Sopenharmony_ci		return 0;
8968c2ecf20Sopenharmony_ci	}
8978c2ecf20Sopenharmony_ci	return 1;
8988c2ecf20Sopenharmony_ci}
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_cistatic int reiserfs_rmdir(struct inode *dir, struct dentry *dentry)
9018c2ecf20Sopenharmony_ci{
9028c2ecf20Sopenharmony_ci	int retval, err;
9038c2ecf20Sopenharmony_ci	struct inode *inode;
9048c2ecf20Sopenharmony_ci	struct reiserfs_transaction_handle th;
9058c2ecf20Sopenharmony_ci	int jbegin_count;
9068c2ecf20Sopenharmony_ci	INITIALIZE_PATH(path);
9078c2ecf20Sopenharmony_ci	struct reiserfs_dir_entry de;
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci	/*
9108c2ecf20Sopenharmony_ci	 * we will be doing 2 balancings and update 2 stat data, we
9118c2ecf20Sopenharmony_ci	 * change quotas of the owner of the directory and of the owner
9128c2ecf20Sopenharmony_ci	 * of the parent directory.  The quota structure is possibly
9138c2ecf20Sopenharmony_ci	 * deleted only on last iput => outside of this transaction
9148c2ecf20Sopenharmony_ci	 */
9158c2ecf20Sopenharmony_ci	jbegin_count =
9168c2ecf20Sopenharmony_ci	    JOURNAL_PER_BALANCE_CNT * 2 + 2 +
9178c2ecf20Sopenharmony_ci	    4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci	retval = dquot_initialize(dir);
9208c2ecf20Sopenharmony_ci	if (retval)
9218c2ecf20Sopenharmony_ci		return retval;
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_ci	reiserfs_write_lock(dir->i_sb);
9248c2ecf20Sopenharmony_ci	retval = journal_begin(&th, dir->i_sb, jbegin_count);
9258c2ecf20Sopenharmony_ci	if (retval)
9268c2ecf20Sopenharmony_ci		goto out_rmdir;
9278c2ecf20Sopenharmony_ci
9288c2ecf20Sopenharmony_ci	de.de_gen_number_bit_string = NULL;
9298c2ecf20Sopenharmony_ci	if ((retval =
9308c2ecf20Sopenharmony_ci	     reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len,
9318c2ecf20Sopenharmony_ci				 &path, &de)) == NAME_NOT_FOUND) {
9328c2ecf20Sopenharmony_ci		retval = -ENOENT;
9338c2ecf20Sopenharmony_ci		goto end_rmdir;
9348c2ecf20Sopenharmony_ci	} else if (retval == IO_ERROR) {
9358c2ecf20Sopenharmony_ci		retval = -EIO;
9368c2ecf20Sopenharmony_ci		goto end_rmdir;
9378c2ecf20Sopenharmony_ci	}
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_ci	inode = d_inode(dentry);
9408c2ecf20Sopenharmony_ci
9418c2ecf20Sopenharmony_ci	reiserfs_update_inode_transaction(inode);
9428c2ecf20Sopenharmony_ci	reiserfs_update_inode_transaction(dir);
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_ci	if (de.de_objectid != inode->i_ino) {
9458c2ecf20Sopenharmony_ci		/*
9468c2ecf20Sopenharmony_ci		 * FIXME: compare key of an object and a key found in the entry
9478c2ecf20Sopenharmony_ci		 */
9488c2ecf20Sopenharmony_ci		retval = -EIO;
9498c2ecf20Sopenharmony_ci		goto end_rmdir;
9508c2ecf20Sopenharmony_ci	}
9518c2ecf20Sopenharmony_ci	if (!reiserfs_empty_dir(inode)) {
9528c2ecf20Sopenharmony_ci		retval = -ENOTEMPTY;
9538c2ecf20Sopenharmony_ci		goto end_rmdir;
9548c2ecf20Sopenharmony_ci	}
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci	/* cut entry from dir directory */
9578c2ecf20Sopenharmony_ci	retval = reiserfs_cut_from_item(&th, &path, &de.de_entry_key,
9588c2ecf20Sopenharmony_ci					dir, NULL,	/* page */
9598c2ecf20Sopenharmony_ci					0 /*new file size - not used here */ );
9608c2ecf20Sopenharmony_ci	if (retval < 0)
9618c2ecf20Sopenharmony_ci		goto end_rmdir;
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_ci	if (inode->i_nlink != 2 && inode->i_nlink != 1)
9648c2ecf20Sopenharmony_ci		reiserfs_error(inode->i_sb, "reiserfs-7040",
9658c2ecf20Sopenharmony_ci			       "empty directory has nlink != 2 (%d)",
9668c2ecf20Sopenharmony_ci			       inode->i_nlink);
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_ci	clear_nlink(inode);
9698c2ecf20Sopenharmony_ci	inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(dir);
9708c2ecf20Sopenharmony_ci	reiserfs_update_sd(&th, inode);
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci	DEC_DIR_INODE_NLINK(dir)
9738c2ecf20Sopenharmony_ci	dir->i_size -= (DEH_SIZE + de.de_entrylen);
9748c2ecf20Sopenharmony_ci	reiserfs_update_sd(&th, dir);
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ci	/* prevent empty directory from getting lost */
9778c2ecf20Sopenharmony_ci	add_save_link(&th, inode, 0 /* not truncate */ );
9788c2ecf20Sopenharmony_ci
9798c2ecf20Sopenharmony_ci	retval = journal_end(&th);
9808c2ecf20Sopenharmony_ci	reiserfs_check_path(&path);
9818c2ecf20Sopenharmony_ciout_rmdir:
9828c2ecf20Sopenharmony_ci	reiserfs_write_unlock(dir->i_sb);
9838c2ecf20Sopenharmony_ci	return retval;
9848c2ecf20Sopenharmony_ci
9858c2ecf20Sopenharmony_ciend_rmdir:
9868c2ecf20Sopenharmony_ci	/*
9878c2ecf20Sopenharmony_ci	 * we must release path, because we did not call
9888c2ecf20Sopenharmony_ci	 * reiserfs_cut_from_item, or reiserfs_cut_from_item does not
9898c2ecf20Sopenharmony_ci	 * release path if operation was not complete
9908c2ecf20Sopenharmony_ci	 */
9918c2ecf20Sopenharmony_ci	pathrelse(&path);
9928c2ecf20Sopenharmony_ci	err = journal_end(&th);
9938c2ecf20Sopenharmony_ci	reiserfs_write_unlock(dir->i_sb);
9948c2ecf20Sopenharmony_ci	return err ? err : retval;
9958c2ecf20Sopenharmony_ci}
9968c2ecf20Sopenharmony_ci
9978c2ecf20Sopenharmony_cistatic int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
9988c2ecf20Sopenharmony_ci{
9998c2ecf20Sopenharmony_ci	int retval, err;
10008c2ecf20Sopenharmony_ci	struct inode *inode;
10018c2ecf20Sopenharmony_ci	struct reiserfs_dir_entry de;
10028c2ecf20Sopenharmony_ci	INITIALIZE_PATH(path);
10038c2ecf20Sopenharmony_ci	struct reiserfs_transaction_handle th;
10048c2ecf20Sopenharmony_ci	int jbegin_count;
10058c2ecf20Sopenharmony_ci	unsigned long savelink;
10068c2ecf20Sopenharmony_ci
10078c2ecf20Sopenharmony_ci	retval = dquot_initialize(dir);
10088c2ecf20Sopenharmony_ci	if (retval)
10098c2ecf20Sopenharmony_ci		return retval;
10108c2ecf20Sopenharmony_ci
10118c2ecf20Sopenharmony_ci	inode = d_inode(dentry);
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci	/*
10148c2ecf20Sopenharmony_ci	 * in this transaction we can be doing at max two balancings and
10158c2ecf20Sopenharmony_ci	 * update two stat datas, we change quotas of the owner of the
10168c2ecf20Sopenharmony_ci	 * directory and of the owner of the parent directory. The quota
10178c2ecf20Sopenharmony_ci	 * structure is possibly deleted only on iput => outside of
10188c2ecf20Sopenharmony_ci	 * this transaction
10198c2ecf20Sopenharmony_ci	 */
10208c2ecf20Sopenharmony_ci	jbegin_count =
10218c2ecf20Sopenharmony_ci	    JOURNAL_PER_BALANCE_CNT * 2 + 2 +
10228c2ecf20Sopenharmony_ci	    4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_ci	reiserfs_write_lock(dir->i_sb);
10258c2ecf20Sopenharmony_ci	retval = journal_begin(&th, dir->i_sb, jbegin_count);
10268c2ecf20Sopenharmony_ci	if (retval)
10278c2ecf20Sopenharmony_ci		goto out_unlink;
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ci	de.de_gen_number_bit_string = NULL;
10308c2ecf20Sopenharmony_ci	if ((retval =
10318c2ecf20Sopenharmony_ci	     reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len,
10328c2ecf20Sopenharmony_ci				 &path, &de)) == NAME_NOT_FOUND) {
10338c2ecf20Sopenharmony_ci		retval = -ENOENT;
10348c2ecf20Sopenharmony_ci		goto end_unlink;
10358c2ecf20Sopenharmony_ci	} else if (retval == IO_ERROR) {
10368c2ecf20Sopenharmony_ci		retval = -EIO;
10378c2ecf20Sopenharmony_ci		goto end_unlink;
10388c2ecf20Sopenharmony_ci	}
10398c2ecf20Sopenharmony_ci
10408c2ecf20Sopenharmony_ci	reiserfs_update_inode_transaction(inode);
10418c2ecf20Sopenharmony_ci	reiserfs_update_inode_transaction(dir);
10428c2ecf20Sopenharmony_ci
10438c2ecf20Sopenharmony_ci	if (de.de_objectid != inode->i_ino) {
10448c2ecf20Sopenharmony_ci		/*
10458c2ecf20Sopenharmony_ci		 * FIXME: compare key of an object and a key found in the entry
10468c2ecf20Sopenharmony_ci		 */
10478c2ecf20Sopenharmony_ci		retval = -EIO;
10488c2ecf20Sopenharmony_ci		goto end_unlink;
10498c2ecf20Sopenharmony_ci	}
10508c2ecf20Sopenharmony_ci
10518c2ecf20Sopenharmony_ci	if (!inode->i_nlink) {
10528c2ecf20Sopenharmony_ci		reiserfs_warning(inode->i_sb, "reiserfs-7042",
10538c2ecf20Sopenharmony_ci				 "deleting nonexistent file (%lu), %d",
10548c2ecf20Sopenharmony_ci				 inode->i_ino, inode->i_nlink);
10558c2ecf20Sopenharmony_ci		set_nlink(inode, 1);
10568c2ecf20Sopenharmony_ci	}
10578c2ecf20Sopenharmony_ci
10588c2ecf20Sopenharmony_ci	drop_nlink(inode);
10598c2ecf20Sopenharmony_ci
10608c2ecf20Sopenharmony_ci	/*
10618c2ecf20Sopenharmony_ci	 * we schedule before doing the add_save_link call, save the link
10628c2ecf20Sopenharmony_ci	 * count so we don't race
10638c2ecf20Sopenharmony_ci	 */
10648c2ecf20Sopenharmony_ci	savelink = inode->i_nlink;
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_ci	retval =
10678c2ecf20Sopenharmony_ci	    reiserfs_cut_from_item(&th, &path, &de.de_entry_key, dir, NULL,
10688c2ecf20Sopenharmony_ci				   0);
10698c2ecf20Sopenharmony_ci	if (retval < 0) {
10708c2ecf20Sopenharmony_ci		inc_nlink(inode);
10718c2ecf20Sopenharmony_ci		goto end_unlink;
10728c2ecf20Sopenharmony_ci	}
10738c2ecf20Sopenharmony_ci	inode->i_ctime = current_time(inode);
10748c2ecf20Sopenharmony_ci	reiserfs_update_sd(&th, inode);
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ci	dir->i_size -= (de.de_entrylen + DEH_SIZE);
10778c2ecf20Sopenharmony_ci	dir->i_ctime = dir->i_mtime = current_time(dir);
10788c2ecf20Sopenharmony_ci	reiserfs_update_sd(&th, dir);
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci	if (!savelink)
10818c2ecf20Sopenharmony_ci		/* prevent file from getting lost */
10828c2ecf20Sopenharmony_ci		add_save_link(&th, inode, 0 /* not truncate */ );
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_ci	retval = journal_end(&th);
10858c2ecf20Sopenharmony_ci	reiserfs_check_path(&path);
10868c2ecf20Sopenharmony_ci	reiserfs_write_unlock(dir->i_sb);
10878c2ecf20Sopenharmony_ci	return retval;
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_ciend_unlink:
10908c2ecf20Sopenharmony_ci	pathrelse(&path);
10918c2ecf20Sopenharmony_ci	err = journal_end(&th);
10928c2ecf20Sopenharmony_ci	reiserfs_check_path(&path);
10938c2ecf20Sopenharmony_ci	if (err)
10948c2ecf20Sopenharmony_ci		retval = err;
10958c2ecf20Sopenharmony_ciout_unlink:
10968c2ecf20Sopenharmony_ci	reiserfs_write_unlock(dir->i_sb);
10978c2ecf20Sopenharmony_ci	return retval;
10988c2ecf20Sopenharmony_ci}
10998c2ecf20Sopenharmony_ci
11008c2ecf20Sopenharmony_cistatic int reiserfs_symlink(struct inode *parent_dir,
11018c2ecf20Sopenharmony_ci			    struct dentry *dentry, const char *symname)
11028c2ecf20Sopenharmony_ci{
11038c2ecf20Sopenharmony_ci	int retval;
11048c2ecf20Sopenharmony_ci	struct inode *inode;
11058c2ecf20Sopenharmony_ci	char *name;
11068c2ecf20Sopenharmony_ci	int item_len;
11078c2ecf20Sopenharmony_ci	struct reiserfs_transaction_handle th;
11088c2ecf20Sopenharmony_ci	struct reiserfs_security_handle security;
11098c2ecf20Sopenharmony_ci	int mode = S_IFLNK | S_IRWXUGO;
11108c2ecf20Sopenharmony_ci	/*
11118c2ecf20Sopenharmony_ci	 * We need blocks for transaction + (user+group)*(quotas for
11128c2ecf20Sopenharmony_ci	 * new inode + update of quota for directory owner)
11138c2ecf20Sopenharmony_ci	 */
11148c2ecf20Sopenharmony_ci	int jbegin_count =
11158c2ecf20Sopenharmony_ci	    JOURNAL_PER_BALANCE_CNT * 3 +
11168c2ecf20Sopenharmony_ci	    2 * (REISERFS_QUOTA_INIT_BLOCKS(parent_dir->i_sb) +
11178c2ecf20Sopenharmony_ci		 REISERFS_QUOTA_TRANS_BLOCKS(parent_dir->i_sb));
11188c2ecf20Sopenharmony_ci
11198c2ecf20Sopenharmony_ci	retval = dquot_initialize(parent_dir);
11208c2ecf20Sopenharmony_ci	if (retval)
11218c2ecf20Sopenharmony_ci		return retval;
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci	if (!(inode = new_inode(parent_dir->i_sb))) {
11248c2ecf20Sopenharmony_ci		return -ENOMEM;
11258c2ecf20Sopenharmony_ci	}
11268c2ecf20Sopenharmony_ci	retval = new_inode_init(inode, parent_dir, mode);
11278c2ecf20Sopenharmony_ci	if (retval) {
11288c2ecf20Sopenharmony_ci		drop_new_inode(inode);
11298c2ecf20Sopenharmony_ci		return retval;
11308c2ecf20Sopenharmony_ci	}
11318c2ecf20Sopenharmony_ci
11328c2ecf20Sopenharmony_ci	retval = reiserfs_security_init(parent_dir, inode, &dentry->d_name,
11338c2ecf20Sopenharmony_ci					&security);
11348c2ecf20Sopenharmony_ci	if (retval < 0) {
11358c2ecf20Sopenharmony_ci		drop_new_inode(inode);
11368c2ecf20Sopenharmony_ci		return retval;
11378c2ecf20Sopenharmony_ci	}
11388c2ecf20Sopenharmony_ci	jbegin_count += retval;
11398c2ecf20Sopenharmony_ci
11408c2ecf20Sopenharmony_ci	reiserfs_write_lock(parent_dir->i_sb);
11418c2ecf20Sopenharmony_ci	item_len = ROUND_UP(strlen(symname));
11428c2ecf20Sopenharmony_ci	if (item_len > MAX_DIRECT_ITEM_LEN(parent_dir->i_sb->s_blocksize)) {
11438c2ecf20Sopenharmony_ci		retval = -ENAMETOOLONG;
11448c2ecf20Sopenharmony_ci		drop_new_inode(inode);
11458c2ecf20Sopenharmony_ci		goto out_failed;
11468c2ecf20Sopenharmony_ci	}
11478c2ecf20Sopenharmony_ci
11488c2ecf20Sopenharmony_ci	name = kmalloc(item_len, GFP_NOFS);
11498c2ecf20Sopenharmony_ci	if (!name) {
11508c2ecf20Sopenharmony_ci		drop_new_inode(inode);
11518c2ecf20Sopenharmony_ci		retval = -ENOMEM;
11528c2ecf20Sopenharmony_ci		goto out_failed;
11538c2ecf20Sopenharmony_ci	}
11548c2ecf20Sopenharmony_ci	memcpy(name, symname, strlen(symname));
11558c2ecf20Sopenharmony_ci	padd_item(name, item_len, strlen(symname));
11568c2ecf20Sopenharmony_ci
11578c2ecf20Sopenharmony_ci	retval = journal_begin(&th, parent_dir->i_sb, jbegin_count);
11588c2ecf20Sopenharmony_ci	if (retval) {
11598c2ecf20Sopenharmony_ci		drop_new_inode(inode);
11608c2ecf20Sopenharmony_ci		kfree(name);
11618c2ecf20Sopenharmony_ci		goto out_failed;
11628c2ecf20Sopenharmony_ci	}
11638c2ecf20Sopenharmony_ci
11648c2ecf20Sopenharmony_ci	retval =
11658c2ecf20Sopenharmony_ci	    reiserfs_new_inode(&th, parent_dir, mode, name, strlen(symname),
11668c2ecf20Sopenharmony_ci			       dentry, inode, &security);
11678c2ecf20Sopenharmony_ci	kfree(name);
11688c2ecf20Sopenharmony_ci	if (retval) {		/* reiserfs_new_inode iputs for us */
11698c2ecf20Sopenharmony_ci		goto out_failed;
11708c2ecf20Sopenharmony_ci	}
11718c2ecf20Sopenharmony_ci
11728c2ecf20Sopenharmony_ci	reiserfs_update_inode_transaction(inode);
11738c2ecf20Sopenharmony_ci	reiserfs_update_inode_transaction(parent_dir);
11748c2ecf20Sopenharmony_ci
11758c2ecf20Sopenharmony_ci	inode->i_op = &reiserfs_symlink_inode_operations;
11768c2ecf20Sopenharmony_ci	inode_nohighmem(inode);
11778c2ecf20Sopenharmony_ci	inode->i_mapping->a_ops = &reiserfs_address_space_operations;
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_ci	retval = reiserfs_add_entry(&th, parent_dir, dentry->d_name.name,
11808c2ecf20Sopenharmony_ci				    dentry->d_name.len, inode, 1 /*visible */ );
11818c2ecf20Sopenharmony_ci	if (retval) {
11828c2ecf20Sopenharmony_ci		int err;
11838c2ecf20Sopenharmony_ci		drop_nlink(inode);
11848c2ecf20Sopenharmony_ci		reiserfs_update_sd(&th, inode);
11858c2ecf20Sopenharmony_ci		err = journal_end(&th);
11868c2ecf20Sopenharmony_ci		if (err)
11878c2ecf20Sopenharmony_ci			retval = err;
11888c2ecf20Sopenharmony_ci		unlock_new_inode(inode);
11898c2ecf20Sopenharmony_ci		iput(inode);
11908c2ecf20Sopenharmony_ci		goto out_failed;
11918c2ecf20Sopenharmony_ci	}
11928c2ecf20Sopenharmony_ci
11938c2ecf20Sopenharmony_ci	d_instantiate_new(dentry, inode);
11948c2ecf20Sopenharmony_ci	retval = journal_end(&th);
11958c2ecf20Sopenharmony_ciout_failed:
11968c2ecf20Sopenharmony_ci	reiserfs_write_unlock(parent_dir->i_sb);
11978c2ecf20Sopenharmony_ci	reiserfs_security_free(&security);
11988c2ecf20Sopenharmony_ci	return retval;
11998c2ecf20Sopenharmony_ci}
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_cistatic int reiserfs_link(struct dentry *old_dentry, struct inode *dir,
12028c2ecf20Sopenharmony_ci			 struct dentry *dentry)
12038c2ecf20Sopenharmony_ci{
12048c2ecf20Sopenharmony_ci	int retval;
12058c2ecf20Sopenharmony_ci	struct inode *inode = d_inode(old_dentry);
12068c2ecf20Sopenharmony_ci	struct reiserfs_transaction_handle th;
12078c2ecf20Sopenharmony_ci	/*
12088c2ecf20Sopenharmony_ci	 * We need blocks for transaction + update of quotas for
12098c2ecf20Sopenharmony_ci	 * the owners of the directory
12108c2ecf20Sopenharmony_ci	 */
12118c2ecf20Sopenharmony_ci	int jbegin_count =
12128c2ecf20Sopenharmony_ci	    JOURNAL_PER_BALANCE_CNT * 3 +
12138c2ecf20Sopenharmony_ci	    2 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
12148c2ecf20Sopenharmony_ci
12158c2ecf20Sopenharmony_ci	retval = dquot_initialize(dir);
12168c2ecf20Sopenharmony_ci	if (retval)
12178c2ecf20Sopenharmony_ci		return retval;
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ci	reiserfs_write_lock(dir->i_sb);
12208c2ecf20Sopenharmony_ci	if (inode->i_nlink >= REISERFS_LINK_MAX) {
12218c2ecf20Sopenharmony_ci		/* FIXME: sd_nlink is 32 bit for new files */
12228c2ecf20Sopenharmony_ci		reiserfs_write_unlock(dir->i_sb);
12238c2ecf20Sopenharmony_ci		return -EMLINK;
12248c2ecf20Sopenharmony_ci	}
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_ci	/* inc before scheduling so reiserfs_unlink knows we are here */
12278c2ecf20Sopenharmony_ci	inc_nlink(inode);
12288c2ecf20Sopenharmony_ci
12298c2ecf20Sopenharmony_ci	retval = journal_begin(&th, dir->i_sb, jbegin_count);
12308c2ecf20Sopenharmony_ci	if (retval) {
12318c2ecf20Sopenharmony_ci		drop_nlink(inode);
12328c2ecf20Sopenharmony_ci		reiserfs_write_unlock(dir->i_sb);
12338c2ecf20Sopenharmony_ci		return retval;
12348c2ecf20Sopenharmony_ci	}
12358c2ecf20Sopenharmony_ci
12368c2ecf20Sopenharmony_ci	/* create new entry */
12378c2ecf20Sopenharmony_ci	retval =
12388c2ecf20Sopenharmony_ci	    reiserfs_add_entry(&th, dir, dentry->d_name.name,
12398c2ecf20Sopenharmony_ci			       dentry->d_name.len, inode, 1 /*visible */ );
12408c2ecf20Sopenharmony_ci
12418c2ecf20Sopenharmony_ci	reiserfs_update_inode_transaction(inode);
12428c2ecf20Sopenharmony_ci	reiserfs_update_inode_transaction(dir);
12438c2ecf20Sopenharmony_ci
12448c2ecf20Sopenharmony_ci	if (retval) {
12458c2ecf20Sopenharmony_ci		int err;
12468c2ecf20Sopenharmony_ci		drop_nlink(inode);
12478c2ecf20Sopenharmony_ci		err = journal_end(&th);
12488c2ecf20Sopenharmony_ci		reiserfs_write_unlock(dir->i_sb);
12498c2ecf20Sopenharmony_ci		return err ? err : retval;
12508c2ecf20Sopenharmony_ci	}
12518c2ecf20Sopenharmony_ci
12528c2ecf20Sopenharmony_ci	inode->i_ctime = current_time(inode);
12538c2ecf20Sopenharmony_ci	reiserfs_update_sd(&th, inode);
12548c2ecf20Sopenharmony_ci
12558c2ecf20Sopenharmony_ci	ihold(inode);
12568c2ecf20Sopenharmony_ci	d_instantiate(dentry, inode);
12578c2ecf20Sopenharmony_ci	retval = journal_end(&th);
12588c2ecf20Sopenharmony_ci	reiserfs_write_unlock(dir->i_sb);
12598c2ecf20Sopenharmony_ci	return retval;
12608c2ecf20Sopenharmony_ci}
12618c2ecf20Sopenharmony_ci
12628c2ecf20Sopenharmony_ci/* de contains information pointing to an entry which */
12638c2ecf20Sopenharmony_cistatic int de_still_valid(const char *name, int len,
12648c2ecf20Sopenharmony_ci			  struct reiserfs_dir_entry *de)
12658c2ecf20Sopenharmony_ci{
12668c2ecf20Sopenharmony_ci	struct reiserfs_dir_entry tmp = *de;
12678c2ecf20Sopenharmony_ci
12688c2ecf20Sopenharmony_ci	/* recalculate pointer to name and name length */
12698c2ecf20Sopenharmony_ci	set_de_name_and_namelen(&tmp);
12708c2ecf20Sopenharmony_ci	/* FIXME: could check more */
12718c2ecf20Sopenharmony_ci	if (tmp.de_namelen != len || memcmp(name, de->de_name, len))
12728c2ecf20Sopenharmony_ci		return 0;
12738c2ecf20Sopenharmony_ci	return 1;
12748c2ecf20Sopenharmony_ci}
12758c2ecf20Sopenharmony_ci
12768c2ecf20Sopenharmony_cistatic int entry_points_to_object(const char *name, int len,
12778c2ecf20Sopenharmony_ci				  struct reiserfs_dir_entry *de,
12788c2ecf20Sopenharmony_ci				  struct inode *inode)
12798c2ecf20Sopenharmony_ci{
12808c2ecf20Sopenharmony_ci	if (!de_still_valid(name, len, de))
12818c2ecf20Sopenharmony_ci		return 0;
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_ci	if (inode) {
12848c2ecf20Sopenharmony_ci		if (!de_visible(de->de_deh + de->de_entry_num))
12858c2ecf20Sopenharmony_ci			reiserfs_panic(inode->i_sb, "vs-7042",
12868c2ecf20Sopenharmony_ci				       "entry must be visible");
12878c2ecf20Sopenharmony_ci		return (de->de_objectid == inode->i_ino) ? 1 : 0;
12888c2ecf20Sopenharmony_ci	}
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_ci	/* this must be added hidden entry */
12918c2ecf20Sopenharmony_ci	if (de_visible(de->de_deh + de->de_entry_num))
12928c2ecf20Sopenharmony_ci		reiserfs_panic(NULL, "vs-7043", "entry must be visible");
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ci	return 1;
12958c2ecf20Sopenharmony_ci}
12968c2ecf20Sopenharmony_ci
12978c2ecf20Sopenharmony_ci/* sets key of objectid the entry has to point to */
12988c2ecf20Sopenharmony_cistatic void set_ino_in_dir_entry(struct reiserfs_dir_entry *de,
12998c2ecf20Sopenharmony_ci				 struct reiserfs_key *key)
13008c2ecf20Sopenharmony_ci{
13018c2ecf20Sopenharmony_ci	/* JDM These operations are endian safe - both are le */
13028c2ecf20Sopenharmony_ci	de->de_deh[de->de_entry_num].deh_dir_id = key->k_dir_id;
13038c2ecf20Sopenharmony_ci	de->de_deh[de->de_entry_num].deh_objectid = key->k_objectid;
13048c2ecf20Sopenharmony_ci}
13058c2ecf20Sopenharmony_ci
13068c2ecf20Sopenharmony_ci/*
13078c2ecf20Sopenharmony_ci * process, that is going to call fix_nodes/do_balance must hold only
13088c2ecf20Sopenharmony_ci * one path. If it holds 2 or more, it can get into endless waiting in
13098c2ecf20Sopenharmony_ci * get_empty_nodes or its clones
13108c2ecf20Sopenharmony_ci */
13118c2ecf20Sopenharmony_cistatic int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry,
13128c2ecf20Sopenharmony_ci			   struct inode *new_dir, struct dentry *new_dentry,
13138c2ecf20Sopenharmony_ci			   unsigned int flags)
13148c2ecf20Sopenharmony_ci{
13158c2ecf20Sopenharmony_ci	int retval;
13168c2ecf20Sopenharmony_ci	INITIALIZE_PATH(old_entry_path);
13178c2ecf20Sopenharmony_ci	INITIALIZE_PATH(new_entry_path);
13188c2ecf20Sopenharmony_ci	INITIALIZE_PATH(dot_dot_entry_path);
13198c2ecf20Sopenharmony_ci	struct item_head new_entry_ih, old_entry_ih, dot_dot_ih;
13208c2ecf20Sopenharmony_ci	struct reiserfs_dir_entry old_de, new_de, dot_dot_de;
13218c2ecf20Sopenharmony_ci	struct inode *old_inode, *new_dentry_inode;
13228c2ecf20Sopenharmony_ci	struct reiserfs_transaction_handle th;
13238c2ecf20Sopenharmony_ci	int jbegin_count;
13248c2ecf20Sopenharmony_ci	umode_t old_inode_mode;
13258c2ecf20Sopenharmony_ci	unsigned long savelink = 1;
13268c2ecf20Sopenharmony_ci	struct timespec64 ctime;
13278c2ecf20Sopenharmony_ci
13288c2ecf20Sopenharmony_ci	if (flags & ~RENAME_NOREPLACE)
13298c2ecf20Sopenharmony_ci		return -EINVAL;
13308c2ecf20Sopenharmony_ci
13318c2ecf20Sopenharmony_ci	/*
13328c2ecf20Sopenharmony_ci	 * three balancings: (1) old name removal, (2) new name insertion
13338c2ecf20Sopenharmony_ci	 * and (3) maybe "save" link insertion
13348c2ecf20Sopenharmony_ci	 * stat data updates: (1) old directory,
13358c2ecf20Sopenharmony_ci	 * (2) new directory and (3) maybe old object stat data (when it is
13368c2ecf20Sopenharmony_ci	 * directory) and (4) maybe stat data of object to which new entry
13378c2ecf20Sopenharmony_ci	 * pointed initially and (5) maybe block containing ".." of
13388c2ecf20Sopenharmony_ci	 * renamed directory
13398c2ecf20Sopenharmony_ci	 * quota updates: two parent directories
13408c2ecf20Sopenharmony_ci	 */
13418c2ecf20Sopenharmony_ci	jbegin_count =
13428c2ecf20Sopenharmony_ci	    JOURNAL_PER_BALANCE_CNT * 3 + 5 +
13438c2ecf20Sopenharmony_ci	    4 * REISERFS_QUOTA_TRANS_BLOCKS(old_dir->i_sb);
13448c2ecf20Sopenharmony_ci
13458c2ecf20Sopenharmony_ci	retval = dquot_initialize(old_dir);
13468c2ecf20Sopenharmony_ci	if (retval)
13478c2ecf20Sopenharmony_ci		return retval;
13488c2ecf20Sopenharmony_ci	retval = dquot_initialize(new_dir);
13498c2ecf20Sopenharmony_ci	if (retval)
13508c2ecf20Sopenharmony_ci		return retval;
13518c2ecf20Sopenharmony_ci
13528c2ecf20Sopenharmony_ci	old_inode = d_inode(old_dentry);
13538c2ecf20Sopenharmony_ci	new_dentry_inode = d_inode(new_dentry);
13548c2ecf20Sopenharmony_ci
13558c2ecf20Sopenharmony_ci	/*
13568c2ecf20Sopenharmony_ci	 * make sure that oldname still exists and points to an object we
13578c2ecf20Sopenharmony_ci	 * are going to rename
13588c2ecf20Sopenharmony_ci	 */
13598c2ecf20Sopenharmony_ci	old_de.de_gen_number_bit_string = NULL;
13608c2ecf20Sopenharmony_ci	reiserfs_write_lock(old_dir->i_sb);
13618c2ecf20Sopenharmony_ci	retval =
13628c2ecf20Sopenharmony_ci	    reiserfs_find_entry(old_dir, old_dentry->d_name.name,
13638c2ecf20Sopenharmony_ci				old_dentry->d_name.len, &old_entry_path,
13648c2ecf20Sopenharmony_ci				&old_de);
13658c2ecf20Sopenharmony_ci	pathrelse(&old_entry_path);
13668c2ecf20Sopenharmony_ci	if (retval == IO_ERROR) {
13678c2ecf20Sopenharmony_ci		reiserfs_write_unlock(old_dir->i_sb);
13688c2ecf20Sopenharmony_ci		return -EIO;
13698c2ecf20Sopenharmony_ci	}
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_ci	if (retval != NAME_FOUND || old_de.de_objectid != old_inode->i_ino) {
13728c2ecf20Sopenharmony_ci		reiserfs_write_unlock(old_dir->i_sb);
13738c2ecf20Sopenharmony_ci		return -ENOENT;
13748c2ecf20Sopenharmony_ci	}
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ci	old_inode_mode = old_inode->i_mode;
13778c2ecf20Sopenharmony_ci	if (S_ISDIR(old_inode_mode)) {
13788c2ecf20Sopenharmony_ci		/*
13798c2ecf20Sopenharmony_ci		 * make sure that directory being renamed has correct ".."
13808c2ecf20Sopenharmony_ci		 * and that its new parent directory has not too many links
13818c2ecf20Sopenharmony_ci		 * already
13828c2ecf20Sopenharmony_ci		 */
13838c2ecf20Sopenharmony_ci		if (new_dentry_inode) {
13848c2ecf20Sopenharmony_ci			if (!reiserfs_empty_dir(new_dentry_inode)) {
13858c2ecf20Sopenharmony_ci				reiserfs_write_unlock(old_dir->i_sb);
13868c2ecf20Sopenharmony_ci				return -ENOTEMPTY;
13878c2ecf20Sopenharmony_ci			}
13888c2ecf20Sopenharmony_ci		}
13898c2ecf20Sopenharmony_ci
13908c2ecf20Sopenharmony_ci		/*
13918c2ecf20Sopenharmony_ci		 * directory is renamed, its parent directory will be changed,
13928c2ecf20Sopenharmony_ci		 * so find ".." entry
13938c2ecf20Sopenharmony_ci		 */
13948c2ecf20Sopenharmony_ci		dot_dot_de.de_gen_number_bit_string = NULL;
13958c2ecf20Sopenharmony_ci		retval =
13968c2ecf20Sopenharmony_ci		    reiserfs_find_entry(old_inode, "..", 2, &dot_dot_entry_path,
13978c2ecf20Sopenharmony_ci					&dot_dot_de);
13988c2ecf20Sopenharmony_ci		pathrelse(&dot_dot_entry_path);
13998c2ecf20Sopenharmony_ci		if (retval != NAME_FOUND) {
14008c2ecf20Sopenharmony_ci			reiserfs_write_unlock(old_dir->i_sb);
14018c2ecf20Sopenharmony_ci			return -EIO;
14028c2ecf20Sopenharmony_ci		}
14038c2ecf20Sopenharmony_ci
14048c2ecf20Sopenharmony_ci		/* inode number of .. must equal old_dir->i_ino */
14058c2ecf20Sopenharmony_ci		if (dot_dot_de.de_objectid != old_dir->i_ino) {
14068c2ecf20Sopenharmony_ci			reiserfs_write_unlock(old_dir->i_sb);
14078c2ecf20Sopenharmony_ci			return -EIO;
14088c2ecf20Sopenharmony_ci		}
14098c2ecf20Sopenharmony_ci	}
14108c2ecf20Sopenharmony_ci
14118c2ecf20Sopenharmony_ci	retval = journal_begin(&th, old_dir->i_sb, jbegin_count);
14128c2ecf20Sopenharmony_ci	if (retval) {
14138c2ecf20Sopenharmony_ci		reiserfs_write_unlock(old_dir->i_sb);
14148c2ecf20Sopenharmony_ci		return retval;
14158c2ecf20Sopenharmony_ci	}
14168c2ecf20Sopenharmony_ci
14178c2ecf20Sopenharmony_ci	/* add new entry (or find the existing one) */
14188c2ecf20Sopenharmony_ci	retval =
14198c2ecf20Sopenharmony_ci	    reiserfs_add_entry(&th, new_dir, new_dentry->d_name.name,
14208c2ecf20Sopenharmony_ci			       new_dentry->d_name.len, old_inode, 0);
14218c2ecf20Sopenharmony_ci	if (retval == -EEXIST) {
14228c2ecf20Sopenharmony_ci		if (!new_dentry_inode) {
14238c2ecf20Sopenharmony_ci			reiserfs_panic(old_dir->i_sb, "vs-7050",
14248c2ecf20Sopenharmony_ci				       "new entry is found, new inode == 0");
14258c2ecf20Sopenharmony_ci		}
14268c2ecf20Sopenharmony_ci	} else if (retval) {
14278c2ecf20Sopenharmony_ci		int err = journal_end(&th);
14288c2ecf20Sopenharmony_ci		reiserfs_write_unlock(old_dir->i_sb);
14298c2ecf20Sopenharmony_ci		return err ? err : retval;
14308c2ecf20Sopenharmony_ci	}
14318c2ecf20Sopenharmony_ci
14328c2ecf20Sopenharmony_ci	reiserfs_update_inode_transaction(old_dir);
14338c2ecf20Sopenharmony_ci	reiserfs_update_inode_transaction(new_dir);
14348c2ecf20Sopenharmony_ci
14358c2ecf20Sopenharmony_ci	/*
14368c2ecf20Sopenharmony_ci	 * this makes it so an fsync on an open fd for the old name will
14378c2ecf20Sopenharmony_ci	 * commit the rename operation
14388c2ecf20Sopenharmony_ci	 */
14398c2ecf20Sopenharmony_ci	reiserfs_update_inode_transaction(old_inode);
14408c2ecf20Sopenharmony_ci
14418c2ecf20Sopenharmony_ci	if (new_dentry_inode)
14428c2ecf20Sopenharmony_ci		reiserfs_update_inode_transaction(new_dentry_inode);
14438c2ecf20Sopenharmony_ci
14448c2ecf20Sopenharmony_ci	while (1) {
14458c2ecf20Sopenharmony_ci		/*
14468c2ecf20Sopenharmony_ci		 * look for old name using corresponding entry key
14478c2ecf20Sopenharmony_ci		 * (found by reiserfs_find_entry)
14488c2ecf20Sopenharmony_ci		 */
14498c2ecf20Sopenharmony_ci		if ((retval =
14508c2ecf20Sopenharmony_ci		     search_by_entry_key(new_dir->i_sb, &old_de.de_entry_key,
14518c2ecf20Sopenharmony_ci					 &old_entry_path,
14528c2ecf20Sopenharmony_ci					 &old_de)) != NAME_FOUND) {
14538c2ecf20Sopenharmony_ci			pathrelse(&old_entry_path);
14548c2ecf20Sopenharmony_ci			journal_end(&th);
14558c2ecf20Sopenharmony_ci			reiserfs_write_unlock(old_dir->i_sb);
14568c2ecf20Sopenharmony_ci			return -EIO;
14578c2ecf20Sopenharmony_ci		}
14588c2ecf20Sopenharmony_ci
14598c2ecf20Sopenharmony_ci		copy_item_head(&old_entry_ih, tp_item_head(&old_entry_path));
14608c2ecf20Sopenharmony_ci
14618c2ecf20Sopenharmony_ci		reiserfs_prepare_for_journal(old_inode->i_sb, old_de.de_bh, 1);
14628c2ecf20Sopenharmony_ci
14638c2ecf20Sopenharmony_ci		/* look for new name by reiserfs_find_entry */
14648c2ecf20Sopenharmony_ci		new_de.de_gen_number_bit_string = NULL;
14658c2ecf20Sopenharmony_ci		retval =
14668c2ecf20Sopenharmony_ci		    reiserfs_find_entry(new_dir, new_dentry->d_name.name,
14678c2ecf20Sopenharmony_ci					new_dentry->d_name.len, &new_entry_path,
14688c2ecf20Sopenharmony_ci					&new_de);
14698c2ecf20Sopenharmony_ci		/*
14708c2ecf20Sopenharmony_ci		 * reiserfs_add_entry should not return IO_ERROR,
14718c2ecf20Sopenharmony_ci		 * because it is called with essentially same parameters from
14728c2ecf20Sopenharmony_ci		 * reiserfs_add_entry above, and we'll catch any i/o errors
14738c2ecf20Sopenharmony_ci		 * before we get here.
14748c2ecf20Sopenharmony_ci		 */
14758c2ecf20Sopenharmony_ci		if (retval != NAME_FOUND_INVISIBLE && retval != NAME_FOUND) {
14768c2ecf20Sopenharmony_ci			pathrelse(&new_entry_path);
14778c2ecf20Sopenharmony_ci			pathrelse(&old_entry_path);
14788c2ecf20Sopenharmony_ci			journal_end(&th);
14798c2ecf20Sopenharmony_ci			reiserfs_write_unlock(old_dir->i_sb);
14808c2ecf20Sopenharmony_ci			return -EIO;
14818c2ecf20Sopenharmony_ci		}
14828c2ecf20Sopenharmony_ci
14838c2ecf20Sopenharmony_ci		copy_item_head(&new_entry_ih, tp_item_head(&new_entry_path));
14848c2ecf20Sopenharmony_ci
14858c2ecf20Sopenharmony_ci		reiserfs_prepare_for_journal(old_inode->i_sb, new_de.de_bh, 1);
14868c2ecf20Sopenharmony_ci
14878c2ecf20Sopenharmony_ci		if (S_ISDIR(old_inode->i_mode)) {
14888c2ecf20Sopenharmony_ci			if ((retval =
14898c2ecf20Sopenharmony_ci			     search_by_entry_key(new_dir->i_sb,
14908c2ecf20Sopenharmony_ci						 &dot_dot_de.de_entry_key,
14918c2ecf20Sopenharmony_ci						 &dot_dot_entry_path,
14928c2ecf20Sopenharmony_ci						 &dot_dot_de)) != NAME_FOUND) {
14938c2ecf20Sopenharmony_ci				pathrelse(&dot_dot_entry_path);
14948c2ecf20Sopenharmony_ci				pathrelse(&new_entry_path);
14958c2ecf20Sopenharmony_ci				pathrelse(&old_entry_path);
14968c2ecf20Sopenharmony_ci				journal_end(&th);
14978c2ecf20Sopenharmony_ci				reiserfs_write_unlock(old_dir->i_sb);
14988c2ecf20Sopenharmony_ci				return -EIO;
14998c2ecf20Sopenharmony_ci			}
15008c2ecf20Sopenharmony_ci			copy_item_head(&dot_dot_ih,
15018c2ecf20Sopenharmony_ci				       tp_item_head(&dot_dot_entry_path));
15028c2ecf20Sopenharmony_ci			/* node containing ".." gets into transaction */
15038c2ecf20Sopenharmony_ci			reiserfs_prepare_for_journal(old_inode->i_sb,
15048c2ecf20Sopenharmony_ci						     dot_dot_de.de_bh, 1);
15058c2ecf20Sopenharmony_ci		}
15068c2ecf20Sopenharmony_ci		/*
15078c2ecf20Sopenharmony_ci		 * we should check seals here, not do
15088c2ecf20Sopenharmony_ci		 * this stuff, yes? Then, having
15098c2ecf20Sopenharmony_ci		 * gathered everything into RAM we
15108c2ecf20Sopenharmony_ci		 * should lock the buffers, yes?  -Hans
15118c2ecf20Sopenharmony_ci		 */
15128c2ecf20Sopenharmony_ci		/*
15138c2ecf20Sopenharmony_ci		 * probably.  our rename needs to hold more
15148c2ecf20Sopenharmony_ci		 * than one path at once.  The seals would
15158c2ecf20Sopenharmony_ci		 * have to be written to deal with multi-path
15168c2ecf20Sopenharmony_ci		 * issues -chris
15178c2ecf20Sopenharmony_ci		 */
15188c2ecf20Sopenharmony_ci		/*
15198c2ecf20Sopenharmony_ci		 * sanity checking before doing the rename - avoid races many
15208c2ecf20Sopenharmony_ci		 * of the above checks could have scheduled.  We have to be
15218c2ecf20Sopenharmony_ci		 * sure our items haven't been shifted by another process.
15228c2ecf20Sopenharmony_ci		 */
15238c2ecf20Sopenharmony_ci		if (item_moved(&new_entry_ih, &new_entry_path) ||
15248c2ecf20Sopenharmony_ci		    !entry_points_to_object(new_dentry->d_name.name,
15258c2ecf20Sopenharmony_ci					    new_dentry->d_name.len,
15268c2ecf20Sopenharmony_ci					    &new_de, new_dentry_inode) ||
15278c2ecf20Sopenharmony_ci		    item_moved(&old_entry_ih, &old_entry_path) ||
15288c2ecf20Sopenharmony_ci		    !entry_points_to_object(old_dentry->d_name.name,
15298c2ecf20Sopenharmony_ci					    old_dentry->d_name.len,
15308c2ecf20Sopenharmony_ci					    &old_de, old_inode)) {
15318c2ecf20Sopenharmony_ci			reiserfs_restore_prepared_buffer(old_inode->i_sb,
15328c2ecf20Sopenharmony_ci							 new_de.de_bh);
15338c2ecf20Sopenharmony_ci			reiserfs_restore_prepared_buffer(old_inode->i_sb,
15348c2ecf20Sopenharmony_ci							 old_de.de_bh);
15358c2ecf20Sopenharmony_ci			if (S_ISDIR(old_inode_mode))
15368c2ecf20Sopenharmony_ci				reiserfs_restore_prepared_buffer(old_inode->
15378c2ecf20Sopenharmony_ci								 i_sb,
15388c2ecf20Sopenharmony_ci								 dot_dot_de.
15398c2ecf20Sopenharmony_ci								 de_bh);
15408c2ecf20Sopenharmony_ci			continue;
15418c2ecf20Sopenharmony_ci		}
15428c2ecf20Sopenharmony_ci		if (S_ISDIR(old_inode_mode)) {
15438c2ecf20Sopenharmony_ci			if (item_moved(&dot_dot_ih, &dot_dot_entry_path) ||
15448c2ecf20Sopenharmony_ci			    !entry_points_to_object("..", 2, &dot_dot_de,
15458c2ecf20Sopenharmony_ci						    old_dir)) {
15468c2ecf20Sopenharmony_ci				reiserfs_restore_prepared_buffer(old_inode->
15478c2ecf20Sopenharmony_ci								 i_sb,
15488c2ecf20Sopenharmony_ci								 old_de.de_bh);
15498c2ecf20Sopenharmony_ci				reiserfs_restore_prepared_buffer(old_inode->
15508c2ecf20Sopenharmony_ci								 i_sb,
15518c2ecf20Sopenharmony_ci								 new_de.de_bh);
15528c2ecf20Sopenharmony_ci				reiserfs_restore_prepared_buffer(old_inode->
15538c2ecf20Sopenharmony_ci								 i_sb,
15548c2ecf20Sopenharmony_ci								 dot_dot_de.
15558c2ecf20Sopenharmony_ci								 de_bh);
15568c2ecf20Sopenharmony_ci				continue;
15578c2ecf20Sopenharmony_ci			}
15588c2ecf20Sopenharmony_ci		}
15598c2ecf20Sopenharmony_ci
15608c2ecf20Sopenharmony_ci		RFALSE(S_ISDIR(old_inode_mode) &&
15618c2ecf20Sopenharmony_ci		       !buffer_journal_prepared(dot_dot_de.de_bh), "");
15628c2ecf20Sopenharmony_ci
15638c2ecf20Sopenharmony_ci		break;
15648c2ecf20Sopenharmony_ci	}
15658c2ecf20Sopenharmony_ci
15668c2ecf20Sopenharmony_ci	/*
15678c2ecf20Sopenharmony_ci	 * ok, all the changes can be done in one fell swoop when we
15688c2ecf20Sopenharmony_ci	 * have claimed all the buffers needed.
15698c2ecf20Sopenharmony_ci	 */
15708c2ecf20Sopenharmony_ci
15718c2ecf20Sopenharmony_ci	mark_de_visible(new_de.de_deh + new_de.de_entry_num);
15728c2ecf20Sopenharmony_ci	set_ino_in_dir_entry(&new_de, INODE_PKEY(old_inode));
15738c2ecf20Sopenharmony_ci	journal_mark_dirty(&th, new_de.de_bh);
15748c2ecf20Sopenharmony_ci
15758c2ecf20Sopenharmony_ci	mark_de_hidden(old_de.de_deh + old_de.de_entry_num);
15768c2ecf20Sopenharmony_ci	journal_mark_dirty(&th, old_de.de_bh);
15778c2ecf20Sopenharmony_ci	ctime = current_time(old_dir);
15788c2ecf20Sopenharmony_ci	old_dir->i_ctime = old_dir->i_mtime = ctime;
15798c2ecf20Sopenharmony_ci	new_dir->i_ctime = new_dir->i_mtime = ctime;
15808c2ecf20Sopenharmony_ci	/*
15818c2ecf20Sopenharmony_ci	 * thanks to Alex Adriaanse <alex_a@caltech.edu> for patch
15828c2ecf20Sopenharmony_ci	 * which adds ctime update of renamed object
15838c2ecf20Sopenharmony_ci	 */
15848c2ecf20Sopenharmony_ci	old_inode->i_ctime = ctime;
15858c2ecf20Sopenharmony_ci
15868c2ecf20Sopenharmony_ci	if (new_dentry_inode) {
15878c2ecf20Sopenharmony_ci		/* adjust link number of the victim */
15888c2ecf20Sopenharmony_ci		if (S_ISDIR(new_dentry_inode->i_mode)) {
15898c2ecf20Sopenharmony_ci			clear_nlink(new_dentry_inode);
15908c2ecf20Sopenharmony_ci		} else {
15918c2ecf20Sopenharmony_ci			drop_nlink(new_dentry_inode);
15928c2ecf20Sopenharmony_ci		}
15938c2ecf20Sopenharmony_ci		new_dentry_inode->i_ctime = ctime;
15948c2ecf20Sopenharmony_ci		savelink = new_dentry_inode->i_nlink;
15958c2ecf20Sopenharmony_ci	}
15968c2ecf20Sopenharmony_ci
15978c2ecf20Sopenharmony_ci	if (S_ISDIR(old_inode_mode)) {
15988c2ecf20Sopenharmony_ci		/* adjust ".." of renamed directory */
15998c2ecf20Sopenharmony_ci		set_ino_in_dir_entry(&dot_dot_de, INODE_PKEY(new_dir));
16008c2ecf20Sopenharmony_ci		journal_mark_dirty(&th, dot_dot_de.de_bh);
16018c2ecf20Sopenharmony_ci
16028c2ecf20Sopenharmony_ci		/*
16038c2ecf20Sopenharmony_ci		 * there (in new_dir) was no directory, so it got new link
16048c2ecf20Sopenharmony_ci		 * (".."  of renamed directory)
16058c2ecf20Sopenharmony_ci		 */
16068c2ecf20Sopenharmony_ci		if (!new_dentry_inode)
16078c2ecf20Sopenharmony_ci			INC_DIR_INODE_NLINK(new_dir);
16088c2ecf20Sopenharmony_ci
16098c2ecf20Sopenharmony_ci		/* old directory lost one link - ".. " of renamed directory */
16108c2ecf20Sopenharmony_ci		DEC_DIR_INODE_NLINK(old_dir);
16118c2ecf20Sopenharmony_ci	}
16128c2ecf20Sopenharmony_ci	/*
16138c2ecf20Sopenharmony_ci	 * looks like in 2.3.99pre3 brelse is atomic.
16148c2ecf20Sopenharmony_ci	 * so we can use pathrelse
16158c2ecf20Sopenharmony_ci	 */
16168c2ecf20Sopenharmony_ci	pathrelse(&new_entry_path);
16178c2ecf20Sopenharmony_ci	pathrelse(&dot_dot_entry_path);
16188c2ecf20Sopenharmony_ci
16198c2ecf20Sopenharmony_ci	/*
16208c2ecf20Sopenharmony_ci	 * FIXME: this reiserfs_cut_from_item's return value may screw up
16218c2ecf20Sopenharmony_ci	 * anybody, but it will panic if will not be able to find the
16228c2ecf20Sopenharmony_ci	 * entry. This needs one more clean up
16238c2ecf20Sopenharmony_ci	 */
16248c2ecf20Sopenharmony_ci	if (reiserfs_cut_from_item
16258c2ecf20Sopenharmony_ci	    (&th, &old_entry_path, &old_de.de_entry_key, old_dir, NULL,
16268c2ecf20Sopenharmony_ci	     0) < 0)
16278c2ecf20Sopenharmony_ci		reiserfs_error(old_dir->i_sb, "vs-7060",
16288c2ecf20Sopenharmony_ci			       "couldn't not cut old name. Fsck later?");
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci	old_dir->i_size -= DEH_SIZE + old_de.de_entrylen;
16318c2ecf20Sopenharmony_ci
16328c2ecf20Sopenharmony_ci	reiserfs_update_sd(&th, old_dir);
16338c2ecf20Sopenharmony_ci	reiserfs_update_sd(&th, new_dir);
16348c2ecf20Sopenharmony_ci	reiserfs_update_sd(&th, old_inode);
16358c2ecf20Sopenharmony_ci
16368c2ecf20Sopenharmony_ci	if (new_dentry_inode) {
16378c2ecf20Sopenharmony_ci		if (savelink == 0)
16388c2ecf20Sopenharmony_ci			add_save_link(&th, new_dentry_inode,
16398c2ecf20Sopenharmony_ci				      0 /* not truncate */ );
16408c2ecf20Sopenharmony_ci		reiserfs_update_sd(&th, new_dentry_inode);
16418c2ecf20Sopenharmony_ci	}
16428c2ecf20Sopenharmony_ci
16438c2ecf20Sopenharmony_ci	retval = journal_end(&th);
16448c2ecf20Sopenharmony_ci	reiserfs_write_unlock(old_dir->i_sb);
16458c2ecf20Sopenharmony_ci	return retval;
16468c2ecf20Sopenharmony_ci}
16478c2ecf20Sopenharmony_ci
16488c2ecf20Sopenharmony_ci/* directories can handle most operations...  */
16498c2ecf20Sopenharmony_ciconst struct inode_operations reiserfs_dir_inode_operations = {
16508c2ecf20Sopenharmony_ci	.create = reiserfs_create,
16518c2ecf20Sopenharmony_ci	.lookup = reiserfs_lookup,
16528c2ecf20Sopenharmony_ci	.link = reiserfs_link,
16538c2ecf20Sopenharmony_ci	.unlink = reiserfs_unlink,
16548c2ecf20Sopenharmony_ci	.symlink = reiserfs_symlink,
16558c2ecf20Sopenharmony_ci	.mkdir = reiserfs_mkdir,
16568c2ecf20Sopenharmony_ci	.rmdir = reiserfs_rmdir,
16578c2ecf20Sopenharmony_ci	.mknod = reiserfs_mknod,
16588c2ecf20Sopenharmony_ci	.rename = reiserfs_rename,
16598c2ecf20Sopenharmony_ci	.setattr = reiserfs_setattr,
16608c2ecf20Sopenharmony_ci	.listxattr = reiserfs_listxattr,
16618c2ecf20Sopenharmony_ci	.permission = reiserfs_permission,
16628c2ecf20Sopenharmony_ci	.get_acl = reiserfs_get_acl,
16638c2ecf20Sopenharmony_ci	.set_acl = reiserfs_set_acl,
16648c2ecf20Sopenharmony_ci};
16658c2ecf20Sopenharmony_ci
16668c2ecf20Sopenharmony_ci/*
16678c2ecf20Sopenharmony_ci * symlink operations.. same as page_symlink_inode_operations, with xattr
16688c2ecf20Sopenharmony_ci * stuff added
16698c2ecf20Sopenharmony_ci */
16708c2ecf20Sopenharmony_ciconst struct inode_operations reiserfs_symlink_inode_operations = {
16718c2ecf20Sopenharmony_ci	.get_link	= page_get_link,
16728c2ecf20Sopenharmony_ci	.setattr = reiserfs_setattr,
16738c2ecf20Sopenharmony_ci	.listxattr = reiserfs_listxattr,
16748c2ecf20Sopenharmony_ci	.permission = reiserfs_permission,
16758c2ecf20Sopenharmony_ci};
16768c2ecf20Sopenharmony_ci
16778c2ecf20Sopenharmony_ci/*
16788c2ecf20Sopenharmony_ci * special file operations.. just xattr/acl stuff
16798c2ecf20Sopenharmony_ci */
16808c2ecf20Sopenharmony_ciconst struct inode_operations reiserfs_special_inode_operations = {
16818c2ecf20Sopenharmony_ci	.setattr = reiserfs_setattr,
16828c2ecf20Sopenharmony_ci	.listxattr = reiserfs_listxattr,
16838c2ecf20Sopenharmony_ci	.permission = reiserfs_permission,
16848c2ecf20Sopenharmony_ci	.get_acl = reiserfs_get_acl,
16858c2ecf20Sopenharmony_ci	.set_acl = reiserfs_set_acl,
16868c2ecf20Sopenharmony_ci};
1687