18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * linux/fs/affs/inode.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * (c) 1996 Hans-Joachim Widmaier - Rewritten 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * (C) 1993 Ray Burr - Modified for Amiga FFS filesystem. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * (C) 1992 Eric Youngdale Modified for ISO9660 filesystem. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * (C) 1991 Linus Torvalds - minix filesystem 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci#include <linux/sched.h> 148c2ecf20Sopenharmony_ci#include <linux/cred.h> 158c2ecf20Sopenharmony_ci#include <linux/gfp.h> 168c2ecf20Sopenharmony_ci#include "affs.h" 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistruct inode *affs_iget(struct super_block *sb, unsigned long ino) 198c2ecf20Sopenharmony_ci{ 208c2ecf20Sopenharmony_ci struct affs_sb_info *sbi = AFFS_SB(sb); 218c2ecf20Sopenharmony_ci struct buffer_head *bh; 228c2ecf20Sopenharmony_ci struct affs_tail *tail; 238c2ecf20Sopenharmony_ci struct inode *inode; 248c2ecf20Sopenharmony_ci u32 block; 258c2ecf20Sopenharmony_ci u32 size; 268c2ecf20Sopenharmony_ci u32 prot; 278c2ecf20Sopenharmony_ci u16 id; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci inode = iget_locked(sb, ino); 308c2ecf20Sopenharmony_ci if (!inode) 318c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 328c2ecf20Sopenharmony_ci if (!(inode->i_state & I_NEW)) 338c2ecf20Sopenharmony_ci return inode; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci pr_debug("affs_iget(%lu)\n", inode->i_ino); 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci block = inode->i_ino; 388c2ecf20Sopenharmony_ci bh = affs_bread(sb, block); 398c2ecf20Sopenharmony_ci if (!bh) { 408c2ecf20Sopenharmony_ci affs_warning(sb, "read_inode", "Cannot read block %d", block); 418c2ecf20Sopenharmony_ci goto bad_inode; 428c2ecf20Sopenharmony_ci } 438c2ecf20Sopenharmony_ci if (affs_checksum_block(sb, bh) || be32_to_cpu(AFFS_HEAD(bh)->ptype) != T_SHORT) { 448c2ecf20Sopenharmony_ci affs_warning(sb,"read_inode", 458c2ecf20Sopenharmony_ci "Checksum or type (ptype=%d) error on inode %d", 468c2ecf20Sopenharmony_ci AFFS_HEAD(bh)->ptype, block); 478c2ecf20Sopenharmony_ci goto bad_inode; 488c2ecf20Sopenharmony_ci } 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci tail = AFFS_TAIL(sb, bh); 518c2ecf20Sopenharmony_ci prot = be32_to_cpu(tail->protect); 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci inode->i_size = 0; 548c2ecf20Sopenharmony_ci set_nlink(inode, 1); 558c2ecf20Sopenharmony_ci inode->i_mode = 0; 568c2ecf20Sopenharmony_ci AFFS_I(inode)->i_extcnt = 1; 578c2ecf20Sopenharmony_ci AFFS_I(inode)->i_ext_last = ~1; 588c2ecf20Sopenharmony_ci AFFS_I(inode)->i_protect = prot; 598c2ecf20Sopenharmony_ci atomic_set(&AFFS_I(inode)->i_opencnt, 0); 608c2ecf20Sopenharmony_ci AFFS_I(inode)->i_blkcnt = 0; 618c2ecf20Sopenharmony_ci AFFS_I(inode)->i_lc = NULL; 628c2ecf20Sopenharmony_ci AFFS_I(inode)->i_lc_size = 0; 638c2ecf20Sopenharmony_ci AFFS_I(inode)->i_lc_shift = 0; 648c2ecf20Sopenharmony_ci AFFS_I(inode)->i_lc_mask = 0; 658c2ecf20Sopenharmony_ci AFFS_I(inode)->i_ac = NULL; 668c2ecf20Sopenharmony_ci AFFS_I(inode)->i_ext_bh = NULL; 678c2ecf20Sopenharmony_ci AFFS_I(inode)->mmu_private = 0; 688c2ecf20Sopenharmony_ci AFFS_I(inode)->i_lastalloc = 0; 698c2ecf20Sopenharmony_ci AFFS_I(inode)->i_pa_cnt = 0; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci if (affs_test_opt(sbi->s_flags, SF_SETMODE)) 728c2ecf20Sopenharmony_ci inode->i_mode = sbi->s_mode; 738c2ecf20Sopenharmony_ci else 748c2ecf20Sopenharmony_ci inode->i_mode = affs_prot_to_mode(prot); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci id = be16_to_cpu(tail->uid); 778c2ecf20Sopenharmony_ci if (id == 0 || affs_test_opt(sbi->s_flags, SF_SETUID)) 788c2ecf20Sopenharmony_ci inode->i_uid = sbi->s_uid; 798c2ecf20Sopenharmony_ci else if (id == 0xFFFF && affs_test_opt(sbi->s_flags, SF_MUFS)) 808c2ecf20Sopenharmony_ci i_uid_write(inode, 0); 818c2ecf20Sopenharmony_ci else 828c2ecf20Sopenharmony_ci i_uid_write(inode, id); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci id = be16_to_cpu(tail->gid); 858c2ecf20Sopenharmony_ci if (id == 0 || affs_test_opt(sbi->s_flags, SF_SETGID)) 868c2ecf20Sopenharmony_ci inode->i_gid = sbi->s_gid; 878c2ecf20Sopenharmony_ci else if (id == 0xFFFF && affs_test_opt(sbi->s_flags, SF_MUFS)) 888c2ecf20Sopenharmony_ci i_gid_write(inode, 0); 898c2ecf20Sopenharmony_ci else 908c2ecf20Sopenharmony_ci i_gid_write(inode, id); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci switch (be32_to_cpu(tail->stype)) { 938c2ecf20Sopenharmony_ci case ST_ROOT: 948c2ecf20Sopenharmony_ci inode->i_uid = sbi->s_uid; 958c2ecf20Sopenharmony_ci inode->i_gid = sbi->s_gid; 968c2ecf20Sopenharmony_ci fallthrough; 978c2ecf20Sopenharmony_ci case ST_USERDIR: 988c2ecf20Sopenharmony_ci if (be32_to_cpu(tail->stype) == ST_USERDIR || 998c2ecf20Sopenharmony_ci affs_test_opt(sbi->s_flags, SF_SETMODE)) { 1008c2ecf20Sopenharmony_ci if (inode->i_mode & S_IRUSR) 1018c2ecf20Sopenharmony_ci inode->i_mode |= S_IXUSR; 1028c2ecf20Sopenharmony_ci if (inode->i_mode & S_IRGRP) 1038c2ecf20Sopenharmony_ci inode->i_mode |= S_IXGRP; 1048c2ecf20Sopenharmony_ci if (inode->i_mode & S_IROTH) 1058c2ecf20Sopenharmony_ci inode->i_mode |= S_IXOTH; 1068c2ecf20Sopenharmony_ci inode->i_mode |= S_IFDIR; 1078c2ecf20Sopenharmony_ci } else 1088c2ecf20Sopenharmony_ci inode->i_mode = S_IRUGO | S_IXUGO | S_IWUSR | S_IFDIR; 1098c2ecf20Sopenharmony_ci /* Maybe it should be controlled by mount parameter? */ 1108c2ecf20Sopenharmony_ci //inode->i_mode |= S_ISVTX; 1118c2ecf20Sopenharmony_ci inode->i_op = &affs_dir_inode_operations; 1128c2ecf20Sopenharmony_ci inode->i_fop = &affs_dir_operations; 1138c2ecf20Sopenharmony_ci break; 1148c2ecf20Sopenharmony_ci case ST_LINKDIR: 1158c2ecf20Sopenharmony_ci#if 0 1168c2ecf20Sopenharmony_ci affs_warning(sb, "read_inode", "inode is LINKDIR"); 1178c2ecf20Sopenharmony_ci goto bad_inode; 1188c2ecf20Sopenharmony_ci#else 1198c2ecf20Sopenharmony_ci inode->i_mode |= S_IFDIR; 1208c2ecf20Sopenharmony_ci /* ... and leave ->i_op and ->i_fop pointing to empty */ 1218c2ecf20Sopenharmony_ci break; 1228c2ecf20Sopenharmony_ci#endif 1238c2ecf20Sopenharmony_ci case ST_LINKFILE: 1248c2ecf20Sopenharmony_ci affs_warning(sb, "read_inode", "inode is LINKFILE"); 1258c2ecf20Sopenharmony_ci goto bad_inode; 1268c2ecf20Sopenharmony_ci case ST_FILE: 1278c2ecf20Sopenharmony_ci size = be32_to_cpu(tail->size); 1288c2ecf20Sopenharmony_ci inode->i_mode |= S_IFREG; 1298c2ecf20Sopenharmony_ci AFFS_I(inode)->mmu_private = inode->i_size = size; 1308c2ecf20Sopenharmony_ci if (inode->i_size) { 1318c2ecf20Sopenharmony_ci AFFS_I(inode)->i_blkcnt = (size - 1) / 1328c2ecf20Sopenharmony_ci sbi->s_data_blksize + 1; 1338c2ecf20Sopenharmony_ci AFFS_I(inode)->i_extcnt = (AFFS_I(inode)->i_blkcnt - 1) / 1348c2ecf20Sopenharmony_ci sbi->s_hashsize + 1; 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci if (tail->link_chain) 1378c2ecf20Sopenharmony_ci set_nlink(inode, 2); 1388c2ecf20Sopenharmony_ci inode->i_mapping->a_ops = affs_test_opt(sbi->s_flags, SF_OFS) ? 1398c2ecf20Sopenharmony_ci &affs_aops_ofs : &affs_aops; 1408c2ecf20Sopenharmony_ci inode->i_op = &affs_file_inode_operations; 1418c2ecf20Sopenharmony_ci inode->i_fop = &affs_file_operations; 1428c2ecf20Sopenharmony_ci break; 1438c2ecf20Sopenharmony_ci case ST_SOFTLINK: 1448c2ecf20Sopenharmony_ci inode->i_size = strlen((char *)AFFS_HEAD(bh)->table); 1458c2ecf20Sopenharmony_ci inode->i_mode |= S_IFLNK; 1468c2ecf20Sopenharmony_ci inode_nohighmem(inode); 1478c2ecf20Sopenharmony_ci inode->i_op = &affs_symlink_inode_operations; 1488c2ecf20Sopenharmony_ci inode->i_data.a_ops = &affs_symlink_aops; 1498c2ecf20Sopenharmony_ci break; 1508c2ecf20Sopenharmony_ci } 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec 1538c2ecf20Sopenharmony_ci = (be32_to_cpu(tail->change.days) * 86400LL + 1548c2ecf20Sopenharmony_ci be32_to_cpu(tail->change.mins) * 60 + 1558c2ecf20Sopenharmony_ci be32_to_cpu(tail->change.ticks) / 50 + 1568c2ecf20Sopenharmony_ci AFFS_EPOCH_DELTA) + 1578c2ecf20Sopenharmony_ci sys_tz.tz_minuteswest * 60; 1588c2ecf20Sopenharmony_ci inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_atime.tv_nsec = 0; 1598c2ecf20Sopenharmony_ci affs_brelse(bh); 1608c2ecf20Sopenharmony_ci unlock_new_inode(inode); 1618c2ecf20Sopenharmony_ci return inode; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_cibad_inode: 1648c2ecf20Sopenharmony_ci affs_brelse(bh); 1658c2ecf20Sopenharmony_ci iget_failed(inode); 1668c2ecf20Sopenharmony_ci return ERR_PTR(-EIO); 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ciint 1708c2ecf20Sopenharmony_ciaffs_write_inode(struct inode *inode, struct writeback_control *wbc) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci struct super_block *sb = inode->i_sb; 1738c2ecf20Sopenharmony_ci struct buffer_head *bh; 1748c2ecf20Sopenharmony_ci struct affs_tail *tail; 1758c2ecf20Sopenharmony_ci uid_t uid; 1768c2ecf20Sopenharmony_ci gid_t gid; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci pr_debug("write_inode(%lu)\n", inode->i_ino); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci if (!inode->i_nlink) 1818c2ecf20Sopenharmony_ci // possibly free block 1828c2ecf20Sopenharmony_ci return 0; 1838c2ecf20Sopenharmony_ci bh = affs_bread(sb, inode->i_ino); 1848c2ecf20Sopenharmony_ci if (!bh) { 1858c2ecf20Sopenharmony_ci affs_error(sb,"write_inode","Cannot read block %lu",inode->i_ino); 1868c2ecf20Sopenharmony_ci return -EIO; 1878c2ecf20Sopenharmony_ci } 1888c2ecf20Sopenharmony_ci tail = AFFS_TAIL(sb, bh); 1898c2ecf20Sopenharmony_ci if (tail->stype == cpu_to_be32(ST_ROOT)) { 1908c2ecf20Sopenharmony_ci affs_secs_to_datestamp(inode->i_mtime.tv_sec, 1918c2ecf20Sopenharmony_ci &AFFS_ROOT_TAIL(sb, bh)->root_change); 1928c2ecf20Sopenharmony_ci } else { 1938c2ecf20Sopenharmony_ci tail->protect = cpu_to_be32(AFFS_I(inode)->i_protect); 1948c2ecf20Sopenharmony_ci tail->size = cpu_to_be32(inode->i_size); 1958c2ecf20Sopenharmony_ci affs_secs_to_datestamp(inode->i_mtime.tv_sec, &tail->change); 1968c2ecf20Sopenharmony_ci if (!(inode->i_ino == AFFS_SB(sb)->s_root_block)) { 1978c2ecf20Sopenharmony_ci uid = i_uid_read(inode); 1988c2ecf20Sopenharmony_ci gid = i_gid_read(inode); 1998c2ecf20Sopenharmony_ci if (affs_test_opt(AFFS_SB(sb)->s_flags, SF_MUFS)) { 2008c2ecf20Sopenharmony_ci if (uid == 0 || uid == 0xFFFF) 2018c2ecf20Sopenharmony_ci uid = uid ^ ~0; 2028c2ecf20Sopenharmony_ci if (gid == 0 || gid == 0xFFFF) 2038c2ecf20Sopenharmony_ci gid = gid ^ ~0; 2048c2ecf20Sopenharmony_ci } 2058c2ecf20Sopenharmony_ci if (!affs_test_opt(AFFS_SB(sb)->s_flags, SF_SETUID)) 2068c2ecf20Sopenharmony_ci tail->uid = cpu_to_be16(uid); 2078c2ecf20Sopenharmony_ci if (!affs_test_opt(AFFS_SB(sb)->s_flags, SF_SETGID)) 2088c2ecf20Sopenharmony_ci tail->gid = cpu_to_be16(gid); 2098c2ecf20Sopenharmony_ci } 2108c2ecf20Sopenharmony_ci } 2118c2ecf20Sopenharmony_ci affs_fix_checksum(sb, bh); 2128c2ecf20Sopenharmony_ci mark_buffer_dirty_inode(bh, inode); 2138c2ecf20Sopenharmony_ci affs_brelse(bh); 2148c2ecf20Sopenharmony_ci affs_free_prealloc(inode); 2158c2ecf20Sopenharmony_ci return 0; 2168c2ecf20Sopenharmony_ci} 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ciint 2198c2ecf20Sopenharmony_ciaffs_notify_change(struct dentry *dentry, struct iattr *attr) 2208c2ecf20Sopenharmony_ci{ 2218c2ecf20Sopenharmony_ci struct inode *inode = d_inode(dentry); 2228c2ecf20Sopenharmony_ci int error; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci pr_debug("notify_change(%lu,0x%x)\n", inode->i_ino, attr->ia_valid); 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci error = setattr_prepare(dentry, attr); 2278c2ecf20Sopenharmony_ci if (error) 2288c2ecf20Sopenharmony_ci goto out; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci if (((attr->ia_valid & ATTR_UID) && 2318c2ecf20Sopenharmony_ci affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_SETUID)) || 2328c2ecf20Sopenharmony_ci ((attr->ia_valid & ATTR_GID) && 2338c2ecf20Sopenharmony_ci affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_SETGID)) || 2348c2ecf20Sopenharmony_ci ((attr->ia_valid & ATTR_MODE) && 2358c2ecf20Sopenharmony_ci (AFFS_SB(inode->i_sb)->s_flags & 2368c2ecf20Sopenharmony_ci (AFFS_MOUNT_SF_SETMODE | AFFS_MOUNT_SF_IMMUTABLE)))) { 2378c2ecf20Sopenharmony_ci if (!affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_QUIET)) 2388c2ecf20Sopenharmony_ci error = -EPERM; 2398c2ecf20Sopenharmony_ci goto out; 2408c2ecf20Sopenharmony_ci } 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci if ((attr->ia_valid & ATTR_SIZE) && 2438c2ecf20Sopenharmony_ci attr->ia_size != i_size_read(inode)) { 2448c2ecf20Sopenharmony_ci error = inode_newsize_ok(inode, attr->ia_size); 2458c2ecf20Sopenharmony_ci if (error) 2468c2ecf20Sopenharmony_ci return error; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci truncate_setsize(inode, attr->ia_size); 2498c2ecf20Sopenharmony_ci affs_truncate(inode); 2508c2ecf20Sopenharmony_ci } 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci setattr_copy(inode, attr); 2538c2ecf20Sopenharmony_ci mark_inode_dirty(inode); 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci if (attr->ia_valid & ATTR_MODE) 2568c2ecf20Sopenharmony_ci affs_mode_to_prot(inode); 2578c2ecf20Sopenharmony_ciout: 2588c2ecf20Sopenharmony_ci return error; 2598c2ecf20Sopenharmony_ci} 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_civoid 2628c2ecf20Sopenharmony_ciaffs_evict_inode(struct inode *inode) 2638c2ecf20Sopenharmony_ci{ 2648c2ecf20Sopenharmony_ci unsigned long cache_page; 2658c2ecf20Sopenharmony_ci pr_debug("evict_inode(ino=%lu, nlink=%u)\n", 2668c2ecf20Sopenharmony_ci inode->i_ino, inode->i_nlink); 2678c2ecf20Sopenharmony_ci truncate_inode_pages_final(&inode->i_data); 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci if (!inode->i_nlink) { 2708c2ecf20Sopenharmony_ci inode->i_size = 0; 2718c2ecf20Sopenharmony_ci affs_truncate(inode); 2728c2ecf20Sopenharmony_ci } 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci invalidate_inode_buffers(inode); 2758c2ecf20Sopenharmony_ci clear_inode(inode); 2768c2ecf20Sopenharmony_ci affs_free_prealloc(inode); 2778c2ecf20Sopenharmony_ci cache_page = (unsigned long)AFFS_I(inode)->i_lc; 2788c2ecf20Sopenharmony_ci if (cache_page) { 2798c2ecf20Sopenharmony_ci pr_debug("freeing ext cache\n"); 2808c2ecf20Sopenharmony_ci AFFS_I(inode)->i_lc = NULL; 2818c2ecf20Sopenharmony_ci AFFS_I(inode)->i_ac = NULL; 2828c2ecf20Sopenharmony_ci free_page(cache_page); 2838c2ecf20Sopenharmony_ci } 2848c2ecf20Sopenharmony_ci affs_brelse(AFFS_I(inode)->i_ext_bh); 2858c2ecf20Sopenharmony_ci AFFS_I(inode)->i_ext_last = ~1; 2868c2ecf20Sopenharmony_ci AFFS_I(inode)->i_ext_bh = NULL; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci if (!inode->i_nlink) 2898c2ecf20Sopenharmony_ci affs_free_block(inode->i_sb, inode->i_ino); 2908c2ecf20Sopenharmony_ci} 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_cistruct inode * 2938c2ecf20Sopenharmony_ciaffs_new_inode(struct inode *dir) 2948c2ecf20Sopenharmony_ci{ 2958c2ecf20Sopenharmony_ci struct super_block *sb = dir->i_sb; 2968c2ecf20Sopenharmony_ci struct inode *inode; 2978c2ecf20Sopenharmony_ci u32 block; 2988c2ecf20Sopenharmony_ci struct buffer_head *bh; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci if (!(inode = new_inode(sb))) 3018c2ecf20Sopenharmony_ci goto err_inode; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci if (!(block = affs_alloc_block(dir, dir->i_ino))) 3048c2ecf20Sopenharmony_ci goto err_block; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci bh = affs_getzeroblk(sb, block); 3078c2ecf20Sopenharmony_ci if (!bh) 3088c2ecf20Sopenharmony_ci goto err_bh; 3098c2ecf20Sopenharmony_ci mark_buffer_dirty_inode(bh, inode); 3108c2ecf20Sopenharmony_ci affs_brelse(bh); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci inode->i_uid = current_fsuid(); 3138c2ecf20Sopenharmony_ci inode->i_gid = current_fsgid(); 3148c2ecf20Sopenharmony_ci inode->i_ino = block; 3158c2ecf20Sopenharmony_ci set_nlink(inode, 1); 3168c2ecf20Sopenharmony_ci inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); 3178c2ecf20Sopenharmony_ci atomic_set(&AFFS_I(inode)->i_opencnt, 0); 3188c2ecf20Sopenharmony_ci AFFS_I(inode)->i_blkcnt = 0; 3198c2ecf20Sopenharmony_ci AFFS_I(inode)->i_lc = NULL; 3208c2ecf20Sopenharmony_ci AFFS_I(inode)->i_lc_size = 0; 3218c2ecf20Sopenharmony_ci AFFS_I(inode)->i_lc_shift = 0; 3228c2ecf20Sopenharmony_ci AFFS_I(inode)->i_lc_mask = 0; 3238c2ecf20Sopenharmony_ci AFFS_I(inode)->i_ac = NULL; 3248c2ecf20Sopenharmony_ci AFFS_I(inode)->i_ext_bh = NULL; 3258c2ecf20Sopenharmony_ci AFFS_I(inode)->mmu_private = 0; 3268c2ecf20Sopenharmony_ci AFFS_I(inode)->i_protect = 0; 3278c2ecf20Sopenharmony_ci AFFS_I(inode)->i_lastalloc = 0; 3288c2ecf20Sopenharmony_ci AFFS_I(inode)->i_pa_cnt = 0; 3298c2ecf20Sopenharmony_ci AFFS_I(inode)->i_extcnt = 1; 3308c2ecf20Sopenharmony_ci AFFS_I(inode)->i_ext_last = ~1; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci insert_inode_hash(inode); 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci return inode; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_cierr_bh: 3378c2ecf20Sopenharmony_ci affs_free_block(sb, block); 3388c2ecf20Sopenharmony_cierr_block: 3398c2ecf20Sopenharmony_ci iput(inode); 3408c2ecf20Sopenharmony_cierr_inode: 3418c2ecf20Sopenharmony_ci return NULL; 3428c2ecf20Sopenharmony_ci} 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci/* 3458c2ecf20Sopenharmony_ci * Add an entry to a directory. Create the header block 3468c2ecf20Sopenharmony_ci * and insert it into the hash table. 3478c2ecf20Sopenharmony_ci */ 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ciint 3508c2ecf20Sopenharmony_ciaffs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s32 type) 3518c2ecf20Sopenharmony_ci{ 3528c2ecf20Sopenharmony_ci struct super_block *sb = dir->i_sb; 3538c2ecf20Sopenharmony_ci struct buffer_head *inode_bh = NULL; 3548c2ecf20Sopenharmony_ci struct buffer_head *bh; 3558c2ecf20Sopenharmony_ci u32 block = 0; 3568c2ecf20Sopenharmony_ci int retval; 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci pr_debug("%s(dir=%lu, inode=%lu, \"%pd\", type=%d)\n", __func__, 3598c2ecf20Sopenharmony_ci dir->i_ino, inode->i_ino, dentry, type); 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci retval = -EIO; 3628c2ecf20Sopenharmony_ci bh = affs_bread(sb, inode->i_ino); 3638c2ecf20Sopenharmony_ci if (!bh) 3648c2ecf20Sopenharmony_ci goto done; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci affs_lock_link(inode); 3678c2ecf20Sopenharmony_ci switch (type) { 3688c2ecf20Sopenharmony_ci case ST_LINKFILE: 3698c2ecf20Sopenharmony_ci case ST_LINKDIR: 3708c2ecf20Sopenharmony_ci retval = -ENOSPC; 3718c2ecf20Sopenharmony_ci block = affs_alloc_block(dir, dir->i_ino); 3728c2ecf20Sopenharmony_ci if (!block) 3738c2ecf20Sopenharmony_ci goto err; 3748c2ecf20Sopenharmony_ci retval = -EIO; 3758c2ecf20Sopenharmony_ci inode_bh = bh; 3768c2ecf20Sopenharmony_ci bh = affs_getzeroblk(sb, block); 3778c2ecf20Sopenharmony_ci if (!bh) 3788c2ecf20Sopenharmony_ci goto err; 3798c2ecf20Sopenharmony_ci break; 3808c2ecf20Sopenharmony_ci default: 3818c2ecf20Sopenharmony_ci break; 3828c2ecf20Sopenharmony_ci } 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci AFFS_HEAD(bh)->ptype = cpu_to_be32(T_SHORT); 3858c2ecf20Sopenharmony_ci AFFS_HEAD(bh)->key = cpu_to_be32(bh->b_blocknr); 3868c2ecf20Sopenharmony_ci affs_copy_name(AFFS_TAIL(sb, bh)->name, dentry); 3878c2ecf20Sopenharmony_ci AFFS_TAIL(sb, bh)->stype = cpu_to_be32(type); 3888c2ecf20Sopenharmony_ci AFFS_TAIL(sb, bh)->parent = cpu_to_be32(dir->i_ino); 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci if (inode_bh) { 3918c2ecf20Sopenharmony_ci __be32 chain; 3928c2ecf20Sopenharmony_ci chain = AFFS_TAIL(sb, inode_bh)->link_chain; 3938c2ecf20Sopenharmony_ci AFFS_TAIL(sb, bh)->original = cpu_to_be32(inode->i_ino); 3948c2ecf20Sopenharmony_ci AFFS_TAIL(sb, bh)->link_chain = chain; 3958c2ecf20Sopenharmony_ci AFFS_TAIL(sb, inode_bh)->link_chain = cpu_to_be32(block); 3968c2ecf20Sopenharmony_ci affs_adjust_checksum(inode_bh, block - be32_to_cpu(chain)); 3978c2ecf20Sopenharmony_ci mark_buffer_dirty_inode(inode_bh, inode); 3988c2ecf20Sopenharmony_ci set_nlink(inode, 2); 3998c2ecf20Sopenharmony_ci ihold(inode); 4008c2ecf20Sopenharmony_ci } 4018c2ecf20Sopenharmony_ci affs_fix_checksum(sb, bh); 4028c2ecf20Sopenharmony_ci mark_buffer_dirty_inode(bh, inode); 4038c2ecf20Sopenharmony_ci dentry->d_fsdata = (void *)(long)bh->b_blocknr; 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci affs_lock_dir(dir); 4068c2ecf20Sopenharmony_ci retval = affs_insert_hash(dir, bh); 4078c2ecf20Sopenharmony_ci mark_buffer_dirty_inode(bh, inode); 4088c2ecf20Sopenharmony_ci affs_unlock_dir(dir); 4098c2ecf20Sopenharmony_ci affs_unlock_link(inode); 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci d_instantiate(dentry, inode); 4128c2ecf20Sopenharmony_cidone: 4138c2ecf20Sopenharmony_ci affs_brelse(inode_bh); 4148c2ecf20Sopenharmony_ci affs_brelse(bh); 4158c2ecf20Sopenharmony_ci return retval; 4168c2ecf20Sopenharmony_cierr: 4178c2ecf20Sopenharmony_ci if (block) 4188c2ecf20Sopenharmony_ci affs_free_block(sb, block); 4198c2ecf20Sopenharmony_ci affs_unlock_link(inode); 4208c2ecf20Sopenharmony_ci goto done; 4218c2ecf20Sopenharmony_ci} 422