18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * linux/fs/ext2/namei.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Rewrite to pagecache. Almost all code had been changed, so blame me 68c2ecf20Sopenharmony_ci * if the things go wrong. Please, send bug reports to 78c2ecf20Sopenharmony_ci * viro@parcelfarce.linux.theplanet.co.uk 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Stuff here is basically a glue between the VFS and generic UNIXish 108c2ecf20Sopenharmony_ci * filesystem that keeps everything in pagecache. All knowledge of the 118c2ecf20Sopenharmony_ci * directory layout is in fs/ext2/dir.c - it turned out to be easily separatable 128c2ecf20Sopenharmony_ci * and it's easier to debug that way. In principle we might want to 138c2ecf20Sopenharmony_ci * generalize that a bit and turn it into a library. Or not. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * The only non-static object here is ext2_dir_inode_operations. 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * TODO: get rid of kmap() use, add readahead. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * Copyright (C) 1992, 1993, 1994, 1995 208c2ecf20Sopenharmony_ci * Remy Card (card@masi.ibp.fr) 218c2ecf20Sopenharmony_ci * Laboratoire MASI - Institut Blaise Pascal 228c2ecf20Sopenharmony_ci * Universite Pierre et Marie Curie (Paris VI) 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * from 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci * linux/fs/minix/namei.c 278c2ecf20Sopenharmony_ci * 288c2ecf20Sopenharmony_ci * Copyright (C) 1991, 1992 Linus Torvalds 298c2ecf20Sopenharmony_ci * 308c2ecf20Sopenharmony_ci * Big-endian to little-endian byte-swapping/bitmaps by 318c2ecf20Sopenharmony_ci * David S. Miller (davem@caip.rutgers.edu), 1995 328c2ecf20Sopenharmony_ci */ 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 358c2ecf20Sopenharmony_ci#include <linux/quotaops.h> 368c2ecf20Sopenharmony_ci#include "ext2.h" 378c2ecf20Sopenharmony_ci#include "xattr.h" 388c2ecf20Sopenharmony_ci#include "acl.h" 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistatic inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci int err = ext2_add_link(dentry, inode); 438c2ecf20Sopenharmony_ci if (!err) { 448c2ecf20Sopenharmony_ci d_instantiate_new(dentry, inode); 458c2ecf20Sopenharmony_ci return 0; 468c2ecf20Sopenharmony_ci } 478c2ecf20Sopenharmony_ci inode_dec_link_count(inode); 488c2ecf20Sopenharmony_ci discard_new_inode(inode); 498c2ecf20Sopenharmony_ci return err; 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci/* 538c2ecf20Sopenharmony_ci * Methods themselves. 548c2ecf20Sopenharmony_ci */ 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cistatic struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci struct inode * inode; 598c2ecf20Sopenharmony_ci ino_t ino; 608c2ecf20Sopenharmony_ci int res; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci if (dentry->d_name.len > EXT2_NAME_LEN) 638c2ecf20Sopenharmony_ci return ERR_PTR(-ENAMETOOLONG); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci res = ext2_inode_by_name(dir, &dentry->d_name, &ino); 668c2ecf20Sopenharmony_ci if (res) { 678c2ecf20Sopenharmony_ci if (res != -ENOENT) 688c2ecf20Sopenharmony_ci return ERR_PTR(res); 698c2ecf20Sopenharmony_ci inode = NULL; 708c2ecf20Sopenharmony_ci } else { 718c2ecf20Sopenharmony_ci inode = ext2_iget(dir->i_sb, ino); 728c2ecf20Sopenharmony_ci if (inode == ERR_PTR(-ESTALE)) { 738c2ecf20Sopenharmony_ci ext2_error(dir->i_sb, __func__, 748c2ecf20Sopenharmony_ci "deleted inode referenced: %lu", 758c2ecf20Sopenharmony_ci (unsigned long) ino); 768c2ecf20Sopenharmony_ci return ERR_PTR(-EIO); 778c2ecf20Sopenharmony_ci } 788c2ecf20Sopenharmony_ci } 798c2ecf20Sopenharmony_ci return d_splice_alias(inode, dentry); 808c2ecf20Sopenharmony_ci} 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistruct dentry *ext2_get_parent(struct dentry *child) 838c2ecf20Sopenharmony_ci{ 848c2ecf20Sopenharmony_ci struct qstr dotdot = QSTR_INIT("..", 2); 858c2ecf20Sopenharmony_ci ino_t ino; 868c2ecf20Sopenharmony_ci int res; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci res = ext2_inode_by_name(d_inode(child), &dotdot, &ino); 898c2ecf20Sopenharmony_ci if (res) 908c2ecf20Sopenharmony_ci return ERR_PTR(res); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci return d_obtain_alias(ext2_iget(child->d_sb, ino)); 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci/* 968c2ecf20Sopenharmony_ci * By the time this is called, we already have created 978c2ecf20Sopenharmony_ci * the directory cache entry for the new file, but it 988c2ecf20Sopenharmony_ci * is so far negative - it has no inode. 998c2ecf20Sopenharmony_ci * 1008c2ecf20Sopenharmony_ci * If the create succeeds, we fill in the inode information 1018c2ecf20Sopenharmony_ci * with d_instantiate(). 1028c2ecf20Sopenharmony_ci */ 1038c2ecf20Sopenharmony_cistatic int ext2_create (struct inode * dir, struct dentry * dentry, umode_t mode, bool excl) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci struct inode *inode; 1068c2ecf20Sopenharmony_ci int err; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci err = dquot_initialize(dir); 1098c2ecf20Sopenharmony_ci if (err) 1108c2ecf20Sopenharmony_ci return err; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci inode = ext2_new_inode(dir, mode, &dentry->d_name); 1138c2ecf20Sopenharmony_ci if (IS_ERR(inode)) 1148c2ecf20Sopenharmony_ci return PTR_ERR(inode); 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci ext2_set_file_ops(inode); 1178c2ecf20Sopenharmony_ci mark_inode_dirty(inode); 1188c2ecf20Sopenharmony_ci return ext2_add_nondir(dentry, inode); 1198c2ecf20Sopenharmony_ci} 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cistatic int ext2_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci struct inode *inode = ext2_new_inode(dir, mode, NULL); 1248c2ecf20Sopenharmony_ci if (IS_ERR(inode)) 1258c2ecf20Sopenharmony_ci return PTR_ERR(inode); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci ext2_set_file_ops(inode); 1288c2ecf20Sopenharmony_ci mark_inode_dirty(inode); 1298c2ecf20Sopenharmony_ci d_tmpfile(dentry, inode); 1308c2ecf20Sopenharmony_ci unlock_new_inode(inode); 1318c2ecf20Sopenharmony_ci return 0; 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cistatic int ext2_mknod (struct inode * dir, struct dentry *dentry, umode_t mode, dev_t rdev) 1358c2ecf20Sopenharmony_ci{ 1368c2ecf20Sopenharmony_ci struct inode * inode; 1378c2ecf20Sopenharmony_ci int err; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci err = dquot_initialize(dir); 1408c2ecf20Sopenharmony_ci if (err) 1418c2ecf20Sopenharmony_ci return err; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci inode = ext2_new_inode (dir, mode, &dentry->d_name); 1448c2ecf20Sopenharmony_ci err = PTR_ERR(inode); 1458c2ecf20Sopenharmony_ci if (!IS_ERR(inode)) { 1468c2ecf20Sopenharmony_ci init_special_inode(inode, inode->i_mode, rdev); 1478c2ecf20Sopenharmony_ci inode->i_op = &ext2_special_inode_operations; 1488c2ecf20Sopenharmony_ci mark_inode_dirty(inode); 1498c2ecf20Sopenharmony_ci err = ext2_add_nondir(dentry, inode); 1508c2ecf20Sopenharmony_ci } 1518c2ecf20Sopenharmony_ci return err; 1528c2ecf20Sopenharmony_ci} 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_cistatic int ext2_symlink (struct inode * dir, struct dentry * dentry, 1558c2ecf20Sopenharmony_ci const char * symname) 1568c2ecf20Sopenharmony_ci{ 1578c2ecf20Sopenharmony_ci struct super_block * sb = dir->i_sb; 1588c2ecf20Sopenharmony_ci int err = -ENAMETOOLONG; 1598c2ecf20Sopenharmony_ci unsigned l = strlen(symname)+1; 1608c2ecf20Sopenharmony_ci struct inode * inode; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci if (l > sb->s_blocksize) 1638c2ecf20Sopenharmony_ci goto out; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci err = dquot_initialize(dir); 1668c2ecf20Sopenharmony_ci if (err) 1678c2ecf20Sopenharmony_ci goto out; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO, &dentry->d_name); 1708c2ecf20Sopenharmony_ci err = PTR_ERR(inode); 1718c2ecf20Sopenharmony_ci if (IS_ERR(inode)) 1728c2ecf20Sopenharmony_ci goto out; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci if (l > sizeof (EXT2_I(inode)->i_data)) { 1758c2ecf20Sopenharmony_ci /* slow symlink */ 1768c2ecf20Sopenharmony_ci inode->i_op = &ext2_symlink_inode_operations; 1778c2ecf20Sopenharmony_ci inode_nohighmem(inode); 1788c2ecf20Sopenharmony_ci if (test_opt(inode->i_sb, NOBH)) 1798c2ecf20Sopenharmony_ci inode->i_mapping->a_ops = &ext2_nobh_aops; 1808c2ecf20Sopenharmony_ci else 1818c2ecf20Sopenharmony_ci inode->i_mapping->a_ops = &ext2_aops; 1828c2ecf20Sopenharmony_ci err = page_symlink(inode, symname, l); 1838c2ecf20Sopenharmony_ci if (err) 1848c2ecf20Sopenharmony_ci goto out_fail; 1858c2ecf20Sopenharmony_ci } else { 1868c2ecf20Sopenharmony_ci /* fast symlink */ 1878c2ecf20Sopenharmony_ci inode->i_op = &ext2_fast_symlink_inode_operations; 1888c2ecf20Sopenharmony_ci inode->i_link = (char*)EXT2_I(inode)->i_data; 1898c2ecf20Sopenharmony_ci memcpy(inode->i_link, symname, l); 1908c2ecf20Sopenharmony_ci inode->i_size = l-1; 1918c2ecf20Sopenharmony_ci } 1928c2ecf20Sopenharmony_ci mark_inode_dirty(inode); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci err = ext2_add_nondir(dentry, inode); 1958c2ecf20Sopenharmony_ciout: 1968c2ecf20Sopenharmony_ci return err; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ciout_fail: 1998c2ecf20Sopenharmony_ci inode_dec_link_count(inode); 2008c2ecf20Sopenharmony_ci discard_new_inode(inode); 2018c2ecf20Sopenharmony_ci goto out; 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_cistatic int ext2_link (struct dentry * old_dentry, struct inode * dir, 2058c2ecf20Sopenharmony_ci struct dentry *dentry) 2068c2ecf20Sopenharmony_ci{ 2078c2ecf20Sopenharmony_ci struct inode *inode = d_inode(old_dentry); 2088c2ecf20Sopenharmony_ci int err; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci err = dquot_initialize(dir); 2118c2ecf20Sopenharmony_ci if (err) 2128c2ecf20Sopenharmony_ci return err; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci inode->i_ctime = current_time(inode); 2158c2ecf20Sopenharmony_ci inode_inc_link_count(inode); 2168c2ecf20Sopenharmony_ci ihold(inode); 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci err = ext2_add_link(dentry, inode); 2198c2ecf20Sopenharmony_ci if (!err) { 2208c2ecf20Sopenharmony_ci d_instantiate(dentry, inode); 2218c2ecf20Sopenharmony_ci return 0; 2228c2ecf20Sopenharmony_ci } 2238c2ecf20Sopenharmony_ci inode_dec_link_count(inode); 2248c2ecf20Sopenharmony_ci iput(inode); 2258c2ecf20Sopenharmony_ci return err; 2268c2ecf20Sopenharmony_ci} 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_cistatic int ext2_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode) 2298c2ecf20Sopenharmony_ci{ 2308c2ecf20Sopenharmony_ci struct inode * inode; 2318c2ecf20Sopenharmony_ci int err; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci err = dquot_initialize(dir); 2348c2ecf20Sopenharmony_ci if (err) 2358c2ecf20Sopenharmony_ci return err; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci inode_inc_link_count(dir); 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci inode = ext2_new_inode(dir, S_IFDIR | mode, &dentry->d_name); 2408c2ecf20Sopenharmony_ci err = PTR_ERR(inode); 2418c2ecf20Sopenharmony_ci if (IS_ERR(inode)) 2428c2ecf20Sopenharmony_ci goto out_dir; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci inode->i_op = &ext2_dir_inode_operations; 2458c2ecf20Sopenharmony_ci inode->i_fop = &ext2_dir_operations; 2468c2ecf20Sopenharmony_ci if (test_opt(inode->i_sb, NOBH)) 2478c2ecf20Sopenharmony_ci inode->i_mapping->a_ops = &ext2_nobh_aops; 2488c2ecf20Sopenharmony_ci else 2498c2ecf20Sopenharmony_ci inode->i_mapping->a_ops = &ext2_aops; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci inode_inc_link_count(inode); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci err = ext2_make_empty(inode, dir); 2548c2ecf20Sopenharmony_ci if (err) 2558c2ecf20Sopenharmony_ci goto out_fail; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci err = ext2_add_link(dentry, inode); 2588c2ecf20Sopenharmony_ci if (err) 2598c2ecf20Sopenharmony_ci goto out_fail; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci d_instantiate_new(dentry, inode); 2628c2ecf20Sopenharmony_ciout: 2638c2ecf20Sopenharmony_ci return err; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ciout_fail: 2668c2ecf20Sopenharmony_ci inode_dec_link_count(inode); 2678c2ecf20Sopenharmony_ci inode_dec_link_count(inode); 2688c2ecf20Sopenharmony_ci discard_new_inode(inode); 2698c2ecf20Sopenharmony_ciout_dir: 2708c2ecf20Sopenharmony_ci inode_dec_link_count(dir); 2718c2ecf20Sopenharmony_ci goto out; 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_cistatic int ext2_unlink(struct inode * dir, struct dentry *dentry) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci struct inode * inode = d_inode(dentry); 2778c2ecf20Sopenharmony_ci struct ext2_dir_entry_2 * de; 2788c2ecf20Sopenharmony_ci struct page * page; 2798c2ecf20Sopenharmony_ci int err; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci err = dquot_initialize(dir); 2828c2ecf20Sopenharmony_ci if (err) 2838c2ecf20Sopenharmony_ci goto out; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci de = ext2_find_entry(dir, &dentry->d_name, &page); 2868c2ecf20Sopenharmony_ci if (IS_ERR(de)) { 2878c2ecf20Sopenharmony_ci err = PTR_ERR(de); 2888c2ecf20Sopenharmony_ci goto out; 2898c2ecf20Sopenharmony_ci } 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci err = ext2_delete_entry (de, page); 2928c2ecf20Sopenharmony_ci if (err) 2938c2ecf20Sopenharmony_ci goto out; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci inode->i_ctime = dir->i_ctime; 2968c2ecf20Sopenharmony_ci inode_dec_link_count(inode); 2978c2ecf20Sopenharmony_ci err = 0; 2988c2ecf20Sopenharmony_ciout: 2998c2ecf20Sopenharmony_ci return err; 3008c2ecf20Sopenharmony_ci} 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistatic int ext2_rmdir (struct inode * dir, struct dentry *dentry) 3038c2ecf20Sopenharmony_ci{ 3048c2ecf20Sopenharmony_ci struct inode * inode = d_inode(dentry); 3058c2ecf20Sopenharmony_ci int err = -ENOTEMPTY; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci if (ext2_empty_dir(inode)) { 3088c2ecf20Sopenharmony_ci err = ext2_unlink(dir, dentry); 3098c2ecf20Sopenharmony_ci if (!err) { 3108c2ecf20Sopenharmony_ci inode->i_size = 0; 3118c2ecf20Sopenharmony_ci inode_dec_link_count(inode); 3128c2ecf20Sopenharmony_ci inode_dec_link_count(dir); 3138c2ecf20Sopenharmony_ci } 3148c2ecf20Sopenharmony_ci } 3158c2ecf20Sopenharmony_ci return err; 3168c2ecf20Sopenharmony_ci} 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_cistatic int ext2_rename (struct inode * old_dir, struct dentry * old_dentry, 3198c2ecf20Sopenharmony_ci struct inode * new_dir, struct dentry * new_dentry, 3208c2ecf20Sopenharmony_ci unsigned int flags) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci struct inode * old_inode = d_inode(old_dentry); 3238c2ecf20Sopenharmony_ci struct inode * new_inode = d_inode(new_dentry); 3248c2ecf20Sopenharmony_ci struct page * dir_page = NULL; 3258c2ecf20Sopenharmony_ci struct ext2_dir_entry_2 * dir_de = NULL; 3268c2ecf20Sopenharmony_ci struct page * old_page; 3278c2ecf20Sopenharmony_ci struct ext2_dir_entry_2 * old_de; 3288c2ecf20Sopenharmony_ci int err; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci if (flags & ~RENAME_NOREPLACE) 3318c2ecf20Sopenharmony_ci return -EINVAL; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci err = dquot_initialize(old_dir); 3348c2ecf20Sopenharmony_ci if (err) 3358c2ecf20Sopenharmony_ci goto out; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci err = dquot_initialize(new_dir); 3388c2ecf20Sopenharmony_ci if (err) 3398c2ecf20Sopenharmony_ci goto out; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci old_de = ext2_find_entry(old_dir, &old_dentry->d_name, &old_page); 3428c2ecf20Sopenharmony_ci if (IS_ERR(old_de)) { 3438c2ecf20Sopenharmony_ci err = PTR_ERR(old_de); 3448c2ecf20Sopenharmony_ci goto out; 3458c2ecf20Sopenharmony_ci } 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci if (S_ISDIR(old_inode->i_mode)) { 3488c2ecf20Sopenharmony_ci err = -EIO; 3498c2ecf20Sopenharmony_ci dir_de = ext2_dotdot(old_inode, &dir_page); 3508c2ecf20Sopenharmony_ci if (!dir_de) 3518c2ecf20Sopenharmony_ci goto out_old; 3528c2ecf20Sopenharmony_ci } 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci if (new_inode) { 3558c2ecf20Sopenharmony_ci struct page *new_page; 3568c2ecf20Sopenharmony_ci struct ext2_dir_entry_2 *new_de; 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci err = -ENOTEMPTY; 3598c2ecf20Sopenharmony_ci if (dir_de && !ext2_empty_dir (new_inode)) 3608c2ecf20Sopenharmony_ci goto out_dir; 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci new_de = ext2_find_entry(new_dir, &new_dentry->d_name, &new_page); 3638c2ecf20Sopenharmony_ci if (IS_ERR(new_de)) { 3648c2ecf20Sopenharmony_ci err = PTR_ERR(new_de); 3658c2ecf20Sopenharmony_ci goto out_dir; 3668c2ecf20Sopenharmony_ci } 3678c2ecf20Sopenharmony_ci ext2_set_link(new_dir, new_de, new_page, old_inode, 1); 3688c2ecf20Sopenharmony_ci new_inode->i_ctime = current_time(new_inode); 3698c2ecf20Sopenharmony_ci if (dir_de) 3708c2ecf20Sopenharmony_ci drop_nlink(new_inode); 3718c2ecf20Sopenharmony_ci inode_dec_link_count(new_inode); 3728c2ecf20Sopenharmony_ci } else { 3738c2ecf20Sopenharmony_ci err = ext2_add_link(new_dentry, old_inode); 3748c2ecf20Sopenharmony_ci if (err) 3758c2ecf20Sopenharmony_ci goto out_dir; 3768c2ecf20Sopenharmony_ci if (dir_de) 3778c2ecf20Sopenharmony_ci inode_inc_link_count(new_dir); 3788c2ecf20Sopenharmony_ci } 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci /* 3818c2ecf20Sopenharmony_ci * Like most other Unix systems, set the ctime for inodes on a 3828c2ecf20Sopenharmony_ci * rename. 3838c2ecf20Sopenharmony_ci */ 3848c2ecf20Sopenharmony_ci old_inode->i_ctime = current_time(old_inode); 3858c2ecf20Sopenharmony_ci mark_inode_dirty(old_inode); 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci ext2_delete_entry (old_de, old_page); 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci if (dir_de) { 3908c2ecf20Sopenharmony_ci if (old_dir != new_dir) 3918c2ecf20Sopenharmony_ci ext2_set_link(old_inode, dir_de, dir_page, new_dir, 0); 3928c2ecf20Sopenharmony_ci else { 3938c2ecf20Sopenharmony_ci kunmap(dir_page); 3948c2ecf20Sopenharmony_ci put_page(dir_page); 3958c2ecf20Sopenharmony_ci } 3968c2ecf20Sopenharmony_ci inode_dec_link_count(old_dir); 3978c2ecf20Sopenharmony_ci } 3988c2ecf20Sopenharmony_ci return 0; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ciout_dir: 4028c2ecf20Sopenharmony_ci if (dir_de) { 4038c2ecf20Sopenharmony_ci kunmap(dir_page); 4048c2ecf20Sopenharmony_ci put_page(dir_page); 4058c2ecf20Sopenharmony_ci } 4068c2ecf20Sopenharmony_ciout_old: 4078c2ecf20Sopenharmony_ci kunmap(old_page); 4088c2ecf20Sopenharmony_ci put_page(old_page); 4098c2ecf20Sopenharmony_ciout: 4108c2ecf20Sopenharmony_ci return err; 4118c2ecf20Sopenharmony_ci} 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ciconst struct inode_operations ext2_dir_inode_operations = { 4148c2ecf20Sopenharmony_ci .create = ext2_create, 4158c2ecf20Sopenharmony_ci .lookup = ext2_lookup, 4168c2ecf20Sopenharmony_ci .link = ext2_link, 4178c2ecf20Sopenharmony_ci .unlink = ext2_unlink, 4188c2ecf20Sopenharmony_ci .symlink = ext2_symlink, 4198c2ecf20Sopenharmony_ci .mkdir = ext2_mkdir, 4208c2ecf20Sopenharmony_ci .rmdir = ext2_rmdir, 4218c2ecf20Sopenharmony_ci .mknod = ext2_mknod, 4228c2ecf20Sopenharmony_ci .rename = ext2_rename, 4238c2ecf20Sopenharmony_ci .listxattr = ext2_listxattr, 4248c2ecf20Sopenharmony_ci .getattr = ext2_getattr, 4258c2ecf20Sopenharmony_ci .setattr = ext2_setattr, 4268c2ecf20Sopenharmony_ci .get_acl = ext2_get_acl, 4278c2ecf20Sopenharmony_ci .set_acl = ext2_set_acl, 4288c2ecf20Sopenharmony_ci .tmpfile = ext2_tmpfile, 4298c2ecf20Sopenharmony_ci}; 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ciconst struct inode_operations ext2_special_inode_operations = { 4328c2ecf20Sopenharmony_ci .listxattr = ext2_listxattr, 4338c2ecf20Sopenharmony_ci .getattr = ext2_getattr, 4348c2ecf20Sopenharmony_ci .setattr = ext2_setattr, 4358c2ecf20Sopenharmony_ci .get_acl = ext2_get_acl, 4368c2ecf20Sopenharmony_ci .set_acl = ext2_set_acl, 4378c2ecf20Sopenharmony_ci}; 438