Blame view

fs/ufs/inode.c 25.1 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
  /*
   *  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 <asm/system.h>
  
  #include <linux/errno.h>
  #include <linux/fs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
34
35
36
  #include <linux/time.h>
  #include <linux/stat.h>
  #include <linux/string.h>
  #include <linux/mm.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
  #include <linux/buffer_head.h>
a9185b41a   Christoph Hellwig   pass writeback_co...
38
  #include <linux/writeback.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39

e54205988   Mike Frysinger   drop linux/ufs_fs...
40
  #include "ufs_fs.h"
bcd6d4ecf   Christoph Hellwig   ufs: move non-lay...
41
  #include "ufs.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
  #include "swab.h"
  #include "util.h"
788257d61   Arnd Bergmann   ufs: remove the BKL
44
  static u64 ufs_frag_map(struct inode *inode, sector_t frag, bool needs_lock);
138bb68ac   Adrian Bunk   [PATCH] fs/ufs/in...
45

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
48
49
50
51
52
53
54
  static int ufs_block_to_path(struct inode *inode, sector_t i_block, sector_t offsets[4])
  {
  	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;
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
55
56
  	UFSD("ptrs=uspi->s_apb = %d,double_blocks=%ld 
  ",ptrs,double_blocks);
37044c86b   Roel Kluin   ufs: sector_t can...
57
  	if (i_block < direct_blocks) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
  		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;
  }
  
  /*
   * Returns the location of the fragment from
25985edce   Lucas De Marchi   Fix common misspe...
79
   * the beginning of the filesystem.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
   */
788257d61   Arnd Bergmann   ufs: remove the BKL
81
  static u64 ufs_frag_map(struct inode *inode, sector_t frag, bool needs_lock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
83
84
85
86
87
88
89
90
91
92
93
94
  {
  	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;
  	sector_t offsets[4], *p;
  	int depth = ufs_block_to_path(inode, frag >> uspi->s_fpbshift, offsets);
  	u64  ret = 0L;
  	__fs32 block;
  	__fs64 u2_block = 0L;
  	unsigned flags = UFS_SB(sb)->s_flags;
  	u64 temp = 0L;
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
95
96
  	UFSD(": frag = %llu  depth = %d
  ", (unsigned long long)frag, depth);
7256d819e   Andrew Morton   [PATCH] ufs: prin...
97
98
99
100
  	UFSD(": uspi->s_fpbshift = %d ,uspi->s_apbmask = %x, mask=%llx
  ",
  		uspi->s_fpbshift, uspi->s_apbmask,
  		(unsigned long long)mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101
102
103
104
105
  
  	if (depth == 0)
  		return 0;
  
  	p = offsets;
788257d61   Arnd Bergmann   ufs: remove the BKL
106
107
  	if (needs_lock)
  		lock_ufs(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
  	if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
  		goto ufs2;
  
  	block = ufsi->i_u1.i_data[*p++];
  	if (!block)
  		goto out;
  	while (--depth) {
  		struct buffer_head *bh;
  		sector_t n = *p++;
  
  		bh = sb_bread(sb, uspi->s_sbbase + fs32_to_cpu(sb, block)+(n>>shift));
  		if (!bh)
  			goto out;
  		block = ((__fs32 *) bh->b_data)[n & mask];
  		brelse (bh);
  		if (!block)
  			goto out;
  	}
  	ret = (u64) (uspi->s_sbbase + fs32_to_cpu(sb, block) + (frag & uspi->s_fpbmask));
  	goto out;
  ufs2:
  	u2_block = ufsi->i_u1.u2_i_data[*p++];
  	if (!u2_block)
  		goto out;
  
  
  	while (--depth) {
  		struct buffer_head *bh;
  		sector_t n = *p++;
  
  
  		temp = (u64)(uspi->s_sbbase) + fs64_to_cpu(sb, u2_block);
  		bh = sb_bread(sb, temp +(u64) (n>>shift));
  		if (!bh)
  			goto out;
  		u2_block = ((__fs64 *)bh->b_data)[n & mask];
  		brelse(bh);
  		if (!u2_block)
  			goto out;
  	}
  	temp = (u64)uspi->s_sbbase + fs64_to_cpu(sb, u2_block);
  	ret = temp + (u64) (frag & uspi->s_fpbmask);
  
  out:
788257d61   Arnd Bergmann   ufs: remove the BKL
152
153
  	if (needs_lock)
  		unlock_ufs(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
155
  	return ret;
  }
022a6dc5f   Evgeniy Dushistov   [PATCH] ufs: zero...
156
157
158
159
160
161
162
163
164
165
166
167
168
169
  /**
   * ufs_inode_getfrag() - allocate new fragment(s)
   * @inode - pointer to inode
   * @fragment - number of `fragment' which hold pointer
   *   to new allocated fragment(s)
   * @new_fragment - number of new allocated fragment(s)
   * @required - how many fragment(s) we require
   * @err - we set it if something wrong
   * @phys - pointer to where we save physical number of new allocated fragments,
   *   NULL if we allocate not data(indirect blocks for example).
   * @new - we set it if we allocate new block
   * @locked_page - for ufs_new_fragments()
   */
  static struct buffer_head *
54fb996ac   Evgeniy Dushistov   [PATCH] ufs2 writ...
170
  ufs_inode_getfrag(struct inode *inode, u64 fragment,
022a6dc5f   Evgeniy Dushistov   [PATCH] ufs: zero...
171
172
  		  sector_t new_fragment, unsigned int required, int *err,
  		  long *phys, int *new, struct page *locked_page)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
174
  {
  	struct ufs_inode_info *ufsi = UFS_I(inode);
022a6dc5f   Evgeniy Dushistov   [PATCH] ufs: zero...
175
176
  	struct super_block *sb = inode->i_sb;
  	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
  	struct buffer_head * result;
54fb996ac   Evgeniy Dushistov   [PATCH] ufs2 writ...
178
179
180
  	unsigned blockoff, lastblockoff;
  	u64 tmp, goal, lastfrag, block, lastblock;
  	void *p, *p2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181

54fb996ac   Evgeniy Dushistov   [PATCH] ufs2 writ...
182
183
184
  	UFSD("ENTER, ino %lu, fragment %llu, new_fragment %llu, required %u, "
  	     "metadata %d
  ", inode->i_ino, (unsigned long long)fragment,
022a6dc5f   Evgeniy Dushistov   [PATCH] ufs: zero...
185
  	     (unsigned long long)new_fragment, required, !phys);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
188
189
190
191
192
193
          /* TODO : to be done for write support
          if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
               goto ufs2;
           */
  
  	block = ufs_fragstoblks (fragment);
  	blockoff = ufs_fragnum (fragment);
54fb996ac   Evgeniy Dushistov   [PATCH] ufs2 writ...
194
  	p = ufs_get_direct_data_ptr(uspi, ufsi, block);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
196
197
  	goal = 0;
  
  repeat:
54fb996ac   Evgeniy Dushistov   [PATCH] ufs2 writ...
198
  	tmp = ufs_data_ptr_to_cpu(sb, p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
  	lastfrag = ufsi->i_lastfrag;
  	if (tmp && fragment < lastfrag) {
022a6dc5f   Evgeniy Dushistov   [PATCH] ufs: zero...
201
  		if (!phys) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
  			result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
54fb996ac   Evgeniy Dushistov   [PATCH] ufs2 writ...
203
204
205
206
  			if (tmp == ufs_data_ptr_to_cpu(sb, p)) {
  				UFSD("EXIT, result %llu
  ",
  				     (unsigned long long)tmp + blockoff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
208
209
210
211
  				return result;
  			}
  			brelse (result);
  			goto repeat;
  		} else {
4b25a37e2   Evgeniy Dushistov   [PATCH] ufs: zero...
212
  			*phys = uspi->s_sbbase + tmp + blockoff;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
214
215
216
217
218
219
220
221
222
223
224
225
226
  			return NULL;
  		}
  	}
  
  	lastblock = ufs_fragstoblks (lastfrag);
  	lastblockoff = ufs_fragnum (lastfrag);
  	/*
  	 * We will extend file into new block beyond last allocated block
  	 */
  	if (lastblock < block) {
  		/*
  		 * We must reallocate last allocated block
  		 */
  		if (lastblockoff) {
54fb996ac   Evgeniy Dushistov   [PATCH] ufs2 writ...
227
228
229
230
231
  			p2 = ufs_get_direct_data_ptr(uspi, ufsi, lastblock);
  			tmp = ufs_new_fragments(inode, p2, lastfrag,
  						ufs_data_ptr_to_cpu(sb, p2),
  						uspi->s_fpb - lastblockoff,
  						err, locked_page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
233
234
235
236
237
238
239
240
  			if (!tmp) {
  				if (lastfrag != ufsi->i_lastfrag)
  					goto repeat;
  				else
  					return NULL;
  			}
  			lastfrag = ufsi->i_lastfrag;
  			
  		}
54fb996ac   Evgeniy Dushistov   [PATCH] ufs2 writ...
241
242
243
  		tmp = ufs_data_ptr_to_cpu(sb,
  					 ufs_get_direct_data_ptr(uspi, ufsi,
  								 lastblock));
c37336b07   Evgeniy Dushistov   [PATCH] ufs: writ...
244
245
  		if (tmp)
  			goal = tmp + uspi->s_fpb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
  		tmp = ufs_new_fragments (inode, p, fragment - blockoff, 
6ef4d6bf8   Evgeniy Dushistov   [PATCH] ufs: chan...
247
  					 goal, required + blockoff,
a685e26ff   Evgeniy Dushistov   [PATCH] ufs: allo...
248
249
  					 err,
  					 phys != NULL ? locked_page : NULL);
54fb996ac   Evgeniy Dushistov   [PATCH] ufs2 writ...
250
  	} else if (lastblock == block) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251
252
253
  	/*
  	 * We will extend last allocated block
  	 */
54fb996ac   Evgeniy Dushistov   [PATCH] ufs2 writ...
254
255
256
257
  		tmp = ufs_new_fragments(inode, p, fragment -
  					(blockoff - lastblockoff),
  					ufs_data_ptr_to_cpu(sb, p),
  					required +  (blockoff - lastblockoff),
a685e26ff   Evgeniy Dushistov   [PATCH] ufs: allo...
258
  					err, phys != NULL ? locked_page : NULL);
c37336b07   Evgeniy Dushistov   [PATCH] ufs: writ...
259
  	} else /* (lastblock > block) */ {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
261
262
  	/*
  	 * We will allocate new block before last allocated block
  	 */
c37336b07   Evgeniy Dushistov   [PATCH] ufs: writ...
263
  		if (block) {
54fb996ac   Evgeniy Dushistov   [PATCH] ufs2 writ...
264
265
  			tmp = ufs_data_ptr_to_cpu(sb,
  						 ufs_get_direct_data_ptr(uspi, ufsi, block - 1));
c37336b07   Evgeniy Dushistov   [PATCH] ufs: writ...
266
267
268
  			if (tmp)
  				goal = tmp + uspi->s_fpb;
  		}
6ef4d6bf8   Evgeniy Dushistov   [PATCH] ufs: chan...
269
  		tmp = ufs_new_fragments(inode, p, fragment - blockoff,
a685e26ff   Evgeniy Dushistov   [PATCH] ufs: allo...
270
271
  					goal, uspi->s_fpb, err,
  					phys != NULL ? locked_page : NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
273
  	}
  	if (!tmp) {
54fb996ac   Evgeniy Dushistov   [PATCH] ufs2 writ...
274
  		if ((!blockoff && ufs_data_ptr_to_cpu(sb, p)) ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275
276
277
278
279
  		    (blockoff && lastfrag != ufsi->i_lastfrag))
  			goto repeat;
  		*err = -ENOSPC;
  		return NULL;
  	}
022a6dc5f   Evgeniy Dushistov   [PATCH] ufs: zero...
280
  	if (!phys) {
4b25a37e2   Evgeniy Dushistov   [PATCH] ufs: zero...
281
  		result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
  	} else {
4b25a37e2   Evgeniy Dushistov   [PATCH] ufs: zero...
283
  		*phys = uspi->s_sbbase + tmp + blockoff;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
285
286
287
288
289
290
291
292
  		result = NULL;
  		*err = 0;
  		*new = 1;
  	}
  
  	inode->i_ctime = CURRENT_TIME_SEC;
  	if (IS_SYNC(inode))
  		ufs_sync_inode (inode);
  	mark_inode_dirty(inode);
54fb996ac   Evgeniy Dushistov   [PATCH] ufs2 writ...
293
294
  	UFSD("EXIT, result %llu
  ", (unsigned long long)tmp + blockoff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
  	return result;
  
       /* 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;
  
       */
  }
022a6dc5f   Evgeniy Dushistov   [PATCH] ufs: zero...
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
  /**
   * ufs_inode_getblock() - allocate new block
   * @inode - pointer to inode
   * @bh - pointer to block which hold "pointer" to new allocated block
   * @fragment - number of `fragment' which hold pointer
   *   to new allocated block
   * @new_fragment - number of new allocated fragment
   *  (block will hold this fragment and also uspi->s_fpb-1)
   * @err - see ufs_inode_getfrag()
   * @phys - see ufs_inode_getfrag()
   * @new - see ufs_inode_getfrag()
   * @locked_page - see ufs_inode_getfrag()
   */
  static struct buffer_head *
  ufs_inode_getblock(struct inode *inode, struct buffer_head *bh,
54fb996ac   Evgeniy Dushistov   [PATCH] ufs2 writ...
327
  		  u64 fragment, sector_t new_fragment, int *err,
022a6dc5f   Evgeniy Dushistov   [PATCH] ufs: zero...
328
  		  long *phys, int *new, struct page *locked_page)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
  {
022a6dc5f   Evgeniy Dushistov   [PATCH] ufs: zero...
330
331
  	struct super_block *sb = inode->i_sb;
  	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
332
  	struct buffer_head * result;
54fb996ac   Evgeniy Dushistov   [PATCH] ufs2 writ...
333
334
335
  	unsigned blockoff;
  	u64 tmp, goal, block;
  	void *p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
338
  	block = ufs_fragstoblks (fragment);
  	blockoff = ufs_fragnum (fragment);
54fb996ac   Evgeniy Dushistov   [PATCH] ufs2 writ...
339
340
341
342
  	UFSD("ENTER, ino %lu, fragment %llu, new_fragment %llu, metadata %d
  ",
  	     inode->i_ino, (unsigned long long)fragment,
  	     (unsigned long long)new_fragment, !phys);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
344
345
346
347
348
349
350
351
352
  
  	result = NULL;
  	if (!bh)
  		goto out;
  	if (!buffer_uptodate(bh)) {
  		ll_rw_block (READ, 1, &bh);
  		wait_on_buffer (bh);
  		if (!buffer_uptodate(bh))
  			goto out;
  	}
54fb996ac   Evgeniy Dushistov   [PATCH] ufs2 writ...
353
354
355
356
  	if (uspi->fs_magic == UFS2_MAGIC)
  		p = (__fs64 *)bh->b_data + block;
  	else
  		p = (__fs32 *)bh->b_data + block;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357
  repeat:
54fb996ac   Evgeniy Dushistov   [PATCH] ufs2 writ...
358
  	tmp = ufs_data_ptr_to_cpu(sb, p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359
  	if (tmp) {
022a6dc5f   Evgeniy Dushistov   [PATCH] ufs: zero...
360
  		if (!phys) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
361
  			result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
54fb996ac   Evgeniy Dushistov   [PATCH] ufs2 writ...
362
  			if (tmp == ufs_data_ptr_to_cpu(sb, p))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
364
365
366
  				goto out;
  			brelse (result);
  			goto repeat;
  		} else {
4b25a37e2   Evgeniy Dushistov   [PATCH] ufs: zero...
367
  			*phys = uspi->s_sbbase + tmp + blockoff;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368
369
370
  			goto out;
  		}
  	}
54fb996ac   Evgeniy Dushistov   [PATCH] ufs2 writ...
371
372
373
  	if (block && (uspi->fs_magic == UFS2_MAGIC ?
  		      (tmp = fs64_to_cpu(sb, ((__fs64 *)bh->b_data)[block-1])) :
  		      (tmp = fs32_to_cpu(sb, ((__fs32 *)bh->b_data)[block-1]))))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374
375
376
  		goal = tmp + uspi->s_fpb;
  	else
  		goal = bh->b_blocknr + uspi->s_fpb;
6ef4d6bf8   Evgeniy Dushistov   [PATCH] ufs: chan...
377
378
  	tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment), goal,
  				uspi->s_fpb, err, locked_page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
  	if (!tmp) {
54fb996ac   Evgeniy Dushistov   [PATCH] ufs2 writ...
380
  		if (ufs_data_ptr_to_cpu(sb, p))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381
382
383
  			goto repeat;
  		goto out;
  	}		
c9a27b5dc   Evgeniy Dushistov   [PATCH] ufs: righ...
384

022a6dc5f   Evgeniy Dushistov   [PATCH] ufs: zero...
385
  	if (!phys) {
4b25a37e2   Evgeniy Dushistov   [PATCH] ufs: zero...
386
  		result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387
  	} else {
4b25a37e2   Evgeniy Dushistov   [PATCH] ufs: zero...
388
  		*phys = uspi->s_sbbase + tmp + blockoff;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
390
391
392
393
394
395
396
  		*new = 1;
  	}
  
  	mark_buffer_dirty(bh);
  	if (IS_SYNC(inode))
  		sync_dirty_buffer(bh);
  	inode->i_ctime = CURRENT_TIME_SEC;
  	mark_inode_dirty(inode);
54fb996ac   Evgeniy Dushistov   [PATCH] ufs2 writ...
397
398
  	UFSD("result %llu
  ", (unsigned long long)tmp + blockoff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399
400
  out:
  	brelse (bh);
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
401
402
  	UFSD("EXIT
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
404
  	return result;
  }
022a6dc5f   Evgeniy Dushistov   [PATCH] ufs: zero...
405
  /**
7422caa5a   Alessio Igor Bogani   ufs: Fix a typo
406
   * ufs_getfrag_block() - `get_block_t' function, interface between UFS and
022a6dc5f   Evgeniy Dushistov   [PATCH] ufs: zero...
407
   * readpage, writepage and so on
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408
   */
022a6dc5f   Evgeniy Dushistov   [PATCH] ufs: zero...
409
  int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410
411
  {
  	struct super_block * sb = inode->i_sb;
788257d61   Arnd Bergmann   ufs: remove the BKL
412
413
  	struct ufs_sb_info * sbi = UFS_SB(sb);
  	struct ufs_sb_private_info * uspi = sbi->s_uspi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
414
415
416
417
  	struct buffer_head * bh;
  	int ret, err, new;
  	unsigned long ptr,phys;
  	u64 phys64 = 0;
788257d61   Arnd Bergmann   ufs: remove the BKL
418
  	bool needs_lock = (sbi->mutex_owner != current);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
420
  	
  	if (!create) {
788257d61   Arnd Bergmann   ufs: remove the BKL
421
  		phys64 = ufs_frag_map(inode, fragment, needs_lock);
7256d819e   Andrew Morton   [PATCH] ufs: prin...
422
423
  		UFSD("phys64 = %llu
  ", (unsigned long long)phys64);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
425
426
427
428
429
430
431
432
433
434
  		if (phys64)
  			map_bh(bh_result, sb, phys64);
  		return 0;
  	}
  
          /* This code entered only while writing ....? */
  
  	err = -EIO;
  	new = 0;
  	ret = 0;
  	bh = NULL;
788257d61   Arnd Bergmann   ufs: remove the BKL
435
436
  	if (needs_lock)
  		lock_ufs(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437

abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
438
439
  	UFSD("ENTER, ino %lu, fragment %llu
  ", inode->i_ino, (unsigned long long)fragment);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
440
441
442
443
444
445
446
447
448
449
450
451
452
  	if (fragment >
  	    ((UFS_NDADDR + uspi->s_apb + uspi->s_2apb + uspi->s_3apb)
  	     << uspi->s_fpbshift))
  		goto abort_too_big;
  
  	err = 0;
  	ptr = fragment;
  	  
  	/*
  	 * ok, these macros clean the logic up a bit and make
  	 * it much more readable:
  	 */
  #define GET_INODE_DATABLOCK(x) \
a685e26ff   Evgeniy Dushistov   [PATCH] ufs: allo...
453
454
  	ufs_inode_getfrag(inode, x, fragment, 1, &err, &phys, &new,\
  			  bh_result->b_page)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455
  #define GET_INODE_PTR(x) \
a685e26ff   Evgeniy Dushistov   [PATCH] ufs: allo...
456
457
  	ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, NULL, NULL,\
  			  bh_result->b_page)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
  #define GET_INDIRECT_DATABLOCK(x) \
022a6dc5f   Evgeniy Dushistov   [PATCH] ufs: zero...
459
  	ufs_inode_getblock(inode, bh, x, fragment,	\
d63b70902   Evgeniy Dushistov   [PATCH] fix garba...
460
  			  &err, &phys, &new, bh_result->b_page)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
461
  #define GET_INDIRECT_PTR(x) \
022a6dc5f   Evgeniy Dushistov   [PATCH] ufs: zero...
462
  	ufs_inode_getblock(inode, bh, x, fragment,	\
d63b70902   Evgeniy Dushistov   [PATCH] fix garba...
463
  			  &err, NULL, NULL, NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
  
  	if (ptr < UFS_NDIR_FRAGMENT) {
  		bh = GET_INODE_DATABLOCK(ptr);
  		goto out;
  	}
  	ptr -= UFS_NDIR_FRAGMENT;
  	if (ptr < (1 << (uspi->s_apbshift + uspi->s_fpbshift))) {
  		bh = GET_INODE_PTR(UFS_IND_FRAGMENT + (ptr >> uspi->s_apbshift));
  		goto get_indirect;
  	}
  	ptr -= 1 << (uspi->s_apbshift + uspi->s_fpbshift);
  	if (ptr < (1 << (uspi->s_2apbshift + uspi->s_fpbshift))) {
  		bh = GET_INODE_PTR(UFS_DIND_FRAGMENT + (ptr >> uspi->s_2apbshift));
  		goto get_double;
  	}
  	ptr -= 1 << (uspi->s_2apbshift + uspi->s_fpbshift);
  	bh = GET_INODE_PTR(UFS_TIND_FRAGMENT + (ptr >> uspi->s_3apbshift));
  	bh = GET_INDIRECT_PTR((ptr >> uspi->s_2apbshift) & uspi->s_apbmask);
  get_double:
  	bh = GET_INDIRECT_PTR((ptr >> uspi->s_apbshift) & uspi->s_apbmask);
  get_indirect:
  	bh = GET_INDIRECT_DATABLOCK(ptr & uspi->s_apbmask);
  
  #undef GET_INODE_DATABLOCK
  #undef GET_INODE_PTR
  #undef GET_INDIRECT_DATABLOCK
  #undef GET_INDIRECT_PTR
  
  out:
  	if (err)
  		goto abort;
  	if (new)
  		set_buffer_new(bh_result);
  	map_bh(bh_result, sb, phys);
  abort:
788257d61   Arnd Bergmann   ufs: remove the BKL
499
500
  	if (needs_lock)
  		unlock_ufs(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
503
504
505
  abort_too_big:
  	ufs_warning(sb, "ufs_get_block", "block > big");
  	goto abort;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
506
507
508
509
  static int ufs_writepage(struct page *page, struct writeback_control *wbc)
  {
  	return block_write_full_page(page,ufs_getfrag_block,wbc);
  }
82b9d1d0d   Nick Piggin   ufs: convert to n...
510

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
512
513
514
  static int ufs_readpage(struct file *file, struct page *page)
  {
  	return block_read_full_page(page,ufs_getfrag_block);
  }
82b9d1d0d   Nick Piggin   ufs: convert to n...
515

f4e420dc4   Christoph Hellwig   clean up write_be...
516
  int ufs_prepare_chunk(struct page *page, loff_t pos, unsigned len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517
  {
6e1db88d5   Christoph Hellwig   introduce __block...
518
  	return __block_write_begin(page, pos, len, ufs_getfrag_block);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
519
  }
82b9d1d0d   Nick Piggin   ufs: convert to n...
520
521
522
523
524
  
  static int ufs_write_begin(struct file *file, struct address_space *mapping,
  			loff_t pos, unsigned len, unsigned flags,
  			struct page **pagep, void **fsdata)
  {
155130a4f   Christoph Hellwig   get rid of block_...
525
526
527
  	int ret;
  
  	ret = block_write_begin(mapping, pos, len, flags, pagep,
f4e420dc4   Christoph Hellwig   clean up write_be...
528
  				ufs_getfrag_block);
155130a4f   Christoph Hellwig   get rid of block_...
529
530
531
532
533
534
535
  	if (unlikely(ret)) {
  		loff_t isize = mapping->host->i_size;
  		if (pos + len > isize)
  			vmtruncate(mapping->host, isize);
  	}
  
  	return ret;
82b9d1d0d   Nick Piggin   ufs: convert to n...
536
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
537
538
539
540
  static sector_t ufs_bmap(struct address_space *mapping, sector_t block)
  {
  	return generic_block_bmap(mapping,block,ufs_getfrag_block);
  }
82b9d1d0d   Nick Piggin   ufs: convert to n...
541

f5e54d6e5   Christoph Hellwig   [PATCH] mark addr...
542
  const struct address_space_operations ufs_aops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
543
544
  	.readpage = ufs_readpage,
  	.writepage = ufs_writepage,
82b9d1d0d   Nick Piggin   ufs: convert to n...
545
546
  	.write_begin = ufs_write_begin,
  	.write_end = generic_write_end,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
548
  	.bmap = ufs_bmap
  };
826843a34   Evgeniy Dushistov   [PATCH] ufs: dire...
549
550
551
552
553
554
555
556
557
558
559
560
561
562
  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)) {
  		if (!inode->i_blocks)
  			inode->i_op = &ufs_fast_symlink_inode_operations;
  		else {
311b9549e   Dmitry Monakhov   ufs: add ufs spec...
563
  			inode->i_op = &ufs_symlink_inode_operations;
826843a34   Evgeniy Dushistov   [PATCH] ufs: dire...
564
565
566
567
568
569
  			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)));
  }
07a0cfec3   Evgeniy Dushistov   ufs proper handli...
570
  static int ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
572
  {
  	struct ufs_inode_info *ufsi = UFS_I(inode);
05f225dc8   Evgeniy Dushistov   [PATCH] ufs: ufs_...
573
  	struct super_block *sb = inode->i_sb;
6a9a06d9c   Al Viro   ufs: propagate um...
574
  	umode_t mode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575
576
577
578
579
  
  	/*
  	 * Copy data to the in-core inode.
  	 */
  	inode->i_mode = mode = fs16_to_cpu(sb, ufs_inode->ui_mode);
bfe868486   Miklos Szeredi   filesystems: add ...
580
  	set_nlink(inode, fs16_to_cpu(sb, ufs_inode->ui_nlink));
07a0cfec3   Evgeniy Dushistov   ufs proper handli...
581
  	if (inode->i_nlink == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582
583
  		ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink
  ", inode->i_ino);
07a0cfec3   Evgeniy Dushistov   ufs proper handli...
584
585
  		return -1;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
  	
  	/*
  	 * Linux now has 32-bit uid and gid, so we can support EFT.
  	 */
  	inode->i_uid = ufs_get_inode_uid(sb, ufs_inode);
  	inode->i_gid = ufs_get_inode_gid(sb, ufs_inode);
  
  	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);
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
601
  	inode->i_generation = fs32_to_cpu(sb, ufs_inode->ui_gen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
602
  	ufsi->i_flags = fs32_to_cpu(sb, ufs_inode->ui_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603
604
  	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);
05f225dc8   Evgeniy Dushistov   [PATCH] ufs: ufs_...
605

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
606
607
  	
  	if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) {
f33219b7a   Duane Griffin   ufs: don't trunca...
608
609
  		memcpy(ufsi->i_u1.i_data, &ufs_inode->ui_u2.ui_addr,
  		       sizeof(ufs_inode->ui_u2.ui_addr));
dd187a260   Evgeniy Dushistov   [PATCH] ufs: litt...
610
  	} else {
f33219b7a   Duane Griffin   ufs: don't trunca...
611
  		memcpy(ufsi->i_u1.i_symlink, ufs_inode->ui_u2.ui_symlink,
b12903f13   Duane Griffin   ufs: ensure fast ...
612
613
  		       sizeof(ufs_inode->ui_u2.ui_symlink) - 1);
  		ufsi->i_u1.i_symlink[sizeof(ufs_inode->ui_u2.ui_symlink) - 1] = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
614
  	}
07a0cfec3   Evgeniy Dushistov   ufs proper handli...
615
  	return 0;
05f225dc8   Evgeniy Dushistov   [PATCH] ufs: ufs_...
616
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
617

07a0cfec3   Evgeniy Dushistov   ufs proper handli...
618
  static int ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode)
05f225dc8   Evgeniy Dushistov   [PATCH] ufs: ufs_...
619
620
621
  {
  	struct ufs_inode_info *ufsi = UFS_I(inode);
  	struct super_block *sb = inode->i_sb;
6a9a06d9c   Al Viro   ufs: propagate um...
622
  	umode_t mode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
623

abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
624
625
  	UFSD("Reading ufs2 inode, ino %lu
  ", inode->i_ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626
627
628
629
  	/*
  	 * Copy data to the in-core inode.
  	 */
  	inode->i_mode = mode = fs16_to_cpu(sb, ufs2_inode->ui_mode);
bfe868486   Miklos Szeredi   filesystems: add ...
630
  	set_nlink(inode, fs16_to_cpu(sb, ufs2_inode->ui_nlink));
07a0cfec3   Evgeniy Dushistov   ufs proper handli...
631
  	if (inode->i_nlink == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
633
  		ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink
  ", inode->i_ino);
07a0cfec3   Evgeniy Dushistov   ufs proper handli...
634
635
  		return -1;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
636
637
638
639
640
641
642
643
  
          /*
           * Linux now has 32-bit uid and gid, so we can support EFT.
           */
  	inode->i_uid = fs32_to_cpu(sb, ufs2_inode->ui_uid);
  	inode->i_gid = fs32_to_cpu(sb, ufs2_inode->ui_gid);
  
  	inode->i_size = fs64_to_cpu(sb, ufs2_inode->ui_size);
2189850f4   Evgeniy Dushistov   [PATCH] ufs2: mor...
644
645
646
647
648
649
  	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);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
  	inode->i_blocks = fs64_to_cpu(sb, ufs2_inode->ui_blocks);
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
651
  	inode->i_generation = fs32_to_cpu(sb, ufs2_inode->ui_gen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
652
  	ufsi->i_flags = fs32_to_cpu(sb, ufs2_inode->ui_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653
654
655
656
  	/*
  	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);
  	*/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
657
658
  
  	if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) {
f33219b7a   Duane Griffin   ufs: don't trunca...
659
660
  		memcpy(ufsi->i_u1.u2_i_data, &ufs2_inode->ui_u2.ui_addr,
  		       sizeof(ufs2_inode->ui_u2.ui_addr));
05f225dc8   Evgeniy Dushistov   [PATCH] ufs: ufs_...
661
  	} else {
f33219b7a   Duane Griffin   ufs: don't trunca...
662
  		memcpy(ufsi->i_u1.i_symlink, ufs2_inode->ui_u2.ui_symlink,
b12903f13   Duane Griffin   ufs: ensure fast ...
663
664
  		       sizeof(ufs2_inode->ui_u2.ui_symlink) - 1);
  		ufsi->i_u1.i_symlink[sizeof(ufs2_inode->ui_u2.ui_symlink) - 1] = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
665
  	}
07a0cfec3   Evgeniy Dushistov   ufs proper handli...
666
  	return 0;
05f225dc8   Evgeniy Dushistov   [PATCH] ufs: ufs_...
667
  }
b55c460da   David Howells   iget: stop UFS fr...
668
  struct inode *ufs_iget(struct super_block *sb, unsigned long ino)
05f225dc8   Evgeniy Dushistov   [PATCH] ufs: ufs_...
669
  {
b55c460da   David Howells   iget: stop UFS fr...
670
671
  	struct ufs_inode_info *ufsi;
  	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
05f225dc8   Evgeniy Dushistov   [PATCH] ufs: ufs_...
672
  	struct buffer_head * bh;
b55c460da   David Howells   iget: stop UFS fr...
673
  	struct inode *inode;
07a0cfec3   Evgeniy Dushistov   ufs proper handli...
674
  	int err;
05f225dc8   Evgeniy Dushistov   [PATCH] ufs: ufs_...
675

b55c460da   David Howells   iget: stop UFS fr...
676
677
  	UFSD("ENTER, ino %lu
  ", ino);
05f225dc8   Evgeniy Dushistov   [PATCH] ufs: ufs_...
678

b55c460da   David Howells   iget: stop UFS fr...
679
  	if (ino < UFS_ROOTINO || ino > (uspi->s_ncg * uspi->s_ipg)) {
05f225dc8   Evgeniy Dushistov   [PATCH] ufs: ufs_...
680
681
  		ufs_warning(sb, "ufs_read_inode", "bad inode number (%lu)
  ",
b55c460da   David Howells   iget: stop UFS fr...
682
683
  			    ino);
  		return ERR_PTR(-EIO);
05f225dc8   Evgeniy Dushistov   [PATCH] ufs: ufs_...
684
  	}
b55c460da   David Howells   iget: stop UFS fr...
685
686
687
688
689
690
691
  	inode = iget_locked(sb, ino);
  	if (!inode)
  		return ERR_PTR(-ENOMEM);
  	if (!(inode->i_state & I_NEW))
  		return inode;
  
  	ufsi = UFS_I(inode);
05f225dc8   Evgeniy Dushistov   [PATCH] ufs: ufs_...
692
693
694
695
696
697
698
699
700
  	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
  ",
  			    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;
07a0cfec3   Evgeniy Dushistov   ufs proper handli...
701
702
  		err = ufs2_read_inode(inode,
  				      ufs2_inode + ufs_inotofsbo(inode->i_ino));
05f225dc8   Evgeniy Dushistov   [PATCH] ufs: ufs_...
703
704
  	} else {
  		struct ufs_inode *ufs_inode = (struct ufs_inode *)bh->b_data;
07a0cfec3   Evgeniy Dushistov   ufs proper handli...
705
706
  		err = ufs1_read_inode(inode,
  				      ufs_inode + ufs_inotofsbo(inode->i_ino));
05f225dc8   Evgeniy Dushistov   [PATCH] ufs: ufs_...
707
  	}
07a0cfec3   Evgeniy Dushistov   ufs proper handli...
708
709
  	if (err)
  		goto bad_inode;
05f225dc8   Evgeniy Dushistov   [PATCH] ufs: ufs_...
710
711
712
713
  	inode->i_version++;
  	ufsi->i_lastfrag =
  		(inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift;
  	ufsi->i_dir_start_lookup = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
714
  	ufsi->i_osync = 0;
826843a34   Evgeniy Dushistov   [PATCH] ufs: dire...
715
  	ufs_set_inode_ops(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
716
717
  
  	brelse(bh);
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
718
719
  	UFSD("EXIT
  ");
b55c460da   David Howells   iget: stop UFS fr...
720
721
  	unlock_new_inode(inode);
  	return inode;
05f225dc8   Evgeniy Dushistov   [PATCH] ufs: ufs_...
722
723
  
  bad_inode:
b55c460da   David Howells   iget: stop UFS fr...
724
725
  	iget_failed(inode);
  	return ERR_PTR(-EIO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
726
  }
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
727
  static void ufs1_update_inode(struct inode *inode, struct ufs_inode *ufs_inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
728
  {
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
729
730
  	struct super_block *sb = inode->i_sb;
   	struct ufs_inode_info *ufsi = UFS_I(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
  
  	ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode);
  	ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink);
  
  	ufs_set_inode_uid(sb, ufs_inode, inode->i_uid);
  	ufs_set_inode_gid(sb, ufs_inode, inode->i_gid);
  		
  	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);
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
747
  	ufs_inode->ui_gen = cpu_to_fs32(sb, inode->i_generation);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
748

3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
749
  	if ((UFS_SB(sb)->s_flags & UFS_UID_MASK) == UFS_UID_EFT) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
750
751
752
753
754
755
756
757
  		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) {
f33219b7a   Duane Griffin   ufs: don't trunca...
758
759
  		memcpy(&ufs_inode->ui_u2.ui_addr, ufsi->i_u1.i_data,
  		       sizeof(ufs_inode->ui_u2.ui_addr));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
760
761
  	}
  	else {
f33219b7a   Duane Griffin   ufs: don't trunca...
762
763
  		memcpy(&ufs_inode->ui_u2.ui_symlink, ufsi->i_u1.i_symlink,
  		       sizeof(ufs_inode->ui_u2.ui_symlink));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
765
766
767
  	}
  
  	if (!inode->i_nlink)
  		memset (ufs_inode, 0, sizeof(struct ufs_inode));
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
768
769
770
771
772
773
  }
  
  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);
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
774
775
776
777
778
779
780
781
782
783
  
  	UFSD("ENTER
  ");
  	ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode);
  	ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink);
  
  	ufs_inode->ui_uid = cpu_to_fs32(sb, inode->i_uid);
  	ufs_inode->ui_gid = cpu_to_fs32(sb, inode->i_gid);
  
  	ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size);
2189850f4   Evgeniy Dushistov   [PATCH] ufs2: mor...
784
785
786
787
788
789
  	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);
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
790
791
792
793
794
795
796
797
798
  
  	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) {
f33219b7a   Duane Griffin   ufs: don't trunca...
799
800
  		memcpy(&ufs_inode->ui_u2.ui_addr, ufsi->i_u1.u2_i_data,
  		       sizeof(ufs_inode->ui_u2.ui_addr));
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
801
  	} else {
f33219b7a   Duane Griffin   ufs: don't trunca...
802
803
  		memcpy(&ufs_inode->ui_u2.ui_symlink, ufsi->i_u1.i_symlink,
  		       sizeof(ufs_inode->ui_u2.ui_symlink));
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
804
805
806
807
808
809
810
811
812
813
814
815
816
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
   	}
  
  	if (!inode->i_nlink)
  		memset (ufs_inode, 0, sizeof(struct ufs2_inode));
  	UFSD("EXIT
  ");
  }
  
  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
  ", 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)
  ", 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
  ", 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));
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
844
845
846
847
848
849
  		
  	mark_buffer_dirty(bh);
  	if (do_sync)
  		sync_dirty_buffer(bh);
  	brelse (bh);
  	
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
850
851
  	UFSD("EXIT
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
852
853
  	return 0;
  }
a9185b41a   Christoph Hellwig   pass writeback_co...
854
  int ufs_write_inode(struct inode *inode, struct writeback_control *wbc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
855
856
  {
  	int ret;
788257d61   Arnd Bergmann   ufs: remove the BKL
857
  	lock_ufs(inode->i_sb);
a9185b41a   Christoph Hellwig   pass writeback_co...
858
  	ret = ufs_update_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
788257d61   Arnd Bergmann   ufs: remove the BKL
859
  	unlock_ufs(inode->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
860
861
862
863
864
865
866
  	return ret;
  }
  
  int ufs_sync_inode (struct inode *inode)
  {
  	return ufs_update_inode (inode, 1);
  }
58e8268c7   Al Viro   switch ufs to ->e...
867
  void ufs_evict_inode(struct inode * inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
868
  {
58e8268c7   Al Viro   switch ufs to ->e...
869
870
871
872
  	int want_delete = 0;
  
  	if (!inode->i_nlink && !is_bad_inode(inode))
  		want_delete = 1;
10e5dce07   Evgeniy Dushistov   [PATCH] ufs: trun...
873

fef266580   Mark Fasheh   [PATCH] update fi...
874
  	truncate_inode_pages(&inode->i_data, 0);
58e8268c7   Al Viro   switch ufs to ->e...
875
876
877
  	if (want_delete) {
  		loff_t old_i_size;
  		/*UFS_I(inode)->i_dtime = CURRENT_TIME;*/
788257d61   Arnd Bergmann   ufs: remove the BKL
878
  		lock_ufs(inode->i_sb);
58e8268c7   Al Viro   switch ufs to ->e...
879
880
881
882
883
884
885
  		mark_inode_dirty(inode);
  		ufs_update_inode(inode, IS_SYNC(inode));
  		old_i_size = inode->i_size;
  		inode->i_size = 0;
  		if (inode->i_blocks && ufs_truncate(inode, old_i_size))
  			ufs_warning(inode->i_sb, __func__, "ufs_truncate failed
  ");
788257d61   Arnd Bergmann   ufs: remove the BKL
886
  		unlock_ufs(inode->i_sb);
58e8268c7   Al Viro   switch ufs to ->e...
887
888
889
890
891
892
  	}
  
  	invalidate_inode_buffers(inode);
  	end_writeback(inode);
  
  	if (want_delete) {
788257d61   Arnd Bergmann   ufs: remove the BKL
893
  		lock_ufs(inode->i_sb);
58e8268c7   Al Viro   switch ufs to ->e...
894
  		ufs_free_inode (inode);
788257d61   Arnd Bergmann   ufs: remove the BKL
895
  		unlock_ufs(inode->i_sb);
58e8268c7   Al Viro   switch ufs to ->e...
896
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
897
  }