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