11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * linux/fs/ufs/inode.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) 1998 51da177e4SLinus Torvalds * Daniel Pirkl <daniel.pirkl@email.cz> 61da177e4SLinus Torvalds * Charles University, Faculty of Mathematics and Physics 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * from 91da177e4SLinus Torvalds * 101da177e4SLinus Torvalds * linux/fs/ext2/inode.c 111da177e4SLinus Torvalds * 121da177e4SLinus Torvalds * Copyright (C) 1992, 1993, 1994, 1995 131da177e4SLinus Torvalds * Remy Card (card@masi.ibp.fr) 141da177e4SLinus Torvalds * Laboratoire MASI - Institut Blaise Pascal 151da177e4SLinus Torvalds * Universite Pierre et Marie Curie (Paris VI) 161da177e4SLinus Torvalds * 171da177e4SLinus Torvalds * from 181da177e4SLinus Torvalds * 191da177e4SLinus Torvalds * linux/fs/minix/inode.c 201da177e4SLinus Torvalds * 211da177e4SLinus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds 221da177e4SLinus Torvalds * 231da177e4SLinus Torvalds * Goal-directed block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993 241da177e4SLinus Torvalds * Big-endian to little-endian byte-swapping/bitmaps by 251da177e4SLinus Torvalds * David S. Miller (davem@caip.rutgers.edu), 1995 261da177e4SLinus Torvalds */ 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds #include <asm/uaccess.h> 291da177e4SLinus Torvalds #include <asm/system.h> 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds #include <linux/errno.h> 321da177e4SLinus Torvalds #include <linux/fs.h> 331da177e4SLinus Torvalds #include <linux/ufs_fs.h> 341da177e4SLinus Torvalds #include <linux/time.h> 351da177e4SLinus Torvalds #include <linux/stat.h> 361da177e4SLinus Torvalds #include <linux/string.h> 371da177e4SLinus Torvalds #include <linux/mm.h> 381da177e4SLinus Torvalds #include <linux/smp_lock.h> 391da177e4SLinus Torvalds #include <linux/buffer_head.h> 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds #include "swab.h" 421da177e4SLinus Torvalds #include "util.h" 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds #undef UFS_INODE_DEBUG 451da177e4SLinus Torvalds #undef UFS_INODE_DEBUG_MORE 461da177e4SLinus Torvalds 471da177e4SLinus Torvalds #ifdef UFS_INODE_DEBUG 481da177e4SLinus Torvalds #define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x; 491da177e4SLinus Torvalds #else 501da177e4SLinus Torvalds #define UFSD(x) 511da177e4SLinus Torvalds #endif 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds static int ufs_block_to_path(struct inode *inode, sector_t i_block, sector_t offsets[4]) 541da177e4SLinus Torvalds { 551da177e4SLinus Torvalds struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi; 561da177e4SLinus Torvalds int ptrs = uspi->s_apb; 571da177e4SLinus Torvalds int ptrs_bits = uspi->s_apbshift; 581da177e4SLinus Torvalds const long direct_blocks = UFS_NDADDR, 591da177e4SLinus Torvalds indirect_blocks = ptrs, 601da177e4SLinus Torvalds double_blocks = (1 << (ptrs_bits * 2)); 611da177e4SLinus Torvalds int n = 0; 621da177e4SLinus Torvalds 631da177e4SLinus Torvalds 647b4ee73eSEvgeniy UFSD(("ptrs=uspi->s_apb = %d,double_blocks=%ld \n",ptrs,double_blocks)); 651da177e4SLinus Torvalds if (i_block < 0) { 661da177e4SLinus Torvalds ufs_warning(inode->i_sb, "ufs_block_to_path", "block < 0"); 671da177e4SLinus Torvalds } else if (i_block < direct_blocks) { 681da177e4SLinus Torvalds offsets[n++] = i_block; 691da177e4SLinus Torvalds } else if ((i_block -= direct_blocks) < indirect_blocks) { 701da177e4SLinus Torvalds offsets[n++] = UFS_IND_BLOCK; 711da177e4SLinus Torvalds offsets[n++] = i_block; 721da177e4SLinus Torvalds } else if ((i_block -= indirect_blocks) < double_blocks) { 731da177e4SLinus Torvalds offsets[n++] = UFS_DIND_BLOCK; 741da177e4SLinus Torvalds offsets[n++] = i_block >> ptrs_bits; 751da177e4SLinus Torvalds offsets[n++] = i_block & (ptrs - 1); 761da177e4SLinus Torvalds } else if (((i_block -= double_blocks) >> (ptrs_bits * 2)) < ptrs) { 771da177e4SLinus Torvalds offsets[n++] = UFS_TIND_BLOCK; 781da177e4SLinus Torvalds offsets[n++] = i_block >> (ptrs_bits * 2); 791da177e4SLinus Torvalds offsets[n++] = (i_block >> ptrs_bits) & (ptrs - 1); 801da177e4SLinus Torvalds offsets[n++] = i_block & (ptrs - 1); 811da177e4SLinus Torvalds } else { 821da177e4SLinus Torvalds ufs_warning(inode->i_sb, "ufs_block_to_path", "block > big"); 831da177e4SLinus Torvalds } 841da177e4SLinus Torvalds return n; 851da177e4SLinus Torvalds } 861da177e4SLinus Torvalds 871da177e4SLinus Torvalds /* 881da177e4SLinus Torvalds * Returns the location of the fragment from 891da177e4SLinus Torvalds * the begining of the filesystem. 901da177e4SLinus Torvalds */ 911da177e4SLinus Torvalds 921da177e4SLinus Torvalds u64 ufs_frag_map(struct inode *inode, sector_t frag) 931da177e4SLinus Torvalds { 941da177e4SLinus Torvalds struct ufs_inode_info *ufsi = UFS_I(inode); 951da177e4SLinus Torvalds struct super_block *sb = inode->i_sb; 961da177e4SLinus Torvalds struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; 971da177e4SLinus Torvalds u64 mask = (u64) uspi->s_apbmask>>uspi->s_fpbshift; 981da177e4SLinus Torvalds int shift = uspi->s_apbshift-uspi->s_fpbshift; 991da177e4SLinus Torvalds sector_t offsets[4], *p; 1001da177e4SLinus Torvalds int depth = ufs_block_to_path(inode, frag >> uspi->s_fpbshift, offsets); 1011da177e4SLinus Torvalds u64 ret = 0L; 1021da177e4SLinus Torvalds __fs32 block; 1031da177e4SLinus Torvalds __fs64 u2_block = 0L; 1041da177e4SLinus Torvalds unsigned flags = UFS_SB(sb)->s_flags; 1051da177e4SLinus Torvalds u64 temp = 0L; 1061da177e4SLinus Torvalds 1077b4ee73eSEvgeniy UFSD((": frag = %llu depth = %d\n", (unsigned long long)frag, depth)); 1081da177e4SLinus Torvalds UFSD((": uspi->s_fpbshift = %d ,uspi->s_apbmask = %x, mask=%llx\n",uspi->s_fpbshift,uspi->s_apbmask,mask)); 1091da177e4SLinus Torvalds 1101da177e4SLinus Torvalds if (depth == 0) 1111da177e4SLinus Torvalds return 0; 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds p = offsets; 1141da177e4SLinus Torvalds 1151da177e4SLinus Torvalds lock_kernel(); 1161da177e4SLinus Torvalds if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) 1171da177e4SLinus Torvalds goto ufs2; 1181da177e4SLinus Torvalds 1191da177e4SLinus Torvalds block = ufsi->i_u1.i_data[*p++]; 1201da177e4SLinus Torvalds if (!block) 1211da177e4SLinus Torvalds goto out; 1221da177e4SLinus Torvalds while (--depth) { 1231da177e4SLinus Torvalds struct buffer_head *bh; 1241da177e4SLinus Torvalds sector_t n = *p++; 1251da177e4SLinus Torvalds 1261da177e4SLinus Torvalds bh = sb_bread(sb, uspi->s_sbbase + fs32_to_cpu(sb, block)+(n>>shift)); 1271da177e4SLinus Torvalds if (!bh) 1281da177e4SLinus Torvalds goto out; 1291da177e4SLinus Torvalds block = ((__fs32 *) bh->b_data)[n & mask]; 1301da177e4SLinus Torvalds brelse (bh); 1311da177e4SLinus Torvalds if (!block) 1321da177e4SLinus Torvalds goto out; 1331da177e4SLinus Torvalds } 1341da177e4SLinus Torvalds ret = (u64) (uspi->s_sbbase + fs32_to_cpu(sb, block) + (frag & uspi->s_fpbmask)); 1351da177e4SLinus Torvalds goto out; 1361da177e4SLinus Torvalds ufs2: 1371da177e4SLinus Torvalds u2_block = ufsi->i_u1.u2_i_data[*p++]; 1381da177e4SLinus Torvalds if (!u2_block) 1391da177e4SLinus Torvalds goto out; 1401da177e4SLinus Torvalds 1411da177e4SLinus Torvalds 1421da177e4SLinus Torvalds while (--depth) { 1431da177e4SLinus Torvalds struct buffer_head *bh; 1441da177e4SLinus Torvalds sector_t n = *p++; 1451da177e4SLinus Torvalds 1461da177e4SLinus Torvalds 1471da177e4SLinus Torvalds temp = (u64)(uspi->s_sbbase) + fs64_to_cpu(sb, u2_block); 1481da177e4SLinus Torvalds bh = sb_bread(sb, temp +(u64) (n>>shift)); 1491da177e4SLinus Torvalds if (!bh) 1501da177e4SLinus Torvalds goto out; 1511da177e4SLinus Torvalds u2_block = ((__fs64 *)bh->b_data)[n & mask]; 1521da177e4SLinus Torvalds brelse(bh); 1531da177e4SLinus Torvalds if (!u2_block) 1541da177e4SLinus Torvalds goto out; 1551da177e4SLinus Torvalds } 1561da177e4SLinus Torvalds temp = (u64)uspi->s_sbbase + fs64_to_cpu(sb, u2_block); 1571da177e4SLinus Torvalds ret = temp + (u64) (frag & uspi->s_fpbmask); 1581da177e4SLinus Torvalds 1591da177e4SLinus Torvalds out: 1601da177e4SLinus Torvalds unlock_kernel(); 1611da177e4SLinus Torvalds return ret; 1621da177e4SLinus Torvalds } 1631da177e4SLinus Torvalds 1641da177e4SLinus Torvalds static struct buffer_head * ufs_inode_getfrag (struct inode *inode, 1651da177e4SLinus Torvalds unsigned int fragment, unsigned int new_fragment, 1661da177e4SLinus Torvalds unsigned int required, int *err, int metadata, long *phys, int *new) 1671da177e4SLinus Torvalds { 1681da177e4SLinus Torvalds struct ufs_inode_info *ufsi = UFS_I(inode); 1691da177e4SLinus Torvalds struct super_block * sb; 1701da177e4SLinus Torvalds struct ufs_sb_private_info * uspi; 1711da177e4SLinus Torvalds struct buffer_head * result; 1721da177e4SLinus Torvalds unsigned block, blockoff, lastfrag, lastblock, lastblockoff; 1731da177e4SLinus Torvalds unsigned tmp, goal; 1741da177e4SLinus Torvalds __fs32 * p, * p2; 1751da177e4SLinus Torvalds unsigned flags = 0; 1761da177e4SLinus Torvalds 1771da177e4SLinus Torvalds UFSD(("ENTER, ino %lu, fragment %u, new_fragment %u, required %u\n", 1781da177e4SLinus Torvalds inode->i_ino, fragment, new_fragment, required)) 1791da177e4SLinus Torvalds 1801da177e4SLinus Torvalds sb = inode->i_sb; 1811da177e4SLinus Torvalds uspi = UFS_SB(sb)->s_uspi; 1821da177e4SLinus Torvalds 1831da177e4SLinus Torvalds flags = UFS_SB(sb)->s_flags; 1841da177e4SLinus Torvalds /* TODO : to be done for write support 1851da177e4SLinus Torvalds if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) 1861da177e4SLinus Torvalds goto ufs2; 1871da177e4SLinus Torvalds */ 1881da177e4SLinus Torvalds 1891da177e4SLinus Torvalds block = ufs_fragstoblks (fragment); 1901da177e4SLinus Torvalds blockoff = ufs_fragnum (fragment); 1911da177e4SLinus Torvalds p = ufsi->i_u1.i_data + block; 1921da177e4SLinus Torvalds goal = 0; 1931da177e4SLinus Torvalds 1941da177e4SLinus Torvalds repeat: 1951da177e4SLinus Torvalds tmp = fs32_to_cpu(sb, *p); 1961da177e4SLinus Torvalds lastfrag = ufsi->i_lastfrag; 1971da177e4SLinus Torvalds if (tmp && fragment < lastfrag) { 1981da177e4SLinus Torvalds if (metadata) { 1991da177e4SLinus Torvalds result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); 2001da177e4SLinus Torvalds if (tmp == fs32_to_cpu(sb, *p)) { 2011da177e4SLinus Torvalds UFSD(("EXIT, result %u\n", tmp + blockoff)) 2021da177e4SLinus Torvalds return result; 2031da177e4SLinus Torvalds } 2041da177e4SLinus Torvalds brelse (result); 2051da177e4SLinus Torvalds goto repeat; 2061da177e4SLinus Torvalds } else { 2071da177e4SLinus Torvalds *phys = tmp; 2081da177e4SLinus Torvalds return NULL; 2091da177e4SLinus Torvalds } 2101da177e4SLinus Torvalds } 2111da177e4SLinus Torvalds 2121da177e4SLinus Torvalds lastblock = ufs_fragstoblks (lastfrag); 2131da177e4SLinus Torvalds lastblockoff = ufs_fragnum (lastfrag); 2141da177e4SLinus Torvalds /* 2151da177e4SLinus Torvalds * We will extend file into new block beyond last allocated block 2161da177e4SLinus Torvalds */ 2171da177e4SLinus Torvalds if (lastblock < block) { 2181da177e4SLinus Torvalds /* 2191da177e4SLinus Torvalds * We must reallocate last allocated block 2201da177e4SLinus Torvalds */ 2211da177e4SLinus Torvalds if (lastblockoff) { 2221da177e4SLinus Torvalds p2 = ufsi->i_u1.i_data + lastblock; 2231da177e4SLinus Torvalds tmp = ufs_new_fragments (inode, p2, lastfrag, 2241da177e4SLinus Torvalds fs32_to_cpu(sb, *p2), uspi->s_fpb - lastblockoff, err); 2251da177e4SLinus Torvalds if (!tmp) { 2261da177e4SLinus Torvalds if (lastfrag != ufsi->i_lastfrag) 2271da177e4SLinus Torvalds goto repeat; 2281da177e4SLinus Torvalds else 2291da177e4SLinus Torvalds return NULL; 2301da177e4SLinus Torvalds } 2311da177e4SLinus Torvalds lastfrag = ufsi->i_lastfrag; 2321da177e4SLinus Torvalds 2331da177e4SLinus Torvalds } 2341da177e4SLinus Torvalds goal = fs32_to_cpu(sb, ufsi->i_u1.i_data[lastblock]) + uspi->s_fpb; 2351da177e4SLinus Torvalds tmp = ufs_new_fragments (inode, p, fragment - blockoff, 2361da177e4SLinus Torvalds goal, required + blockoff, err); 2371da177e4SLinus Torvalds } 2381da177e4SLinus Torvalds /* 2391da177e4SLinus Torvalds * We will extend last allocated block 2401da177e4SLinus Torvalds */ 2411da177e4SLinus Torvalds else if (lastblock == block) { 2421da177e4SLinus Torvalds tmp = ufs_new_fragments (inode, p, fragment - (blockoff - lastblockoff), 2431da177e4SLinus Torvalds fs32_to_cpu(sb, *p), required + (blockoff - lastblockoff), err); 2441da177e4SLinus Torvalds } 2451da177e4SLinus Torvalds /* 2461da177e4SLinus Torvalds * We will allocate new block before last allocated block 2471da177e4SLinus Torvalds */ 2481da177e4SLinus Torvalds else /* (lastblock > block) */ { 2491da177e4SLinus Torvalds if (lastblock && (tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[lastblock-1]))) 2501da177e4SLinus Torvalds goal = tmp + uspi->s_fpb; 2511da177e4SLinus Torvalds tmp = ufs_new_fragments (inode, p, fragment - blockoff, 2521da177e4SLinus Torvalds goal, uspi->s_fpb, err); 2531da177e4SLinus Torvalds } 2541da177e4SLinus Torvalds if (!tmp) { 2551da177e4SLinus Torvalds if ((!blockoff && *p) || 2561da177e4SLinus Torvalds (blockoff && lastfrag != ufsi->i_lastfrag)) 2571da177e4SLinus Torvalds goto repeat; 2581da177e4SLinus Torvalds *err = -ENOSPC; 2591da177e4SLinus Torvalds return NULL; 2601da177e4SLinus Torvalds } 2611da177e4SLinus Torvalds 2621da177e4SLinus Torvalds /* The nullification of framgents done in ufs/balloc.c is 2631da177e4SLinus Torvalds * something I don't have the stomache to move into here right 2641da177e4SLinus Torvalds * now. -DaveM 2651da177e4SLinus Torvalds */ 2661da177e4SLinus Torvalds if (metadata) { 2671da177e4SLinus Torvalds result = sb_getblk(inode->i_sb, tmp + blockoff); 2681da177e4SLinus Torvalds } else { 2691da177e4SLinus Torvalds *phys = tmp; 2701da177e4SLinus Torvalds result = NULL; 2711da177e4SLinus Torvalds *err = 0; 2721da177e4SLinus Torvalds *new = 1; 2731da177e4SLinus Torvalds } 2741da177e4SLinus Torvalds 2751da177e4SLinus Torvalds inode->i_ctime = CURRENT_TIME_SEC; 2761da177e4SLinus Torvalds if (IS_SYNC(inode)) 2771da177e4SLinus Torvalds ufs_sync_inode (inode); 2781da177e4SLinus Torvalds mark_inode_dirty(inode); 2791da177e4SLinus Torvalds UFSD(("EXIT, result %u\n", tmp + blockoff)) 2801da177e4SLinus Torvalds return result; 2811da177e4SLinus Torvalds 2821da177e4SLinus Torvalds /* This part : To be implemented .... 2831da177e4SLinus Torvalds Required only for writing, not required for READ-ONLY. 2841da177e4SLinus Torvalds ufs2: 2851da177e4SLinus Torvalds 2861da177e4SLinus Torvalds u2_block = ufs_fragstoblks(fragment); 2871da177e4SLinus Torvalds u2_blockoff = ufs_fragnum(fragment); 2881da177e4SLinus Torvalds p = ufsi->i_u1.u2_i_data + block; 2891da177e4SLinus Torvalds goal = 0; 2901da177e4SLinus Torvalds 2911da177e4SLinus Torvalds repeat2: 2921da177e4SLinus Torvalds tmp = fs32_to_cpu(sb, *p); 2931da177e4SLinus Torvalds lastfrag = ufsi->i_lastfrag; 2941da177e4SLinus Torvalds 2951da177e4SLinus Torvalds */ 2961da177e4SLinus Torvalds } 2971da177e4SLinus Torvalds 2981da177e4SLinus Torvalds static struct buffer_head * ufs_block_getfrag (struct inode *inode, 2991da177e4SLinus Torvalds struct buffer_head *bh, unsigned int fragment, unsigned int new_fragment, 3001da177e4SLinus Torvalds unsigned int blocksize, int * err, int metadata, long *phys, int *new) 3011da177e4SLinus Torvalds { 3021da177e4SLinus Torvalds struct super_block * sb; 3031da177e4SLinus Torvalds struct ufs_sb_private_info * uspi; 3041da177e4SLinus Torvalds struct buffer_head * result; 3051da177e4SLinus Torvalds unsigned tmp, goal, block, blockoff; 3061da177e4SLinus Torvalds __fs32 * p; 3071da177e4SLinus Torvalds 3081da177e4SLinus Torvalds sb = inode->i_sb; 3091da177e4SLinus Torvalds uspi = UFS_SB(sb)->s_uspi; 3101da177e4SLinus Torvalds block = ufs_fragstoblks (fragment); 3111da177e4SLinus Torvalds blockoff = ufs_fragnum (fragment); 3121da177e4SLinus Torvalds 3131da177e4SLinus Torvalds UFSD(("ENTER, ino %lu, fragment %u, new_fragment %u\n", inode->i_ino, fragment, new_fragment)) 3141da177e4SLinus Torvalds 3151da177e4SLinus Torvalds result = NULL; 3161da177e4SLinus Torvalds if (!bh) 3171da177e4SLinus Torvalds goto out; 3181da177e4SLinus Torvalds if (!buffer_uptodate(bh)) { 3191da177e4SLinus Torvalds ll_rw_block (READ, 1, &bh); 3201da177e4SLinus Torvalds wait_on_buffer (bh); 3211da177e4SLinus Torvalds if (!buffer_uptodate(bh)) 3221da177e4SLinus Torvalds goto out; 3231da177e4SLinus Torvalds } 3241da177e4SLinus Torvalds 3251da177e4SLinus Torvalds p = (__fs32 *) bh->b_data + block; 3261da177e4SLinus Torvalds repeat: 3271da177e4SLinus Torvalds tmp = fs32_to_cpu(sb, *p); 3281da177e4SLinus Torvalds if (tmp) { 3291da177e4SLinus Torvalds if (metadata) { 3301da177e4SLinus Torvalds result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); 3311da177e4SLinus Torvalds if (tmp == fs32_to_cpu(sb, *p)) 3321da177e4SLinus Torvalds goto out; 3331da177e4SLinus Torvalds brelse (result); 3341da177e4SLinus Torvalds goto repeat; 3351da177e4SLinus Torvalds } else { 3361da177e4SLinus Torvalds *phys = tmp; 3371da177e4SLinus Torvalds goto out; 3381da177e4SLinus Torvalds } 3391da177e4SLinus Torvalds } 3401da177e4SLinus Torvalds 3411da177e4SLinus Torvalds if (block && (tmp = fs32_to_cpu(sb, ((__fs32*)bh->b_data)[block-1]) + uspi->s_fpb)) 3421da177e4SLinus Torvalds goal = tmp + uspi->s_fpb; 3431da177e4SLinus Torvalds else 3441da177e4SLinus Torvalds goal = bh->b_blocknr + uspi->s_fpb; 3451da177e4SLinus Torvalds tmp = ufs_new_fragments (inode, p, ufs_blknum(new_fragment), goal, uspi->s_fpb, err); 3461da177e4SLinus Torvalds if (!tmp) { 3471da177e4SLinus Torvalds if (fs32_to_cpu(sb, *p)) 3481da177e4SLinus Torvalds goto repeat; 3491da177e4SLinus Torvalds goto out; 3501da177e4SLinus Torvalds } 3511da177e4SLinus Torvalds 3521da177e4SLinus Torvalds /* The nullification of framgents done in ufs/balloc.c is 3531da177e4SLinus Torvalds * something I don't have the stomache to move into here right 3541da177e4SLinus Torvalds * now. -DaveM 3551da177e4SLinus Torvalds */ 3561da177e4SLinus Torvalds if (metadata) { 3571da177e4SLinus Torvalds result = sb_getblk(sb, tmp + blockoff); 3581da177e4SLinus Torvalds } else { 3591da177e4SLinus Torvalds *phys = tmp; 3601da177e4SLinus Torvalds *new = 1; 3611da177e4SLinus Torvalds } 3621da177e4SLinus Torvalds 3631da177e4SLinus Torvalds mark_buffer_dirty(bh); 3641da177e4SLinus Torvalds if (IS_SYNC(inode)) 3651da177e4SLinus Torvalds sync_dirty_buffer(bh); 3661da177e4SLinus Torvalds inode->i_ctime = CURRENT_TIME_SEC; 3671da177e4SLinus Torvalds mark_inode_dirty(inode); 3687b4ee73eSEvgeniy UFSD(("result %u\n", tmp + blockoff)); 3691da177e4SLinus Torvalds out: 3701da177e4SLinus Torvalds brelse (bh); 3717b4ee73eSEvgeniy UFSD(("EXIT\n")); 3721da177e4SLinus Torvalds return result; 3731da177e4SLinus Torvalds } 3741da177e4SLinus Torvalds 3751da177e4SLinus Torvalds /* 3761da177e4SLinus Torvalds * This function gets the block which contains the fragment. 3771da177e4SLinus Torvalds */ 3781da177e4SLinus Torvalds 3791da177e4SLinus Torvalds static int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create) 3801da177e4SLinus Torvalds { 3811da177e4SLinus Torvalds struct super_block * sb = inode->i_sb; 3821da177e4SLinus Torvalds struct ufs_sb_private_info * uspi = UFS_SB(sb)->s_uspi; 3831da177e4SLinus Torvalds struct buffer_head * bh; 3841da177e4SLinus Torvalds int ret, err, new; 3851da177e4SLinus Torvalds unsigned long ptr,phys; 3861da177e4SLinus Torvalds u64 phys64 = 0; 3871da177e4SLinus Torvalds 3881da177e4SLinus Torvalds if (!create) { 3891da177e4SLinus Torvalds phys64 = ufs_frag_map(inode, fragment); 3907b4ee73eSEvgeniy UFSD(("phys64 = %llu \n",phys64)); 3911da177e4SLinus Torvalds if (phys64) 3921da177e4SLinus Torvalds map_bh(bh_result, sb, phys64); 3931da177e4SLinus Torvalds return 0; 3941da177e4SLinus Torvalds } 3951da177e4SLinus Torvalds 3961da177e4SLinus Torvalds /* This code entered only while writing ....? */ 3971da177e4SLinus Torvalds 3981da177e4SLinus Torvalds err = -EIO; 3991da177e4SLinus Torvalds new = 0; 4001da177e4SLinus Torvalds ret = 0; 4011da177e4SLinus Torvalds bh = NULL; 4021da177e4SLinus Torvalds 4031da177e4SLinus Torvalds lock_kernel(); 4041da177e4SLinus Torvalds 4057b4ee73eSEvgeniy UFSD(("ENTER, ino %lu, fragment %llu\n", inode->i_ino, (unsigned long long)fragment)) 4061da177e4SLinus Torvalds if (fragment < 0) 4071da177e4SLinus Torvalds goto abort_negative; 4081da177e4SLinus Torvalds if (fragment > 4091da177e4SLinus Torvalds ((UFS_NDADDR + uspi->s_apb + uspi->s_2apb + uspi->s_3apb) 4101da177e4SLinus Torvalds << uspi->s_fpbshift)) 4111da177e4SLinus Torvalds goto abort_too_big; 4121da177e4SLinus Torvalds 4131da177e4SLinus Torvalds err = 0; 4141da177e4SLinus Torvalds ptr = fragment; 4151da177e4SLinus Torvalds 4161da177e4SLinus Torvalds /* 4171da177e4SLinus Torvalds * ok, these macros clean the logic up a bit and make 4181da177e4SLinus Torvalds * it much more readable: 4191da177e4SLinus Torvalds */ 4201da177e4SLinus Torvalds #define GET_INODE_DATABLOCK(x) \ 4211da177e4SLinus Torvalds ufs_inode_getfrag(inode, x, fragment, 1, &err, 0, &phys, &new) 4221da177e4SLinus Torvalds #define GET_INODE_PTR(x) \ 4231da177e4SLinus Torvalds ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, 1, NULL, NULL) 4241da177e4SLinus Torvalds #define GET_INDIRECT_DATABLOCK(x) \ 4251da177e4SLinus Torvalds ufs_block_getfrag(inode, bh, x, fragment, sb->s_blocksize, \ 4261da177e4SLinus Torvalds &err, 0, &phys, &new); 4271da177e4SLinus Torvalds #define GET_INDIRECT_PTR(x) \ 4281da177e4SLinus Torvalds ufs_block_getfrag(inode, bh, x, fragment, sb->s_blocksize, \ 4291da177e4SLinus Torvalds &err, 1, NULL, NULL); 4301da177e4SLinus Torvalds 4311da177e4SLinus Torvalds if (ptr < UFS_NDIR_FRAGMENT) { 4321da177e4SLinus Torvalds bh = GET_INODE_DATABLOCK(ptr); 4331da177e4SLinus Torvalds goto out; 4341da177e4SLinus Torvalds } 4351da177e4SLinus Torvalds ptr -= UFS_NDIR_FRAGMENT; 4361da177e4SLinus Torvalds if (ptr < (1 << (uspi->s_apbshift + uspi->s_fpbshift))) { 4371da177e4SLinus Torvalds bh = GET_INODE_PTR(UFS_IND_FRAGMENT + (ptr >> uspi->s_apbshift)); 4381da177e4SLinus Torvalds goto get_indirect; 4391da177e4SLinus Torvalds } 4401da177e4SLinus Torvalds ptr -= 1 << (uspi->s_apbshift + uspi->s_fpbshift); 4411da177e4SLinus Torvalds if (ptr < (1 << (uspi->s_2apbshift + uspi->s_fpbshift))) { 4421da177e4SLinus Torvalds bh = GET_INODE_PTR(UFS_DIND_FRAGMENT + (ptr >> uspi->s_2apbshift)); 4431da177e4SLinus Torvalds goto get_double; 4441da177e4SLinus Torvalds } 4451da177e4SLinus Torvalds ptr -= 1 << (uspi->s_2apbshift + uspi->s_fpbshift); 4461da177e4SLinus Torvalds bh = GET_INODE_PTR(UFS_TIND_FRAGMENT + (ptr >> uspi->s_3apbshift)); 4471da177e4SLinus Torvalds bh = GET_INDIRECT_PTR((ptr >> uspi->s_2apbshift) & uspi->s_apbmask); 4481da177e4SLinus Torvalds get_double: 4491da177e4SLinus Torvalds bh = GET_INDIRECT_PTR((ptr >> uspi->s_apbshift) & uspi->s_apbmask); 4501da177e4SLinus Torvalds get_indirect: 4511da177e4SLinus Torvalds bh = GET_INDIRECT_DATABLOCK(ptr & uspi->s_apbmask); 4521da177e4SLinus Torvalds 4531da177e4SLinus Torvalds #undef GET_INODE_DATABLOCK 4541da177e4SLinus Torvalds #undef GET_INODE_PTR 4551da177e4SLinus Torvalds #undef GET_INDIRECT_DATABLOCK 4561da177e4SLinus Torvalds #undef GET_INDIRECT_PTR 4571da177e4SLinus Torvalds 4581da177e4SLinus Torvalds out: 4591da177e4SLinus Torvalds if (err) 4601da177e4SLinus Torvalds goto abort; 4611da177e4SLinus Torvalds if (new) 4621da177e4SLinus Torvalds set_buffer_new(bh_result); 4631da177e4SLinus Torvalds map_bh(bh_result, sb, phys); 4641da177e4SLinus Torvalds abort: 4651da177e4SLinus Torvalds unlock_kernel(); 4661da177e4SLinus Torvalds return err; 4671da177e4SLinus Torvalds 4681da177e4SLinus Torvalds abort_negative: 4691da177e4SLinus Torvalds ufs_warning(sb, "ufs_get_block", "block < 0"); 4701da177e4SLinus Torvalds goto abort; 4711da177e4SLinus Torvalds 4721da177e4SLinus Torvalds abort_too_big: 4731da177e4SLinus Torvalds ufs_warning(sb, "ufs_get_block", "block > big"); 4741da177e4SLinus Torvalds goto abort; 4751da177e4SLinus Torvalds } 4761da177e4SLinus Torvalds 4771da177e4SLinus Torvalds struct buffer_head *ufs_getfrag(struct inode *inode, unsigned int fragment, 4781da177e4SLinus Torvalds int create, int *err) 4791da177e4SLinus Torvalds { 4801da177e4SLinus Torvalds struct buffer_head dummy; 4811da177e4SLinus Torvalds int error; 4821da177e4SLinus Torvalds 4831da177e4SLinus Torvalds dummy.b_state = 0; 4841da177e4SLinus Torvalds dummy.b_blocknr = -1000; 4851da177e4SLinus Torvalds error = ufs_getfrag_block(inode, fragment, &dummy, create); 4861da177e4SLinus Torvalds *err = error; 4871da177e4SLinus Torvalds if (!error && buffer_mapped(&dummy)) { 4881da177e4SLinus Torvalds struct buffer_head *bh; 4891da177e4SLinus Torvalds bh = sb_getblk(inode->i_sb, dummy.b_blocknr); 4901da177e4SLinus Torvalds if (buffer_new(&dummy)) { 4911da177e4SLinus Torvalds memset(bh->b_data, 0, inode->i_sb->s_blocksize); 4921da177e4SLinus Torvalds set_buffer_uptodate(bh); 4931da177e4SLinus Torvalds mark_buffer_dirty(bh); 4941da177e4SLinus Torvalds } 4951da177e4SLinus Torvalds return bh; 4961da177e4SLinus Torvalds } 4971da177e4SLinus Torvalds return NULL; 4981da177e4SLinus Torvalds } 4991da177e4SLinus Torvalds 5001da177e4SLinus Torvalds struct buffer_head * ufs_bread (struct inode * inode, unsigned fragment, 5011da177e4SLinus Torvalds int create, int * err) 5021da177e4SLinus Torvalds { 5031da177e4SLinus Torvalds struct buffer_head * bh; 5041da177e4SLinus Torvalds 5051da177e4SLinus Torvalds UFSD(("ENTER, ino %lu, fragment %u\n", inode->i_ino, fragment)) 5061da177e4SLinus Torvalds bh = ufs_getfrag (inode, fragment, create, err); 5071da177e4SLinus Torvalds if (!bh || buffer_uptodate(bh)) 5081da177e4SLinus Torvalds return bh; 5091da177e4SLinus Torvalds ll_rw_block (READ, 1, &bh); 5101da177e4SLinus Torvalds wait_on_buffer (bh); 5111da177e4SLinus Torvalds if (buffer_uptodate(bh)) 5121da177e4SLinus Torvalds return bh; 5131da177e4SLinus Torvalds brelse (bh); 5141da177e4SLinus Torvalds *err = -EIO; 5151da177e4SLinus Torvalds return NULL; 5161da177e4SLinus Torvalds } 5171da177e4SLinus Torvalds 5181da177e4SLinus Torvalds static int ufs_writepage(struct page *page, struct writeback_control *wbc) 5191da177e4SLinus Torvalds { 5201da177e4SLinus Torvalds return block_write_full_page(page,ufs_getfrag_block,wbc); 5211da177e4SLinus Torvalds } 5221da177e4SLinus Torvalds static int ufs_readpage(struct file *file, struct page *page) 5231da177e4SLinus Torvalds { 5241da177e4SLinus Torvalds return block_read_full_page(page,ufs_getfrag_block); 5251da177e4SLinus Torvalds } 5261da177e4SLinus Torvalds static int ufs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) 5271da177e4SLinus Torvalds { 5281da177e4SLinus Torvalds return block_prepare_write(page,from,to,ufs_getfrag_block); 5291da177e4SLinus Torvalds } 5301da177e4SLinus Torvalds static sector_t ufs_bmap(struct address_space *mapping, sector_t block) 5311da177e4SLinus Torvalds { 5321da177e4SLinus Torvalds return generic_block_bmap(mapping,block,ufs_getfrag_block); 5331da177e4SLinus Torvalds } 5341da177e4SLinus Torvalds struct address_space_operations ufs_aops = { 5351da177e4SLinus Torvalds .readpage = ufs_readpage, 5361da177e4SLinus Torvalds .writepage = ufs_writepage, 5371da177e4SLinus Torvalds .sync_page = block_sync_page, 5381da177e4SLinus Torvalds .prepare_write = ufs_prepare_write, 5391da177e4SLinus Torvalds .commit_write = generic_commit_write, 5401da177e4SLinus Torvalds .bmap = ufs_bmap 5411da177e4SLinus Torvalds }; 5421da177e4SLinus Torvalds 5431da177e4SLinus Torvalds void ufs_read_inode (struct inode * inode) 5441da177e4SLinus Torvalds { 5451da177e4SLinus Torvalds struct ufs_inode_info *ufsi = UFS_I(inode); 5461da177e4SLinus Torvalds struct super_block * sb; 5471da177e4SLinus Torvalds struct ufs_sb_private_info * uspi; 5481da177e4SLinus Torvalds struct ufs_inode * ufs_inode; 5491da177e4SLinus Torvalds struct ufs2_inode *ufs2_inode; 5501da177e4SLinus Torvalds struct buffer_head * bh; 5511da177e4SLinus Torvalds mode_t mode; 5521da177e4SLinus Torvalds unsigned i; 5531da177e4SLinus Torvalds unsigned flags; 5541da177e4SLinus Torvalds 5551da177e4SLinus Torvalds UFSD(("ENTER, ino %lu\n", inode->i_ino)) 5561da177e4SLinus Torvalds 5571da177e4SLinus Torvalds sb = inode->i_sb; 5581da177e4SLinus Torvalds uspi = UFS_SB(sb)->s_uspi; 5591da177e4SLinus Torvalds flags = UFS_SB(sb)->s_flags; 5601da177e4SLinus Torvalds 5611da177e4SLinus Torvalds if (inode->i_ino < UFS_ROOTINO || 5621da177e4SLinus Torvalds inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) { 5631da177e4SLinus Torvalds ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino); 5641da177e4SLinus Torvalds goto bad_inode; 5651da177e4SLinus Torvalds } 5661da177e4SLinus Torvalds 5671da177e4SLinus Torvalds bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino)); 5681da177e4SLinus Torvalds if (!bh) { 5691da177e4SLinus Torvalds ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino); 5701da177e4SLinus Torvalds goto bad_inode; 5711da177e4SLinus Torvalds } 5721da177e4SLinus Torvalds if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) 5731da177e4SLinus Torvalds goto ufs2_inode; 5741da177e4SLinus Torvalds 5751da177e4SLinus Torvalds ufs_inode = (struct ufs_inode *) (bh->b_data + sizeof(struct ufs_inode) * ufs_inotofsbo(inode->i_ino)); 5761da177e4SLinus Torvalds 5771da177e4SLinus Torvalds /* 5781da177e4SLinus Torvalds * Copy data to the in-core inode. 5791da177e4SLinus Torvalds */ 5801da177e4SLinus Torvalds inode->i_mode = mode = fs16_to_cpu(sb, ufs_inode->ui_mode); 5811da177e4SLinus Torvalds inode->i_nlink = fs16_to_cpu(sb, ufs_inode->ui_nlink); 5821da177e4SLinus Torvalds if (inode->i_nlink == 0) 5831da177e4SLinus Torvalds ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino); 5841da177e4SLinus Torvalds 5851da177e4SLinus Torvalds /* 5861da177e4SLinus Torvalds * Linux now has 32-bit uid and gid, so we can support EFT. 5871da177e4SLinus Torvalds */ 5881da177e4SLinus Torvalds inode->i_uid = ufs_get_inode_uid(sb, ufs_inode); 5891da177e4SLinus Torvalds inode->i_gid = ufs_get_inode_gid(sb, ufs_inode); 5901da177e4SLinus Torvalds 5911da177e4SLinus Torvalds inode->i_size = fs64_to_cpu(sb, ufs_inode->ui_size); 5921da177e4SLinus Torvalds inode->i_atime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_atime.tv_sec); 5931da177e4SLinus Torvalds inode->i_ctime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_ctime.tv_sec); 5941da177e4SLinus Torvalds inode->i_mtime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_mtime.tv_sec); 5951da177e4SLinus Torvalds inode->i_mtime.tv_nsec = 0; 5961da177e4SLinus Torvalds inode->i_atime.tv_nsec = 0; 5971da177e4SLinus Torvalds inode->i_ctime.tv_nsec = 0; 5981da177e4SLinus Torvalds inode->i_blocks = fs32_to_cpu(sb, ufs_inode->ui_blocks); 5991da177e4SLinus Torvalds inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size (for stat) */ 6001da177e4SLinus Torvalds inode->i_version++; 6011da177e4SLinus Torvalds ufsi->i_flags = fs32_to_cpu(sb, ufs_inode->ui_flags); 6021da177e4SLinus Torvalds ufsi->i_gen = fs32_to_cpu(sb, ufs_inode->ui_gen); 6031da177e4SLinus Torvalds ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow); 6041da177e4SLinus Torvalds ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); 6051da177e4SLinus Torvalds ufsi->i_lastfrag = (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift; 6061da177e4SLinus Torvalds 6071da177e4SLinus Torvalds if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) { 6081da177e4SLinus Torvalds for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) 6091da177e4SLinus Torvalds ufsi->i_u1.i_data[i] = ufs_inode->ui_u2.ui_addr.ui_db[i]; 6101da177e4SLinus Torvalds } 6111da177e4SLinus Torvalds else { 6121da177e4SLinus Torvalds for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) 6131da177e4SLinus Torvalds ufsi->i_u1.i_symlink[i] = ufs_inode->ui_u2.ui_symlink[i]; 6141da177e4SLinus Torvalds } 6151da177e4SLinus Torvalds ufsi->i_osync = 0; 6161da177e4SLinus Torvalds 6171da177e4SLinus Torvalds if (S_ISREG(inode->i_mode)) { 6181da177e4SLinus Torvalds inode->i_op = &ufs_file_inode_operations; 6191da177e4SLinus Torvalds inode->i_fop = &ufs_file_operations; 6201da177e4SLinus Torvalds inode->i_mapping->a_ops = &ufs_aops; 6211da177e4SLinus Torvalds } else if (S_ISDIR(inode->i_mode)) { 6221da177e4SLinus Torvalds inode->i_op = &ufs_dir_inode_operations; 6231da177e4SLinus Torvalds inode->i_fop = &ufs_dir_operations; 6241da177e4SLinus Torvalds } else if (S_ISLNK(inode->i_mode)) { 6251da177e4SLinus Torvalds if (!inode->i_blocks) 6261da177e4SLinus Torvalds inode->i_op = &ufs_fast_symlink_inode_operations; 6271da177e4SLinus Torvalds else { 6281da177e4SLinus Torvalds inode->i_op = &page_symlink_inode_operations; 6291da177e4SLinus Torvalds inode->i_mapping->a_ops = &ufs_aops; 6301da177e4SLinus Torvalds } 6311da177e4SLinus Torvalds } else 6321da177e4SLinus Torvalds init_special_inode(inode, inode->i_mode, 6331da177e4SLinus Torvalds ufs_get_inode_dev(sb, ufsi)); 6341da177e4SLinus Torvalds 6351da177e4SLinus Torvalds brelse (bh); 6361da177e4SLinus Torvalds 6371da177e4SLinus Torvalds UFSD(("EXIT\n")) 6381da177e4SLinus Torvalds return; 6391da177e4SLinus Torvalds 6401da177e4SLinus Torvalds bad_inode: 6411da177e4SLinus Torvalds make_bad_inode(inode); 6421da177e4SLinus Torvalds return; 6431da177e4SLinus Torvalds 6441da177e4SLinus Torvalds ufs2_inode : 6451da177e4SLinus Torvalds UFSD(("Reading ufs2 inode, ino %lu\n", inode->i_ino)) 6461da177e4SLinus Torvalds 6471da177e4SLinus Torvalds ufs2_inode = (struct ufs2_inode *)(bh->b_data + sizeof(struct ufs2_inode) * ufs_inotofsbo(inode->i_ino)); 6481da177e4SLinus Torvalds 6491da177e4SLinus Torvalds /* 6501da177e4SLinus Torvalds * Copy data to the in-core inode. 6511da177e4SLinus Torvalds */ 6521da177e4SLinus Torvalds inode->i_mode = mode = fs16_to_cpu(sb, ufs2_inode->ui_mode); 6531da177e4SLinus Torvalds inode->i_nlink = fs16_to_cpu(sb, ufs2_inode->ui_nlink); 6541da177e4SLinus Torvalds if (inode->i_nlink == 0) 6551da177e4SLinus Torvalds ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino); 6561da177e4SLinus Torvalds 6571da177e4SLinus Torvalds /* 6581da177e4SLinus Torvalds * Linux now has 32-bit uid and gid, so we can support EFT. 6591da177e4SLinus Torvalds */ 6601da177e4SLinus Torvalds inode->i_uid = fs32_to_cpu(sb, ufs2_inode->ui_uid); 6611da177e4SLinus Torvalds inode->i_gid = fs32_to_cpu(sb, ufs2_inode->ui_gid); 6621da177e4SLinus Torvalds 6631da177e4SLinus Torvalds inode->i_size = fs64_to_cpu(sb, ufs2_inode->ui_size); 6641da177e4SLinus Torvalds inode->i_atime.tv_sec = fs32_to_cpu(sb, ufs2_inode->ui_atime.tv_sec); 6651da177e4SLinus Torvalds inode->i_ctime.tv_sec = fs32_to_cpu(sb, ufs2_inode->ui_ctime.tv_sec); 6661da177e4SLinus Torvalds inode->i_mtime.tv_sec = fs32_to_cpu(sb, ufs2_inode->ui_mtime.tv_sec); 6671da177e4SLinus Torvalds inode->i_mtime.tv_nsec = 0; 6681da177e4SLinus Torvalds inode->i_atime.tv_nsec = 0; 6691da177e4SLinus Torvalds inode->i_ctime.tv_nsec = 0; 6701da177e4SLinus Torvalds inode->i_blocks = fs64_to_cpu(sb, ufs2_inode->ui_blocks); 6711da177e4SLinus Torvalds inode->i_blksize = PAGE_SIZE; /*This is the optimal IO size(for stat)*/ 6721da177e4SLinus Torvalds 6731da177e4SLinus Torvalds inode->i_version++; 6741da177e4SLinus Torvalds ufsi->i_flags = fs32_to_cpu(sb, ufs2_inode->ui_flags); 6751da177e4SLinus Torvalds ufsi->i_gen = fs32_to_cpu(sb, ufs2_inode->ui_gen); 6761da177e4SLinus Torvalds /* 6771da177e4SLinus Torvalds ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow); 6781da177e4SLinus Torvalds ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); 6791da177e4SLinus Torvalds */ 6801da177e4SLinus Torvalds ufsi->i_lastfrag= (inode->i_size + uspi->s_fsize- 1) >> uspi->s_fshift; 6811da177e4SLinus Torvalds 6821da177e4SLinus Torvalds if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) { 6831da177e4SLinus Torvalds for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) 6841da177e4SLinus Torvalds ufsi->i_u1.u2_i_data[i] = 6851da177e4SLinus Torvalds ufs2_inode->ui_u2.ui_addr.ui_db[i]; 6861da177e4SLinus Torvalds } 6871da177e4SLinus Torvalds else { 6881da177e4SLinus Torvalds for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) 6891da177e4SLinus Torvalds ufsi->i_u1.i_symlink[i] = ufs2_inode->ui_u2.ui_symlink[i]; 6901da177e4SLinus Torvalds } 6911da177e4SLinus Torvalds ufsi->i_osync = 0; 6921da177e4SLinus Torvalds 6931da177e4SLinus Torvalds if (S_ISREG(inode->i_mode)) { 6941da177e4SLinus Torvalds inode->i_op = &ufs_file_inode_operations; 6951da177e4SLinus Torvalds inode->i_fop = &ufs_file_operations; 6961da177e4SLinus Torvalds inode->i_mapping->a_ops = &ufs_aops; 6971da177e4SLinus Torvalds } else if (S_ISDIR(inode->i_mode)) { 6981da177e4SLinus Torvalds inode->i_op = &ufs_dir_inode_operations; 6991da177e4SLinus Torvalds inode->i_fop = &ufs_dir_operations; 7001da177e4SLinus Torvalds } else if (S_ISLNK(inode->i_mode)) { 7011da177e4SLinus Torvalds if (!inode->i_blocks) 7021da177e4SLinus Torvalds inode->i_op = &ufs_fast_symlink_inode_operations; 7031da177e4SLinus Torvalds else { 7041da177e4SLinus Torvalds inode->i_op = &page_symlink_inode_operations; 7051da177e4SLinus Torvalds inode->i_mapping->a_ops = &ufs_aops; 7061da177e4SLinus Torvalds } 7071da177e4SLinus Torvalds } else /* TODO : here ...*/ 7081da177e4SLinus Torvalds init_special_inode(inode, inode->i_mode, 7091da177e4SLinus Torvalds ufs_get_inode_dev(sb, ufsi)); 7101da177e4SLinus Torvalds 7111da177e4SLinus Torvalds brelse(bh); 7121da177e4SLinus Torvalds 7131da177e4SLinus Torvalds UFSD(("EXIT\n")) 7141da177e4SLinus Torvalds return; 7151da177e4SLinus Torvalds } 7161da177e4SLinus Torvalds 7171da177e4SLinus Torvalds static int ufs_update_inode(struct inode * inode, int do_sync) 7181da177e4SLinus Torvalds { 7191da177e4SLinus Torvalds struct ufs_inode_info *ufsi = UFS_I(inode); 7201da177e4SLinus Torvalds struct super_block * sb; 7211da177e4SLinus Torvalds struct ufs_sb_private_info * uspi; 7221da177e4SLinus Torvalds struct buffer_head * bh; 7231da177e4SLinus Torvalds struct ufs_inode * ufs_inode; 7241da177e4SLinus Torvalds unsigned i; 7251da177e4SLinus Torvalds unsigned flags; 7261da177e4SLinus Torvalds 7271da177e4SLinus Torvalds UFSD(("ENTER, ino %lu\n", inode->i_ino)) 7281da177e4SLinus Torvalds 7291da177e4SLinus Torvalds sb = inode->i_sb; 7301da177e4SLinus Torvalds uspi = UFS_SB(sb)->s_uspi; 7311da177e4SLinus Torvalds flags = UFS_SB(sb)->s_flags; 7321da177e4SLinus Torvalds 7331da177e4SLinus Torvalds if (inode->i_ino < UFS_ROOTINO || 7341da177e4SLinus Torvalds inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) { 7351da177e4SLinus Torvalds ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino); 7361da177e4SLinus Torvalds return -1; 7371da177e4SLinus Torvalds } 7381da177e4SLinus Torvalds 7391da177e4SLinus Torvalds bh = sb_bread(sb, ufs_inotofsba(inode->i_ino)); 7401da177e4SLinus Torvalds if (!bh) { 7411da177e4SLinus Torvalds ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino); 7421da177e4SLinus Torvalds return -1; 7431da177e4SLinus Torvalds } 7441da177e4SLinus Torvalds ufs_inode = (struct ufs_inode *) (bh->b_data + ufs_inotofsbo(inode->i_ino) * sizeof(struct ufs_inode)); 7451da177e4SLinus Torvalds 7461da177e4SLinus Torvalds ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode); 7471da177e4SLinus Torvalds ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink); 7481da177e4SLinus Torvalds 7491da177e4SLinus Torvalds ufs_set_inode_uid(sb, ufs_inode, inode->i_uid); 7501da177e4SLinus Torvalds ufs_set_inode_gid(sb, ufs_inode, inode->i_gid); 7511da177e4SLinus Torvalds 7521da177e4SLinus Torvalds ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size); 7531da177e4SLinus Torvalds ufs_inode->ui_atime.tv_sec = cpu_to_fs32(sb, inode->i_atime.tv_sec); 7541da177e4SLinus Torvalds ufs_inode->ui_atime.tv_usec = 0; 7551da177e4SLinus Torvalds ufs_inode->ui_ctime.tv_sec = cpu_to_fs32(sb, inode->i_ctime.tv_sec); 7561da177e4SLinus Torvalds ufs_inode->ui_ctime.tv_usec = 0; 7571da177e4SLinus Torvalds ufs_inode->ui_mtime.tv_sec = cpu_to_fs32(sb, inode->i_mtime.tv_sec); 7581da177e4SLinus Torvalds ufs_inode->ui_mtime.tv_usec = 0; 7591da177e4SLinus Torvalds ufs_inode->ui_blocks = cpu_to_fs32(sb, inode->i_blocks); 7601da177e4SLinus Torvalds ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags); 7611da177e4SLinus Torvalds ufs_inode->ui_gen = cpu_to_fs32(sb, ufsi->i_gen); 7621da177e4SLinus Torvalds 7631da177e4SLinus Torvalds if ((flags & UFS_UID_MASK) == UFS_UID_EFT) { 7641da177e4SLinus Torvalds ufs_inode->ui_u3.ui_sun.ui_shadow = cpu_to_fs32(sb, ufsi->i_shadow); 7651da177e4SLinus Torvalds ufs_inode->ui_u3.ui_sun.ui_oeftflag = cpu_to_fs32(sb, ufsi->i_oeftflag); 7661da177e4SLinus Torvalds } 7671da177e4SLinus Torvalds 7681da177e4SLinus Torvalds if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { 7691da177e4SLinus Torvalds /* ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev); */ 7701da177e4SLinus Torvalds ufs_inode->ui_u2.ui_addr.ui_db[0] = ufsi->i_u1.i_data[0]; 7711da177e4SLinus Torvalds } else if (inode->i_blocks) { 7721da177e4SLinus Torvalds for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) 7731da177e4SLinus Torvalds ufs_inode->ui_u2.ui_addr.ui_db[i] = ufsi->i_u1.i_data[i]; 7741da177e4SLinus Torvalds } 7751da177e4SLinus Torvalds else { 7761da177e4SLinus Torvalds for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) 7771da177e4SLinus Torvalds ufs_inode->ui_u2.ui_symlink[i] = ufsi->i_u1.i_symlink[i]; 7781da177e4SLinus Torvalds } 7791da177e4SLinus Torvalds 7801da177e4SLinus Torvalds if (!inode->i_nlink) 7811da177e4SLinus Torvalds memset (ufs_inode, 0, sizeof(struct ufs_inode)); 7821da177e4SLinus Torvalds 7831da177e4SLinus Torvalds mark_buffer_dirty(bh); 7841da177e4SLinus Torvalds if (do_sync) 7851da177e4SLinus Torvalds sync_dirty_buffer(bh); 7861da177e4SLinus Torvalds brelse (bh); 7871da177e4SLinus Torvalds 7881da177e4SLinus Torvalds UFSD(("EXIT\n")) 7891da177e4SLinus Torvalds return 0; 7901da177e4SLinus Torvalds } 7911da177e4SLinus Torvalds 7921da177e4SLinus Torvalds int ufs_write_inode (struct inode * inode, int wait) 7931da177e4SLinus Torvalds { 7941da177e4SLinus Torvalds int ret; 7951da177e4SLinus Torvalds lock_kernel(); 7961da177e4SLinus Torvalds ret = ufs_update_inode (inode, wait); 7971da177e4SLinus Torvalds unlock_kernel(); 7981da177e4SLinus Torvalds return ret; 7991da177e4SLinus Torvalds } 8001da177e4SLinus Torvalds 8011da177e4SLinus Torvalds int ufs_sync_inode (struct inode *inode) 8021da177e4SLinus Torvalds { 8031da177e4SLinus Torvalds return ufs_update_inode (inode, 1); 8041da177e4SLinus Torvalds } 8051da177e4SLinus Torvalds 8061da177e4SLinus Torvalds void ufs_delete_inode (struct inode * inode) 8071da177e4SLinus Torvalds { 808fef26658SMark Fasheh truncate_inode_pages(&inode->i_data, 0); 8091da177e4SLinus Torvalds /*UFS_I(inode)->i_dtime = CURRENT_TIME;*/ 8101da177e4SLinus Torvalds lock_kernel(); 8111da177e4SLinus Torvalds mark_inode_dirty(inode); 8121da177e4SLinus Torvalds ufs_update_inode(inode, IS_SYNC(inode)); 8131da177e4SLinus Torvalds inode->i_size = 0; 8141da177e4SLinus Torvalds if (inode->i_blocks) 8151da177e4SLinus Torvalds ufs_truncate (inode); 8161da177e4SLinus Torvalds ufs_free_inode (inode); 8171da177e4SLinus Torvalds unlock_kernel(); 8181da177e4SLinus Torvalds } 819