b24413180f560 (Greg Kroah-Hartman 2017-11-01 15:07:57 +0100 1) // SPDX-License-Identifier: GPL-2.0
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 3) * linux/fs/ufs/inode.c
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 4) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 5) * Copyright (C) 1998
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 6) * Daniel Pirkl <daniel.pirkl@email.cz>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 7) * Charles University, Faculty of Mathematics and Physics
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 8) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 9) * from
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 10) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 11) * linux/fs/ext2/inode.c
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 12) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 13) * Copyright (C) 1992, 1993, 1994, 1995
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 14) * Remy Card (card@masi.ibp.fr)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 15) * Laboratoire MASI - Institut Blaise Pascal
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 16) * Universite Pierre et Marie Curie (Paris VI)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 17) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 18) * from
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 19) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 20) * linux/fs/minix/inode.c
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 21) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 22) * Copyright (C) 1991, 1992 Linus Torvalds
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 23) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 24) * Goal-directed block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 25) * Big-endian to little-endian byte-swapping/bitmaps by
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 26) * David S. Miller (davem@caip.rutgers.edu), 1995
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 27) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 28)
7c0f6ba682b9c (Linus Torvalds 2016-12-24 11:46:01 -0800 29) #include <linux/uaccess.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 30)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 31) #include <linux/errno.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 32) #include <linux/fs.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 33) #include <linux/time.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 34) #include <linux/stat.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 35) #include <linux/string.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 36) #include <linux/mm.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 37) #include <linux/buffer_head.h>
a9185b41a4f84 (Christoph Hellwig 2010-03-05 09:21:37 +0100 38) #include <linux/writeback.h>
bb8c2d66bc6f7 (Jeff Layton 2017-12-11 06:35:18 -0500 39) #include <linux/iversion.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 40)
e542059884bb6 (Mike Frysinger 2008-02-08 04:21:31 -0800 41) #include "ufs_fs.h"
bcd6d4ecf6868 (Christoph Hellwig 2007-10-16 23:26:51 -0700 42) #include "ufs.h"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 43) #include "swab.h"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 44) #include "util.h"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 45)
4e3911f3d704d (Al Viro 2015-06-04 14:13:14 -0400 46) static int ufs_block_to_path(struct inode *inode, sector_t i_block, unsigned offsets[4])
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 47) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 48) struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 49) int ptrs = uspi->s_apb;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 50) int ptrs_bits = uspi->s_apbshift;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 51) const long direct_blocks = UFS_NDADDR,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 52) indirect_blocks = ptrs,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 53) double_blocks = (1 << (ptrs_bits * 2));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 54) int n = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 55)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 56)
abf5d15fd2e52 (Evgeniy Dushistov 2006-06-25 05:47:24 -0700 57) UFSD("ptrs=uspi->s_apb = %d,double_blocks=%ld \n",ptrs,double_blocks);
37044c86baf8c (Roel Kluin 2009-06-17 16:26:28 -0700 58) if (i_block < direct_blocks) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 59) offsets[n++] = i_block;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 60) } else if ((i_block -= direct_blocks) < indirect_blocks) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 61) offsets[n++] = UFS_IND_BLOCK;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 62) offsets[n++] = i_block;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 63) } else if ((i_block -= indirect_blocks) < double_blocks) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 64) offsets[n++] = UFS_DIND_BLOCK;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 65) offsets[n++] = i_block >> ptrs_bits;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 66) offsets[n++] = i_block & (ptrs - 1);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 67) } else if (((i_block -= double_blocks) >> (ptrs_bits * 2)) < ptrs) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 68) offsets[n++] = UFS_TIND_BLOCK;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 69) offsets[n++] = i_block >> (ptrs_bits * 2);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 70) offsets[n++] = (i_block >> ptrs_bits) & (ptrs - 1);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 71) offsets[n++] = i_block & (ptrs - 1);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 72) } else {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 73) ufs_warning(inode->i_sb, "ufs_block_to_path", "block > big");
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 74) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 75) return n;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 76) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 77)
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 78) typedef struct {
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 79) void *p;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 80) union {
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 81) __fs32 key32;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 82) __fs64 key64;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 83) };
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 84) struct buffer_head *bh;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 85) } Indirect;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 86)
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 87) static inline int grow_chain32(struct ufs_inode_info *ufsi,
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 88) struct buffer_head *bh, __fs32 *v,
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 89) Indirect *from, Indirect *to)
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 90) {
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 91) Indirect *p;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 92) unsigned seq;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 93) to->bh = bh;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 94) do {
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 95) seq = read_seqbegin(&ufsi->meta_lock);
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 96) to->key32 = *(__fs32 *)(to->p = v);
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 97) for (p = from; p <= to && p->key32 == *(__fs32 *)p->p; p++)
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 98) ;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 99) } while (read_seqretry(&ufsi->meta_lock, seq));
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 100) return (p > to);
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 101) }
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 102)
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 103) static inline int grow_chain64(struct ufs_inode_info *ufsi,
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 104) struct buffer_head *bh, __fs64 *v,
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 105) Indirect *from, Indirect *to)
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 106) {
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 107) Indirect *p;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 108) unsigned seq;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 109) to->bh = bh;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 110) do {
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 111) seq = read_seqbegin(&ufsi->meta_lock);
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 112) to->key64 = *(__fs64 *)(to->p = v);
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 113) for (p = from; p <= to && p->key64 == *(__fs64 *)p->p; p++)
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 114) ;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 115) } while (read_seqretry(&ufsi->meta_lock, seq));
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 116) return (p > to);
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 117) }
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 118)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 119) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 120) * Returns the location of the fragment from
25985edcedea6 (Lucas De Marchi 2011-03-30 22:57:33 -0300 121) * the beginning of the filesystem.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 122) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 123)
4b7068c8b1784 (Al Viro 2015-06-04 14:27:23 -0400 124) static u64 ufs_frag_map(struct inode *inode, unsigned offsets[4], int depth)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 125) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 126) struct ufs_inode_info *ufsi = UFS_I(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 127) struct super_block *sb = inode->i_sb;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 128) struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 129) u64 mask = (u64) uspi->s_apbmask>>uspi->s_fpbshift;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 130) int shift = uspi->s_apbshift-uspi->s_fpbshift;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 131) Indirect chain[4], *q = chain;
4b7068c8b1784 (Al Viro 2015-06-04 14:27:23 -0400 132) unsigned *p;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 133) unsigned flags = UFS_SB(sb)->s_flags;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 134) u64 res = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 135)
7256d819e43f8 (Andrew Morton 2006-06-29 02:24:29 -0700 136) UFSD(": uspi->s_fpbshift = %d ,uspi->s_apbmask = %x, mask=%llx\n",
7256d819e43f8 (Andrew Morton 2006-06-29 02:24:29 -0700 137) uspi->s_fpbshift, uspi->s_apbmask,
7256d819e43f8 (Andrew Morton 2006-06-29 02:24:29 -0700 138) (unsigned long long)mask);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 139)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 140) if (depth == 0)
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 141) goto no_block;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 142)
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 143) again:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 144) p = offsets;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 145)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 146) if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 147) goto ufs2;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 148)
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 149) if (!grow_chain32(ufsi, NULL, &ufsi->i_u1.i_data[*p++], chain, q))
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 150) goto changed;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 151) if (!q->key32)
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 152) goto no_block;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 153) while (--depth) {
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 154) __fs32 *ptr;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 155) struct buffer_head *bh;
4e3911f3d704d (Al Viro 2015-06-04 14:13:14 -0400 156) unsigned n = *p++;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 157)
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 158) bh = sb_bread(sb, uspi->s_sbbase +
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 159) fs32_to_cpu(sb, q->key32) + (n>>shift));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 160) if (!bh)
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 161) goto no_block;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 162) ptr = (__fs32 *)bh->b_data + (n & mask);
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 163) if (!grow_chain32(ufsi, bh, ptr, chain, ++q))
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 164) goto changed;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 165) if (!q->key32)
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 166) goto no_block;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 167) }
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 168) res = fs32_to_cpu(sb, q->key32);
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 169) goto found;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 170)
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 171) ufs2:
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 172) if (!grow_chain64(ufsi, NULL, &ufsi->i_u1.u2_i_data[*p++], chain, q))
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 173) goto changed;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 174) if (!q->key64)
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 175) goto no_block;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 176)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 177) while (--depth) {
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 178) __fs64 *ptr;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 179) struct buffer_head *bh;
4e3911f3d704d (Al Viro 2015-06-04 14:13:14 -0400 180) unsigned n = *p++;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 181)
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 182) bh = sb_bread(sb, uspi->s_sbbase +
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 183) fs64_to_cpu(sb, q->key64) + (n>>shift));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 184) if (!bh)
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 185) goto no_block;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 186) ptr = (__fs64 *)bh->b_data + (n & mask);
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 187) if (!grow_chain64(ufsi, bh, ptr, chain, ++q))
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 188) goto changed;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 189) if (!q->key64)
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 190) goto no_block;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 191) }
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 192) res = fs64_to_cpu(sb, q->key64);
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 193) found:
4b7068c8b1784 (Al Viro 2015-06-04 14:27:23 -0400 194) res += uspi->s_sbbase;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 195) no_block:
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 196) while (q > chain) {
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 197) brelse(q->bh);
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 198) q--;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 199) }
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 200) return res;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 201)
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 202) changed:
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 203) while (q > chain) {
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 204) brelse(q->bh);
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 205) q--;
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 206) }
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 207) goto again;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 208) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 209)
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 210) /*
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 211) * Unpacking tails: we have a file with partial final block and
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 212) * we had been asked to extend it. If the fragment being written
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 213) * is within the same block, we need to extend the tail just to cover
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 214) * that fragment. Otherwise the tail is extended to full block.
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 215) *
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 216) * Note that we might need to create a _new_ tail, but that will
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 217) * be handled elsewhere; this is strictly for resizing old
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 218) * ones.
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 219) */
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 220) static bool
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 221) ufs_extend_tail(struct inode *inode, u64 writes_to,
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 222) int *err, struct page *locked_page)
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 223) {
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 224) struct ufs_inode_info *ufsi = UFS_I(inode);
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 225) struct super_block *sb = inode->i_sb;
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 226) struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 227) unsigned lastfrag = ufsi->i_lastfrag; /* it's a short file, so unsigned is enough */
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 228) unsigned block = ufs_fragstoblks(lastfrag);
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 229) unsigned new_size;
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 230) void *p;
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 231) u64 tmp;
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 232)
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 233) if (writes_to < (lastfrag | uspi->s_fpbmask))
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 234) new_size = (writes_to & uspi->s_fpbmask) + 1;
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 235) else
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 236) new_size = uspi->s_fpb;
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 237)
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 238) p = ufs_get_direct_data_ptr(uspi, ufsi, block);
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 239) tmp = ufs_new_fragments(inode, p, lastfrag, ufs_data_ptr_to_cpu(sb, p),
940ef1a0ed939 (Al Viro 2017-06-08 23:27:12 -0400 240) new_size - (lastfrag & uspi->s_fpbmask), err,
940ef1a0ed939 (Al Viro 2017-06-08 23:27:12 -0400 241) locked_page);
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 242) return tmp != 0;
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 243) }
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 244)
022a6dc5f461a (Evgeniy Dushistov 2006-06-25 05:47:27 -0700 245) /**
022a6dc5f461a (Evgeniy Dushistov 2006-06-25 05:47:27 -0700 246) * ufs_inode_getfrag() - allocate new fragment(s)
edc023caf407b (Fabian Frederick 2014-08-08 14:21:08 -0700 247) * @inode: pointer to inode
5336970be09be (Al Viro 2015-06-19 13:53:52 -0400 248) * @index: number of block pointer within the inode's array.
edc023caf407b (Fabian Frederick 2014-08-08 14:21:08 -0700 249) * @new_fragment: number of new allocated fragment(s)
edc023caf407b (Fabian Frederick 2014-08-08 14:21:08 -0700 250) * @err: we set it if something wrong
edc023caf407b (Fabian Frederick 2014-08-08 14:21:08 -0700 251) * @new: we set it if we allocate new block
edc023caf407b (Fabian Frederick 2014-08-08 14:21:08 -0700 252) * @locked_page: for ufs_new_fragments()
022a6dc5f461a (Evgeniy Dushistov 2006-06-25 05:47:27 -0700 253) */
177848a018cb2 (Al Viro 2015-06-19 00:53:06 -0400 254) static u64
5336970be09be (Al Viro 2015-06-19 13:53:52 -0400 255) ufs_inode_getfrag(struct inode *inode, unsigned index,
5336970be09be (Al Viro 2015-06-19 13:53:52 -0400 256) sector_t new_fragment, int *err,
4e317ce73aecb (Al Viro 2015-06-19 14:27:10 -0400 257) int *new, struct page *locked_page)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 258) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 259) struct ufs_inode_info *ufsi = UFS_I(inode);
022a6dc5f461a (Evgeniy Dushistov 2006-06-25 05:47:27 -0700 260) struct super_block *sb = inode->i_sb;
022a6dc5f461a (Evgeniy Dushistov 2006-06-25 05:47:27 -0700 261) struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
5336970be09be (Al Viro 2015-06-19 13:53:52 -0400 262) u64 tmp, goal, lastfrag;
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 263) unsigned nfrags = uspi->s_fpb;
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 264) void *p;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 265)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 266) /* TODO : to be done for write support
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 267) if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 268) goto ufs2;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 269) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 270)
5336970be09be (Al Viro 2015-06-19 13:53:52 -0400 271) p = ufs_get_direct_data_ptr(uspi, ufsi, index);
54fb996ac15c4 (Evgeniy Dushistov 2007-02-12 00:54:32 -0800 272) tmp = ufs_data_ptr_to_cpu(sb, p);
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 273) if (tmp)
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 274) goto out;
54fb996ac15c4 (Evgeniy Dushistov 2007-02-12 00:54:32 -0800 275)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 276) lastfrag = ufsi->i_lastfrag;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 277)
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 278) /* will that be a new tail? */
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 279) if (new_fragment < UFS_NDIR_FRAGMENT && new_fragment >= lastfrag)
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 280) nfrags = (new_fragment & uspi->s_fpbmask) + 1;
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 281)
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 282) goal = 0;
5336970be09be (Al Viro 2015-06-19 13:53:52 -0400 283) if (index) {
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 284) goal = ufs_data_ptr_to_cpu(sb,
5336970be09be (Al Viro 2015-06-19 13:53:52 -0400 285) ufs_get_direct_data_ptr(uspi, ufsi, index - 1));
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 286) if (goal)
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 287) goal += uspi->s_fpb;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 288) }
5336970be09be (Al Viro 2015-06-19 13:53:52 -0400 289) tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment),
8785d84d002c2 (Al Viro 2017-06-08 02:42:03 -0400 290) goal, nfrags, err, locked_page);
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 291)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 292) if (!tmp) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 293) *err = -ENOSPC;
177848a018cb2 (Al Viro 2015-06-19 00:53:06 -0400 294) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 295) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 296)
4e317ce73aecb (Al Viro 2015-06-19 14:27:10 -0400 297) if (new)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 298) *new = 1;
02027d42c3f74 (Deepa Dinamani 2016-09-14 07:48:05 -0700 299) inode->i_ctime = current_time(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 300) if (IS_SYNC(inode))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 301) ufs_sync_inode (inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 302) mark_inode_dirty(inode);
bbb3eb9d3432c (Al Viro 2015-06-19 00:10:00 -0400 303) out:
177848a018cb2 (Al Viro 2015-06-19 00:53:06 -0400 304) return tmp + uspi->s_sbbase;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 305)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 306) /* This part : To be implemented ....
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 307) Required only for writing, not required for READ-ONLY.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 308) ufs2:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 309)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 310) u2_block = ufs_fragstoblks(fragment);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 311) u2_blockoff = ufs_fragnum(fragment);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 312) p = ufsi->i_u1.u2_i_data + block;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 313) goal = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 314)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 315) repeat2:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 316) tmp = fs32_to_cpu(sb, *p);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 317) lastfrag = ufsi->i_lastfrag;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 318)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 319) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 320) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 321)
022a6dc5f461a (Evgeniy Dushistov 2006-06-25 05:47:27 -0700 322) /**
022a6dc5f461a (Evgeniy Dushistov 2006-06-25 05:47:27 -0700 323) * ufs_inode_getblock() - allocate new block
edc023caf407b (Fabian Frederick 2014-08-08 14:21:08 -0700 324) * @inode: pointer to inode
619cfac09134b (Al Viro 2015-06-19 01:23:08 -0400 325) * @ind_block: block number of the indirect block
619cfac09134b (Al Viro 2015-06-19 01:23:08 -0400 326) * @index: number of pointer within the indirect block
edc023caf407b (Fabian Frederick 2014-08-08 14:21:08 -0700 327) * @new_fragment: number of new allocated fragment
022a6dc5f461a (Evgeniy Dushistov 2006-06-25 05:47:27 -0700 328) * (block will hold this fragment and also uspi->s_fpb-1)
edc023caf407b (Fabian Frederick 2014-08-08 14:21:08 -0700 329) * @err: see ufs_inode_getfrag()
edc023caf407b (Fabian Frederick 2014-08-08 14:21:08 -0700 330) * @new: see ufs_inode_getfrag()
edc023caf407b (Fabian Frederick 2014-08-08 14:21:08 -0700 331) * @locked_page: see ufs_inode_getfrag()
022a6dc5f461a (Evgeniy Dushistov 2006-06-25 05:47:27 -0700 332) */
177848a018cb2 (Al Viro 2015-06-19 00:53:06 -0400 333) static u64
619cfac09134b (Al Viro 2015-06-19 01:23:08 -0400 334) ufs_inode_getblock(struct inode *inode, u64 ind_block,
721435a7679e1 (Al Viro 2015-06-19 01:06:21 -0400 335) unsigned index, sector_t new_fragment, int *err,
4e317ce73aecb (Al Viro 2015-06-19 14:27:10 -0400 336) int *new, struct page *locked_page)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 337) {
022a6dc5f461a (Evgeniy Dushistov 2006-06-25 05:47:27 -0700 338) struct super_block *sb = inode->i_sb;
022a6dc5f461a (Evgeniy Dushistov 2006-06-25 05:47:27 -0700 339) struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
619cfac09134b (Al Viro 2015-06-19 01:23:08 -0400 340) int shift = uspi->s_apbshift - uspi->s_fpbshift;
721435a7679e1 (Al Viro 2015-06-19 01:06:21 -0400 341) u64 tmp = 0, goal;
619cfac09134b (Al Viro 2015-06-19 01:23:08 -0400 342) struct buffer_head *bh;
54fb996ac15c4 (Evgeniy Dushistov 2007-02-12 00:54:32 -0800 343) void *p;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 344)
619cfac09134b (Al Viro 2015-06-19 01:23:08 -0400 345) if (!ind_block)
619cfac09134b (Al Viro 2015-06-19 01:23:08 -0400 346) return 0;
619cfac09134b (Al Viro 2015-06-19 01:23:08 -0400 347)
619cfac09134b (Al Viro 2015-06-19 01:23:08 -0400 348) bh = sb_bread(sb, ind_block + (index >> shift));
5fbfb238f7a0a (Al Viro 2015-06-19 14:10:53 -0400 349) if (unlikely(!bh)) {
5fbfb238f7a0a (Al Viro 2015-06-19 14:10:53 -0400 350) *err = -EIO;
619cfac09134b (Al Viro 2015-06-19 01:23:08 -0400 351) return 0;
5fbfb238f7a0a (Al Viro 2015-06-19 14:10:53 -0400 352) }
619cfac09134b (Al Viro 2015-06-19 01:23:08 -0400 353)
619cfac09134b (Al Viro 2015-06-19 01:23:08 -0400 354) index &= uspi->s_apbmask >> uspi->s_fpbshift;
54fb996ac15c4 (Evgeniy Dushistov 2007-02-12 00:54:32 -0800 355) if (uspi->fs_magic == UFS2_MAGIC)
721435a7679e1 (Al Viro 2015-06-19 01:06:21 -0400 356) p = (__fs64 *)bh->b_data + index;
54fb996ac15c4 (Evgeniy Dushistov 2007-02-12 00:54:32 -0800 357) else
721435a7679e1 (Al Viro 2015-06-19 01:06:21 -0400 358) p = (__fs32 *)bh->b_data + index;
5a39c25562aa5 (Al Viro 2015-06-18 22:39:46 -0400 359)
54fb996ac15c4 (Evgeniy Dushistov 2007-02-12 00:54:32 -0800 360) tmp = ufs_data_ptr_to_cpu(sb, p);
bbb3eb9d3432c (Al Viro 2015-06-19 00:10:00 -0400 361) if (tmp)
5a39c25562aa5 (Al Viro 2015-06-18 22:39:46 -0400 362) goto out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 363)
721435a7679e1 (Al Viro 2015-06-19 01:06:21 -0400 364) if (index && (uspi->fs_magic == UFS2_MAGIC ?
721435a7679e1 (Al Viro 2015-06-19 01:06:21 -0400 365) (tmp = fs64_to_cpu(sb, ((__fs64 *)bh->b_data)[index-1])) :
721435a7679e1 (Al Viro 2015-06-19 01:06:21 -0400 366) (tmp = fs32_to_cpu(sb, ((__fs32 *)bh->b_data)[index-1]))))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 367) goal = tmp + uspi->s_fpb;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 368) else
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 369) goal = bh->b_blocknr + uspi->s_fpb;
6ef4d6bf86a82 (Evgeniy Dushistov 2006-06-25 05:47:20 -0700 370) tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment), goal,
6ef4d6bf86a82 (Evgeniy Dushistov 2006-06-25 05:47:20 -0700 371) uspi->s_fpb, err, locked_page);
5a39c25562aa5 (Al Viro 2015-06-18 22:39:46 -0400 372) if (!tmp)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 373) goto out;
c9a27b5dca52b (Evgeniy Dushistov 2006-06-25 05:47:19 -0700 374)
bbb3eb9d3432c (Al Viro 2015-06-19 00:10:00 -0400 375) if (new)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 376) *new = 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 377)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 378) mark_buffer_dirty(bh);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 379) if (IS_SYNC(inode))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 380) sync_dirty_buffer(bh);
02027d42c3f74 (Deepa Dinamani 2016-09-14 07:48:05 -0700 381) inode->i_ctime = current_time(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 382) mark_inode_dirty(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 383) out:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 384) brelse (bh);
abf5d15fd2e52 (Evgeniy Dushistov 2006-06-25 05:47:24 -0700 385) UFSD("EXIT\n");
177848a018cb2 (Al Viro 2015-06-19 00:53:06 -0400 386) if (tmp)
177848a018cb2 (Al Viro 2015-06-19 00:53:06 -0400 387) tmp += uspi->s_sbbase;
177848a018cb2 (Al Viro 2015-06-19 00:53:06 -0400 388) return tmp;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 389) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 390)
022a6dc5f461a (Evgeniy Dushistov 2006-06-25 05:47:27 -0700 391) /**
7422caa5a1a53 (Alessio Igor Bogani 2011-04-08 19:33:07 +0200 392) * ufs_getfrag_block() - `get_block_t' function, interface between UFS and
022a6dc5f461a (Evgeniy Dushistov 2006-06-25 05:47:27 -0700 393) * readpage, writepage and so on
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 394) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 395)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 396) static int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 397) {
0385f1f9e3e5c (Al Viro 2015-06-19 14:20:21 -0400 398) struct super_block *sb = inode->i_sb;
0385f1f9e3e5c (Al Viro 2015-06-19 14:20:21 -0400 399) struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
0385f1f9e3e5c (Al Viro 2015-06-19 14:20:21 -0400 400) int err = 0, new = 0;
4b7068c8b1784 (Al Viro 2015-06-04 14:27:23 -0400 401) unsigned offsets[4];
4b7068c8b1784 (Al Viro 2015-06-04 14:27:23 -0400 402) int depth = ufs_block_to_path(inode, fragment >> uspi->s_fpbshift, offsets);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 403) u64 phys64 = 0;
177848a018cb2 (Al Viro 2015-06-19 00:53:06 -0400 404) unsigned frag = fragment & uspi->s_fpbmask;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 405)
09bf4f5b6e601 (Al Viro 2017-06-15 00:17:30 -0400 406) phys64 = ufs_frag_map(inode, offsets, depth);
09bf4f5b6e601 (Al Viro 2017-06-15 00:17:30 -0400 407) if (!create)
09bf4f5b6e601 (Al Viro 2017-06-15 00:17:30 -0400 408) goto done;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 409)
09bf4f5b6e601 (Al Viro 2017-06-15 00:17:30 -0400 410) if (phys64) {
09bf4f5b6e601 (Al Viro 2017-06-15 00:17:30 -0400 411) if (fragment >= UFS_NDIR_FRAGMENT)
09bf4f5b6e601 (Al Viro 2017-06-15 00:17:30 -0400 412) goto done;
09bf4f5b6e601 (Al Viro 2017-06-15 00:17:30 -0400 413) read_seqlock_excl(&UFS_I(inode)->meta_lock);
09bf4f5b6e601 (Al Viro 2017-06-15 00:17:30 -0400 414) if (fragment < UFS_I(inode)->i_lastfrag) {
09bf4f5b6e601 (Al Viro 2017-06-15 00:17:30 -0400 415) read_sequnlock_excl(&UFS_I(inode)->meta_lock);
09bf4f5b6e601 (Al Viro 2017-06-15 00:17:30 -0400 416) goto done;
09bf4f5b6e601 (Al Viro 2017-06-15 00:17:30 -0400 417) }
09bf4f5b6e601 (Al Viro 2017-06-15 00:17:30 -0400 418) read_sequnlock_excl(&UFS_I(inode)->meta_lock);
09bf4f5b6e601 (Al Viro 2017-06-15 00:17:30 -0400 419) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 420) /* This code entered only while writing ....? */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 421)
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 422) mutex_lock(&UFS_I(inode)->truncate_mutex);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 423)
abf5d15fd2e52 (Evgeniy Dushistov 2006-06-25 05:47:24 -0700 424) UFSD("ENTER, ino %lu, fragment %llu\n", inode->i_ino, (unsigned long long)fragment);
0385f1f9e3e5c (Al Viro 2015-06-19 14:20:21 -0400 425) if (unlikely(!depth)) {
0385f1f9e3e5c (Al Viro 2015-06-19 14:20:21 -0400 426) ufs_warning(sb, "ufs_get_block", "block > big");
0385f1f9e3e5c (Al Viro 2015-06-19 14:20:21 -0400 427) err = -EIO;
0385f1f9e3e5c (Al Viro 2015-06-19 14:20:21 -0400 428) goto out;
0385f1f9e3e5c (Al Viro 2015-06-19 14:20:21 -0400 429) }
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 430)
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 431) if (UFS_I(inode)->i_lastfrag < UFS_NDIR_FRAGMENT) {
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 432) unsigned lastfrag = UFS_I(inode)->i_lastfrag;
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 433) unsigned tailfrags = lastfrag & uspi->s_fpbmask;
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 434) if (tailfrags && fragment >= lastfrag) {
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 435) if (!ufs_extend_tail(inode, fragment,
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 436) &err, bh_result->b_page))
0385f1f9e3e5c (Al Viro 2015-06-19 14:20:21 -0400 437) goto out;
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 438) }
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 439) }
0f3c1294bedcc (Al Viro 2015-06-19 13:40:25 -0400 440)
71dd42846ffb2 (Al Viro 2015-06-04 14:34:43 -0400 441) if (depth == 1) {
5336970be09be (Al Viro 2015-06-19 13:53:52 -0400 442) phys64 = ufs_inode_getfrag(inode, offsets[0], fragment,
4e317ce73aecb (Al Viro 2015-06-19 14:27:10 -0400 443) &err, &new, bh_result->b_page);
4eeff4c932687 (Al Viro 2015-06-19 14:08:16 -0400 444) } else {
4eeff4c932687 (Al Viro 2015-06-19 14:08:16 -0400 445) int i;
5336970be09be (Al Viro 2015-06-19 13:53:52 -0400 446) phys64 = ufs_inode_getfrag(inode, offsets[0], fragment,
4e317ce73aecb (Al Viro 2015-06-19 14:27:10 -0400 447) &err, NULL, NULL);
4eeff4c932687 (Al Viro 2015-06-19 14:08:16 -0400 448) for (i = 1; i < depth - 1; i++)
4eeff4c932687 (Al Viro 2015-06-19 14:08:16 -0400 449) phys64 = ufs_inode_getblock(inode, phys64, offsets[i],
4e317ce73aecb (Al Viro 2015-06-19 14:27:10 -0400 450) fragment, &err, NULL, NULL);
4eeff4c932687 (Al Viro 2015-06-19 14:08:16 -0400 451) phys64 = ufs_inode_getblock(inode, phys64, offsets[depth - 1],
4e317ce73aecb (Al Viro 2015-06-19 14:27:10 -0400 452) fragment, &err, &new, bh_result->b_page);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 453) }
0385f1f9e3e5c (Al Viro 2015-06-19 14:20:21 -0400 454) out:
177848a018cb2 (Al Viro 2015-06-19 00:53:06 -0400 455) if (phys64) {
177848a018cb2 (Al Viro 2015-06-19 00:53:06 -0400 456) phys64 += frag;
0385f1f9e3e5c (Al Viro 2015-06-19 14:20:21 -0400 457) map_bh(bh_result, sb, phys64);
0385f1f9e3e5c (Al Viro 2015-06-19 14:20:21 -0400 458) if (new)
0385f1f9e3e5c (Al Viro 2015-06-19 14:20:21 -0400 459) set_buffer_new(bh_result);
177848a018cb2 (Al Viro 2015-06-19 00:53:06 -0400 460) }
724bb09fdc06d (Al Viro 2015-06-17 12:02:56 -0400 461) mutex_unlock(&UFS_I(inode)->truncate_mutex);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 462) return err;
09bf4f5b6e601 (Al Viro 2017-06-15 00:17:30 -0400 463)
09bf4f5b6e601 (Al Viro 2017-06-15 00:17:30 -0400 464) done:
09bf4f5b6e601 (Al Viro 2017-06-15 00:17:30 -0400 465) if (phys64)
09bf4f5b6e601 (Al Viro 2017-06-15 00:17:30 -0400 466) map_bh(bh_result, sb, phys64 + frag);
09bf4f5b6e601 (Al Viro 2017-06-15 00:17:30 -0400 467) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 468) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 469)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 470) static int ufs_writepage(struct page *page, struct writeback_control *wbc)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 471) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 472) return block_write_full_page(page,ufs_getfrag_block,wbc);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 473) }
82b9d1d0da804 (Nicholas Piggin 2007-10-16 01:25:19 -0700 474)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 475) static int ufs_readpage(struct file *file, struct page *page)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 476) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 477) return block_read_full_page(page,ufs_getfrag_block);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 478) }
82b9d1d0da804 (Nicholas Piggin 2007-10-16 01:25:19 -0700 479)
f4e420dc42314 (Christoph Hellwig 2010-06-04 11:29:56 +0200 480) int ufs_prepare_chunk(struct page *page, loff_t pos, unsigned len)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 481) {
6e1db88d536ad (Christoph Hellwig 2010-06-04 11:29:57 +0200 482) return __block_write_begin(page, pos, len, ufs_getfrag_block);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 483) }
82b9d1d0da804 (Nicholas Piggin 2007-10-16 01:25:19 -0700 484)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 485) static void ufs_truncate_blocks(struct inode *);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 486)
83f6e3710a932 (Marco Stornelli 2012-12-15 11:45:14 +0100 487) static void ufs_write_failed(struct address_space *mapping, loff_t to)
83f6e3710a932 (Marco Stornelli 2012-12-15 11:45:14 +0100 488) {
83f6e3710a932 (Marco Stornelli 2012-12-15 11:45:14 +0100 489) struct inode *inode = mapping->host;
83f6e3710a932 (Marco Stornelli 2012-12-15 11:45:14 +0100 490)
3b7a3a05e8b00 (Al Viro 2015-06-16 18:06:40 -0400 491) if (to > inode->i_size) {
7caef26767c17 (Kirill A. Shutemov 2013-09-12 15:13:56 -0700 492) truncate_pagecache(inode, inode->i_size);
3b7a3a05e8b00 (Al Viro 2015-06-16 18:06:40 -0400 493) ufs_truncate_blocks(inode);
3b7a3a05e8b00 (Al Viro 2015-06-16 18:06:40 -0400 494) }
83f6e3710a932 (Marco Stornelli 2012-12-15 11:45:14 +0100 495) }
83f6e3710a932 (Marco Stornelli 2012-12-15 11:45:14 +0100 496)
82b9d1d0da804 (Nicholas Piggin 2007-10-16 01:25:19 -0700 497) static int ufs_write_begin(struct file *file, struct address_space *mapping,
82b9d1d0da804 (Nicholas Piggin 2007-10-16 01:25:19 -0700 498) loff_t pos, unsigned len, unsigned flags,
82b9d1d0da804 (Nicholas Piggin 2007-10-16 01:25:19 -0700 499) struct page **pagep, void **fsdata)
82b9d1d0da804 (Nicholas Piggin 2007-10-16 01:25:19 -0700 500) {
155130a4f7848 (Christoph Hellwig 2010-06-04 11:29:58 +0200 501) int ret;
155130a4f7848 (Christoph Hellwig 2010-06-04 11:29:58 +0200 502)
155130a4f7848 (Christoph Hellwig 2010-06-04 11:29:58 +0200 503) ret = block_write_begin(mapping, pos, len, flags, pagep,
f4e420dc42314 (Christoph Hellwig 2010-06-04 11:29:56 +0200 504) ufs_getfrag_block);
83f6e3710a932 (Marco Stornelli 2012-12-15 11:45:14 +0100 505) if (unlikely(ret))
83f6e3710a932 (Marco Stornelli 2012-12-15 11:45:14 +0100 506) ufs_write_failed(mapping, pos + len);
155130a4f7848 (Christoph Hellwig 2010-06-04 11:29:58 +0200 507)
155130a4f7848 (Christoph Hellwig 2010-06-04 11:29:58 +0200 508) return ret;
82b9d1d0da804 (Nicholas Piggin 2007-10-16 01:25:19 -0700 509) }
82b9d1d0da804 (Nicholas Piggin 2007-10-16 01:25:19 -0700 510)
3b7a3a05e8b00 (Al Viro 2015-06-16 18:06:40 -0400 511) static int ufs_write_end(struct file *file, struct address_space *mapping,
3b7a3a05e8b00 (Al Viro 2015-06-16 18:06:40 -0400 512) loff_t pos, unsigned len, unsigned copied,
3b7a3a05e8b00 (Al Viro 2015-06-16 18:06:40 -0400 513) struct page *page, void *fsdata)
3b7a3a05e8b00 (Al Viro 2015-06-16 18:06:40 -0400 514) {
3b7a3a05e8b00 (Al Viro 2015-06-16 18:06:40 -0400 515) int ret;
3b7a3a05e8b00 (Al Viro 2015-06-16 18:06:40 -0400 516)
3b7a3a05e8b00 (Al Viro 2015-06-16 18:06:40 -0400 517) ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
3b7a3a05e8b00 (Al Viro 2015-06-16 18:06:40 -0400 518) if (ret < len)
3b7a3a05e8b00 (Al Viro 2015-06-16 18:06:40 -0400 519) ufs_write_failed(mapping, pos + len);
3b7a3a05e8b00 (Al Viro 2015-06-16 18:06:40 -0400 520) return ret;
3b7a3a05e8b00 (Al Viro 2015-06-16 18:06:40 -0400 521) }
3b7a3a05e8b00 (Al Viro 2015-06-16 18:06:40 -0400 522)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 523) static sector_t ufs_bmap(struct address_space *mapping, sector_t block)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 524) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 525) return generic_block_bmap(mapping,block,ufs_getfrag_block);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 526) }
82b9d1d0da804 (Nicholas Piggin 2007-10-16 01:25:19 -0700 527)
f5e54d6e53a20 (Christoph Hellwig 2006-06-28 04:26:44 -0700 528) const struct address_space_operations ufs_aops = {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 529) .readpage = ufs_readpage,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 530) .writepage = ufs_writepage,
82b9d1d0da804 (Nicholas Piggin 2007-10-16 01:25:19 -0700 531) .write_begin = ufs_write_begin,
3b7a3a05e8b00 (Al Viro 2015-06-16 18:06:40 -0400 532) .write_end = ufs_write_end,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 533) .bmap = ufs_bmap
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 534) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 535)
826843a347cc8 (Evgeniy Dushistov 2006-06-25 05:47:21 -0700 536) static void ufs_set_inode_ops(struct inode *inode)
826843a347cc8 (Evgeniy Dushistov 2006-06-25 05:47:21 -0700 537) {
826843a347cc8 (Evgeniy Dushistov 2006-06-25 05:47:21 -0700 538) if (S_ISREG(inode->i_mode)) {
826843a347cc8 (Evgeniy Dushistov 2006-06-25 05:47:21 -0700 539) inode->i_op = &ufs_file_inode_operations;
826843a347cc8 (Evgeniy Dushistov 2006-06-25 05:47:21 -0700 540) inode->i_fop = &ufs_file_operations;
826843a347cc8 (Evgeniy Dushistov 2006-06-25 05:47:21 -0700 541) inode->i_mapping->a_ops = &ufs_aops;
826843a347cc8 (Evgeniy Dushistov 2006-06-25 05:47:21 -0700 542) } else if (S_ISDIR(inode->i_mode)) {
826843a347cc8 (Evgeniy Dushistov 2006-06-25 05:47:21 -0700 543) inode->i_op = &ufs_dir_inode_operations;
826843a347cc8 (Evgeniy Dushistov 2006-06-25 05:47:21 -0700 544) inode->i_fop = &ufs_dir_operations;
826843a347cc8 (Evgeniy Dushistov 2006-06-25 05:47:21 -0700 545) inode->i_mapping->a_ops = &ufs_aops;
826843a347cc8 (Evgeniy Dushistov 2006-06-25 05:47:21 -0700 546) } else if (S_ISLNK(inode->i_mode)) {
4b8061a67f67e (Al Viro 2015-05-02 10:28:56 -0400 547) if (!inode->i_blocks) {
4b8061a67f67e (Al Viro 2015-05-02 10:28:56 -0400 548) inode->i_link = (char *)UFS_I(inode)->i_u1.i_symlink;
9cdce3c074fbd (Al Viro 2015-11-15 18:24:17 -0500 549) inode->i_op = &simple_symlink_inode_operations;
4b8061a67f67e (Al Viro 2015-05-02 10:28:56 -0400 550) } else {
826843a347cc8 (Evgeniy Dushistov 2006-06-25 05:47:21 -0700 551) inode->i_mapping->a_ops = &ufs_aops;
9cdce3c074fbd (Al Viro 2015-11-15 18:24:17 -0500 552) inode->i_op = &page_symlink_inode_operations;
21fc61c73c390 (Al Viro 2015-11-17 01:07:57 -0500 553) inode_nohighmem(inode);
826843a347cc8 (Evgeniy Dushistov 2006-06-25 05:47:21 -0700 554) }
826843a347cc8 (Evgeniy Dushistov 2006-06-25 05:47:21 -0700 555) } else
826843a347cc8 (Evgeniy Dushistov 2006-06-25 05:47:21 -0700 556) init_special_inode(inode, inode->i_mode,
826843a347cc8 (Evgeniy Dushistov 2006-06-25 05:47:21 -0700 557) ufs_get_inode_dev(inode->i_sb, UFS_I(inode)));
826843a347cc8 (Evgeniy Dushistov 2006-06-25 05:47:21 -0700 558) }
826843a347cc8 (Evgeniy Dushistov 2006-06-25 05:47:21 -0700 559)
07a0cfec30848 (Evgeniy Dushistov 2007-04-16 22:53:24 -0700 560) static int ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 561) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 562) struct ufs_inode_info *ufsi = UFS_I(inode);
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 563) struct super_block *sb = inode->i_sb;
6a9a06d9ca3d3 (Al Viro 2011-07-26 02:49:13 -0400 564) umode_t mode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 565)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 566) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 567) * Copy data to the in-core inode.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 568) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 569) inode->i_mode = mode = fs16_to_cpu(sb, ufs_inode->ui_mode);
bfe8684869601 (Miklos Szeredi 2011-10-28 14:13:29 +0200 570) set_nlink(inode, fs16_to_cpu(sb, ufs_inode->ui_nlink));
c0ef65d292824 (Al Viro 2017-06-16 23:54:47 -0400 571) if (inode->i_nlink == 0)
c0ef65d292824 (Al Viro 2017-06-16 23:54:47 -0400 572) return -ESTALE;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 573)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 574) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 575) * Linux now has 32-bit uid and gid, so we can support EFT.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 576) */
72235465864d8 (Eric W. Biederman 2012-02-10 12:21:22 -0800 577) i_uid_write(inode, ufs_get_inode_uid(sb, ufs_inode));
72235465864d8 (Eric W. Biederman 2012-02-10 12:21:22 -0800 578) i_gid_write(inode, ufs_get_inode_gid(sb, ufs_inode));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 579)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 580) inode->i_size = fs64_to_cpu(sb, ufs_inode->ui_size);
23ac7cba73bb2 (Al Viro 2017-06-16 23:49:17 -0400 581) inode->i_atime.tv_sec = (signed)fs32_to_cpu(sb, ufs_inode->ui_atime.tv_sec);
23ac7cba73bb2 (Al Viro 2017-06-16 23:49:17 -0400 582) inode->i_ctime.tv_sec = (signed)fs32_to_cpu(sb, ufs_inode->ui_ctime.tv_sec);
23ac7cba73bb2 (Al Viro 2017-06-16 23:49:17 -0400 583) inode->i_mtime.tv_sec = (signed)fs32_to_cpu(sb, ufs_inode->ui_mtime.tv_sec);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 584) inode->i_mtime.tv_nsec = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 585) inode->i_atime.tv_nsec = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 586) inode->i_ctime.tv_nsec = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 587) inode->i_blocks = fs32_to_cpu(sb, ufs_inode->ui_blocks);
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 588) inode->i_generation = fs32_to_cpu(sb, ufs_inode->ui_gen);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 589) ufsi->i_flags = fs32_to_cpu(sb, ufs_inode->ui_flags);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 590) ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 591) ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag);
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 592)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 593)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 594) if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) {
f33219b7a90c4 (Duane Griffin 2009-01-08 22:43:49 +0000 595) memcpy(ufsi->i_u1.i_data, &ufs_inode->ui_u2.ui_addr,
f33219b7a90c4 (Duane Griffin 2009-01-08 22:43:49 +0000 596) sizeof(ufs_inode->ui_u2.ui_addr));
dd187a2603d99 (Evgeniy Dushistov 2006-06-25 05:47:25 -0700 597) } else {
f33219b7a90c4 (Duane Griffin 2009-01-08 22:43:49 +0000 598) memcpy(ufsi->i_u1.i_symlink, ufs_inode->ui_u2.ui_symlink,
b12903f1384cd (Duane Griffin 2009-01-08 22:43:50 +0000 599) sizeof(ufs_inode->ui_u2.ui_symlink) - 1);
b12903f1384cd (Duane Griffin 2009-01-08 22:43:50 +0000 600) ufsi->i_u1.i_symlink[sizeof(ufs_inode->ui_u2.ui_symlink) - 1] = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 601) }
07a0cfec30848 (Evgeniy Dushistov 2007-04-16 22:53:24 -0700 602) return 0;
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 603) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 604)
07a0cfec30848 (Evgeniy Dushistov 2007-04-16 22:53:24 -0700 605) static int ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode)
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 606) {
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 607) struct ufs_inode_info *ufsi = UFS_I(inode);
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 608) struct super_block *sb = inode->i_sb;
6a9a06d9ca3d3 (Al Viro 2011-07-26 02:49:13 -0400 609) umode_t mode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 610)
abf5d15fd2e52 (Evgeniy Dushistov 2006-06-25 05:47:24 -0700 611) UFSD("Reading ufs2 inode, ino %lu\n", inode->i_ino);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 612) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 613) * Copy data to the in-core inode.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 614) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 615) inode->i_mode = mode = fs16_to_cpu(sb, ufs2_inode->ui_mode);
bfe8684869601 (Miklos Szeredi 2011-10-28 14:13:29 +0200 616) set_nlink(inode, fs16_to_cpu(sb, ufs2_inode->ui_nlink));
c0ef65d292824 (Al Viro 2017-06-16 23:54:47 -0400 617) if (inode->i_nlink == 0)
c0ef65d292824 (Al Viro 2017-06-16 23:54:47 -0400 618) return -ESTALE;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 619)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 620) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 621) * Linux now has 32-bit uid and gid, so we can support EFT.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 622) */
72235465864d8 (Eric W. Biederman 2012-02-10 12:21:22 -0800 623) i_uid_write(inode, fs32_to_cpu(sb, ufs2_inode->ui_uid));
72235465864d8 (Eric W. Biederman 2012-02-10 12:21:22 -0800 624) i_gid_write(inode, fs32_to_cpu(sb, ufs2_inode->ui_gid));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 625)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 626) inode->i_size = fs64_to_cpu(sb, ufs2_inode->ui_size);
2189850f42bef (Evgeniy Dushistov 2007-03-16 13:38:07 -0800 627) inode->i_atime.tv_sec = fs64_to_cpu(sb, ufs2_inode->ui_atime);
2189850f42bef (Evgeniy Dushistov 2007-03-16 13:38:07 -0800 628) inode->i_ctime.tv_sec = fs64_to_cpu(sb, ufs2_inode->ui_ctime);
2189850f42bef (Evgeniy Dushistov 2007-03-16 13:38:07 -0800 629) inode->i_mtime.tv_sec = fs64_to_cpu(sb, ufs2_inode->ui_mtime);
2189850f42bef (Evgeniy Dushistov 2007-03-16 13:38:07 -0800 630) inode->i_atime.tv_nsec = fs32_to_cpu(sb, ufs2_inode->ui_atimensec);
2189850f42bef (Evgeniy Dushistov 2007-03-16 13:38:07 -0800 631) inode->i_ctime.tv_nsec = fs32_to_cpu(sb, ufs2_inode->ui_ctimensec);
2189850f42bef (Evgeniy Dushistov 2007-03-16 13:38:07 -0800 632) inode->i_mtime.tv_nsec = fs32_to_cpu(sb, ufs2_inode->ui_mtimensec);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 633) inode->i_blocks = fs64_to_cpu(sb, ufs2_inode->ui_blocks);
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 634) inode->i_generation = fs32_to_cpu(sb, ufs2_inode->ui_gen);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 635) ufsi->i_flags = fs32_to_cpu(sb, ufs2_inode->ui_flags);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 636) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 637) ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 638) ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 639) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 640)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 641) if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) {
f33219b7a90c4 (Duane Griffin 2009-01-08 22:43:49 +0000 642) memcpy(ufsi->i_u1.u2_i_data, &ufs2_inode->ui_u2.ui_addr,
f33219b7a90c4 (Duane Griffin 2009-01-08 22:43:49 +0000 643) sizeof(ufs2_inode->ui_u2.ui_addr));
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 644) } else {
f33219b7a90c4 (Duane Griffin 2009-01-08 22:43:49 +0000 645) memcpy(ufsi->i_u1.i_symlink, ufs2_inode->ui_u2.ui_symlink,
b12903f1384cd (Duane Griffin 2009-01-08 22:43:50 +0000 646) sizeof(ufs2_inode->ui_u2.ui_symlink) - 1);
b12903f1384cd (Duane Griffin 2009-01-08 22:43:50 +0000 647) ufsi->i_u1.i_symlink[sizeof(ufs2_inode->ui_u2.ui_symlink) - 1] = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 648) }
07a0cfec30848 (Evgeniy Dushistov 2007-04-16 22:53:24 -0700 649) return 0;
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 650) }
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 651)
b55c460da6df4 (David Howells 2008-02-07 00:15:48 -0800 652) struct inode *ufs_iget(struct super_block *sb, unsigned long ino)
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 653) {
b55c460da6df4 (David Howells 2008-02-07 00:15:48 -0800 654) struct ufs_inode_info *ufsi;
b55c460da6df4 (David Howells 2008-02-07 00:15:48 -0800 655) struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 656) struct buffer_head * bh;
b55c460da6df4 (David Howells 2008-02-07 00:15:48 -0800 657) struct inode *inode;
c0ef65d292824 (Al Viro 2017-06-16 23:54:47 -0400 658) int err = -EIO;
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 659)
b55c460da6df4 (David Howells 2008-02-07 00:15:48 -0800 660) UFSD("ENTER, ino %lu\n", ino);
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 661)
b55c460da6df4 (David Howells 2008-02-07 00:15:48 -0800 662) if (ino < UFS_ROOTINO || ino > (uspi->s_ncg * uspi->s_ipg)) {
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 663) ufs_warning(sb, "ufs_read_inode", "bad inode number (%lu)\n",
b55c460da6df4 (David Howells 2008-02-07 00:15:48 -0800 664) ino);
b55c460da6df4 (David Howells 2008-02-07 00:15:48 -0800 665) return ERR_PTR(-EIO);
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 666) }
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 667)
b55c460da6df4 (David Howells 2008-02-07 00:15:48 -0800 668) inode = iget_locked(sb, ino);
b55c460da6df4 (David Howells 2008-02-07 00:15:48 -0800 669) if (!inode)
b55c460da6df4 (David Howells 2008-02-07 00:15:48 -0800 670) return ERR_PTR(-ENOMEM);
b55c460da6df4 (David Howells 2008-02-07 00:15:48 -0800 671) if (!(inode->i_state & I_NEW))
b55c460da6df4 (David Howells 2008-02-07 00:15:48 -0800 672) return inode;
b55c460da6df4 (David Howells 2008-02-07 00:15:48 -0800 673)
b55c460da6df4 (David Howells 2008-02-07 00:15:48 -0800 674) ufsi = UFS_I(inode);
b55c460da6df4 (David Howells 2008-02-07 00:15:48 -0800 675)
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 676) bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino));
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 677) if (!bh) {
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 678) ufs_warning(sb, "ufs_read_inode", "unable to read inode %lu\n",
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 679) inode->i_ino);
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 680) goto bad_inode;
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 681) }
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 682) if ((UFS_SB(sb)->s_flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 683) struct ufs2_inode *ufs2_inode = (struct ufs2_inode *)bh->b_data;
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 684)
07a0cfec30848 (Evgeniy Dushistov 2007-04-16 22:53:24 -0700 685) err = ufs2_read_inode(inode,
07a0cfec30848 (Evgeniy Dushistov 2007-04-16 22:53:24 -0700 686) ufs2_inode + ufs_inotofsbo(inode->i_ino));
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 687) } else {
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 688) struct ufs_inode *ufs_inode = (struct ufs_inode *)bh->b_data;
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 689)
07a0cfec30848 (Evgeniy Dushistov 2007-04-16 22:53:24 -0700 690) err = ufs1_read_inode(inode,
07a0cfec30848 (Evgeniy Dushistov 2007-04-16 22:53:24 -0700 691) ufs_inode + ufs_inotofsbo(inode->i_ino));
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 692) }
c0ef65d292824 (Al Viro 2017-06-16 23:54:47 -0400 693) brelse(bh);
07a0cfec30848 (Evgeniy Dushistov 2007-04-16 22:53:24 -0700 694) if (err)
07a0cfec30848 (Evgeniy Dushistov 2007-04-16 22:53:24 -0700 695) goto bad_inode;
c0ef65d292824 (Al Viro 2017-06-16 23:54:47 -0400 696)
bb8c2d66bc6f7 (Jeff Layton 2017-12-11 06:35:18 -0500 697) inode_inc_iversion(inode);
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 698) ufsi->i_lastfrag =
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 699) (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift;
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 700) ufsi->i_dir_start_lookup = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 701) ufsi->i_osync = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 702)
826843a347cc8 (Evgeniy Dushistov 2006-06-25 05:47:21 -0700 703) ufs_set_inode_ops(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 704)
abf5d15fd2e52 (Evgeniy Dushistov 2006-06-25 05:47:24 -0700 705) UFSD("EXIT\n");
b55c460da6df4 (David Howells 2008-02-07 00:15:48 -0800 706) unlock_new_inode(inode);
b55c460da6df4 (David Howells 2008-02-07 00:15:48 -0800 707) return inode;
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 708)
05f225dc8729d (Evgeniy Dushistov 2006-06-27 02:53:59 -0700 709) bad_inode:
b55c460da6df4 (David Howells 2008-02-07 00:15:48 -0800 710) iget_failed(inode);
c0ef65d292824 (Al Viro 2017-06-16 23:54:47 -0400 711) return ERR_PTR(err);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 712) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 713)
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 714) static void ufs1_update_inode(struct inode *inode, struct ufs_inode *ufs_inode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 715) {
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 716) struct super_block *sb = inode->i_sb;
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 717) struct ufs_inode_info *ufsi = UFS_I(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 718)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 719) ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 720) ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 721)
72235465864d8 (Eric W. Biederman 2012-02-10 12:21:22 -0800 722) ufs_set_inode_uid(sb, ufs_inode, i_uid_read(inode));
72235465864d8 (Eric W. Biederman 2012-02-10 12:21:22 -0800 723) ufs_set_inode_gid(sb, ufs_inode, i_gid_read(inode));
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 724)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 725) ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 726) ufs_inode->ui_atime.tv_sec = cpu_to_fs32(sb, inode->i_atime.tv_sec);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 727) ufs_inode->ui_atime.tv_usec = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 728) ufs_inode->ui_ctime.tv_sec = cpu_to_fs32(sb, inode->i_ctime.tv_sec);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 729) ufs_inode->ui_ctime.tv_usec = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 730) ufs_inode->ui_mtime.tv_sec = cpu_to_fs32(sb, inode->i_mtime.tv_sec);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 731) ufs_inode->ui_mtime.tv_usec = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 732) ufs_inode->ui_blocks = cpu_to_fs32(sb, inode->i_blocks);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 733) ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags);
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 734) ufs_inode->ui_gen = cpu_to_fs32(sb, inode->i_generation);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 735)
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 736) if ((UFS_SB(sb)->s_flags & UFS_UID_MASK) == UFS_UID_EFT) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 737) ufs_inode->ui_u3.ui_sun.ui_shadow = cpu_to_fs32(sb, ufsi->i_shadow);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 738) ufs_inode->ui_u3.ui_sun.ui_oeftflag = cpu_to_fs32(sb, ufsi->i_oeftflag);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 739) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 740)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 741) if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 742) /* ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev); */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 743) ufs_inode->ui_u2.ui_addr.ui_db[0] = ufsi->i_u1.i_data[0];
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 744) } else if (inode->i_blocks) {
f33219b7a90c4 (Duane Griffin 2009-01-08 22:43:49 +0000 745) memcpy(&ufs_inode->ui_u2.ui_addr, ufsi->i_u1.i_data,
f33219b7a90c4 (Duane Griffin 2009-01-08 22:43:49 +0000 746) sizeof(ufs_inode->ui_u2.ui_addr));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 747) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 748) else {
f33219b7a90c4 (Duane Griffin 2009-01-08 22:43:49 +0000 749) memcpy(&ufs_inode->ui_u2.ui_symlink, ufsi->i_u1.i_symlink,
f33219b7a90c4 (Duane Griffin 2009-01-08 22:43:49 +0000 750) sizeof(ufs_inode->ui_u2.ui_symlink));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 751) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 752)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 753) if (!inode->i_nlink)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 754) memset (ufs_inode, 0, sizeof(struct ufs_inode));
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 755) }
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 756)
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 757) static void ufs2_update_inode(struct inode *inode, struct ufs2_inode *ufs_inode)
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 758) {
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 759) struct super_block *sb = inode->i_sb;
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 760) struct ufs_inode_info *ufsi = UFS_I(inode);
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 761)
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 762) UFSD("ENTER\n");
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 763) ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode);
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 764) ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink);
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 765)
72235465864d8 (Eric W. Biederman 2012-02-10 12:21:22 -0800 766) ufs_inode->ui_uid = cpu_to_fs32(sb, i_uid_read(inode));
72235465864d8 (Eric W. Biederman 2012-02-10 12:21:22 -0800 767) ufs_inode->ui_gid = cpu_to_fs32(sb, i_gid_read(inode));
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 768)
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 769) ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size);
2189850f42bef (Evgeniy Dushistov 2007-03-16 13:38:07 -0800 770) ufs_inode->ui_atime = cpu_to_fs64(sb, inode->i_atime.tv_sec);
2189850f42bef (Evgeniy Dushistov 2007-03-16 13:38:07 -0800 771) ufs_inode->ui_atimensec = cpu_to_fs32(sb, inode->i_atime.tv_nsec);
2189850f42bef (Evgeniy Dushistov 2007-03-16 13:38:07 -0800 772) ufs_inode->ui_ctime = cpu_to_fs64(sb, inode->i_ctime.tv_sec);
2189850f42bef (Evgeniy Dushistov 2007-03-16 13:38:07 -0800 773) ufs_inode->ui_ctimensec = cpu_to_fs32(sb, inode->i_ctime.tv_nsec);
2189850f42bef (Evgeniy Dushistov 2007-03-16 13:38:07 -0800 774) ufs_inode->ui_mtime = cpu_to_fs64(sb, inode->i_mtime.tv_sec);
2189850f42bef (Evgeniy Dushistov 2007-03-16 13:38:07 -0800 775) ufs_inode->ui_mtimensec = cpu_to_fs32(sb, inode->i_mtime.tv_nsec);
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 776)
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 777) ufs_inode->ui_blocks = cpu_to_fs64(sb, inode->i_blocks);
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 778) ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags);
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 779) ufs_inode->ui_gen = cpu_to_fs32(sb, inode->i_generation);
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 780)
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 781) if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 782) /* ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev); */
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 783) ufs_inode->ui_u2.ui_addr.ui_db[0] = ufsi->i_u1.u2_i_data[0];
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 784) } else if (inode->i_blocks) {
f33219b7a90c4 (Duane Griffin 2009-01-08 22:43:49 +0000 785) memcpy(&ufs_inode->ui_u2.ui_addr, ufsi->i_u1.u2_i_data,
f33219b7a90c4 (Duane Griffin 2009-01-08 22:43:49 +0000 786) sizeof(ufs_inode->ui_u2.ui_addr));
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 787) } else {
f33219b7a90c4 (Duane Griffin 2009-01-08 22:43:49 +0000 788) memcpy(&ufs_inode->ui_u2.ui_symlink, ufsi->i_u1.i_symlink,
f33219b7a90c4 (Duane Griffin 2009-01-08 22:43:49 +0000 789) sizeof(ufs_inode->ui_u2.ui_symlink));
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 790) }
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 791)
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 792) if (!inode->i_nlink)
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 793) memset (ufs_inode, 0, sizeof(struct ufs2_inode));
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 794) UFSD("EXIT\n");
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 795) }
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 796)
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 797) static int ufs_update_inode(struct inode * inode, int do_sync)
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 798) {
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 799) struct super_block *sb = inode->i_sb;
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 800) struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 801) struct buffer_head * bh;
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 802)
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 803) UFSD("ENTER, ino %lu\n", inode->i_ino);
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 804)
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 805) if (inode->i_ino < UFS_ROOTINO ||
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 806) inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) {
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 807) ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino);
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 808) return -1;
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 809) }
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 810)
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 811) bh = sb_bread(sb, ufs_inotofsba(inode->i_ino));
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 812) if (!bh) {
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 813) ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino);
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 814) return -1;
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 815) }
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 816) if (uspi->fs_magic == UFS2_MAGIC) {
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 817) struct ufs2_inode *ufs2_inode = (struct ufs2_inode *)bh->b_data;
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 818)
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 819) ufs2_update_inode(inode,
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 820) ufs2_inode + ufs_inotofsbo(inode->i_ino));
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 821) } else {
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 822) struct ufs_inode *ufs_inode = (struct ufs_inode *) bh->b_data;
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 823)
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 824) ufs1_update_inode(inode, ufs_inode + ufs_inotofsbo(inode->i_ino));
3313e29267414 (Evgeniy Dushistov 2007-02-12 00:54:31 -0800 825) }
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 826)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 827) mark_buffer_dirty(bh);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 828) if (do_sync)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 829) sync_dirty_buffer(bh);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 830) brelse (bh);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 831)
abf5d15fd2e52 (Evgeniy Dushistov 2006-06-25 05:47:24 -0700 832) UFSD("EXIT\n");
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 833) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 834) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 835)
a9185b41a4f84 (Christoph Hellwig 2010-03-05 09:21:37 +0100 836) int ufs_write_inode(struct inode *inode, struct writeback_control *wbc)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 837) {
f3e0f3da1b65e (Al Viro 2015-06-16 02:35:14 -0400 838) return ufs_update_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 839) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 840)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 841) int ufs_sync_inode (struct inode *inode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 842) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 843) return ufs_update_inode (inode, 1);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 844) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 845)
58e8268c7bae5 (Al Viro 2010-06-05 19:40:56 -0400 846) void ufs_evict_inode(struct inode * inode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 847) {
58e8268c7bae5 (Al Viro 2010-06-05 19:40:56 -0400 848) int want_delete = 0;
58e8268c7bae5 (Al Viro 2010-06-05 19:40:56 -0400 849)
58e8268c7bae5 (Al Viro 2010-06-05 19:40:56 -0400 850) if (!inode->i_nlink && !is_bad_inode(inode))
58e8268c7bae5 (Al Viro 2010-06-05 19:40:56 -0400 851) want_delete = 1;
10e5dce07e6f8 (Evgeniy Dushistov 2006-07-01 04:36:24 -0700 852)
91b0abe36a7b2 (Johannes Weiner 2014-04-03 14:47:49 -0700 853) truncate_inode_pages_final(&inode->i_data);
58e8268c7bae5 (Al Viro 2010-06-05 19:40:56 -0400 854) if (want_delete) {
58e8268c7bae5 (Al Viro 2010-06-05 19:40:56 -0400 855) inode->i_size = 0;
babef37dccbaa (Al Viro 2017-06-09 16:20:34 -0400 856) if (inode->i_blocks &&
babef37dccbaa (Al Viro 2017-06-09 16:20:34 -0400 857) (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
babef37dccbaa (Al Viro 2017-06-09 16:20:34 -0400 858) S_ISLNK(inode->i_mode)))
d622f167b8435 (Al Viro 2015-06-16 18:04:16 -0400 859) ufs_truncate_blocks(inode);
67a70017fa0a1 (Al Viro 2017-06-10 12:01:50 -0400 860) ufs_update_inode(inode, inode_needs_sync(inode));
58e8268c7bae5 (Al Viro 2010-06-05 19:40:56 -0400 861) }
58e8268c7bae5 (Al Viro 2010-06-05 19:40:56 -0400 862)
58e8268c7bae5 (Al Viro 2010-06-05 19:40:56 -0400 863) invalidate_inode_buffers(inode);
dbd5768f87ff6 (Jan Kara 2012-05-03 14:48:02 +0200 864) clear_inode(inode);
58e8268c7bae5 (Al Viro 2010-06-05 19:40:56 -0400 865)
f3e0f3da1b65e (Al Viro 2015-06-16 02:35:14 -0400 866) if (want_delete)
9ef7db7f38d04 (Alexey Khoroshilov 2014-09-02 11:40:17 +0400 867) ufs_free_inode(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 868) }
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 869)
a138b4b688c10 (Al Viro 2015-06-18 02:18:54 -0400 870) struct to_free {
a138b4b688c10 (Al Viro 2015-06-18 02:18:54 -0400 871) struct inode *inode;
a138b4b688c10 (Al Viro 2015-06-18 02:18:54 -0400 872) u64 to;
a138b4b688c10 (Al Viro 2015-06-18 02:18:54 -0400 873) unsigned count;
a138b4b688c10 (Al Viro 2015-06-18 02:18:54 -0400 874) };
a138b4b688c10 (Al Viro 2015-06-18 02:18:54 -0400 875)
a138b4b688c10 (Al Viro 2015-06-18 02:18:54 -0400 876) static inline void free_data(struct to_free *ctx, u64 from, unsigned count)
a138b4b688c10 (Al Viro 2015-06-18 02:18:54 -0400 877) {
a138b4b688c10 (Al Viro 2015-06-18 02:18:54 -0400 878) if (ctx->count && ctx->to != from) {
a138b4b688c10 (Al Viro 2015-06-18 02:18:54 -0400 879) ufs_free_blocks(ctx->inode, ctx->to - ctx->count, ctx->count);
a138b4b688c10 (Al Viro 2015-06-18 02:18:54 -0400 880) ctx->count = 0;
a138b4b688c10 (Al Viro 2015-06-18 02:18:54 -0400 881) }
a138b4b688c10 (Al Viro 2015-06-18 02:18:54 -0400 882) ctx->count += count;
a138b4b688c10 (Al Viro 2015-06-18 02:18:54 -0400 883) ctx->to = from + count;
a138b4b688c10 (Al Viro 2015-06-18 02:18:54 -0400 884) }
a138b4b688c10 (Al Viro 2015-06-18 02:18:54 -0400 885)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 886) #define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 887)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 888) static void ufs_trunc_direct(struct inode *inode)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 889) {
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 890) struct ufs_inode_info *ufsi = UFS_I(inode);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 891) struct super_block * sb;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 892) struct ufs_sb_private_info * uspi;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 893) void *p;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 894) u64 frag1, frag2, frag3, frag4, block1, block2;
a138b4b688c10 (Al Viro 2015-06-18 02:18:54 -0400 895) struct to_free ctx = {.inode = inode};
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 896) unsigned i, tmp;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 897)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 898) UFSD("ENTER: ino %lu\n", inode->i_ino);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 899)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 900) sb = inode->i_sb;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 901) uspi = UFS_SB(sb)->s_uspi;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 902)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 903) frag1 = DIRECT_FRAGMENT;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 904) frag4 = min_t(u64, UFS_NDIR_FRAGMENT, ufsi->i_lastfrag);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 905) frag2 = ((frag1 & uspi->s_fpbmask) ? ((frag1 | uspi->s_fpbmask) + 1) : frag1);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 906) frag3 = frag4 & ~uspi->s_fpbmask;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 907) block1 = block2 = 0;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 908) if (frag2 > frag3) {
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 909) frag2 = frag4;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 910) frag3 = frag4 = 0;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 911) } else if (frag2 < frag3) {
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 912) block1 = ufs_fragstoblks (frag2);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 913) block2 = ufs_fragstoblks (frag3);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 914) }
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 915)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 916) UFSD("ino %lu, frag1 %llu, frag2 %llu, block1 %llu, block2 %llu,"
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 917) " frag3 %llu, frag4 %llu\n", inode->i_ino,
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 918) (unsigned long long)frag1, (unsigned long long)frag2,
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 919) (unsigned long long)block1, (unsigned long long)block2,
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 920) (unsigned long long)frag3, (unsigned long long)frag4);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 921)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 922) if (frag1 >= frag2)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 923) goto next1;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 924)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 925) /*
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 926) * Free first free fragments
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 927) */
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 928) p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag1));
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 929) tmp = ufs_data_ptr_to_cpu(sb, p);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 930) if (!tmp )
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 931) ufs_panic (sb, "ufs_trunc_direct", "internal error");
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 932) frag2 -= frag1;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 933) frag1 = ufs_fragnum (frag1);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 934)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 935) ufs_free_fragments(inode, tmp + frag1, frag2);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 936)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 937) next1:
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 938) /*
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 939) * Free whole blocks
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 940) */
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 941) for (i = block1 ; i < block2; i++) {
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 942) p = ufs_get_direct_data_ptr(uspi, ufsi, i);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 943) tmp = ufs_data_ptr_to_cpu(sb, p);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 944) if (!tmp)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 945) continue;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 946) write_seqlock(&ufsi->meta_lock);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 947) ufs_data_ptr_clear(uspi, p);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 948) write_sequnlock(&ufsi->meta_lock);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 949)
a138b4b688c10 (Al Viro 2015-06-18 02:18:54 -0400 950) free_data(&ctx, tmp, uspi->s_fpb);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 951) }
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 952)
a138b4b688c10 (Al Viro 2015-06-18 02:18:54 -0400 953) free_data(&ctx, 0, 0);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 954)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 955) if (frag3 >= frag4)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 956) goto next3;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 957)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 958) /*
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 959) * Free last free fragments
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 960) */
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 961) p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag3));
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 962) tmp = ufs_data_ptr_to_cpu(sb, p);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 963) if (!tmp )
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 964) ufs_panic(sb, "ufs_truncate_direct", "internal error");
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 965) frag4 = ufs_fragnum (frag4);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 966) write_seqlock(&ufsi->meta_lock);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 967) ufs_data_ptr_clear(uspi, p);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 968) write_sequnlock(&ufsi->meta_lock);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 969)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 970) ufs_free_fragments (inode, tmp, frag4);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 971) next3:
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 972)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 973) UFSD("EXIT: ino %lu\n", inode->i_ino);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 974) }
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 975)
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 976) static void free_full_branch(struct inode *inode, u64 ind_block, int depth)
6d1ebbca2b2fe (Al Viro 2015-06-18 17:11:49 -0400 977) {
6d1ebbca2b2fe (Al Viro 2015-06-18 17:11:49 -0400 978) struct super_block *sb = inode->i_sb;
6d1ebbca2b2fe (Al Viro 2015-06-18 17:11:49 -0400 979) struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 980) struct ufs_buffer_head *ubh = ubh_bread(sb, ind_block, uspi->s_bsize);
6d1ebbca2b2fe (Al Viro 2015-06-18 17:11:49 -0400 981) unsigned i;
6d1ebbca2b2fe (Al Viro 2015-06-18 17:11:49 -0400 982)
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 983) if (!ubh)
6d1ebbca2b2fe (Al Viro 2015-06-18 17:11:49 -0400 984) return;
6d1ebbca2b2fe (Al Viro 2015-06-18 17:11:49 -0400 985)
6d1ebbca2b2fe (Al Viro 2015-06-18 17:11:49 -0400 986) if (--depth) {
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 987) for (i = 0; i < uspi->s_apb; i++) {
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 988) void *p = ubh_get_data_ptr(uspi, ubh, i);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 989) u64 block = ufs_data_ptr_to_cpu(sb, p);
cc7231e30916f (Al Viro 2015-06-18 20:14:02 -0400 990) if (block)
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 991) free_full_branch(inode, block, depth);
6d1ebbca2b2fe (Al Viro 2015-06-18 17:11:49 -0400 992) }
6d1ebbca2b2fe (Al Viro 2015-06-18 17:11:49 -0400 993) } else {
6d1ebbca2b2fe (Al Viro 2015-06-18 17:11:49 -0400 994) struct to_free ctx = {.inode = inode};
6d1ebbca2b2fe (Al Viro 2015-06-18 17:11:49 -0400 995)
6d1ebbca2b2fe (Al Viro 2015-06-18 17:11:49 -0400 996) for (i = 0; i < uspi->s_apb; i++) {
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 997) void *p = ubh_get_data_ptr(uspi, ubh, i);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 998) u64 block = ufs_data_ptr_to_cpu(sb, p);
cc7231e30916f (Al Viro 2015-06-18 20:14:02 -0400 999) if (block)
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1000) free_data(&ctx, block, uspi->s_fpb);
6d1ebbca2b2fe (Al Viro 2015-06-18 17:11:49 -0400 1001) }
6d1ebbca2b2fe (Al Viro 2015-06-18 17:11:49 -0400 1002) free_data(&ctx, 0, 0);
6d1ebbca2b2fe (Al Viro 2015-06-18 17:11:49 -0400 1003) }
6d1ebbca2b2fe (Al Viro 2015-06-18 17:11:49 -0400 1004)
6d1ebbca2b2fe (Al Viro 2015-06-18 17:11:49 -0400 1005) ubh_bforget(ubh);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1006) ufs_free_blocks(inode, ind_block, uspi->s_fpb);
6d1ebbca2b2fe (Al Viro 2015-06-18 17:11:49 -0400 1007) }
6d1ebbca2b2fe (Al Viro 2015-06-18 17:11:49 -0400 1008)
7b4e4f7f815db (Al Viro 2015-06-18 19:13:02 -0400 1009) static void free_branch_tail(struct inode *inode, unsigned from, struct ufs_buffer_head *ubh, int depth)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1010) {
7bad5939fcd04 (Al Viro 2015-06-18 14:21:09 -0400 1011) struct super_block *sb = inode->i_sb;
7bad5939fcd04 (Al Viro 2015-06-18 14:21:09 -0400 1012) struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
7bad5939fcd04 (Al Viro 2015-06-18 14:21:09 -0400 1013) unsigned i;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1014)
9e0fbbde2724d (Al Viro 2015-06-18 15:33:47 -0400 1015) if (--depth) {
7b4e4f7f815db (Al Viro 2015-06-18 19:13:02 -0400 1016) for (i = from; i < uspi->s_apb ; i++) {
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1017) void *p = ubh_get_data_ptr(uspi, ubh, i);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1018) u64 block = ufs_data_ptr_to_cpu(sb, p);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1019) if (block) {
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1020) write_seqlock(&UFS_I(inode)->meta_lock);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1021) ufs_data_ptr_clear(uspi, p);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1022) write_sequnlock(&UFS_I(inode)->meta_lock);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1023) ubh_mark_buffer_dirty(ubh);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1024) free_full_branch(inode, block, depth);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1025) }
a96574233c5d2 (Al Viro 2015-06-18 16:13:56 -0400 1026) }
9e0fbbde2724d (Al Viro 2015-06-18 15:33:47 -0400 1027) } else {
a138b4b688c10 (Al Viro 2015-06-18 02:18:54 -0400 1028) struct to_free ctx = {.inode = inode};
9e0fbbde2724d (Al Viro 2015-06-18 15:33:47 -0400 1029)
9e0fbbde2724d (Al Viro 2015-06-18 15:33:47 -0400 1030) for (i = from; i < uspi->s_apb; i++) {
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1031) void *p = ubh_get_data_ptr(uspi, ubh, i);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1032) u64 block = ufs_data_ptr_to_cpu(sb, p);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1033) if (block) {
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1034) write_seqlock(&UFS_I(inode)->meta_lock);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1035) ufs_data_ptr_clear(uspi, p);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1036) write_sequnlock(&UFS_I(inode)->meta_lock);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1037) ubh_mark_buffer_dirty(ubh);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1038) free_data(&ctx, block, uspi->s_fpb);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1039) }
9e0fbbde2724d (Al Viro 2015-06-18 15:33:47 -0400 1040) }
a138b4b688c10 (Al Viro 2015-06-18 02:18:54 -0400 1041) free_data(&ctx, 0, 0);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1042) }
9e0fbbde2724d (Al Viro 2015-06-18 15:33:47 -0400 1043) if (IS_SYNC(inode) && ubh_buffer_dirty(ubh))
9e0fbbde2724d (Al Viro 2015-06-18 15:33:47 -0400 1044) ubh_sync_block(ubh);
9e0fbbde2724d (Al Viro 2015-06-18 15:33:47 -0400 1045) ubh_brelse(ubh);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1046) }
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1047)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1048) static int ufs_alloc_lastblock(struct inode *inode, loff_t size)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1049) {
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1050) int err = 0;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1051) struct super_block *sb = inode->i_sb;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1052) struct address_space *mapping = inode->i_mapping;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1053) struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1054) unsigned i, end;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1055) sector_t lastfrag;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1056) struct page *lastpage;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1057) struct buffer_head *bh;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1058) u64 phys64;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1059)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1060) lastfrag = (size + uspi->s_fsize - 1) >> uspi->s_fshift;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1061)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1062) if (!lastfrag)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1063) goto out;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1064)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1065) lastfrag--;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1066)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1067) lastpage = ufs_get_locked_page(mapping, lastfrag >>
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1068) (PAGE_SHIFT - inode->i_blkbits));
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1069) if (IS_ERR(lastpage)) {
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1070) err = -EIO;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1071) goto out;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1072) }
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1073)
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1074) end = lastfrag & ((1 << (PAGE_SHIFT - inode->i_blkbits)) - 1);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1075) bh = page_buffers(lastpage);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1076) for (i = 0; i < end; ++i)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1077) bh = bh->b_this_page;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1078)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1079)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1080) err = ufs_getfrag_block(inode, lastfrag, bh, 1);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1081)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1082) if (unlikely(err))
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1083) goto out_unlock;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1084)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1085) if (buffer_new(bh)) {
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1086) clear_buffer_new(bh);
e64855c6cfaa0 (Jan Kara 2016-11-04 18:08:15 +0100 1087) clean_bdev_bh_alias(bh);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1088) /*
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1089) * we do not zeroize fragment, because of
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1090) * if it maped to hole, it already contains zeroes
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1091) */
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1092) set_buffer_uptodate(bh);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1093) mark_buffer_dirty(bh);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1094) set_page_dirty(lastpage);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1095) }
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1096)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1097) if (lastfrag >= UFS_IND_FRAGMENT) {
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1098) end = uspi->s_fpb - ufs_fragnum(lastfrag) - 1;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1099) phys64 = bh->b_blocknr + 1;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1100) for (i = 0; i < end; ++i) {
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1101) bh = sb_getblk(sb, i + phys64);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1102) lock_buffer(bh);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1103) memset(bh->b_data, 0, sb->s_blocksize);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1104) set_buffer_uptodate(bh);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1105) mark_buffer_dirty(bh);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1106) unlock_buffer(bh);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1107) sync_dirty_buffer(bh);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1108) brelse(bh);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1109) }
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1110) }
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1111) out_unlock:
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1112) ufs_put_locked_page(lastpage);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1113) out:
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1114) return err;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1115) }
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1116)
babef37dccbaa (Al Viro 2017-06-09 16:20:34 -0400 1117) static void ufs_truncate_blocks(struct inode *inode)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1118) {
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1119) struct ufs_inode_info *ufsi = UFS_I(inode);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1120) struct super_block *sb = inode->i_sb;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1121) struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
7bad5939fcd04 (Al Viro 2015-06-18 14:21:09 -0400 1122) unsigned offsets[4];
a8fad98483383 (Al Viro 2017-06-15 03:57:46 -0400 1123) int depth;
6775e24d9ccf6 (Al Viro 2015-06-18 14:55:50 -0400 1124) int depth2;
42432739b5902 (Al Viro 2015-06-18 15:47:17 -0400 1125) unsigned i;
7b4e4f7f815db (Al Viro 2015-06-18 19:13:02 -0400 1126) struct ufs_buffer_head *ubh[3];
7b4e4f7f815db (Al Viro 2015-06-18 19:13:02 -0400 1127) void *p;
7b4e4f7f815db (Al Viro 2015-06-18 19:13:02 -0400 1128) u64 block;
6775e24d9ccf6 (Al Viro 2015-06-18 14:55:50 -0400 1129)
a8fad98483383 (Al Viro 2017-06-15 03:57:46 -0400 1130) if (inode->i_size) {
a8fad98483383 (Al Viro 2017-06-15 03:57:46 -0400 1131) sector_t last = (inode->i_size - 1) >> uspi->s_bshift;
a8fad98483383 (Al Viro 2017-06-15 03:57:46 -0400 1132) depth = ufs_block_to_path(inode, last, offsets);
a8fad98483383 (Al Viro 2017-06-15 03:57:46 -0400 1133) if (!depth)
a8fad98483383 (Al Viro 2017-06-15 03:57:46 -0400 1134) return;
a8fad98483383 (Al Viro 2017-06-15 03:57:46 -0400 1135) } else {
a8fad98483383 (Al Viro 2017-06-15 03:57:46 -0400 1136) depth = 1;
a8fad98483383 (Al Viro 2017-06-15 03:57:46 -0400 1137) }
6775e24d9ccf6 (Al Viro 2015-06-18 14:55:50 -0400 1138)
6775e24d9ccf6 (Al Viro 2015-06-18 14:55:50 -0400 1139) for (depth2 = depth - 1; depth2; depth2--)
a8fad98483383 (Al Viro 2017-06-15 03:57:46 -0400 1140) if (offsets[depth2] != uspi->s_apb - 1)
6775e24d9ccf6 (Al Viro 2015-06-18 14:55:50 -0400 1141) break;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1142)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1143) mutex_lock(&ufsi->truncate_mutex);
42432739b5902 (Al Viro 2015-06-18 15:47:17 -0400 1144) if (depth == 1) {
31cd043e1a09c (Al Viro 2015-06-17 01:10:03 -0400 1145) ufs_trunc_direct(inode);
42432739b5902 (Al Viro 2015-06-18 15:47:17 -0400 1146) offsets[0] = UFS_IND_BLOCK;
42432739b5902 (Al Viro 2015-06-18 15:47:17 -0400 1147) } else {
7b4e4f7f815db (Al Viro 2015-06-18 19:13:02 -0400 1148) /* get the blocks that should be partially emptied */
a8fad98483383 (Al Viro 2017-06-15 03:57:46 -0400 1149) p = ufs_get_direct_data_ptr(uspi, ufsi, offsets[0]++);
7b4e4f7f815db (Al Viro 2015-06-18 19:13:02 -0400 1150) for (i = 0; i < depth2; i++) {
7b4e4f7f815db (Al Viro 2015-06-18 19:13:02 -0400 1151) block = ufs_data_ptr_to_cpu(sb, p);
7b4e4f7f815db (Al Viro 2015-06-18 19:13:02 -0400 1152) if (!block)
7b4e4f7f815db (Al Viro 2015-06-18 19:13:02 -0400 1153) break;
7b4e4f7f815db (Al Viro 2015-06-18 19:13:02 -0400 1154) ubh[i] = ubh_bread(sb, block, uspi->s_bsize);
7b4e4f7f815db (Al Viro 2015-06-18 19:13:02 -0400 1155) if (!ubh[i]) {
7b4e4f7f815db (Al Viro 2015-06-18 19:13:02 -0400 1156) write_seqlock(&ufsi->meta_lock);
7b4e4f7f815db (Al Viro 2015-06-18 19:13:02 -0400 1157) ufs_data_ptr_clear(uspi, p);
7b4e4f7f815db (Al Viro 2015-06-18 19:13:02 -0400 1158) write_sequnlock(&ufsi->meta_lock);
7b4e4f7f815db (Al Viro 2015-06-18 19:13:02 -0400 1159) break;
7b4e4f7f815db (Al Viro 2015-06-18 19:13:02 -0400 1160) }
a8fad98483383 (Al Viro 2017-06-15 03:57:46 -0400 1161) p = ubh_get_data_ptr(uspi, ubh[i], offsets[i + 1]++);
7b4e4f7f815db (Al Viro 2015-06-18 19:13:02 -0400 1162) }
f53bd1421b3eb (Al Viro 2015-06-18 20:17:32 -0400 1163) while (i--)
7b4e4f7f815db (Al Viro 2015-06-18 19:13:02 -0400 1164) free_branch_tail(inode, offsets[i + 1], ubh[i], depth - i - 1);
42432739b5902 (Al Viro 2015-06-18 15:47:17 -0400 1165) }
42432739b5902 (Al Viro 2015-06-18 15:47:17 -0400 1166) for (i = offsets[0]; i <= UFS_TIND_BLOCK; i++) {
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1167) p = ufs_get_direct_data_ptr(uspi, ufsi, i);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1168) block = ufs_data_ptr_to_cpu(sb, p);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1169) if (block) {
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1170) write_seqlock(&ufsi->meta_lock);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1171) ufs_data_ptr_clear(uspi, p);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1172) write_sequnlock(&ufsi->meta_lock);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1173) free_full_branch(inode, block, i - UFS_IND_BLOCK + 1);
163073db51930 (Al Viro 2015-06-18 20:07:08 -0400 1174) }
31cd043e1a09c (Al Viro 2015-06-17 01:10:03 -0400 1175) }
09bf4f5b6e601 (Al Viro 2017-06-15 00:17:30 -0400 1176) read_seqlock_excl(&ufsi->meta_lock);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1177) ufsi->i_lastfrag = DIRECT_FRAGMENT;
09bf4f5b6e601 (Al Viro 2017-06-15 00:17:30 -0400 1178) read_sequnlock_excl(&ufsi->meta_lock);
b6eede0ec642d (Al Viro 2015-06-18 20:09:39 -0400 1179) mark_inode_dirty(inode);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1180) mutex_unlock(&ufsi->truncate_mutex);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1181) }
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1182)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1183) static int ufs_truncate(struct inode *inode, loff_t size)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1184) {
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1185) int err = 0;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1186)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1187) UFSD("ENTER: ino %lu, i_size: %llu, old_i_size: %llu\n",
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1188) inode->i_ino, (unsigned long long)size,
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1189) (unsigned long long)i_size_read(inode));
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1190)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1191) if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1192) S_ISLNK(inode->i_mode)))
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1193) return -EINVAL;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1194) if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1195) return -EPERM;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1196)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1197) err = ufs_alloc_lastblock(inode, size);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1198)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1199) if (err)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1200) goto out;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1201)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1202) block_truncate_page(inode->i_mapping, size, ufs_getfrag_block);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1203)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1204) truncate_setsize(inode, size);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1205)
babef37dccbaa (Al Viro 2017-06-09 16:20:34 -0400 1206) ufs_truncate_blocks(inode);
02027d42c3f74 (Deepa Dinamani 2016-09-14 07:48:05 -0700 1207) inode->i_mtime = inode->i_ctime = current_time(inode);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1208) mark_inode_dirty(inode);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1209) out:
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1210) UFSD("EXIT: err %d\n", err);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1211) return err;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1212) }
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1213)
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 1214) int ufs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 1215) struct iattr *attr)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1216) {
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1217) struct inode *inode = d_inode(dentry);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1218) unsigned int ia_valid = attr->ia_valid;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1219) int error;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1220)
2f221d6f7b881 (Christian Brauner 2021-01-21 14:19:26 +0100 1221) error = setattr_prepare(&init_user_ns, dentry, attr);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1222) if (error)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1223) return error;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1224)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1225) if (ia_valid & ATTR_SIZE && attr->ia_size != inode->i_size) {
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1226) error = ufs_truncate(inode, attr->ia_size);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1227) if (error)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1228) return error;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1229) }
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1230)
2f221d6f7b881 (Christian Brauner 2021-01-21 14:19:26 +0100 1231) setattr_copy(&init_user_ns, inode, attr);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1232) mark_inode_dirty(inode);
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1233) return 0;
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1234) }
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1235)
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1236) const struct inode_operations ufs_file_inode_operations = {
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1237) .setattr = ufs_setattr,
010d331fc315c (Al Viro 2015-06-17 12:44:14 -0400 1238) };