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 164c9a27b5dSEvgeniy Dushistov static void ufs_clear_block(struct inode *inode, struct buffer_head *bh) 165c9a27b5dSEvgeniy Dushistov { 166c9a27b5dSEvgeniy Dushistov lock_buffer(bh); 167c9a27b5dSEvgeniy Dushistov memset(bh->b_data, 0, inode->i_sb->s_blocksize); 168c9a27b5dSEvgeniy Dushistov set_buffer_uptodate(bh); 169c9a27b5dSEvgeniy Dushistov mark_buffer_dirty(bh); 170c9a27b5dSEvgeniy Dushistov unlock_buffer(bh); 171c9a27b5dSEvgeniy Dushistov if (IS_SYNC(inode)) 172c9a27b5dSEvgeniy Dushistov sync_dirty_buffer(bh); 173c9a27b5dSEvgeniy Dushistov } 174c9a27b5dSEvgeniy Dushistov 1751da177e4SLinus Torvalds static struct buffer_head *ufs_inode_getfrag(struct inode *inode, 1761da177e4SLinus Torvalds unsigned int fragment, unsigned int new_fragment, 1776ef4d6bfSEvgeniy Dushistov unsigned int required, int *err, int metadata, 1786ef4d6bfSEvgeniy Dushistov long *phys, int *new, struct page *locked_page) 1791da177e4SLinus Torvalds { 1801da177e4SLinus Torvalds struct ufs_inode_info *ufsi = UFS_I(inode); 1811da177e4SLinus Torvalds struct super_block * sb; 1821da177e4SLinus Torvalds struct ufs_sb_private_info * uspi; 1831da177e4SLinus Torvalds struct buffer_head * result; 1841da177e4SLinus Torvalds unsigned block, blockoff, lastfrag, lastblock, lastblockoff; 1851da177e4SLinus Torvalds unsigned tmp, goal; 1861da177e4SLinus Torvalds __fs32 * p, * p2; 1871da177e4SLinus Torvalds unsigned flags = 0; 1881da177e4SLinus Torvalds 1891da177e4SLinus Torvalds UFSD(("ENTER, ino %lu, fragment %u, new_fragment %u, required %u\n", 1901da177e4SLinus Torvalds inode->i_ino, fragment, new_fragment, required)) 1911da177e4SLinus Torvalds 1921da177e4SLinus Torvalds sb = inode->i_sb; 1931da177e4SLinus Torvalds uspi = UFS_SB(sb)->s_uspi; 1941da177e4SLinus Torvalds 1951da177e4SLinus Torvalds flags = UFS_SB(sb)->s_flags; 1961da177e4SLinus Torvalds /* TODO : to be done for write support 1971da177e4SLinus Torvalds if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) 1981da177e4SLinus Torvalds goto ufs2; 1991da177e4SLinus Torvalds */ 2001da177e4SLinus Torvalds 2011da177e4SLinus Torvalds block = ufs_fragstoblks (fragment); 2021da177e4SLinus Torvalds blockoff = ufs_fragnum (fragment); 2031da177e4SLinus Torvalds p = ufsi->i_u1.i_data + block; 2041da177e4SLinus Torvalds goal = 0; 2051da177e4SLinus Torvalds 2061da177e4SLinus Torvalds repeat: 2071da177e4SLinus Torvalds tmp = fs32_to_cpu(sb, *p); 2081da177e4SLinus Torvalds lastfrag = ufsi->i_lastfrag; 2091da177e4SLinus Torvalds if (tmp && fragment < lastfrag) { 2101da177e4SLinus Torvalds if (metadata) { 2111da177e4SLinus Torvalds result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); 2121da177e4SLinus Torvalds if (tmp == fs32_to_cpu(sb, *p)) { 2131da177e4SLinus Torvalds UFSD(("EXIT, result %u\n", tmp + blockoff)) 2141da177e4SLinus Torvalds return result; 2151da177e4SLinus Torvalds } 2161da177e4SLinus Torvalds brelse (result); 2171da177e4SLinus Torvalds goto repeat; 2181da177e4SLinus Torvalds } else { 219c9a27b5dSEvgeniy Dushistov *phys = tmp + blockoff; 2201da177e4SLinus Torvalds return NULL; 2211da177e4SLinus Torvalds } 2221da177e4SLinus Torvalds } 2231da177e4SLinus Torvalds 2241da177e4SLinus Torvalds lastblock = ufs_fragstoblks (lastfrag); 2251da177e4SLinus Torvalds lastblockoff = ufs_fragnum (lastfrag); 2261da177e4SLinus Torvalds /* 2271da177e4SLinus Torvalds * We will extend file into new block beyond last allocated block 2281da177e4SLinus Torvalds */ 2291da177e4SLinus Torvalds if (lastblock < block) { 2301da177e4SLinus Torvalds /* 2311da177e4SLinus Torvalds * We must reallocate last allocated block 2321da177e4SLinus Torvalds */ 2331da177e4SLinus Torvalds if (lastblockoff) { 2341da177e4SLinus Torvalds p2 = ufsi->i_u1.i_data + lastblock; 2351da177e4SLinus Torvalds tmp = ufs_new_fragments (inode, p2, lastfrag, 2366ef4d6bfSEvgeniy Dushistov fs32_to_cpu(sb, *p2), uspi->s_fpb - lastblockoff, 2376ef4d6bfSEvgeniy Dushistov err, locked_page); 2381da177e4SLinus Torvalds if (!tmp) { 2391da177e4SLinus Torvalds if (lastfrag != ufsi->i_lastfrag) 2401da177e4SLinus Torvalds goto repeat; 2411da177e4SLinus Torvalds else 2421da177e4SLinus Torvalds return NULL; 2431da177e4SLinus Torvalds } 2441da177e4SLinus Torvalds lastfrag = ufsi->i_lastfrag; 2451da177e4SLinus Torvalds 2461da177e4SLinus Torvalds } 2471da177e4SLinus Torvalds goal = fs32_to_cpu(sb, ufsi->i_u1.i_data[lastblock]) + uspi->s_fpb; 2481da177e4SLinus Torvalds tmp = ufs_new_fragments (inode, p, fragment - blockoff, 2496ef4d6bfSEvgeniy Dushistov goal, required + blockoff, 2506ef4d6bfSEvgeniy Dushistov err, locked_page); 2511da177e4SLinus Torvalds } 2521da177e4SLinus Torvalds /* 2531da177e4SLinus Torvalds * We will extend last allocated block 2541da177e4SLinus Torvalds */ 2551da177e4SLinus Torvalds else if (lastblock == block) { 2561da177e4SLinus Torvalds tmp = ufs_new_fragments(inode, p, fragment - (blockoff - lastblockoff), 2576ef4d6bfSEvgeniy Dushistov fs32_to_cpu(sb, *p), required + (blockoff - lastblockoff), 2586ef4d6bfSEvgeniy Dushistov err, locked_page); 2591da177e4SLinus Torvalds } 2601da177e4SLinus Torvalds /* 2611da177e4SLinus Torvalds * We will allocate new block before last allocated block 2621da177e4SLinus Torvalds */ 2631da177e4SLinus Torvalds else /* (lastblock > block) */ { 2641da177e4SLinus Torvalds if (lastblock && (tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[lastblock-1]))) 2651da177e4SLinus Torvalds goal = tmp + uspi->s_fpb; 2661da177e4SLinus Torvalds tmp = ufs_new_fragments(inode, p, fragment - blockoff, 2676ef4d6bfSEvgeniy Dushistov goal, uspi->s_fpb, err, locked_page); 2681da177e4SLinus Torvalds } 2691da177e4SLinus Torvalds if (!tmp) { 2701da177e4SLinus Torvalds if ((!blockoff && *p) || 2711da177e4SLinus Torvalds (blockoff && lastfrag != ufsi->i_lastfrag)) 2721da177e4SLinus Torvalds goto repeat; 2731da177e4SLinus Torvalds *err = -ENOSPC; 2741da177e4SLinus Torvalds return NULL; 2751da177e4SLinus Torvalds } 2761da177e4SLinus Torvalds 2771da177e4SLinus Torvalds if (metadata) { 2781da177e4SLinus Torvalds result = sb_getblk(inode->i_sb, tmp + blockoff); 279c9a27b5dSEvgeniy Dushistov ufs_clear_block(inode, result); 2801da177e4SLinus Torvalds } else { 281c9a27b5dSEvgeniy Dushistov *phys = tmp + blockoff; 2821da177e4SLinus Torvalds result = NULL; 2831da177e4SLinus Torvalds *err = 0; 2841da177e4SLinus Torvalds *new = 1; 2851da177e4SLinus Torvalds } 2861da177e4SLinus Torvalds 2871da177e4SLinus Torvalds inode->i_ctime = CURRENT_TIME_SEC; 2881da177e4SLinus Torvalds if (IS_SYNC(inode)) 2891da177e4SLinus Torvalds ufs_sync_inode (inode); 2901da177e4SLinus Torvalds mark_inode_dirty(inode); 2911da177e4SLinus Torvalds UFSD(("EXIT, result %u\n", tmp + blockoff)) 2921da177e4SLinus Torvalds return result; 2931da177e4SLinus Torvalds 2941da177e4SLinus Torvalds /* This part : To be implemented .... 2951da177e4SLinus Torvalds Required only for writing, not required for READ-ONLY. 2961da177e4SLinus Torvalds ufs2: 2971da177e4SLinus Torvalds 2981da177e4SLinus Torvalds u2_block = ufs_fragstoblks(fragment); 2991da177e4SLinus Torvalds u2_blockoff = ufs_fragnum(fragment); 3001da177e4SLinus Torvalds p = ufsi->i_u1.u2_i_data + block; 3011da177e4SLinus Torvalds goal = 0; 3021da177e4SLinus Torvalds 3031da177e4SLinus Torvalds repeat2: 3041da177e4SLinus Torvalds tmp = fs32_to_cpu(sb, *p); 3051da177e4SLinus Torvalds lastfrag = ufsi->i_lastfrag; 3061da177e4SLinus Torvalds 3071da177e4SLinus Torvalds */ 3081da177e4SLinus Torvalds } 3091da177e4SLinus Torvalds 3106ef4d6bfSEvgeniy Dushistov static struct buffer_head *ufs_block_getfrag(struct inode *inode, struct buffer_head *bh, 3116ef4d6bfSEvgeniy Dushistov unsigned int fragment, unsigned int new_fragment, 3126ef4d6bfSEvgeniy Dushistov unsigned int blocksize, int * err, int metadata, 3136ef4d6bfSEvgeniy Dushistov long *phys, int *new, struct page *locked_page) 3141da177e4SLinus Torvalds { 3151da177e4SLinus Torvalds struct super_block * sb; 3161da177e4SLinus Torvalds struct ufs_sb_private_info * uspi; 3171da177e4SLinus Torvalds struct buffer_head * result; 3181da177e4SLinus Torvalds unsigned tmp, goal, block, blockoff; 3191da177e4SLinus Torvalds __fs32 * p; 3201da177e4SLinus Torvalds 3211da177e4SLinus Torvalds sb = inode->i_sb; 3221da177e4SLinus Torvalds uspi = UFS_SB(sb)->s_uspi; 3231da177e4SLinus Torvalds block = ufs_fragstoblks (fragment); 3241da177e4SLinus Torvalds blockoff = ufs_fragnum (fragment); 3251da177e4SLinus Torvalds 3261da177e4SLinus Torvalds UFSD(("ENTER, ino %lu, fragment %u, new_fragment %u\n", inode->i_ino, fragment, new_fragment)) 3271da177e4SLinus Torvalds 3281da177e4SLinus Torvalds result = NULL; 3291da177e4SLinus Torvalds if (!bh) 3301da177e4SLinus Torvalds goto out; 3311da177e4SLinus Torvalds if (!buffer_uptodate(bh)) { 3321da177e4SLinus Torvalds ll_rw_block (READ, 1, &bh); 3331da177e4SLinus Torvalds wait_on_buffer (bh); 3341da177e4SLinus Torvalds if (!buffer_uptodate(bh)) 3351da177e4SLinus Torvalds goto out; 3361da177e4SLinus Torvalds } 3371da177e4SLinus Torvalds 3381da177e4SLinus Torvalds p = (__fs32 *) bh->b_data + block; 3391da177e4SLinus Torvalds repeat: 3401da177e4SLinus Torvalds tmp = fs32_to_cpu(sb, *p); 3411da177e4SLinus Torvalds if (tmp) { 3421da177e4SLinus Torvalds if (metadata) { 3431da177e4SLinus Torvalds result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); 3441da177e4SLinus Torvalds if (tmp == fs32_to_cpu(sb, *p)) 3451da177e4SLinus Torvalds goto out; 3461da177e4SLinus Torvalds brelse (result); 3471da177e4SLinus Torvalds goto repeat; 3481da177e4SLinus Torvalds } else { 349c9a27b5dSEvgeniy Dushistov *phys = tmp + blockoff; 3501da177e4SLinus Torvalds goto out; 3511da177e4SLinus Torvalds } 3521da177e4SLinus Torvalds } 3531da177e4SLinus Torvalds 3541da177e4SLinus Torvalds if (block && (tmp = fs32_to_cpu(sb, ((__fs32*)bh->b_data)[block-1]) + uspi->s_fpb)) 3551da177e4SLinus Torvalds goal = tmp + uspi->s_fpb; 3561da177e4SLinus Torvalds else 3571da177e4SLinus Torvalds goal = bh->b_blocknr + uspi->s_fpb; 3586ef4d6bfSEvgeniy Dushistov tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment), goal, 3596ef4d6bfSEvgeniy Dushistov uspi->s_fpb, err, locked_page); 3601da177e4SLinus Torvalds if (!tmp) { 3611da177e4SLinus Torvalds if (fs32_to_cpu(sb, *p)) 3621da177e4SLinus Torvalds goto repeat; 3631da177e4SLinus Torvalds goto out; 3641da177e4SLinus Torvalds } 3651da177e4SLinus Torvalds 366c9a27b5dSEvgeniy Dushistov 3671da177e4SLinus Torvalds if (metadata) { 3681da177e4SLinus Torvalds result = sb_getblk(sb, tmp + blockoff); 369c9a27b5dSEvgeniy Dushistov ufs_clear_block(inode, result); 3701da177e4SLinus Torvalds } else { 371c9a27b5dSEvgeniy Dushistov *phys = tmp + blockoff; 3721da177e4SLinus Torvalds *new = 1; 3731da177e4SLinus Torvalds } 3741da177e4SLinus Torvalds 3751da177e4SLinus Torvalds mark_buffer_dirty(bh); 3761da177e4SLinus Torvalds if (IS_SYNC(inode)) 3771da177e4SLinus Torvalds sync_dirty_buffer(bh); 3781da177e4SLinus Torvalds inode->i_ctime = CURRENT_TIME_SEC; 3791da177e4SLinus Torvalds mark_inode_dirty(inode); 3807b4ee73eSEvgeniy UFSD(("result %u\n", tmp + blockoff)); 3811da177e4SLinus Torvalds out: 3821da177e4SLinus Torvalds brelse (bh); 3837b4ee73eSEvgeniy UFSD(("EXIT\n")); 3841da177e4SLinus Torvalds return result; 3851da177e4SLinus Torvalds } 3861da177e4SLinus Torvalds 3871da177e4SLinus Torvalds /* 3881da177e4SLinus Torvalds * This function gets the block which contains the fragment. 3891da177e4SLinus Torvalds */ 3901da177e4SLinus Torvalds 39109114eb8SEvgeniy Dushistov int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create) 3921da177e4SLinus Torvalds { 3931da177e4SLinus Torvalds struct super_block * sb = inode->i_sb; 3941da177e4SLinus Torvalds struct ufs_sb_private_info * uspi = UFS_SB(sb)->s_uspi; 3951da177e4SLinus Torvalds struct buffer_head * bh; 3961da177e4SLinus Torvalds int ret, err, new; 3971da177e4SLinus Torvalds unsigned long ptr,phys; 3981da177e4SLinus Torvalds u64 phys64 = 0; 3991da177e4SLinus Torvalds 4001da177e4SLinus Torvalds if (!create) { 4011da177e4SLinus Torvalds phys64 = ufs_frag_map(inode, fragment); 4027b4ee73eSEvgeniy UFSD(("phys64 = %llu \n",phys64)); 4031da177e4SLinus Torvalds if (phys64) 4041da177e4SLinus Torvalds map_bh(bh_result, sb, phys64); 4051da177e4SLinus Torvalds return 0; 4061da177e4SLinus Torvalds } 4071da177e4SLinus Torvalds 4081da177e4SLinus Torvalds /* This code entered only while writing ....? */ 4091da177e4SLinus Torvalds 4101da177e4SLinus Torvalds err = -EIO; 4111da177e4SLinus Torvalds new = 0; 4121da177e4SLinus Torvalds ret = 0; 4131da177e4SLinus Torvalds bh = NULL; 4141da177e4SLinus Torvalds 4151da177e4SLinus Torvalds lock_kernel(); 4161da177e4SLinus Torvalds 4177b4ee73eSEvgeniy UFSD(("ENTER, ino %lu, fragment %llu\n", inode->i_ino, (unsigned long long)fragment)) 4181da177e4SLinus Torvalds if (fragment < 0) 4191da177e4SLinus Torvalds goto abort_negative; 4201da177e4SLinus Torvalds if (fragment > 4211da177e4SLinus Torvalds ((UFS_NDADDR + uspi->s_apb + uspi->s_2apb + uspi->s_3apb) 4221da177e4SLinus Torvalds << uspi->s_fpbshift)) 4231da177e4SLinus Torvalds goto abort_too_big; 4241da177e4SLinus Torvalds 4251da177e4SLinus Torvalds err = 0; 4261da177e4SLinus Torvalds ptr = fragment; 4271da177e4SLinus Torvalds 4281da177e4SLinus Torvalds /* 4291da177e4SLinus Torvalds * ok, these macros clean the logic up a bit and make 4301da177e4SLinus Torvalds * it much more readable: 4311da177e4SLinus Torvalds */ 4321da177e4SLinus Torvalds #define GET_INODE_DATABLOCK(x) \ 4336ef4d6bfSEvgeniy Dushistov ufs_inode_getfrag(inode, x, fragment, 1, &err, 0, &phys, &new, bh_result->b_page) 4341da177e4SLinus Torvalds #define GET_INODE_PTR(x) \ 4356ef4d6bfSEvgeniy Dushistov ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, 1, NULL, NULL, bh_result->b_page) 4361da177e4SLinus Torvalds #define GET_INDIRECT_DATABLOCK(x) \ 4371da177e4SLinus Torvalds ufs_block_getfrag(inode, bh, x, fragment, sb->s_blocksize, \ 4386ef4d6bfSEvgeniy Dushistov &err, 0, &phys, &new, bh_result->b_page); 4391da177e4SLinus Torvalds #define GET_INDIRECT_PTR(x) \ 4401da177e4SLinus Torvalds ufs_block_getfrag(inode, bh, x, fragment, sb->s_blocksize, \ 4416ef4d6bfSEvgeniy Dushistov &err, 1, NULL, NULL, bh_result->b_page); 4421da177e4SLinus Torvalds 4431da177e4SLinus Torvalds if (ptr < UFS_NDIR_FRAGMENT) { 4441da177e4SLinus Torvalds bh = GET_INODE_DATABLOCK(ptr); 4451da177e4SLinus Torvalds goto out; 4461da177e4SLinus Torvalds } 4471da177e4SLinus Torvalds ptr -= UFS_NDIR_FRAGMENT; 4481da177e4SLinus Torvalds if (ptr < (1 << (uspi->s_apbshift + uspi->s_fpbshift))) { 4491da177e4SLinus Torvalds bh = GET_INODE_PTR(UFS_IND_FRAGMENT + (ptr >> uspi->s_apbshift)); 4501da177e4SLinus Torvalds goto get_indirect; 4511da177e4SLinus Torvalds } 4521da177e4SLinus Torvalds ptr -= 1 << (uspi->s_apbshift + uspi->s_fpbshift); 4531da177e4SLinus Torvalds if (ptr < (1 << (uspi->s_2apbshift + uspi->s_fpbshift))) { 4541da177e4SLinus Torvalds bh = GET_INODE_PTR(UFS_DIND_FRAGMENT + (ptr >> uspi->s_2apbshift)); 4551da177e4SLinus Torvalds goto get_double; 4561da177e4SLinus Torvalds } 4571da177e4SLinus Torvalds ptr -= 1 << (uspi->s_2apbshift + uspi->s_fpbshift); 4581da177e4SLinus Torvalds bh = GET_INODE_PTR(UFS_TIND_FRAGMENT + (ptr >> uspi->s_3apbshift)); 4591da177e4SLinus Torvalds bh = GET_INDIRECT_PTR((ptr >> uspi->s_2apbshift) & uspi->s_apbmask); 4601da177e4SLinus Torvalds get_double: 4611da177e4SLinus Torvalds bh = GET_INDIRECT_PTR((ptr >> uspi->s_apbshift) & uspi->s_apbmask); 4621da177e4SLinus Torvalds get_indirect: 4631da177e4SLinus Torvalds bh = GET_INDIRECT_DATABLOCK(ptr & uspi->s_apbmask); 4641da177e4SLinus Torvalds 4651da177e4SLinus Torvalds #undef GET_INODE_DATABLOCK 4661da177e4SLinus Torvalds #undef GET_INODE_PTR 4671da177e4SLinus Torvalds #undef GET_INDIRECT_DATABLOCK 4681da177e4SLinus Torvalds #undef GET_INDIRECT_PTR 4691da177e4SLinus Torvalds 4701da177e4SLinus Torvalds out: 4711da177e4SLinus Torvalds if (err) 4721da177e4SLinus Torvalds goto abort; 4731da177e4SLinus Torvalds if (new) 4741da177e4SLinus Torvalds set_buffer_new(bh_result); 4751da177e4SLinus Torvalds map_bh(bh_result, sb, phys); 4761da177e4SLinus Torvalds abort: 4771da177e4SLinus Torvalds unlock_kernel(); 4781da177e4SLinus Torvalds return err; 4791da177e4SLinus Torvalds 4801da177e4SLinus Torvalds abort_negative: 4811da177e4SLinus Torvalds ufs_warning(sb, "ufs_get_block", "block < 0"); 4821da177e4SLinus Torvalds goto abort; 4831da177e4SLinus Torvalds 4841da177e4SLinus Torvalds abort_too_big: 4851da177e4SLinus Torvalds ufs_warning(sb, "ufs_get_block", "block > big"); 4861da177e4SLinus Torvalds goto abort; 4871da177e4SLinus Torvalds } 4881da177e4SLinus Torvalds 4891da177e4SLinus Torvalds struct buffer_head *ufs_getfrag(struct inode *inode, unsigned int fragment, 4901da177e4SLinus Torvalds int create, int *err) 4911da177e4SLinus Torvalds { 4921da177e4SLinus Torvalds struct buffer_head dummy; 4931da177e4SLinus Torvalds int error; 4941da177e4SLinus Torvalds 4951da177e4SLinus Torvalds dummy.b_state = 0; 4961da177e4SLinus Torvalds dummy.b_blocknr = -1000; 4971da177e4SLinus Torvalds error = ufs_getfrag_block(inode, fragment, &dummy, create); 4981da177e4SLinus Torvalds *err = error; 4991da177e4SLinus Torvalds if (!error && buffer_mapped(&dummy)) { 5001da177e4SLinus Torvalds struct buffer_head *bh; 5011da177e4SLinus Torvalds bh = sb_getblk(inode->i_sb, dummy.b_blocknr); 5021da177e4SLinus Torvalds if (buffer_new(&dummy)) { 5031da177e4SLinus Torvalds memset(bh->b_data, 0, inode->i_sb->s_blocksize); 5041da177e4SLinus Torvalds set_buffer_uptodate(bh); 5051da177e4SLinus Torvalds mark_buffer_dirty(bh); 5061da177e4SLinus Torvalds } 5071da177e4SLinus Torvalds return bh; 5081da177e4SLinus Torvalds } 5091da177e4SLinus Torvalds return NULL; 5101da177e4SLinus Torvalds } 5111da177e4SLinus Torvalds 5121da177e4SLinus Torvalds struct buffer_head * ufs_bread (struct inode * inode, unsigned fragment, 5131da177e4SLinus Torvalds int create, int * err) 5141da177e4SLinus Torvalds { 5151da177e4SLinus Torvalds struct buffer_head * bh; 5161da177e4SLinus Torvalds 5171da177e4SLinus Torvalds UFSD(("ENTER, ino %lu, fragment %u\n", inode->i_ino, fragment)) 5181da177e4SLinus Torvalds bh = ufs_getfrag (inode, fragment, create, err); 5191da177e4SLinus Torvalds if (!bh || buffer_uptodate(bh)) 5201da177e4SLinus Torvalds return bh; 5211da177e4SLinus Torvalds ll_rw_block (READ, 1, &bh); 5221da177e4SLinus Torvalds wait_on_buffer (bh); 5231da177e4SLinus Torvalds if (buffer_uptodate(bh)) 5241da177e4SLinus Torvalds return bh; 5251da177e4SLinus Torvalds brelse (bh); 5261da177e4SLinus Torvalds *err = -EIO; 5271da177e4SLinus Torvalds return NULL; 5281da177e4SLinus Torvalds } 5291da177e4SLinus Torvalds 5301da177e4SLinus Torvalds static int ufs_writepage(struct page *page, struct writeback_control *wbc) 5311da177e4SLinus Torvalds { 5321da177e4SLinus Torvalds return block_write_full_page(page,ufs_getfrag_block,wbc); 5331da177e4SLinus Torvalds } 5341da177e4SLinus Torvalds static int ufs_readpage(struct file *file, struct page *page) 5351da177e4SLinus Torvalds { 5361da177e4SLinus Torvalds return block_read_full_page(page,ufs_getfrag_block); 5371da177e4SLinus Torvalds } 5381da177e4SLinus Torvalds static int ufs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) 5391da177e4SLinus Torvalds { 5401da177e4SLinus Torvalds return block_prepare_write(page,from,to,ufs_getfrag_block); 5411da177e4SLinus Torvalds } 5421da177e4SLinus Torvalds static sector_t ufs_bmap(struct address_space *mapping, sector_t block) 5431da177e4SLinus Torvalds { 5441da177e4SLinus Torvalds return generic_block_bmap(mapping,block,ufs_getfrag_block); 5451da177e4SLinus Torvalds } 5461da177e4SLinus Torvalds struct address_space_operations ufs_aops = { 5471da177e4SLinus Torvalds .readpage = ufs_readpage, 5481da177e4SLinus Torvalds .writepage = ufs_writepage, 5491da177e4SLinus Torvalds .sync_page = block_sync_page, 5501da177e4SLinus Torvalds .prepare_write = ufs_prepare_write, 5511da177e4SLinus Torvalds .commit_write = generic_commit_write, 5521da177e4SLinus Torvalds .bmap = ufs_bmap 5531da177e4SLinus Torvalds }; 5541da177e4SLinus Torvalds 5551da177e4SLinus Torvalds void ufs_read_inode (struct inode * inode) 5561da177e4SLinus Torvalds { 5571da177e4SLinus Torvalds struct ufs_inode_info *ufsi = UFS_I(inode); 5581da177e4SLinus Torvalds struct super_block * sb; 5591da177e4SLinus Torvalds struct ufs_sb_private_info * uspi; 5601da177e4SLinus Torvalds struct ufs_inode * ufs_inode; 5611da177e4SLinus Torvalds struct ufs2_inode *ufs2_inode; 5621da177e4SLinus Torvalds struct buffer_head * bh; 5631da177e4SLinus Torvalds mode_t mode; 5641da177e4SLinus Torvalds unsigned i; 5651da177e4SLinus Torvalds unsigned flags; 5661da177e4SLinus Torvalds 5671da177e4SLinus Torvalds UFSD(("ENTER, ino %lu\n", inode->i_ino)) 5681da177e4SLinus Torvalds 5691da177e4SLinus Torvalds sb = inode->i_sb; 5701da177e4SLinus Torvalds uspi = UFS_SB(sb)->s_uspi; 5711da177e4SLinus Torvalds flags = UFS_SB(sb)->s_flags; 5721da177e4SLinus Torvalds 5731da177e4SLinus Torvalds if (inode->i_ino < UFS_ROOTINO || 5741da177e4SLinus Torvalds inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) { 5751da177e4SLinus Torvalds ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino); 5761da177e4SLinus Torvalds goto bad_inode; 5771da177e4SLinus Torvalds } 5781da177e4SLinus Torvalds 5791da177e4SLinus Torvalds bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino)); 5801da177e4SLinus Torvalds if (!bh) { 5811da177e4SLinus Torvalds ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino); 5821da177e4SLinus Torvalds goto bad_inode; 5831da177e4SLinus Torvalds } 5841da177e4SLinus Torvalds if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) 5851da177e4SLinus Torvalds goto ufs2_inode; 5861da177e4SLinus Torvalds 5871da177e4SLinus Torvalds ufs_inode = (struct ufs_inode *) (bh->b_data + sizeof(struct ufs_inode) * ufs_inotofsbo(inode->i_ino)); 5881da177e4SLinus Torvalds 5891da177e4SLinus Torvalds /* 5901da177e4SLinus Torvalds * Copy data to the in-core inode. 5911da177e4SLinus Torvalds */ 5921da177e4SLinus Torvalds inode->i_mode = mode = fs16_to_cpu(sb, ufs_inode->ui_mode); 5931da177e4SLinus Torvalds inode->i_nlink = fs16_to_cpu(sb, ufs_inode->ui_nlink); 5941da177e4SLinus Torvalds if (inode->i_nlink == 0) 5951da177e4SLinus Torvalds ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino); 5961da177e4SLinus Torvalds 5971da177e4SLinus Torvalds /* 5981da177e4SLinus Torvalds * Linux now has 32-bit uid and gid, so we can support EFT. 5991da177e4SLinus Torvalds */ 6001da177e4SLinus Torvalds inode->i_uid = ufs_get_inode_uid(sb, ufs_inode); 6011da177e4SLinus Torvalds inode->i_gid = ufs_get_inode_gid(sb, ufs_inode); 6021da177e4SLinus Torvalds 6031da177e4SLinus Torvalds inode->i_size = fs64_to_cpu(sb, ufs_inode->ui_size); 6041da177e4SLinus Torvalds inode->i_atime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_atime.tv_sec); 6051da177e4SLinus Torvalds inode->i_ctime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_ctime.tv_sec); 6061da177e4SLinus Torvalds inode->i_mtime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_mtime.tv_sec); 6071da177e4SLinus Torvalds inode->i_mtime.tv_nsec = 0; 6081da177e4SLinus Torvalds inode->i_atime.tv_nsec = 0; 6091da177e4SLinus Torvalds inode->i_ctime.tv_nsec = 0; 6101da177e4SLinus Torvalds inode->i_blocks = fs32_to_cpu(sb, ufs_inode->ui_blocks); 6111da177e4SLinus Torvalds inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size (for stat) */ 6121da177e4SLinus Torvalds inode->i_version++; 6131da177e4SLinus Torvalds ufsi->i_flags = fs32_to_cpu(sb, ufs_inode->ui_flags); 6141da177e4SLinus Torvalds ufsi->i_gen = fs32_to_cpu(sb, ufs_inode->ui_gen); 6151da177e4SLinus Torvalds ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow); 6161da177e4SLinus Torvalds ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); 6171da177e4SLinus Torvalds ufsi->i_lastfrag = (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift; 6181da177e4SLinus Torvalds 6191da177e4SLinus Torvalds if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) { 6201da177e4SLinus Torvalds for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) 6211da177e4SLinus Torvalds ufsi->i_u1.i_data[i] = ufs_inode->ui_u2.ui_addr.ui_db[i]; 6221da177e4SLinus Torvalds } 6231da177e4SLinus Torvalds else { 6241da177e4SLinus Torvalds for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) 6251da177e4SLinus Torvalds ufsi->i_u1.i_symlink[i] = ufs_inode->ui_u2.ui_symlink[i]; 6261da177e4SLinus Torvalds } 6271da177e4SLinus Torvalds ufsi->i_osync = 0; 6281da177e4SLinus Torvalds 6291da177e4SLinus Torvalds if (S_ISREG(inode->i_mode)) { 6301da177e4SLinus Torvalds inode->i_op = &ufs_file_inode_operations; 6311da177e4SLinus Torvalds inode->i_fop = &ufs_file_operations; 6321da177e4SLinus Torvalds inode->i_mapping->a_ops = &ufs_aops; 6331da177e4SLinus Torvalds } else if (S_ISDIR(inode->i_mode)) { 6341da177e4SLinus Torvalds inode->i_op = &ufs_dir_inode_operations; 6351da177e4SLinus Torvalds inode->i_fop = &ufs_dir_operations; 6361da177e4SLinus Torvalds } else if (S_ISLNK(inode->i_mode)) { 6371da177e4SLinus Torvalds if (!inode->i_blocks) 6381da177e4SLinus Torvalds inode->i_op = &ufs_fast_symlink_inode_operations; 6391da177e4SLinus Torvalds else { 6401da177e4SLinus Torvalds inode->i_op = &page_symlink_inode_operations; 6411da177e4SLinus Torvalds inode->i_mapping->a_ops = &ufs_aops; 6421da177e4SLinus Torvalds } 6431da177e4SLinus Torvalds } else 6441da177e4SLinus Torvalds init_special_inode(inode, inode->i_mode, 6451da177e4SLinus Torvalds ufs_get_inode_dev(sb, ufsi)); 6461da177e4SLinus Torvalds 6471da177e4SLinus Torvalds brelse (bh); 6481da177e4SLinus Torvalds 6491da177e4SLinus Torvalds UFSD(("EXIT\n")) 6501da177e4SLinus Torvalds return; 6511da177e4SLinus Torvalds 6521da177e4SLinus Torvalds bad_inode: 6531da177e4SLinus Torvalds make_bad_inode(inode); 6541da177e4SLinus Torvalds return; 6551da177e4SLinus Torvalds 6561da177e4SLinus Torvalds ufs2_inode : 6571da177e4SLinus Torvalds UFSD(("Reading ufs2 inode, ino %lu\n", inode->i_ino)) 6581da177e4SLinus Torvalds 6591da177e4SLinus Torvalds ufs2_inode = (struct ufs2_inode *)(bh->b_data + sizeof(struct ufs2_inode) * ufs_inotofsbo(inode->i_ino)); 6601da177e4SLinus Torvalds 6611da177e4SLinus Torvalds /* 6621da177e4SLinus Torvalds * Copy data to the in-core inode. 6631da177e4SLinus Torvalds */ 6641da177e4SLinus Torvalds inode->i_mode = mode = fs16_to_cpu(sb, ufs2_inode->ui_mode); 6651da177e4SLinus Torvalds inode->i_nlink = fs16_to_cpu(sb, ufs2_inode->ui_nlink); 6661da177e4SLinus Torvalds if (inode->i_nlink == 0) 6671da177e4SLinus Torvalds ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino); 6681da177e4SLinus Torvalds 6691da177e4SLinus Torvalds /* 6701da177e4SLinus Torvalds * Linux now has 32-bit uid and gid, so we can support EFT. 6711da177e4SLinus Torvalds */ 6721da177e4SLinus Torvalds inode->i_uid = fs32_to_cpu(sb, ufs2_inode->ui_uid); 6731da177e4SLinus Torvalds inode->i_gid = fs32_to_cpu(sb, ufs2_inode->ui_gid); 6741da177e4SLinus Torvalds 6751da177e4SLinus Torvalds inode->i_size = fs64_to_cpu(sb, ufs2_inode->ui_size); 6761da177e4SLinus Torvalds inode->i_atime.tv_sec = fs32_to_cpu(sb, ufs2_inode->ui_atime.tv_sec); 6771da177e4SLinus Torvalds inode->i_ctime.tv_sec = fs32_to_cpu(sb, ufs2_inode->ui_ctime.tv_sec); 6781da177e4SLinus Torvalds inode->i_mtime.tv_sec = fs32_to_cpu(sb, ufs2_inode->ui_mtime.tv_sec); 6791da177e4SLinus Torvalds inode->i_mtime.tv_nsec = 0; 6801da177e4SLinus Torvalds inode->i_atime.tv_nsec = 0; 6811da177e4SLinus Torvalds inode->i_ctime.tv_nsec = 0; 6821da177e4SLinus Torvalds inode->i_blocks = fs64_to_cpu(sb, ufs2_inode->ui_blocks); 6831da177e4SLinus Torvalds inode->i_blksize = PAGE_SIZE; /*This is the optimal IO size(for stat)*/ 6841da177e4SLinus Torvalds 6851da177e4SLinus Torvalds inode->i_version++; 6861da177e4SLinus Torvalds ufsi->i_flags = fs32_to_cpu(sb, ufs2_inode->ui_flags); 6871da177e4SLinus Torvalds ufsi->i_gen = fs32_to_cpu(sb, ufs2_inode->ui_gen); 6881da177e4SLinus Torvalds /* 6891da177e4SLinus Torvalds ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow); 6901da177e4SLinus Torvalds ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); 6911da177e4SLinus Torvalds */ 6921da177e4SLinus Torvalds ufsi->i_lastfrag= (inode->i_size + uspi->s_fsize- 1) >> uspi->s_fshift; 6931da177e4SLinus Torvalds 6941da177e4SLinus Torvalds if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) { 6951da177e4SLinus Torvalds for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) 6961da177e4SLinus Torvalds ufsi->i_u1.u2_i_data[i] = 6971da177e4SLinus Torvalds ufs2_inode->ui_u2.ui_addr.ui_db[i]; 6981da177e4SLinus Torvalds } 6991da177e4SLinus Torvalds else { 7001da177e4SLinus Torvalds for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) 7011da177e4SLinus Torvalds ufsi->i_u1.i_symlink[i] = ufs2_inode->ui_u2.ui_symlink[i]; 7021da177e4SLinus Torvalds } 7031da177e4SLinus Torvalds ufsi->i_osync = 0; 7041da177e4SLinus Torvalds 7051da177e4SLinus Torvalds if (S_ISREG(inode->i_mode)) { 7061da177e4SLinus Torvalds inode->i_op = &ufs_file_inode_operations; 7071da177e4SLinus Torvalds inode->i_fop = &ufs_file_operations; 7081da177e4SLinus Torvalds inode->i_mapping->a_ops = &ufs_aops; 7091da177e4SLinus Torvalds } else if (S_ISDIR(inode->i_mode)) { 7101da177e4SLinus Torvalds inode->i_op = &ufs_dir_inode_operations; 7111da177e4SLinus Torvalds inode->i_fop = &ufs_dir_operations; 7121da177e4SLinus Torvalds } else if (S_ISLNK(inode->i_mode)) { 7131da177e4SLinus Torvalds if (!inode->i_blocks) 7141da177e4SLinus Torvalds inode->i_op = &ufs_fast_symlink_inode_operations; 7151da177e4SLinus Torvalds else { 7161da177e4SLinus Torvalds inode->i_op = &page_symlink_inode_operations; 7171da177e4SLinus Torvalds inode->i_mapping->a_ops = &ufs_aops; 7181da177e4SLinus Torvalds } 7191da177e4SLinus Torvalds } else /* TODO : here ...*/ 7201da177e4SLinus Torvalds init_special_inode(inode, inode->i_mode, 7211da177e4SLinus Torvalds ufs_get_inode_dev(sb, ufsi)); 7221da177e4SLinus Torvalds 7231da177e4SLinus Torvalds brelse(bh); 7241da177e4SLinus Torvalds 7251da177e4SLinus Torvalds UFSD(("EXIT\n")) 7261da177e4SLinus Torvalds return; 7271da177e4SLinus Torvalds } 7281da177e4SLinus Torvalds 7291da177e4SLinus Torvalds static int ufs_update_inode(struct inode * inode, int do_sync) 7301da177e4SLinus Torvalds { 7311da177e4SLinus Torvalds struct ufs_inode_info *ufsi = UFS_I(inode); 7321da177e4SLinus Torvalds struct super_block * sb; 7331da177e4SLinus Torvalds struct ufs_sb_private_info * uspi; 7341da177e4SLinus Torvalds struct buffer_head * bh; 7351da177e4SLinus Torvalds struct ufs_inode * ufs_inode; 7361da177e4SLinus Torvalds unsigned i; 7371da177e4SLinus Torvalds unsigned flags; 7381da177e4SLinus Torvalds 7391da177e4SLinus Torvalds UFSD(("ENTER, ino %lu\n", inode->i_ino)) 7401da177e4SLinus Torvalds 7411da177e4SLinus Torvalds sb = inode->i_sb; 7421da177e4SLinus Torvalds uspi = UFS_SB(sb)->s_uspi; 7431da177e4SLinus Torvalds flags = UFS_SB(sb)->s_flags; 7441da177e4SLinus Torvalds 7451da177e4SLinus Torvalds if (inode->i_ino < UFS_ROOTINO || 7461da177e4SLinus Torvalds inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) { 7471da177e4SLinus Torvalds ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino); 7481da177e4SLinus Torvalds return -1; 7491da177e4SLinus Torvalds } 7501da177e4SLinus Torvalds 7511da177e4SLinus Torvalds bh = sb_bread(sb, ufs_inotofsba(inode->i_ino)); 7521da177e4SLinus Torvalds if (!bh) { 7531da177e4SLinus Torvalds ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino); 7541da177e4SLinus Torvalds return -1; 7551da177e4SLinus Torvalds } 7561da177e4SLinus Torvalds ufs_inode = (struct ufs_inode *) (bh->b_data + ufs_inotofsbo(inode->i_ino) * sizeof(struct ufs_inode)); 7571da177e4SLinus Torvalds 7581da177e4SLinus Torvalds ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode); 7591da177e4SLinus Torvalds ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink); 7601da177e4SLinus Torvalds 7611da177e4SLinus Torvalds ufs_set_inode_uid(sb, ufs_inode, inode->i_uid); 7621da177e4SLinus Torvalds ufs_set_inode_gid(sb, ufs_inode, inode->i_gid); 7631da177e4SLinus Torvalds 7641da177e4SLinus Torvalds ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size); 7651da177e4SLinus Torvalds ufs_inode->ui_atime.tv_sec = cpu_to_fs32(sb, inode->i_atime.tv_sec); 7661da177e4SLinus Torvalds ufs_inode->ui_atime.tv_usec = 0; 7671da177e4SLinus Torvalds ufs_inode->ui_ctime.tv_sec = cpu_to_fs32(sb, inode->i_ctime.tv_sec); 7681da177e4SLinus Torvalds ufs_inode->ui_ctime.tv_usec = 0; 7691da177e4SLinus Torvalds ufs_inode->ui_mtime.tv_sec = cpu_to_fs32(sb, inode->i_mtime.tv_sec); 7701da177e4SLinus Torvalds ufs_inode->ui_mtime.tv_usec = 0; 7711da177e4SLinus Torvalds ufs_inode->ui_blocks = cpu_to_fs32(sb, inode->i_blocks); 7721da177e4SLinus Torvalds ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags); 7731da177e4SLinus Torvalds ufs_inode->ui_gen = cpu_to_fs32(sb, ufsi->i_gen); 7741da177e4SLinus Torvalds 7751da177e4SLinus Torvalds if ((flags & UFS_UID_MASK) == UFS_UID_EFT) { 7761da177e4SLinus Torvalds ufs_inode->ui_u3.ui_sun.ui_shadow = cpu_to_fs32(sb, ufsi->i_shadow); 7771da177e4SLinus Torvalds ufs_inode->ui_u3.ui_sun.ui_oeftflag = cpu_to_fs32(sb, ufsi->i_oeftflag); 7781da177e4SLinus Torvalds } 7791da177e4SLinus Torvalds 7801da177e4SLinus Torvalds if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { 7811da177e4SLinus Torvalds /* ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev); */ 7821da177e4SLinus Torvalds ufs_inode->ui_u2.ui_addr.ui_db[0] = ufsi->i_u1.i_data[0]; 7831da177e4SLinus Torvalds } else if (inode->i_blocks) { 7841da177e4SLinus Torvalds for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) 7851da177e4SLinus Torvalds ufs_inode->ui_u2.ui_addr.ui_db[i] = ufsi->i_u1.i_data[i]; 7861da177e4SLinus Torvalds } 7871da177e4SLinus Torvalds else { 7881da177e4SLinus Torvalds for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) 7891da177e4SLinus Torvalds ufs_inode->ui_u2.ui_symlink[i] = ufsi->i_u1.i_symlink[i]; 7901da177e4SLinus Torvalds } 7911da177e4SLinus Torvalds 7921da177e4SLinus Torvalds if (!inode->i_nlink) 7931da177e4SLinus Torvalds memset (ufs_inode, 0, sizeof(struct ufs_inode)); 7941da177e4SLinus Torvalds 7951da177e4SLinus Torvalds mark_buffer_dirty(bh); 7961da177e4SLinus Torvalds if (do_sync) 7971da177e4SLinus Torvalds sync_dirty_buffer(bh); 7981da177e4SLinus Torvalds brelse (bh); 7991da177e4SLinus Torvalds 8001da177e4SLinus Torvalds UFSD(("EXIT\n")) 8011da177e4SLinus Torvalds return 0; 8021da177e4SLinus Torvalds } 8031da177e4SLinus Torvalds 8041da177e4SLinus Torvalds int ufs_write_inode (struct inode * inode, int wait) 8051da177e4SLinus Torvalds { 8061da177e4SLinus Torvalds int ret; 8071da177e4SLinus Torvalds lock_kernel(); 8081da177e4SLinus Torvalds ret = ufs_update_inode (inode, wait); 8091da177e4SLinus Torvalds unlock_kernel(); 8101da177e4SLinus Torvalds return ret; 8111da177e4SLinus Torvalds } 8121da177e4SLinus Torvalds 8131da177e4SLinus Torvalds int ufs_sync_inode (struct inode *inode) 8141da177e4SLinus Torvalds { 8151da177e4SLinus Torvalds return ufs_update_inode (inode, 1); 8161da177e4SLinus Torvalds } 8171da177e4SLinus Torvalds 8181da177e4SLinus Torvalds void ufs_delete_inode (struct inode * inode) 8191da177e4SLinus Torvalds { 820fef26658SMark Fasheh truncate_inode_pages(&inode->i_data, 0); 8211da177e4SLinus Torvalds /*UFS_I(inode)->i_dtime = CURRENT_TIME;*/ 8221da177e4SLinus Torvalds lock_kernel(); 8231da177e4SLinus Torvalds mark_inode_dirty(inode); 8241da177e4SLinus Torvalds ufs_update_inode(inode, IS_SYNC(inode)); 8251da177e4SLinus Torvalds inode->i_size = 0; 8261da177e4SLinus Torvalds if (inode->i_blocks) 8271da177e4SLinus Torvalds ufs_truncate (inode); 8281da177e4SLinus Torvalds ufs_free_inode (inode); 8291da177e4SLinus Torvalds unlock_kernel(); 8301da177e4SLinus Torvalds } 831