inode.c 33.5 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
/*
 *  linux/fs/ufs/inode.c
 *
 * Copyright (C) 1998
 * Daniel Pirkl <daniel.pirkl@email.cz>
 * Charles University, Faculty of Mathematics and Physics
 *
 *  from
 *
 *  linux/fs/ext2/inode.c
 *
 * Copyright (C) 1992, 1993, 1994, 1995
 * Remy Card (card@masi.ibp.fr)
 * Laboratoire MASI - Institut Blaise Pascal
 * Universite Pierre et Marie Curie (Paris VI)
 *
 *  from
 *
 *  linux/fs/minix/inode.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
 *  Goal-directed block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
 *  Big-endian to little-endian byte-swapping/bitmaps by
 *        David S. Miller (davem@caip.rutgers.edu), 1995
 */

#include <asm/uaccess.h>

#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/time.h>
#include <linux/stat.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/buffer_head.h>
37
#include <linux/writeback.h>
L
Linus Torvalds 已提交
38

39
#include "ufs_fs.h"
40
#include "ufs.h"
L
Linus Torvalds 已提交
41 42 43
#include "swab.h"
#include "util.h"

44
static int ufs_block_to_path(struct inode *inode, sector_t i_block, unsigned offsets[4])
L
Linus Torvalds 已提交
45 46 47 48 49 50 51 52 53 54
{
	struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi;
	int ptrs = uspi->s_apb;
	int ptrs_bits = uspi->s_apbshift;
	const long direct_blocks = UFS_NDADDR,
		indirect_blocks = ptrs,
		double_blocks = (1 << (ptrs_bits * 2));
	int n = 0;


E
Evgeniy Dushistov 已提交
55
	UFSD("ptrs=uspi->s_apb = %d,double_blocks=%ld \n",ptrs,double_blocks);
R
Roel Kluin 已提交
56
	if (i_block < direct_blocks) {
L
Linus Torvalds 已提交
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
		offsets[n++] = i_block;
	} else if ((i_block -= direct_blocks) < indirect_blocks) {
		offsets[n++] = UFS_IND_BLOCK;
		offsets[n++] = i_block;
	} else if ((i_block -= indirect_blocks) < double_blocks) {
		offsets[n++] = UFS_DIND_BLOCK;
		offsets[n++] = i_block >> ptrs_bits;
		offsets[n++] = i_block & (ptrs - 1);
	} else if (((i_block -= double_blocks) >> (ptrs_bits * 2)) < ptrs) {
		offsets[n++] = UFS_TIND_BLOCK;
		offsets[n++] = i_block >> (ptrs_bits * 2);
		offsets[n++] = (i_block >> ptrs_bits) & (ptrs - 1);
		offsets[n++] = i_block & (ptrs - 1);
	} else {
		ufs_warning(inode->i_sb, "ufs_block_to_path", "block > big");
	}
	return n;
}

76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
typedef struct {
	void	*p;
	union {
		__fs32	key32;
		__fs64	key64;
	};
	struct buffer_head *bh;
} Indirect;

static inline int grow_chain32(struct ufs_inode_info *ufsi,
			       struct buffer_head *bh, __fs32 *v,
			       Indirect *from, Indirect *to)
{
	Indirect *p;
	unsigned seq;
	to->bh = bh;
	do {
		seq = read_seqbegin(&ufsi->meta_lock);
		to->key32 = *(__fs32 *)(to->p = v);
		for (p = from; p <= to && p->key32 == *(__fs32 *)p->p; p++)
			;
	} while (read_seqretry(&ufsi->meta_lock, seq));
	return (p > to);
}

static inline int grow_chain64(struct ufs_inode_info *ufsi,
			       struct buffer_head *bh, __fs64 *v,
			       Indirect *from, Indirect *to)
{
	Indirect *p;
	unsigned seq;
	to->bh = bh;
	do {
		seq = read_seqbegin(&ufsi->meta_lock);
		to->key64 = *(__fs64 *)(to->p = v);
		for (p = from; p <= to && p->key64 == *(__fs64 *)p->p; p++)
			;
	} while (read_seqretry(&ufsi->meta_lock, seq));
	return (p > to);
}

L
Linus Torvalds 已提交
117 118
/*
 * Returns the location of the fragment from
L
Lucas De Marchi 已提交
119
 * the beginning of the filesystem.
L
Linus Torvalds 已提交
120 121
 */

122
static u64 ufs_frag_map(struct inode *inode, unsigned offsets[4], int depth)
L
Linus Torvalds 已提交
123 124 125 126 127 128
{
	struct ufs_inode_info *ufsi = UFS_I(inode);
	struct super_block *sb = inode->i_sb;
	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
	u64 mask = (u64) uspi->s_apbmask>>uspi->s_fpbshift;
	int shift = uspi->s_apbshift-uspi->s_fpbshift;
129
	Indirect chain[4], *q = chain;
130
	unsigned *p;
L
Linus Torvalds 已提交
131
	unsigned flags = UFS_SB(sb)->s_flags;
132
	u64 res = 0;
L
Linus Torvalds 已提交
133

A
Andrew Morton 已提交
134 135 136
	UFSD(": uspi->s_fpbshift = %d ,uspi->s_apbmask = %x, mask=%llx\n",
		uspi->s_fpbshift, uspi->s_apbmask,
		(unsigned long long)mask);
L
Linus Torvalds 已提交
137 138

	if (depth == 0)
139
		goto no_block;
L
Linus Torvalds 已提交
140

141
again:
L
Linus Torvalds 已提交
142 143 144 145 146
	p = offsets;

	if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
		goto ufs2;

147 148 149 150
	if (!grow_chain32(ufsi, NULL, &ufsi->i_u1.i_data[*p++], chain, q))
		goto changed;
	if (!q->key32)
		goto no_block;
L
Linus Torvalds 已提交
151
	while (--depth) {
152
		__fs32 *ptr;
L
Linus Torvalds 已提交
153
		struct buffer_head *bh;
154
		unsigned n = *p++;
L
Linus Torvalds 已提交
155

156 157
		bh = sb_bread(sb, uspi->s_sbbase +
				  fs32_to_cpu(sb, q->key32) + (n>>shift));
L
Linus Torvalds 已提交
158
		if (!bh)
159 160 161 162 163 164
			goto no_block;
		ptr = (__fs32 *)bh->b_data + (n & mask);
		if (!grow_chain32(ufsi, bh, ptr, chain, ++q))
			goto changed;
		if (!q->key32)
			goto no_block;
L
Linus Torvalds 已提交
165
	}
166 167
	res = fs32_to_cpu(sb, q->key32);
	goto found;
L
Linus Torvalds 已提交
168

169 170 171 172 173
ufs2:
	if (!grow_chain64(ufsi, NULL, &ufsi->i_u1.u2_i_data[*p++], chain, q))
		goto changed;
	if (!q->key64)
		goto no_block;
L
Linus Torvalds 已提交
174 175

	while (--depth) {
176
		__fs64 *ptr;
L
Linus Torvalds 已提交
177
		struct buffer_head *bh;
178
		unsigned n = *p++;
L
Linus Torvalds 已提交
179

180 181
		bh = sb_bread(sb, uspi->s_sbbase +
				  fs64_to_cpu(sb, q->key64) + (n>>shift));
L
Linus Torvalds 已提交
182
		if (!bh)
183 184 185 186 187 188 189 190 191
			goto no_block;
		ptr = (__fs64 *)bh->b_data + (n & mask);
		if (!grow_chain64(ufsi, bh, ptr, chain, ++q))
			goto changed;
		if (!q->key64)
			goto no_block;
	}
	res = fs64_to_cpu(sb, q->key64);
found:
192
	res += uspi->s_sbbase;
193 194 195 196
no_block:
	while (q > chain) {
		brelse(q->bh);
		q--;
L
Linus Torvalds 已提交
197
	}
198
	return res;
L
Linus Torvalds 已提交
199

200 201 202 203 204 205
changed:
	while (q > chain) {
		brelse(q->bh);
		q--;
	}
	goto again;
L
Linus Torvalds 已提交
206 207
}

208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
/*
 * Unpacking tails: we have a file with partial final block and
 * we had been asked to extend it.  If the fragment being written
 * is within the same block, we need to extend the tail just to cover
 * that fragment.  Otherwise the tail is extended to full block.
 *
 * Note that we might need to create a _new_ tail, but that will
 * be handled elsewhere; this is strictly for resizing old
 * ones.
 */
static bool
ufs_extend_tail(struct inode *inode, u64 writes_to,
		  int *err, struct page *locked_page)
{
	struct ufs_inode_info *ufsi = UFS_I(inode);
	struct super_block *sb = inode->i_sb;
	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
	unsigned lastfrag = ufsi->i_lastfrag;	/* it's a short file, so unsigned is enough */
	unsigned block = ufs_fragstoblks(lastfrag);
	unsigned new_size;
	void *p;
	u64 tmp;

	if (writes_to < (lastfrag | uspi->s_fpbmask))
		new_size = (writes_to & uspi->s_fpbmask) + 1;
	else
		new_size = uspi->s_fpb;

	p = ufs_get_direct_data_ptr(uspi, ufsi, block);
	tmp = ufs_new_fragments(inode, p, lastfrag, ufs_data_ptr_to_cpu(sb, p),
				new_size, err, locked_page);
	return tmp != 0;
}

E
Evgeniy Dushistov 已提交
242 243
/**
 * ufs_inode_getfrag() - allocate new fragment(s)
244
 * @inode: pointer to inode
245
 * @index: number of block pointer within the inode's array.
246 247 248
 * @new_fragment: number of new allocated fragment(s)
 * @err: we set it if something wrong
 * @phys: pointer to where we save physical number of new allocated fragments,
E
Evgeniy Dushistov 已提交
249
 *   NULL if we allocate not data(indirect blocks for example).
250 251
 * @new: we set it if we allocate new block
 * @locked_page: for ufs_new_fragments()
E
Evgeniy Dushistov 已提交
252
 */
253
static u64
254 255
ufs_inode_getfrag(struct inode *inode, unsigned index,
		  sector_t new_fragment, int *err,
E
Evgeniy Dushistov 已提交
256
		  long *phys, int *new, struct page *locked_page)
L
Linus Torvalds 已提交
257 258
{
	struct ufs_inode_info *ufsi = UFS_I(inode);
E
Evgeniy Dushistov 已提交
259 260
	struct super_block *sb = inode->i_sb;
	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
261
	u64 tmp, goal, lastfrag;
262 263
	unsigned nfrags = uspi->s_fpb;
	void *p;
L
Linus Torvalds 已提交
264 265 266 267 268 269

        /* TODO : to be done for write support
        if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
             goto ufs2;
         */

270
	p = ufs_get_direct_data_ptr(uspi, ufsi, index);
271
	tmp = ufs_data_ptr_to_cpu(sb, p);
272 273
	if (tmp)
		goto out;
274

L
Linus Torvalds 已提交
275 276
	lastfrag = ufsi->i_lastfrag;

277 278 279 280 281
	/* will that be a new tail? */
	if (new_fragment < UFS_NDIR_FRAGMENT && new_fragment >= lastfrag)
		nfrags = (new_fragment & uspi->s_fpbmask) + 1;

	goal = 0;
282
	if (index) {
283
		goal = ufs_data_ptr_to_cpu(sb,
284
				 ufs_get_direct_data_ptr(uspi, ufsi, index - 1));
285 286
		if (goal)
			goal += uspi->s_fpb;
L
Linus Torvalds 已提交
287
	}
288
	tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment),
289 290 291
				goal, uspi->s_fpb, err,
				phys != NULL ? locked_page : NULL);

L
Linus Torvalds 已提交
292 293
	if (!tmp) {
		*err = -ENOSPC;
294
		return 0;
L
Linus Torvalds 已提交
295 296
	}

297
	if (phys) {
L
Linus Torvalds 已提交
298 299 300 301 302 303 304
		*err = 0;
		*new = 1;
	}
	inode->i_ctime = CURRENT_TIME_SEC;
	if (IS_SYNC(inode))
		ufs_sync_inode (inode);
	mark_inode_dirty(inode);
305
out:
306
	return tmp + uspi->s_sbbase;
L
Linus Torvalds 已提交
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323

     /* This part : To be implemented ....
        Required only for writing, not required for READ-ONLY.
ufs2:

	u2_block = ufs_fragstoblks(fragment);
	u2_blockoff = ufs_fragnum(fragment);
	p = ufsi->i_u1.u2_i_data + block;
	goal = 0;

repeat2:
	tmp = fs32_to_cpu(sb, *p);
	lastfrag = ufsi->i_lastfrag;

     */
}

E
Evgeniy Dushistov 已提交
324 325
/**
 * ufs_inode_getblock() - allocate new block
326
 * @inode: pointer to inode
327 328
 * @ind_block: block number of the indirect block
 * @index: number of pointer within the indirect block
329
 * @new_fragment: number of new allocated fragment
E
Evgeniy Dushistov 已提交
330
 *  (block will hold this fragment and also uspi->s_fpb-1)
331 332 333 334
 * @err: see ufs_inode_getfrag()
 * @phys: see ufs_inode_getfrag()
 * @new: see ufs_inode_getfrag()
 * @locked_page: see ufs_inode_getfrag()
E
Evgeniy Dushistov 已提交
335
 */
336
static u64
337
ufs_inode_getblock(struct inode *inode, u64 ind_block,
338
		  unsigned index, sector_t new_fragment, int *err,
E
Evgeniy Dushistov 已提交
339
		  long *phys, int *new, struct page *locked_page)
L
Linus Torvalds 已提交
340
{
E
Evgeniy Dushistov 已提交
341 342
	struct super_block *sb = inode->i_sb;
	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
343
	int shift = uspi->s_apbshift - uspi->s_fpbshift;
344
	u64 tmp = 0, goal;
345
	struct buffer_head *bh;
346
	void *p;
L
Linus Torvalds 已提交
347

348 349 350 351 352 353 354 355
	if (!ind_block)
		return 0;

	bh = sb_bread(sb, ind_block + (index >> shift));
	if (unlikely(!bh))
		return 0;

	index &= uspi->s_apbmask >> uspi->s_fpbshift;
356
	if (uspi->fs_magic == UFS2_MAGIC)
357
		p = (__fs64 *)bh->b_data + index;
358
	else
359
		p = (__fs32 *)bh->b_data + index;
360

361
	tmp = ufs_data_ptr_to_cpu(sb, p);
362
	if (tmp)
363
		goto out;
L
Linus Torvalds 已提交
364

365 366 367
	if (index && (uspi->fs_magic == UFS2_MAGIC ?
		      (tmp = fs64_to_cpu(sb, ((__fs64 *)bh->b_data)[index-1])) :
		      (tmp = fs32_to_cpu(sb, ((__fs32 *)bh->b_data)[index-1]))))
L
Linus Torvalds 已提交
368 369 370
		goal = tmp + uspi->s_fpb;
	else
		goal = bh->b_blocknr + uspi->s_fpb;
371 372
	tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment), goal,
				uspi->s_fpb, err, locked_page);
373
	if (!tmp)
L
Linus Torvalds 已提交
374
		goto out;
375

376
	if (new)
L
Linus Torvalds 已提交
377 378 379 380 381 382 383 384 385
		*new = 1;

	mark_buffer_dirty(bh);
	if (IS_SYNC(inode))
		sync_dirty_buffer(bh);
	inode->i_ctime = CURRENT_TIME_SEC;
	mark_inode_dirty(inode);
out:
	brelse (bh);
E
Evgeniy Dushistov 已提交
386
	UFSD("EXIT\n");
387 388 389
	if (tmp)
		tmp += uspi->s_sbbase;
	return tmp;
L
Linus Torvalds 已提交
390 391
}

E
Evgeniy Dushistov 已提交
392
/**
A
Alessio Igor Bogani 已提交
393
 * ufs_getfrag_block() - `get_block_t' function, interface between UFS and
E
Evgeniy Dushistov 已提交
394
 * readpage, writepage and so on
L
Linus Torvalds 已提交
395 396
 */

A
Al Viro 已提交
397
static int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create)
L
Linus Torvalds 已提交
398 399
{
	struct super_block * sb = inode->i_sb;
A
Arnd Bergmann 已提交
400 401
	struct ufs_sb_info * sbi = UFS_SB(sb);
	struct ufs_sb_private_info * uspi = sbi->s_uspi;
L
Linus Torvalds 已提交
402 403
	struct buffer_head * bh;
	int ret, err, new;
404 405
	unsigned offsets[4];
	int depth = ufs_block_to_path(inode, fragment >> uspi->s_fpbshift, offsets);
406
	unsigned long phys;
L
Linus Torvalds 已提交
407
	u64 phys64 = 0;
408
	unsigned frag = fragment & uspi->s_fpbmask;
A
Al Viro 已提交
409

L
Linus Torvalds 已提交
410
	if (!create) {
411 412
		phys64 = ufs_frag_map(inode, offsets, depth);
		if (phys64) {
413
			phys64 += frag;
L
Linus Torvalds 已提交
414
			map_bh(bh_result, sb, phys64);
415
		}
L
Linus Torvalds 已提交
416 417 418 419 420 421 422 423 424 425
		return 0;
	}

        /* This code entered only while writing ....? */

	err = -EIO;
	new = 0;
	ret = 0;
	bh = NULL;

426
	mutex_lock(&UFS_I(inode)->truncate_mutex);
L
Linus Torvalds 已提交
427

E
Evgeniy Dushistov 已提交
428
	UFSD("ENTER, ino %lu, fragment %llu\n", inode->i_ino, (unsigned long long)fragment);
429
	if (!depth)
L
Linus Torvalds 已提交
430 431 432
		goto abort_too_big;

	err = 0;
433 434 435 436 437 438 439 440 441 442 443

	if (UFS_I(inode)->i_lastfrag < UFS_NDIR_FRAGMENT) {
		unsigned lastfrag = UFS_I(inode)->i_lastfrag;
		unsigned tailfrags = lastfrag & uspi->s_fpbmask;
		if (tailfrags && fragment >= lastfrag) {
			if (!ufs_extend_tail(inode, fragment,
					     &err, bh_result->b_page))
				goto abort;
		}
	}

444
	if (depth == 1) {
445 446
		phys64 = ufs_inode_getfrag(inode, offsets[0], fragment,
					   &err, &phys, &new, bh_result->b_page);
447 448 449 450
		if (phys64) {
			phys64 += frag;
			phys = phys64;
		}
L
Linus Torvalds 已提交
451 452
		goto out;
	}
453
	if (depth == 2) {
454 455
		phys64 = ufs_inode_getfrag(inode, offsets[0], fragment,
					   &err, NULL, NULL, bh_result->b_page);
L
Linus Torvalds 已提交
456 457
		goto get_indirect;
	}
458
	if (depth == 3) {
459 460
		phys64 = ufs_inode_getfrag(inode, offsets[0], fragment,
					   &err, NULL, NULL, bh_result->b_page);
L
Linus Torvalds 已提交
461 462
		goto get_double;
	}
463 464
	phys64 = ufs_inode_getfrag(inode, offsets[0], fragment,
				   &err, NULL, NULL, bh_result->b_page);
465
	phys64 = ufs_inode_getblock(inode, phys64, offsets[1],
466
				fragment, &err, NULL, NULL, NULL);
L
Linus Torvalds 已提交
467
get_double:
468
	phys64 = ufs_inode_getblock(inode, phys64, offsets[depth - 2],
469
				fragment, &err, NULL, NULL, NULL);
L
Linus Torvalds 已提交
470
get_indirect:
471
	phys64 = ufs_inode_getblock(inode, phys64, offsets[depth - 1],
472
				fragment, &err, &phys, &new, bh_result->b_page);
473 474 475 476
	if (phys64) {
		phys64 += frag;
		phys = phys64;
	}
L
Linus Torvalds 已提交
477 478 479 480 481 482 483
out:
	if (err)
		goto abort;
	if (new)
		set_buffer_new(bh_result);
	map_bh(bh_result, sb, phys);
abort:
484
	mutex_unlock(&UFS_I(inode)->truncate_mutex);
A
Arnd Bergmann 已提交
485

L
Linus Torvalds 已提交
486 487 488 489 490 491 492 493 494 495 496
	return err;

abort_too_big:
	ufs_warning(sb, "ufs_get_block", "block > big");
	goto abort;
}

static int ufs_writepage(struct page *page, struct writeback_control *wbc)
{
	return block_write_full_page(page,ufs_getfrag_block,wbc);
}
N
Nick Piggin 已提交
497

L
Linus Torvalds 已提交
498 499 500 501
static int ufs_readpage(struct file *file, struct page *page)
{
	return block_read_full_page(page,ufs_getfrag_block);
}
N
Nick Piggin 已提交
502

503
int ufs_prepare_chunk(struct page *page, loff_t pos, unsigned len)
L
Linus Torvalds 已提交
504
{
505
	return __block_write_begin(page, pos, len, ufs_getfrag_block);
L
Linus Torvalds 已提交
506
}
N
Nick Piggin 已提交
507

A
Al Viro 已提交
508 509
static void ufs_truncate_blocks(struct inode *);

M
Marco Stornelli 已提交
510 511 512 513
static void ufs_write_failed(struct address_space *mapping, loff_t to)
{
	struct inode *inode = mapping->host;

514
	if (to > inode->i_size) {
515
		truncate_pagecache(inode, inode->i_size);
516 517
		ufs_truncate_blocks(inode);
	}
M
Marco Stornelli 已提交
518 519
}

N
Nick Piggin 已提交
520 521 522 523
static int ufs_write_begin(struct file *file, struct address_space *mapping,
			loff_t pos, unsigned len, unsigned flags,
			struct page **pagep, void **fsdata)
{
524 525 526
	int ret;

	ret = block_write_begin(mapping, pos, len, flags, pagep,
527
				ufs_getfrag_block);
M
Marco Stornelli 已提交
528 529
	if (unlikely(ret))
		ufs_write_failed(mapping, pos + len);
530 531

	return ret;
N
Nick Piggin 已提交
532 533
}

534 535 536 537 538 539 540 541 542 543 544 545
static int ufs_write_end(struct file *file, struct address_space *mapping,
			loff_t pos, unsigned len, unsigned copied,
			struct page *page, void *fsdata)
{
	int ret;

	ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
	if (ret < len)
		ufs_write_failed(mapping, pos + len);
	return ret;
}

L
Linus Torvalds 已提交
546 547 548 549
static sector_t ufs_bmap(struct address_space *mapping, sector_t block)
{
	return generic_block_bmap(mapping,block,ufs_getfrag_block);
}
N
Nick Piggin 已提交
550

551
const struct address_space_operations ufs_aops = {
L
Linus Torvalds 已提交
552 553
	.readpage = ufs_readpage,
	.writepage = ufs_writepage,
N
Nick Piggin 已提交
554
	.write_begin = ufs_write_begin,
555
	.write_end = ufs_write_end,
L
Linus Torvalds 已提交
556 557 558
	.bmap = ufs_bmap
};

559 560 561 562 563 564 565 566 567 568 569
static void ufs_set_inode_ops(struct inode *inode)
{
	if (S_ISREG(inode->i_mode)) {
		inode->i_op = &ufs_file_inode_operations;
		inode->i_fop = &ufs_file_operations;
		inode->i_mapping->a_ops = &ufs_aops;
	} else if (S_ISDIR(inode->i_mode)) {
		inode->i_op = &ufs_dir_inode_operations;
		inode->i_fop = &ufs_dir_operations;
		inode->i_mapping->a_ops = &ufs_aops;
	} else if (S_ISLNK(inode->i_mode)) {
A
Al Viro 已提交
570
		if (!inode->i_blocks) {
571
			inode->i_op = &ufs_fast_symlink_inode_operations;
A
Al Viro 已提交
572 573
			inode->i_link = (char *)UFS_I(inode)->i_u1.i_symlink;
		} else {
574
			inode->i_op = &ufs_symlink_inode_operations;
575 576 577 578 579 580 581
			inode->i_mapping->a_ops = &ufs_aops;
		}
	} else
		init_special_inode(inode, inode->i_mode,
				   ufs_get_inode_dev(inode->i_sb, UFS_I(inode)));
}

582
static int ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode)
L
Linus Torvalds 已提交
583 584
{
	struct ufs_inode_info *ufsi = UFS_I(inode);
585
	struct super_block *sb = inode->i_sb;
A
Al Viro 已提交
586
	umode_t mode;
L
Linus Torvalds 已提交
587 588 589 590 591

	/*
	 * Copy data to the in-core inode.
	 */
	inode->i_mode = mode = fs16_to_cpu(sb, ufs_inode->ui_mode);
M
Miklos Szeredi 已提交
592
	set_nlink(inode, fs16_to_cpu(sb, ufs_inode->ui_nlink));
593
	if (inode->i_nlink == 0) {
L
Linus Torvalds 已提交
594
		ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino);
595 596
		return -1;
	}
A
Al Viro 已提交
597

L
Linus Torvalds 已提交
598 599 600
	/*
	 * Linux now has 32-bit uid and gid, so we can support EFT.
	 */
601 602
	i_uid_write(inode, ufs_get_inode_uid(sb, ufs_inode));
	i_gid_write(inode, ufs_get_inode_gid(sb, ufs_inode));
L
Linus Torvalds 已提交
603 604 605 606 607 608 609 610 611

	inode->i_size = fs64_to_cpu(sb, ufs_inode->ui_size);
	inode->i_atime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_atime.tv_sec);
	inode->i_ctime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_ctime.tv_sec);
	inode->i_mtime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_mtime.tv_sec);
	inode->i_mtime.tv_nsec = 0;
	inode->i_atime.tv_nsec = 0;
	inode->i_ctime.tv_nsec = 0;
	inode->i_blocks = fs32_to_cpu(sb, ufs_inode->ui_blocks);
612
	inode->i_generation = fs32_to_cpu(sb, ufs_inode->ui_gen);
L
Linus Torvalds 已提交
613 614 615
	ufsi->i_flags = fs32_to_cpu(sb, ufs_inode->ui_flags);
	ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow);
	ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag);
616

A
Al Viro 已提交
617

L
Linus Torvalds 已提交
618
	if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) {
619 620
		memcpy(ufsi->i_u1.i_data, &ufs_inode->ui_u2.ui_addr,
		       sizeof(ufs_inode->ui_u2.ui_addr));
621
	} else {
622
		memcpy(ufsi->i_u1.i_symlink, ufs_inode->ui_u2.ui_symlink,
623 624
		       sizeof(ufs_inode->ui_u2.ui_symlink) - 1);
		ufsi->i_u1.i_symlink[sizeof(ufs_inode->ui_u2.ui_symlink) - 1] = 0;
L
Linus Torvalds 已提交
625
	}
626
	return 0;
627
}
L
Linus Torvalds 已提交
628

629
static int ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode)
630 631 632
{
	struct ufs_inode_info *ufsi = UFS_I(inode);
	struct super_block *sb = inode->i_sb;
A
Al Viro 已提交
633
	umode_t mode;
L
Linus Torvalds 已提交
634

E
Evgeniy Dushistov 已提交
635
	UFSD("Reading ufs2 inode, ino %lu\n", inode->i_ino);
L
Linus Torvalds 已提交
636 637 638 639
	/*
	 * Copy data to the in-core inode.
	 */
	inode->i_mode = mode = fs16_to_cpu(sb, ufs2_inode->ui_mode);
M
Miklos Szeredi 已提交
640
	set_nlink(inode, fs16_to_cpu(sb, ufs2_inode->ui_nlink));
641
	if (inode->i_nlink == 0) {
L
Linus Torvalds 已提交
642
		ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino);
643 644
		return -1;
	}
L
Linus Torvalds 已提交
645 646 647 648

        /*
         * Linux now has 32-bit uid and gid, so we can support EFT.
         */
649 650
	i_uid_write(inode, fs32_to_cpu(sb, ufs2_inode->ui_uid));
	i_gid_write(inode, fs32_to_cpu(sb, ufs2_inode->ui_gid));
L
Linus Torvalds 已提交
651 652

	inode->i_size = fs64_to_cpu(sb, ufs2_inode->ui_size);
653 654 655 656 657 658
	inode->i_atime.tv_sec = fs64_to_cpu(sb, ufs2_inode->ui_atime);
	inode->i_ctime.tv_sec = fs64_to_cpu(sb, ufs2_inode->ui_ctime);
	inode->i_mtime.tv_sec = fs64_to_cpu(sb, ufs2_inode->ui_mtime);
	inode->i_atime.tv_nsec = fs32_to_cpu(sb, ufs2_inode->ui_atimensec);
	inode->i_ctime.tv_nsec = fs32_to_cpu(sb, ufs2_inode->ui_ctimensec);
	inode->i_mtime.tv_nsec = fs32_to_cpu(sb, ufs2_inode->ui_mtimensec);
L
Linus Torvalds 已提交
659
	inode->i_blocks = fs64_to_cpu(sb, ufs2_inode->ui_blocks);
660
	inode->i_generation = fs32_to_cpu(sb, ufs2_inode->ui_gen);
L
Linus Torvalds 已提交
661 662 663 664 665 666 667
	ufsi->i_flags = fs32_to_cpu(sb, ufs2_inode->ui_flags);
	/*
	ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow);
	ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag);
	*/

	if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) {
668 669
		memcpy(ufsi->i_u1.u2_i_data, &ufs2_inode->ui_u2.ui_addr,
		       sizeof(ufs2_inode->ui_u2.ui_addr));
670
	} else {
671
		memcpy(ufsi->i_u1.i_symlink, ufs2_inode->ui_u2.ui_symlink,
672 673
		       sizeof(ufs2_inode->ui_u2.ui_symlink) - 1);
		ufsi->i_u1.i_symlink[sizeof(ufs2_inode->ui_u2.ui_symlink) - 1] = 0;
L
Linus Torvalds 已提交
674
	}
675
	return 0;
676 677
}

678
struct inode *ufs_iget(struct super_block *sb, unsigned long ino)
679
{
680 681
	struct ufs_inode_info *ufsi;
	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
682
	struct buffer_head * bh;
683
	struct inode *inode;
684
	int err;
685

686
	UFSD("ENTER, ino %lu\n", ino);
687

688
	if (ino < UFS_ROOTINO || ino > (uspi->s_ncg * uspi->s_ipg)) {
689
		ufs_warning(sb, "ufs_read_inode", "bad inode number (%lu)\n",
690 691
			    ino);
		return ERR_PTR(-EIO);
692 693
	}

694 695 696 697 698 699 700 701
	inode = iget_locked(sb, ino);
	if (!inode)
		return ERR_PTR(-ENOMEM);
	if (!(inode->i_state & I_NEW))
		return inode;

	ufsi = UFS_I(inode);

702 703 704 705 706 707 708 709 710
	bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino));
	if (!bh) {
		ufs_warning(sb, "ufs_read_inode", "unable to read inode %lu\n",
			    inode->i_ino);
		goto bad_inode;
	}
	if ((UFS_SB(sb)->s_flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
		struct ufs2_inode *ufs2_inode = (struct ufs2_inode *)bh->b_data;

711 712
		err = ufs2_read_inode(inode,
				      ufs2_inode + ufs_inotofsbo(inode->i_ino));
713 714 715
	} else {
		struct ufs_inode *ufs_inode = (struct ufs_inode *)bh->b_data;

716 717
		err = ufs1_read_inode(inode,
				      ufs_inode + ufs_inotofsbo(inode->i_ino));
718 719
	}

720 721
	if (err)
		goto bad_inode;
722 723 724 725
	inode->i_version++;
	ufsi->i_lastfrag =
		(inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift;
	ufsi->i_dir_start_lookup = 0;
L
Linus Torvalds 已提交
726 727
	ufsi->i_osync = 0;

728
	ufs_set_inode_ops(inode);
L
Linus Torvalds 已提交
729 730 731

	brelse(bh);

E
Evgeniy Dushistov 已提交
732
	UFSD("EXIT\n");
733 734
	unlock_new_inode(inode);
	return inode;
735 736

bad_inode:
737 738
	iget_failed(inode);
	return ERR_PTR(-EIO);
L
Linus Torvalds 已提交
739 740
}

741
static void ufs1_update_inode(struct inode *inode, struct ufs_inode *ufs_inode)
L
Linus Torvalds 已提交
742
{
743 744
	struct super_block *sb = inode->i_sb;
 	struct ufs_inode_info *ufsi = UFS_I(inode);
L
Linus Torvalds 已提交
745 746 747 748

	ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode);
	ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink);

749 750
	ufs_set_inode_uid(sb, ufs_inode, i_uid_read(inode));
	ufs_set_inode_gid(sb, ufs_inode, i_gid_read(inode));
A
Al Viro 已提交
751

L
Linus Torvalds 已提交
752 753 754 755 756 757 758 759 760
	ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size);
	ufs_inode->ui_atime.tv_sec = cpu_to_fs32(sb, inode->i_atime.tv_sec);
	ufs_inode->ui_atime.tv_usec = 0;
	ufs_inode->ui_ctime.tv_sec = cpu_to_fs32(sb, inode->i_ctime.tv_sec);
	ufs_inode->ui_ctime.tv_usec = 0;
	ufs_inode->ui_mtime.tv_sec = cpu_to_fs32(sb, inode->i_mtime.tv_sec);
	ufs_inode->ui_mtime.tv_usec = 0;
	ufs_inode->ui_blocks = cpu_to_fs32(sb, inode->i_blocks);
	ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags);
761
	ufs_inode->ui_gen = cpu_to_fs32(sb, inode->i_generation);
L
Linus Torvalds 已提交
762

763
	if ((UFS_SB(sb)->s_flags & UFS_UID_MASK) == UFS_UID_EFT) {
L
Linus Torvalds 已提交
764 765 766 767 768 769 770 771
		ufs_inode->ui_u3.ui_sun.ui_shadow = cpu_to_fs32(sb, ufsi->i_shadow);
		ufs_inode->ui_u3.ui_sun.ui_oeftflag = cpu_to_fs32(sb, ufsi->i_oeftflag);
	}

	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
		/* ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev); */
		ufs_inode->ui_u2.ui_addr.ui_db[0] = ufsi->i_u1.i_data[0];
	} else if (inode->i_blocks) {
772 773
		memcpy(&ufs_inode->ui_u2.ui_addr, ufsi->i_u1.i_data,
		       sizeof(ufs_inode->ui_u2.ui_addr));
L
Linus Torvalds 已提交
774 775
	}
	else {
776 777
		memcpy(&ufs_inode->ui_u2.ui_symlink, ufsi->i_u1.i_symlink,
		       sizeof(ufs_inode->ui_u2.ui_symlink));
L
Linus Torvalds 已提交
778 779 780 781
	}

	if (!inode->i_nlink)
		memset (ufs_inode, 0, sizeof(struct ufs_inode));
782 783 784 785 786 787 788 789 790 791 792
}

static void ufs2_update_inode(struct inode *inode, struct ufs2_inode *ufs_inode)
{
	struct super_block *sb = inode->i_sb;
 	struct ufs_inode_info *ufsi = UFS_I(inode);

	UFSD("ENTER\n");
	ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode);
	ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink);

793 794
	ufs_inode->ui_uid = cpu_to_fs32(sb, i_uid_read(inode));
	ufs_inode->ui_gid = cpu_to_fs32(sb, i_gid_read(inode));
795 796

	ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size);
797 798 799 800 801 802
	ufs_inode->ui_atime = cpu_to_fs64(sb, inode->i_atime.tv_sec);
	ufs_inode->ui_atimensec = cpu_to_fs32(sb, inode->i_atime.tv_nsec);
	ufs_inode->ui_ctime = cpu_to_fs64(sb, inode->i_ctime.tv_sec);
	ufs_inode->ui_ctimensec = cpu_to_fs32(sb, inode->i_ctime.tv_nsec);
	ufs_inode->ui_mtime = cpu_to_fs64(sb, inode->i_mtime.tv_sec);
	ufs_inode->ui_mtimensec = cpu_to_fs32(sb, inode->i_mtime.tv_nsec);
803 804 805 806 807 808 809 810 811

	ufs_inode->ui_blocks = cpu_to_fs64(sb, inode->i_blocks);
	ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags);
	ufs_inode->ui_gen = cpu_to_fs32(sb, inode->i_generation);

	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
		/* ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev); */
		ufs_inode->ui_u2.ui_addr.ui_db[0] = ufsi->i_u1.u2_i_data[0];
	} else if (inode->i_blocks) {
812 813
		memcpy(&ufs_inode->ui_u2.ui_addr, ufsi->i_u1.u2_i_data,
		       sizeof(ufs_inode->ui_u2.ui_addr));
814
	} else {
815 816
		memcpy(&ufs_inode->ui_u2.ui_symlink, ufsi->i_u1.i_symlink,
		       sizeof(ufs_inode->ui_u2.ui_symlink));
817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852
 	}

	if (!inode->i_nlink)
		memset (ufs_inode, 0, sizeof(struct ufs2_inode));
	UFSD("EXIT\n");
}

static int ufs_update_inode(struct inode * inode, int do_sync)
{
	struct super_block *sb = inode->i_sb;
	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
	struct buffer_head * bh;

	UFSD("ENTER, ino %lu\n", inode->i_ino);

	if (inode->i_ino < UFS_ROOTINO ||
	    inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) {
		ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino);
		return -1;
	}

	bh = sb_bread(sb, ufs_inotofsba(inode->i_ino));
	if (!bh) {
		ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino);
		return -1;
	}
	if (uspi->fs_magic == UFS2_MAGIC) {
		struct ufs2_inode *ufs2_inode = (struct ufs2_inode *)bh->b_data;

		ufs2_update_inode(inode,
				  ufs2_inode + ufs_inotofsbo(inode->i_ino));
	} else {
		struct ufs_inode *ufs_inode = (struct ufs_inode *) bh->b_data;

		ufs1_update_inode(inode, ufs_inode + ufs_inotofsbo(inode->i_ino));
	}
A
Al Viro 已提交
853

L
Linus Torvalds 已提交
854 855 856 857
	mark_buffer_dirty(bh);
	if (do_sync)
		sync_dirty_buffer(bh);
	brelse (bh);
A
Al Viro 已提交
858

E
Evgeniy Dushistov 已提交
859
	UFSD("EXIT\n");
L
Linus Torvalds 已提交
860 861 862
	return 0;
}

863
int ufs_write_inode(struct inode *inode, struct writeback_control *wbc)
L
Linus Torvalds 已提交
864
{
A
Al Viro 已提交
865
	return ufs_update_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
L
Linus Torvalds 已提交
866 867 868 869 870 871 872
}

int ufs_sync_inode (struct inode *inode)
{
	return ufs_update_inode (inode, 1);
}

A
Al Viro 已提交
873
void ufs_evict_inode(struct inode * inode)
L
Linus Torvalds 已提交
874
{
A
Al Viro 已提交
875 876 877 878
	int want_delete = 0;

	if (!inode->i_nlink && !is_bad_inode(inode))
		want_delete = 1;
879

880
	truncate_inode_pages_final(&inode->i_data);
A
Al Viro 已提交
881 882
	if (want_delete) {
		inode->i_size = 0;
883 884
		if (inode->i_blocks)
			ufs_truncate_blocks(inode);
A
Al Viro 已提交
885 886 887
	}

	invalidate_inode_buffers(inode);
888
	clear_inode(inode);
A
Al Viro 已提交
889

A
Al Viro 已提交
890
	if (want_delete)
891
		ufs_free_inode(inode);
L
Linus Torvalds 已提交
892
}
A
Al Viro 已提交
893

894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909
struct to_free {
	struct inode *inode;
	u64 to;
	unsigned count;
};

static inline void free_data(struct to_free *ctx, u64 from, unsigned count)
{
	if (ctx->count && ctx->to != from) {
		ufs_free_blocks(ctx->inode, ctx->to - ctx->count, ctx->count);
		ctx->count = 0;
	}
	ctx->count += count;
	ctx->to = from + count;
}

A
Al Viro 已提交
910 911 912 913 914 915 916 917 918 919
#define DIRECT_BLOCK ((inode->i_size + uspi->s_bsize - 1) >> uspi->s_bshift)
#define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift)

static void ufs_trunc_direct(struct inode *inode)
{
	struct ufs_inode_info *ufsi = UFS_I(inode);
	struct super_block * sb;
	struct ufs_sb_private_info * uspi;
	void *p;
	u64 frag1, frag2, frag3, frag4, block1, block2;
920
	struct to_free ctx = {.inode = inode};
A
Al Viro 已提交
921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974
	unsigned i, tmp;

	UFSD("ENTER: ino %lu\n", inode->i_ino);

	sb = inode->i_sb;
	uspi = UFS_SB(sb)->s_uspi;

	frag1 = DIRECT_FRAGMENT;
	frag4 = min_t(u64, UFS_NDIR_FRAGMENT, ufsi->i_lastfrag);
	frag2 = ((frag1 & uspi->s_fpbmask) ? ((frag1 | uspi->s_fpbmask) + 1) : frag1);
	frag3 = frag4 & ~uspi->s_fpbmask;
	block1 = block2 = 0;
	if (frag2 > frag3) {
		frag2 = frag4;
		frag3 = frag4 = 0;
	} else if (frag2 < frag3) {
		block1 = ufs_fragstoblks (frag2);
		block2 = ufs_fragstoblks (frag3);
	}

	UFSD("ino %lu, frag1 %llu, frag2 %llu, block1 %llu, block2 %llu,"
	     " frag3 %llu, frag4 %llu\n", inode->i_ino,
	     (unsigned long long)frag1, (unsigned long long)frag2,
	     (unsigned long long)block1, (unsigned long long)block2,
	     (unsigned long long)frag3, (unsigned long long)frag4);

	if (frag1 >= frag2)
		goto next1;

	/*
	 * Free first free fragments
	 */
	p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag1));
	tmp = ufs_data_ptr_to_cpu(sb, p);
	if (!tmp )
		ufs_panic (sb, "ufs_trunc_direct", "internal error");
	frag2 -= frag1;
	frag1 = ufs_fragnum (frag1);

	ufs_free_fragments(inode, tmp + frag1, frag2);

next1:
	/*
	 * Free whole blocks
	 */
	for (i = block1 ; i < block2; i++) {
		p = ufs_get_direct_data_ptr(uspi, ufsi, i);
		tmp = ufs_data_ptr_to_cpu(sb, p);
		if (!tmp)
			continue;
		write_seqlock(&ufsi->meta_lock);
		ufs_data_ptr_clear(uspi, p);
		write_sequnlock(&ufsi->meta_lock);

975
		free_data(&ctx, tmp, uspi->s_fpb);
A
Al Viro 已提交
976 977
	}

978
	free_data(&ctx, 0, 0);
A
Al Viro 已提交
979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000

	if (frag3 >= frag4)
		goto next3;

	/*
	 * Free last free fragments
	 */
	p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag3));
	tmp = ufs_data_ptr_to_cpu(sb, p);
	if (!tmp )
		ufs_panic(sb, "ufs_truncate_direct", "internal error");
	frag4 = ufs_fragnum (frag4);
	write_seqlock(&ufsi->meta_lock);
	ufs_data_ptr_clear(uspi, p);
	write_sequnlock(&ufsi->meta_lock);

	ufs_free_fragments (inode, tmp, frag4);
 next3:

	UFSD("EXIT: ino %lu\n", inode->i_ino);
}

1001
static void free_full_branch(struct inode *inode, u64 ind_block, int depth)
1002 1003 1004
{
	struct super_block *sb = inode->i_sb;
	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
1005
	struct ufs_buffer_head *ubh = ubh_bread(sb, ind_block, uspi->s_bsize);
1006 1007
	unsigned i;

1008
	if (!ubh)
1009 1010 1011
		return;

	if (--depth) {
1012 1013 1014
		for (i = 0; i < uspi->s_apb; i++) {
			void *p = ubh_get_data_ptr(uspi, ubh, i);
			u64 block = ufs_data_ptr_to_cpu(sb, p);
1015
			if (block)
1016
				free_full_branch(inode, block, depth);
1017 1018 1019 1020 1021
		}
	} else {
		struct to_free ctx = {.inode = inode};

		for (i = 0; i < uspi->s_apb; i++) {
1022 1023
			void *p = ubh_get_data_ptr(uspi, ubh, i);
			u64 block = ufs_data_ptr_to_cpu(sb, p);
1024
			if (block)
1025
				free_data(&ctx, block, uspi->s_fpb);
1026 1027 1028 1029 1030
		}
		free_data(&ctx, 0, 0);
	}

	ubh_bforget(ubh);
1031
	ufs_free_blocks(inode, ind_block, uspi->s_fpb);
1032 1033
}

A
Al Viro 已提交
1034
static void free_branch_tail(struct inode *inode, unsigned from, struct ufs_buffer_head *ubh, int depth)
A
Al Viro 已提交
1035
{
1036 1037 1038
	struct super_block *sb = inode->i_sb;
	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
	unsigned i;
A
Al Viro 已提交
1039

A
Al Viro 已提交
1040
	if (--depth) {
A
Al Viro 已提交
1041
		for (i = from; i < uspi->s_apb ; i++) {
1042 1043 1044 1045 1046 1047 1048 1049 1050
			void *p = ubh_get_data_ptr(uspi, ubh, i);
			u64 block = ufs_data_ptr_to_cpu(sb, p);
			if (block) {
				write_seqlock(&UFS_I(inode)->meta_lock);
				ufs_data_ptr_clear(uspi, p);
				write_sequnlock(&UFS_I(inode)->meta_lock);
				ubh_mark_buffer_dirty(ubh);
				free_full_branch(inode, block, depth);
			}
1051
		}
A
Al Viro 已提交
1052
	} else {
1053
		struct to_free ctx = {.inode = inode};
A
Al Viro 已提交
1054 1055

		for (i = from; i < uspi->s_apb; i++) {
1056 1057 1058 1059 1060 1061 1062 1063 1064
			void *p = ubh_get_data_ptr(uspi, ubh, i);
			u64 block = ufs_data_ptr_to_cpu(sb, p);
			if (block) {
				write_seqlock(&UFS_I(inode)->meta_lock);
				ufs_data_ptr_clear(uspi, p);
				write_sequnlock(&UFS_I(inode)->meta_lock);
				ubh_mark_buffer_dirty(ubh);
				free_data(&ctx, block, uspi->s_fpb);
			}
A
Al Viro 已提交
1065
		}
1066
		free_data(&ctx, 0, 0);
A
Al Viro 已提交
1067
	}
A
Al Viro 已提交
1068 1069 1070
	if (IS_SYNC(inode) && ubh_buffer_dirty(ubh))
		ubh_sync_block(ubh);
	ubh_brelse(ubh);
A
Al Viro 已提交
1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147
}

static int ufs_alloc_lastblock(struct inode *inode, loff_t size)
{
	int err = 0;
	struct super_block *sb = inode->i_sb;
	struct address_space *mapping = inode->i_mapping;
	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
	unsigned i, end;
	sector_t lastfrag;
	struct page *lastpage;
	struct buffer_head *bh;
	u64 phys64;

	lastfrag = (size + uspi->s_fsize - 1) >> uspi->s_fshift;

	if (!lastfrag)
		goto out;

	lastfrag--;

	lastpage = ufs_get_locked_page(mapping, lastfrag >>
				       (PAGE_CACHE_SHIFT - inode->i_blkbits));
       if (IS_ERR(lastpage)) {
               err = -EIO;
               goto out;
       }

       end = lastfrag & ((1 << (PAGE_CACHE_SHIFT - inode->i_blkbits)) - 1);
       bh = page_buffers(lastpage);
       for (i = 0; i < end; ++i)
               bh = bh->b_this_page;


       err = ufs_getfrag_block(inode, lastfrag, bh, 1);

       if (unlikely(err))
	       goto out_unlock;

       if (buffer_new(bh)) {
	       clear_buffer_new(bh);
	       unmap_underlying_metadata(bh->b_bdev,
					 bh->b_blocknr);
	       /*
		* we do not zeroize fragment, because of
		* if it maped to hole, it already contains zeroes
		*/
	       set_buffer_uptodate(bh);
	       mark_buffer_dirty(bh);
	       set_page_dirty(lastpage);
       }

       if (lastfrag >= UFS_IND_FRAGMENT) {
	       end = uspi->s_fpb - ufs_fragnum(lastfrag) - 1;
	       phys64 = bh->b_blocknr + 1;
	       for (i = 0; i < end; ++i) {
		       bh = sb_getblk(sb, i + phys64);
		       lock_buffer(bh);
		       memset(bh->b_data, 0, sb->s_blocksize);
		       set_buffer_uptodate(bh);
		       mark_buffer_dirty(bh);
		       unlock_buffer(bh);
		       sync_dirty_buffer(bh);
		       brelse(bh);
	       }
       }
out_unlock:
       ufs_put_locked_page(lastpage);
out:
       return err;
}

static void __ufs_truncate_blocks(struct inode *inode)
{
	struct ufs_inode_info *ufsi = UFS_I(inode);
	struct super_block *sb = inode->i_sb;
	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
1148
	unsigned offsets[4];
1149
	int depth = ufs_block_to_path(inode, DIRECT_BLOCK, offsets);
1150
	int depth2;
1151
	unsigned i;
A
Al Viro 已提交
1152 1153 1154
	struct ufs_buffer_head *ubh[3];
	void *p;
	u64 block;
1155 1156 1157 1158 1159 1160 1161 1162

	if (!depth)
		return;

	/* find the last non-zero in offsets[] */
	for (depth2 = depth - 1; depth2; depth2--)
		if (offsets[depth2])
			break;
A
Al Viro 已提交
1163 1164

	mutex_lock(&ufsi->truncate_mutex);
1165
	if (depth == 1) {
1166
		ufs_trunc_direct(inode);
1167 1168
		offsets[0] = UFS_IND_BLOCK;
	} else {
A
Al Viro 已提交
1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184
		/* get the blocks that should be partially emptied */
		p = ufs_get_direct_data_ptr(uspi, ufsi, offsets[0]);
		for (i = 0; i < depth2; i++) {
			offsets[i]++;	/* next branch is fully freed */
			block = ufs_data_ptr_to_cpu(sb, p);
			if (!block)
				break;
			ubh[i] = ubh_bread(sb, block, uspi->s_bsize);
			if (!ubh[i]) {
				write_seqlock(&ufsi->meta_lock);
				ufs_data_ptr_clear(uspi, p);
				write_sequnlock(&ufsi->meta_lock);
				break;
			}
			p = ubh_get_data_ptr(uspi, ubh[i], offsets[i + 1]);
		}
1185
		while (i--)
A
Al Viro 已提交
1186
			free_branch_tail(inode, offsets[i + 1], ubh[i], depth - i - 1);
1187 1188
	}
	for (i = offsets[0]; i <= UFS_TIND_BLOCK; i++) {
1189 1190 1191 1192 1193 1194 1195 1196
		p = ufs_get_direct_data_ptr(uspi, ufsi, i);
		block = ufs_data_ptr_to_cpu(sb, p);
		if (block) {
			write_seqlock(&ufsi->meta_lock);
			ufs_data_ptr_clear(uspi, p);
			write_sequnlock(&ufsi->meta_lock);
			free_full_branch(inode, block, i - UFS_IND_BLOCK + 1);
		}
1197
	}
A
Al Viro 已提交
1198
	ufsi->i_lastfrag = DIRECT_FRAGMENT;
1199
	mark_inode_dirty(inode);
A
Al Viro 已提交
1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267
	mutex_unlock(&ufsi->truncate_mutex);
}

static int ufs_truncate(struct inode *inode, loff_t size)
{
	int err = 0;

	UFSD("ENTER: ino %lu, i_size: %llu, old_i_size: %llu\n",
	     inode->i_ino, (unsigned long long)size,
	     (unsigned long long)i_size_read(inode));

	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
	      S_ISLNK(inode->i_mode)))
		return -EINVAL;
	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
		return -EPERM;

	err = ufs_alloc_lastblock(inode, size);

	if (err)
		goto out;

	block_truncate_page(inode->i_mapping, size, ufs_getfrag_block);

	truncate_setsize(inode, size);

	__ufs_truncate_blocks(inode);
	inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
	mark_inode_dirty(inode);
out:
	UFSD("EXIT: err %d\n", err);
	return err;
}

void ufs_truncate_blocks(struct inode *inode)
{
	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
	      S_ISLNK(inode->i_mode)))
		return;
	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
		return;
	__ufs_truncate_blocks(inode);
}

int ufs_setattr(struct dentry *dentry, struct iattr *attr)
{
	struct inode *inode = d_inode(dentry);
	unsigned int ia_valid = attr->ia_valid;
	int error;

	error = inode_change_ok(inode, attr);
	if (error)
		return error;

	if (ia_valid & ATTR_SIZE && attr->ia_size != inode->i_size) {
		error = ufs_truncate(inode, attr->ia_size);
		if (error)
			return error;
	}

	setattr_copy(inode, attr);
	mark_inode_dirty(inode);
	return 0;
}

const struct inode_operations ufs_file_inode_operations = {
	.setattr = ufs_setattr,
};