Blame view

fs/ufs/super.c 44.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
33
34
35
36
37
38
39
40
41
42
43
  /*
   *  linux/fs/ufs/super.c
   *
   * Copyright (C) 1998
   * Daniel Pirkl <daniel.pirkl@email.cz>
   * Charles University, Faculty of Mathematics and Physics
   */
  
  /* Derived from
   *
   *  linux/fs/ext2/super.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
   *
   *  Big-endian to little-endian byte-swapping/bitmaps by
   *        David S. Miller (davem@caip.rutgers.edu), 1995
   */
   
  /*
   * Inspired by
   *
   *  linux/fs/ufs/super.c
   *
   * Copyright (C) 1996
   * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
   * Laboratory for Computer Science Research Computing Facility
   * Rutgers, The State University of New Jersey
   *
   * Copyright (C) 1996  Eddie C. Dost  (ecd@skynet.be)
   *
   * Kernel module support added on 96/04/26 by
   * Stefan Reinauer <stepan@home.culture.mipt.ru>
   *
   * Module usage counts added on 96/04/29 by
f762dd682   Gertjan van Wingerde   Update my email a...
44
   * Gertjan van Wingerde <gwingerde@gmail.com>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
   *
   * Clean swab support on 19970406 by
   * Francois-Rene Rideau <fare@tunes.org>
   *
   * 4.4BSD (FreeBSD) support added on February 1st 1998 by
   * Niels Kristian Bech Jensen <nkbj@image.dk> partially based
   * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>.
   *
   * NeXTstep support added on February 5th 1998 by
   * Niels Kristian Bech Jensen <nkbj@image.dk>.
   *
   * write support Daniel Pirkl <daniel.pirkl@email.cz> 1998
   * 
   * HP/UX hfs filesystem support added by
   * Martin K. Petersen <mkp@mkp.net>, August 1999
   *
   * UFS2 (of FreeBSD 5.x) support added by
   * Niraj Kumar <niraj17@iitbombay.org>, Jan 2004
   *
cbcae39fa   Evgeniy Dushistov   [PATCH] ufs2 writ...
64
65
   * UFS2 write support added by
   * Evgeniy Dushistov <dushistov@mail.ru>, 2007
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
   */
f3e2a520f   Alexey Dobriyan   ufs: NFS support
67
  #include <linux/exportfs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
69
70
71
72
73
  #include <linux/module.h>
  #include <linux/bitops.h>
  
  #include <stdarg.h>
  
  #include <asm/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
76
  
  #include <linux/errno.h>
  #include <linux/fs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
78
79
80
81
82
83
  #include <linux/slab.h>
  #include <linux/time.h>
  #include <linux/stat.h>
  #include <linux/string.h>
  #include <linux/blkdev.h>
  #include <linux/init.h>
  #include <linux/parser.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
85
  #include <linux/buffer_head.h>
  #include <linux/vfs.h>
9e8c4273e   vignesh babu   is_power_of_2: uf...
86
  #include <linux/log2.h>
2a9807c0d   Evgeniy Dushistov   ufs: implement sh...
87
88
  #include <linux/mount.h>
  #include <linux/seq_file.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89

e54205988   Mike Frysinger   drop linux/ufs_fs...
90
  #include "ufs_fs.h"
bcd6d4ecf   Christoph Hellwig   ufs: move non-lay...
91
  #include "ufs.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
93
  #include "swab.h"
  #include "util.h"
788257d61   Arnd Bergmann   ufs: remove the BKL
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
  void lock_ufs(struct super_block *sb)
  {
  #if defined(CONFIG_SMP) || defined (CONFIG_PREEMPT)
  	struct ufs_sb_info *sbi = UFS_SB(sb);
  
  	mutex_lock(&sbi->mutex);
  	sbi->mutex_owner = current;
  #endif
  }
  
  void unlock_ufs(struct super_block *sb)
  {
  #if defined(CONFIG_SMP) || defined (CONFIG_PREEMPT)
  	struct ufs_sb_info *sbi = UFS_SB(sb);
  
  	sbi->mutex_owner = NULL;
  	mutex_unlock(&sbi->mutex);
  #endif
  }
f3e2a520f   Alexey Dobriyan   ufs: NFS support
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
  static struct inode *ufs_nfs_get_inode(struct super_block *sb, u64 ino, u32 generation)
  {
  	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
  	struct inode *inode;
  
  	if (ino < UFS_ROOTINO || ino > uspi->s_ncg * uspi->s_ipg)
  		return ERR_PTR(-ESTALE);
  
  	inode = ufs_iget(sb, ino);
  	if (IS_ERR(inode))
  		return ERR_CAST(inode);
  	if (generation && inode->i_generation != generation) {
  		iput(inode);
  		return ERR_PTR(-ESTALE);
  	}
  	return inode;
  }
  
  static struct dentry *ufs_fh_to_dentry(struct super_block *sb, struct fid *fid,
  				       int fh_len, int fh_type)
  {
  	return generic_fh_to_dentry(sb, fid, fh_len, fh_type, ufs_nfs_get_inode);
  }
  
  static struct dentry *ufs_fh_to_parent(struct super_block *sb, struct fid *fid,
  				       int fh_len, int fh_type)
  {
  	return generic_fh_to_parent(sb, fid, fh_len, fh_type, ufs_nfs_get_inode);
  }
  
  static struct dentry *ufs_get_parent(struct dentry *child)
  {
26fe57502   Linus Torvalds   vfs: make it poss...
145
  	struct qstr dot_dot = QSTR_INIT("..", 2);
f3e2a520f   Alexey Dobriyan   ufs: NFS support
146
147
148
149
150
151
152
153
154
155
156
157
158
  	ino_t ino;
  
  	ino = ufs_inode_by_name(child->d_inode, &dot_dot);
  	if (!ino)
  		return ERR_PTR(-ENOENT);
  	return d_obtain_alias(ufs_iget(child->d_inode->i_sb, ino));
  }
  
  static const struct export_operations ufs_export_ops = {
  	.fh_to_dentry	= ufs_fh_to_dentry,
  	.fh_to_parent	= ufs_fh_to_parent,
  	.get_parent	= ufs_get_parent,
  };
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
159
  #ifdef CONFIG_UFS_DEBUG
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
162
  /*
   * Print contents of ufs_super_block, useful for debugging
   */
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
163
  static void ufs_print_super_stuff(struct super_block *sb,
647b7e87b   Evgeniy Dushistov   [PATCH] ufs: one ...
164
165
166
  				  struct ufs_super_block_first *usb1,
  				  struct ufs_super_block_second *usb2,
  				  struct ufs_super_block_third *usb3)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
  {
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
168
  	u32 magic = fs32_to_cpu(sb, usb3->fs_magic);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169
170
  	printk("ufs_print_super_stuff
  ");
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
171
172
173
  	printk("  magic:     0x%x
  ", magic);
  	if (fs32_to_cpu(sb, usb3->fs_magic) == UFS2_MAGIC) {
647b7e87b   Evgeniy Dushistov   [PATCH] ufs: one ...
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
  		printk("  fs_size:   %llu
  ", (unsigned long long)
  		       fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size));
  		printk("  fs_dsize:  %llu
  ", (unsigned long long)
  		       fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize));
  		printk("  bsize:         %u
  ",
  		       fs32_to_cpu(sb, usb1->fs_bsize));
  		printk("  fsize:         %u
  ",
  		       fs32_to_cpu(sb, usb1->fs_fsize));
  		printk("  fs_volname:  %s
  ", usb2->fs_un.fs_u2.fs_volname);
  		printk("  fs_sblockloc: %llu
  ", (unsigned long long)
  		       fs64_to_cpu(sb, usb2->fs_un.fs_u2.fs_sblockloc));
  		printk("  cs_ndir(No of dirs):  %llu
  ", (unsigned long long)
  		       fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_ndir));
  		printk("  cs_nbfree(No of free blocks):  %llu
  ",
  		       (unsigned long long)
  		       fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_nbfree));
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
198
199
200
201
202
203
204
205
  		printk(KERN_INFO"  cs_nifree(Num of free inodes): %llu
  ",
  		       (unsigned long long)
  		       fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nifree));
  		printk(KERN_INFO"  cs_nffree(Num of free frags): %llu
  ",
  		       (unsigned long long)
  		       fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nffree));
90b315af1   Evgeniy Dushistov   ufs: fix symlink ...
206
207
208
  		printk(KERN_INFO"  fs_maxsymlinklen: %u
  ",
  		       fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_maxsymlinklen));
647b7e87b   Evgeniy Dushistov   [PATCH] ufs: one ...
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
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
  	} else {
  		printk(" sblkno:      %u
  ", fs32_to_cpu(sb, usb1->fs_sblkno));
  		printk(" cblkno:      %u
  ", fs32_to_cpu(sb, usb1->fs_cblkno));
  		printk(" iblkno:      %u
  ", fs32_to_cpu(sb, usb1->fs_iblkno));
  		printk(" dblkno:      %u
  ", fs32_to_cpu(sb, usb1->fs_dblkno));
  		printk(" cgoffset:    %u
  ",
  		       fs32_to_cpu(sb, usb1->fs_cgoffset));
  		printk(" ~cgmask:     0x%x
  ",
  		       ~fs32_to_cpu(sb, usb1->fs_cgmask));
  		printk(" size:        %u
  ", fs32_to_cpu(sb, usb1->fs_size));
  		printk(" dsize:       %u
  ", fs32_to_cpu(sb, usb1->fs_dsize));
  		printk(" ncg:         %u
  ", fs32_to_cpu(sb, usb1->fs_ncg));
  		printk(" bsize:       %u
  ", fs32_to_cpu(sb, usb1->fs_bsize));
  		printk(" fsize:       %u
  ", fs32_to_cpu(sb, usb1->fs_fsize));
  		printk(" frag:        %u
  ", fs32_to_cpu(sb, usb1->fs_frag));
  		printk(" fragshift:   %u
  ",
  		       fs32_to_cpu(sb, usb1->fs_fragshift));
  		printk(" ~fmask:      %u
  ", ~fs32_to_cpu(sb, usb1->fs_fmask));
  		printk(" fshift:      %u
  ", fs32_to_cpu(sb, usb1->fs_fshift));
  		printk(" sbsize:      %u
  ", fs32_to_cpu(sb, usb1->fs_sbsize));
  		printk(" spc:         %u
  ", fs32_to_cpu(sb, usb1->fs_spc));
  		printk(" cpg:         %u
  ", fs32_to_cpu(sb, usb1->fs_cpg));
  		printk(" ipg:         %u
  ", fs32_to_cpu(sb, usb1->fs_ipg));
  		printk(" fpg:         %u
  ", fs32_to_cpu(sb, usb1->fs_fpg));
  		printk(" csaddr:      %u
  ", fs32_to_cpu(sb, usb1->fs_csaddr));
  		printk(" cssize:      %u
  ", fs32_to_cpu(sb, usb1->fs_cssize));
  		printk(" cgsize:      %u
  ", fs32_to_cpu(sb, usb1->fs_cgsize));
  		printk(" fstodb:      %u
  ",
  		       fs32_to_cpu(sb, usb1->fs_fsbtodb));
  		printk(" nrpos:       %u
  ", fs32_to_cpu(sb, usb3->fs_nrpos));
  		printk(" ndir         %u
  ",
  		       fs32_to_cpu(sb, usb1->fs_cstotal.cs_ndir));
  		printk(" nifree       %u
  ",
  		       fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree));
  		printk(" nbfree       %u
  ",
  		       fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree));
  		printk(" nffree       %u
  ",
  		       fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree));
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
278
279
280
281
282
283
  	printk("
  ");
  }
  
  /*
   * Print contents of ufs_cylinder_group, useful for debugging
   */
647b7e87b   Evgeniy Dushistov   [PATCH] ufs: one ...
284
285
  static void ufs_print_cylinder_stuff(struct super_block *sb,
  				     struct ufs_cylinder_group *cg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286
287
288
289
  {
  	printk("
  ufs_print_cylinder_stuff
  ");
96710b29e   Andrew Morton   [PATCH] ufs: prin...
290
291
  	printk("size of ucg: %zu
  ", sizeof(struct ufs_cylinder_group));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
  	printk("  magic:        %x
  ", fs32_to_cpu(sb, cg->cg_magic));
  	printk("  time:         %u
  ", fs32_to_cpu(sb, cg->cg_time));
  	printk("  cgx:          %u
  ", fs32_to_cpu(sb, cg->cg_cgx));
  	printk("  ncyl:         %u
  ", fs16_to_cpu(sb, cg->cg_ncyl));
  	printk("  niblk:        %u
  ", fs16_to_cpu(sb, cg->cg_niblk));
  	printk("  ndblk:        %u
  ", fs32_to_cpu(sb, cg->cg_ndblk));
  	printk("  cs_ndir:      %u
  ", fs32_to_cpu(sb, cg->cg_cs.cs_ndir));
  	printk("  cs_nbfree:    %u
  ", fs32_to_cpu(sb, cg->cg_cs.cs_nbfree));
  	printk("  cs_nifree:    %u
  ", fs32_to_cpu(sb, cg->cg_cs.cs_nifree));
  	printk("  cs_nffree:    %u
  ", fs32_to_cpu(sb, cg->cg_cs.cs_nffree));
  	printk("  rotor:        %u
  ", fs32_to_cpu(sb, cg->cg_rotor));
  	printk("  frotor:       %u
  ", fs32_to_cpu(sb, cg->cg_frotor));
  	printk("  irotor:       %u
  ", fs32_to_cpu(sb, cg->cg_irotor));
  	printk("  frsum:        %u, %u, %u, %u, %u, %u, %u, %u
  ",
  	    fs32_to_cpu(sb, cg->cg_frsum[0]), fs32_to_cpu(sb, cg->cg_frsum[1]),
  	    fs32_to_cpu(sb, cg->cg_frsum[2]), fs32_to_cpu(sb, cg->cg_frsum[3]),
  	    fs32_to_cpu(sb, cg->cg_frsum[4]), fs32_to_cpu(sb, cg->cg_frsum[5]),
  	    fs32_to_cpu(sb, cg->cg_frsum[6]), fs32_to_cpu(sb, cg->cg_frsum[7]));
  	printk("  btotoff:      %u
  ", fs32_to_cpu(sb, cg->cg_btotoff));
  	printk("  boff:         %u
  ", fs32_to_cpu(sb, cg->cg_boff));
  	printk("  iuseoff:      %u
  ", fs32_to_cpu(sb, cg->cg_iusedoff));
  	printk("  freeoff:      %u
  ", fs32_to_cpu(sb, cg->cg_freeoff));
  	printk("  nextfreeoff:  %u
  ", fs32_to_cpu(sb, cg->cg_nextfreeoff));
647b7e87b   Evgeniy Dushistov   [PATCH] ufs: one ...
334
335
336
337
338
339
340
341
342
  	printk("  clustersumoff %u
  ",
  	       fs32_to_cpu(sb, cg->cg_u.cg_44.cg_clustersumoff));
  	printk("  clusteroff    %u
  ",
  	       fs32_to_cpu(sb, cg->cg_u.cg_44.cg_clusteroff));
  	printk("  nclusterblks  %u
  ",
  	       fs32_to_cpu(sb, cg->cg_u.cg_44.cg_nclusterblks));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
344
345
  	printk("
  ");
  }
647b7e87b   Evgeniy Dushistov   [PATCH] ufs: one ...
346
  #else
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
347
  #  define ufs_print_super_stuff(sb, usb1, usb2, usb3) /**/
647b7e87b   Evgeniy Dushistov   [PATCH] ufs: one ...
348
  #  define ufs_print_cylinder_stuff(sb, cg) /**/
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
349
  #endif /* CONFIG_UFS_DEBUG */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350

ee9b6d61a   Josef 'Jeff' Sipek   [PATCH] Mark stru...
351
  static const struct super_operations ufs_super_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
353
354
355
356
357
358
359
360
361
362
  
  static char error_buf[1024];
  
  void ufs_error (struct super_block * sb, const char * function,
  	const char * fmt, ...)
  {
  	struct ufs_sb_private_info * uspi;
  	struct ufs_super_block_first * usb1;
  	va_list args;
  
  	uspi = UFS_SB(sb)->s_uspi;
7b4ee73e2   Evgeniy   [PATCH] ufs cleanup
363
  	usb1 = ubh_get_usb_first(uspi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364
365
366
  	
  	if (!(sb->s_flags & MS_RDONLY)) {
  		usb1->fs_clean = UFS_FSBAD;
9695ef16e   Evgeniy Dushistov   [PATCH] ufs: wron...
367
  		ubh_mark_buffer_dirty(USPI_UBH(uspi));
9e9ad5f40   Artem Bityutskiy   fs/ufs: get rid o...
368
  		ufs_mark_sb_dirty(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
370
371
  		sb->s_flags |= MS_RDONLY;
  	}
  	va_start (args, fmt);
4a6e617a4   Alexey Dobriyan   [PATCH] fs/*: tri...
372
  	vsnprintf (error_buf, sizeof(error_buf), fmt, args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
  	va_end (args);
  	switch (UFS_SB(sb)->s_mount_opt & UFS_MOUNT_ONERROR) {
  	case UFS_MOUNT_ONERROR_PANIC:
  		panic ("UFS-fs panic (device %s): %s: %s
  ", 
  			sb->s_id, function, error_buf);
  
  	case UFS_MOUNT_ONERROR_LOCK:
  	case UFS_MOUNT_ONERROR_UMOUNT:
  	case UFS_MOUNT_ONERROR_REPAIR:
  		printk (KERN_CRIT "UFS-fs error (device %s): %s: %s
  ",
  			sb->s_id, function, error_buf);
  	}		
  }
  
  void ufs_panic (struct super_block * sb, const char * function,
  	const char * fmt, ...)
  {
  	struct ufs_sb_private_info * uspi;
  	struct ufs_super_block_first * usb1;
  	va_list args;
  	
  	uspi = UFS_SB(sb)->s_uspi;
7b4ee73e2   Evgeniy   [PATCH] ufs cleanup
397
  	usb1 = ubh_get_usb_first(uspi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398
399
400
  	
  	if (!(sb->s_flags & MS_RDONLY)) {
  		usb1->fs_clean = UFS_FSBAD;
9695ef16e   Evgeniy Dushistov   [PATCH] ufs: wron...
401
  		ubh_mark_buffer_dirty(USPI_UBH(uspi));
9e9ad5f40   Artem Bityutskiy   fs/ufs: get rid o...
402
  		ufs_mark_sb_dirty(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
404
  	}
  	va_start (args, fmt);
4a6e617a4   Alexey Dobriyan   [PATCH] fs/*: tri...
405
  	vsnprintf (error_buf, sizeof(error_buf), fmt, args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
407
408
409
410
411
412
413
414
415
416
417
418
  	va_end (args);
  	sb->s_flags |= MS_RDONLY;
  	printk (KERN_CRIT "UFS-fs panic (device %s): %s: %s
  ",
  		sb->s_id, function, error_buf);
  }
  
  void ufs_warning (struct super_block * sb, const char * function,
  	const char * fmt, ...)
  {
  	va_list args;
  
  	va_start (args, fmt);
4a6e617a4   Alexey Dobriyan   [PATCH] fs/*: tri...
419
  	vsnprintf (error_buf, sizeof(error_buf), fmt, args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420
421
422
423
424
425
426
  	va_end (args);
  	printk (KERN_WARNING "UFS-fs warning (device %s): %s: %s
  ",
  		sb->s_id, function, error_buf);
  }
  
  enum {
2a9807c0d   Evgeniy Dushistov   ufs: implement sh...
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
         Opt_type_old = UFS_MOUNT_UFSTYPE_OLD,
         Opt_type_sunx86 = UFS_MOUNT_UFSTYPE_SUNx86,
         Opt_type_sun = UFS_MOUNT_UFSTYPE_SUN,
         Opt_type_sunos = UFS_MOUNT_UFSTYPE_SUNOS,
         Opt_type_44bsd = UFS_MOUNT_UFSTYPE_44BSD,
         Opt_type_ufs2 = UFS_MOUNT_UFSTYPE_UFS2,
         Opt_type_hp = UFS_MOUNT_UFSTYPE_HP,
         Opt_type_nextstepcd = UFS_MOUNT_UFSTYPE_NEXTSTEP_CD,
         Opt_type_nextstep = UFS_MOUNT_UFSTYPE_NEXTSTEP,
         Opt_type_openstep = UFS_MOUNT_UFSTYPE_OPENSTEP,
         Opt_onerror_panic = UFS_MOUNT_ONERROR_PANIC,
         Opt_onerror_lock = UFS_MOUNT_ONERROR_LOCK,
         Opt_onerror_umount = UFS_MOUNT_ONERROR_UMOUNT,
         Opt_onerror_repair = UFS_MOUNT_ONERROR_REPAIR,
         Opt_err
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
442
  };
a447c0932   Steven Whitehouse   vfs: Use const fo...
443
  static const match_table_t tokens = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
445
446
  	{Opt_type_old, "ufstype=old"},
  	{Opt_type_sunx86, "ufstype=sunx86"},
  	{Opt_type_sun, "ufstype=sun"},
252e211e9   Mark   Add in SunOS 4.1....
447
  	{Opt_type_sunos, "ufstype=sunos"},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
449
450
451
452
453
454
  	{Opt_type_44bsd, "ufstype=44bsd"},
  	{Opt_type_ufs2, "ufstype=ufs2"},
  	{Opt_type_ufs2, "ufstype=5xbsd"},
  	{Opt_type_hp, "ufstype=hp"},
  	{Opt_type_nextstepcd, "ufstype=nextstep-cd"},
  	{Opt_type_nextstep, "ufstype=nextstep"},
  	{Opt_type_openstep, "ufstype=openstep"},
2a9807c0d   Evgeniy Dushistov   ufs: implement sh...
455
  /*end of possible ufs types */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
456
457
458
459
460
461
462
463
464
465
466
  	{Opt_onerror_panic, "onerror=panic"},
  	{Opt_onerror_lock, "onerror=lock"},
  	{Opt_onerror_umount, "onerror=umount"},
  	{Opt_onerror_repair, "onerror=repair"},
  	{Opt_err, NULL}
  };
  
  static int ufs_parse_options (char * options, unsigned * mount_options)
  {
  	char * p;
  	
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
467
468
  	UFSD("ENTER
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
  	
  	if (!options)
  		return 1;
  
  	while ((p = strsep(&options, ",")) != NULL) {
  		substring_t args[MAX_OPT_ARGS];
  		int token;
  		if (!*p)
  			continue;
  
  		token = match_token(p, tokens, args);
  		switch (token) {
  		case Opt_type_old:
  			ufs_clear_opt (*mount_options, UFSTYPE);
  			ufs_set_opt (*mount_options, UFSTYPE_OLD);
  			break;
  		case Opt_type_sunx86:
  			ufs_clear_opt (*mount_options, UFSTYPE);
  			ufs_set_opt (*mount_options, UFSTYPE_SUNx86);
  			break;
  		case Opt_type_sun:
  			ufs_clear_opt (*mount_options, UFSTYPE);
  			ufs_set_opt (*mount_options, UFSTYPE_SUN);
  			break;
252e211e9   Mark   Add in SunOS 4.1....
493
494
495
496
  		case Opt_type_sunos:
  			ufs_clear_opt(*mount_options, UFSTYPE);
  			ufs_set_opt(*mount_options, UFSTYPE_SUNOS);
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
  		case Opt_type_44bsd:
  			ufs_clear_opt (*mount_options, UFSTYPE);
  			ufs_set_opt (*mount_options, UFSTYPE_44BSD);
  			break;
  		case Opt_type_ufs2:
  			ufs_clear_opt(*mount_options, UFSTYPE);
  			ufs_set_opt(*mount_options, UFSTYPE_UFS2);
  			break;
  		case Opt_type_hp:
  			ufs_clear_opt (*mount_options, UFSTYPE);
  			ufs_set_opt (*mount_options, UFSTYPE_HP);
  			break;
  		case Opt_type_nextstepcd:
  			ufs_clear_opt (*mount_options, UFSTYPE);
  			ufs_set_opt (*mount_options, UFSTYPE_NEXTSTEP_CD);
  			break;
  		case Opt_type_nextstep:
  			ufs_clear_opt (*mount_options, UFSTYPE);
  			ufs_set_opt (*mount_options, UFSTYPE_NEXTSTEP);
  			break;
  		case Opt_type_openstep:
  			ufs_clear_opt (*mount_options, UFSTYPE);
  			ufs_set_opt (*mount_options, UFSTYPE_OPENSTEP);
  			break;
  		case Opt_onerror_panic:
  			ufs_clear_opt (*mount_options, ONERROR);
  			ufs_set_opt (*mount_options, ONERROR_PANIC);
  			break;
  		case Opt_onerror_lock:
  			ufs_clear_opt (*mount_options, ONERROR);
  			ufs_set_opt (*mount_options, ONERROR_LOCK);
  			break;
  		case Opt_onerror_umount:
  			ufs_clear_opt (*mount_options, ONERROR);
  			ufs_set_opt (*mount_options, ONERROR_UMOUNT);
  			break;
  		case Opt_onerror_repair:
  			printk("UFS-fs: Unable to do repair on error, "
  				"will lock lock instead
  ");
  			ufs_clear_opt (*mount_options, ONERROR);
  			ufs_set_opt (*mount_options, ONERROR_REPAIR);
  			break;
  		default:
  			printk("UFS-fs: Invalid option: \"%s\" "
  					"or missing value
  ", p);
  			return 0;
  		}
  	}
  	return 1;
  }
  
  /*
25985edce   Lucas De Marchi   Fix common misspe...
551
552
553
   * Different types of UFS hold fs_cstotal in different
   * places, and use different data structure for it.
   * To make things simpler we just copy fs_cstotal to ufs_sb_private_info
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
   */
ee3ffd6c1   Evgeniy Dushistov   [PATCH] ufs: make...
555
  static void ufs_setup_cstotal(struct super_block *sb)
e295cfcb2   Evgeniy Dushistov   [PATCH] ufs: fix ...
556
  {
647b7e87b   Evgeniy Dushistov   [PATCH] ufs: one ...
557
558
  	struct ufs_sb_info *sbi = UFS_SB(sb);
  	struct ufs_sb_private_info *uspi = sbi->s_uspi;
ee3ffd6c1   Evgeniy Dushistov   [PATCH] ufs: make...
559
560
  	struct ufs_super_block_first *usb1;
  	struct ufs_super_block_second *usb2;
647b7e87b   Evgeniy Dushistov   [PATCH] ufs: one ...
561
  	struct ufs_super_block_third *usb3;
ee3ffd6c1   Evgeniy Dushistov   [PATCH] ufs: make...
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
  	unsigned mtype = sbi->s_mount_opt & UFS_MOUNT_UFSTYPE;
  
  	UFSD("ENTER, mtype=%u
  ", mtype);
  	usb1 = ubh_get_usb_first(uspi);
  	usb2 = ubh_get_usb_second(uspi);
  	usb3 = ubh_get_usb_third(uspi);
  
  	if ((mtype == UFS_MOUNT_UFSTYPE_44BSD &&
  	     (usb1->fs_flags & UFS_FLAGS_UPDATED)) ||
  	    mtype == UFS_MOUNT_UFSTYPE_UFS2) {
  		/*we have statistic in different place, then usual*/
  		uspi->cs_total.cs_ndir = fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_ndir);
  		uspi->cs_total.cs_nbfree = fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_nbfree);
  		uspi->cs_total.cs_nifree = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nifree);
  		uspi->cs_total.cs_nffree = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nffree);
  	} else {
  		uspi->cs_total.cs_ndir = fs32_to_cpu(sb, usb1->fs_cstotal.cs_ndir);
  		uspi->cs_total.cs_nbfree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree);
  		uspi->cs_total.cs_nifree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree);
  		uspi->cs_total.cs_nffree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree);
  	}
  	UFSD("EXIT
  ");
  }
  
  /*
   * Read on-disk structures associated with cylinder groups
   */
  static int ufs_read_cylinder_structures(struct super_block *sb)
  {
  	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
595
596
597
  	struct ufs_buffer_head * ubh;
  	unsigned char * base, * space;
  	unsigned size, blks, i;
ee3ffd6c1   Evgeniy Dushistov   [PATCH] ufs: make...
598
  	struct ufs_super_block_third *usb3;
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
599
600
  	UFSD("ENTER
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601

ee3ffd6c1   Evgeniy Dushistov   [PATCH] ufs: make...
602
  	usb3 = ubh_get_usb_third(uspi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603
604
605
606
607
608
  	/*
  	 * Read cs structures from (usually) first data block
  	 * on the device. 
  	 */
  	size = uspi->s_cssize;
  	blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift;
788257d61   Arnd Bergmann   ufs: remove the BKL
609
  	base = space = kmalloc(size, GFP_NOFS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
610
611
  	if (!base)
  		goto failed; 
e295cfcb2   Evgeniy Dushistov   [PATCH] ufs: fix ...
612
  	sbi->s_csp = (struct ufs_csum *)space;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613
614
615
616
  	for (i = 0; i < blks; i += uspi->s_fpb) {
  		size = uspi->s_bsize;
  		if (i + uspi->s_fpb > blks)
  			size = (blks - i) * uspi->s_fsize;
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
617
  		ubh = ubh_bread(sb, uspi->s_csaddr + i, size);
7b4ee73e2   Evgeniy   [PATCH] ufs cleanup
618
619
620
621
622
  		
  		if (!ubh)
  			goto failed;
  
  		ubh_ubhcpymem (space, ubh, size);
7b4ee73e2   Evgeniy   [PATCH] ufs cleanup
623

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
624
625
626
627
628
629
630
631
632
  		space += size;
  		ubh_brelse (ubh);
  		ubh = NULL;
  	}
  
  	/*
  	 * Read cylinder group (we read only first fragment from block
  	 * at this time) and prepare internal data structures for cg caching.
  	 */
788257d61   Arnd Bergmann   ufs: remove the BKL
633
  	if (!(sbi->s_ucg = kmalloc (sizeof(struct buffer_head *) * uspi->s_ncg, GFP_NOFS)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
634
635
636
637
638
639
640
641
  		goto failed;
  	for (i = 0; i < uspi->s_ncg; i++) 
  		sbi->s_ucg[i] = NULL;
  	for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) {
  		sbi->s_ucpi[i] = NULL;
  		sbi->s_cgno[i] = UFS_CGNO_EMPTY;
  	}
  	for (i = 0; i < uspi->s_ncg; i++) {
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
642
643
  		UFSD("read cg %u
  ", i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
644
645
646
647
  		if (!(sbi->s_ucg[i] = sb_bread(sb, ufs_cgcmin(i))))
  			goto failed;
  		if (!ufs_cg_chkmagic (sb, (struct ufs_cylinder_group *) sbi->s_ucg[i]->b_data))
  			goto failed;
647b7e87b   Evgeniy Dushistov   [PATCH] ufs: one ...
648

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
649
  		ufs_print_cylinder_stuff(sb, (struct ufs_cylinder_group *) sbi->s_ucg[i]->b_data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
651
  	}
  	for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) {
788257d61   Arnd Bergmann   ufs: remove the BKL
652
  		if (!(sbi->s_ucpi[i] = kmalloc (sizeof(struct ufs_cg_private_info), GFP_NOFS)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653
654
655
656
  			goto failed;
  		sbi->s_cgno[i] = UFS_CGNO_EMPTY;
  	}
  	sbi->s_cg_loaded = 0;
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
657
658
  	UFSD("EXIT
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659
660
661
  	return 1;
  
  failed:
f99d49adf   Jesper Juhl   [PATCH] kfree cle...
662
  	kfree (base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
663
664
  	if (sbi->s_ucg) {
  		for (i = 0; i < uspi->s_ncg; i++)
f99d49adf   Jesper Juhl   [PATCH] kfree cle...
665
666
  			if (sbi->s_ucg[i])
  				brelse (sbi->s_ucg[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
667
668
  		kfree (sbi->s_ucg);
  		for (i = 0; i < UFS_MAX_GROUP_LOADED; i++)
f99d49adf   Jesper Juhl   [PATCH] kfree cle...
669
  			kfree (sbi->s_ucpi[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
670
  	}
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
671
672
  	UFSD("EXIT (FAILED)
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
673
674
675
676
  	return 0;
  }
  
  /*
ee3ffd6c1   Evgeniy Dushistov   [PATCH] ufs: make...
677
   * Sync our internal copy of fs_cstotal with disk
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
678
   */
ee3ffd6c1   Evgeniy Dushistov   [PATCH] ufs: make...
679
  static void ufs_put_cstotal(struct super_block *sb)
e295cfcb2   Evgeniy Dushistov   [PATCH] ufs: fix ...
680
  {
ee3ffd6c1   Evgeniy Dushistov   [PATCH] ufs: make...
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
  	unsigned mtype = UFS_SB(sb)->s_mount_opt & UFS_MOUNT_UFSTYPE;
  	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
  	struct ufs_super_block_first *usb1;
  	struct ufs_super_block_second *usb2;
  	struct ufs_super_block_third *usb3;
  
  	UFSD("ENTER
  ");
  	usb1 = ubh_get_usb_first(uspi);
  	usb2 = ubh_get_usb_second(uspi);
  	usb3 = ubh_get_usb_third(uspi);
  
  	if ((mtype == UFS_MOUNT_UFSTYPE_44BSD &&
  	     (usb1->fs_flags & UFS_FLAGS_UPDATED)) ||
  	    mtype == UFS_MOUNT_UFSTYPE_UFS2) {
  		/*we have statistic in different place, then usual*/
  		usb2->fs_un.fs_u2.cs_ndir =
  			cpu_to_fs64(sb, uspi->cs_total.cs_ndir);
  		usb2->fs_un.fs_u2.cs_nbfree =
  			cpu_to_fs64(sb, uspi->cs_total.cs_nbfree);
  		usb3->fs_un1.fs_u2.cs_nifree =
  			cpu_to_fs64(sb, uspi->cs_total.cs_nifree);
  		usb3->fs_un1.fs_u2.cs_nffree =
  			cpu_to_fs64(sb, uspi->cs_total.cs_nffree);
  	} else {
  		usb1->fs_cstotal.cs_ndir =
  			cpu_to_fs32(sb, uspi->cs_total.cs_ndir);
  		usb1->fs_cstotal.cs_nbfree =
  			cpu_to_fs32(sb, uspi->cs_total.cs_nbfree);
  		usb1->fs_cstotal.cs_nifree =
  			cpu_to_fs32(sb, uspi->cs_total.cs_nifree);
  		usb1->fs_cstotal.cs_nffree =
  			cpu_to_fs32(sb, uspi->cs_total.cs_nffree);
  	}
  	ubh_mark_buffer_dirty(USPI_UBH(uspi));
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
716
  	ufs_print_super_stuff(sb, usb1, usb2, usb3);
ee3ffd6c1   Evgeniy Dushistov   [PATCH] ufs: make...
717
718
719
720
721
722
723
724
725
726
727
728
729
730
  	UFSD("EXIT
  ");
  }
  
  /**
   * ufs_put_super_internal() - put on-disk intrenal structures
   * @sb: pointer to super_block structure
   * Put on-disk structures associated with cylinder groups
   * and write them back to disk, also update cs_total on disk
   */
  static void ufs_put_super_internal(struct super_block *sb)
  {
  	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
731
732
733
  	struct ufs_buffer_head * ubh;
  	unsigned char * base, * space;
  	unsigned blks, size, i;
ee3ffd6c1   Evgeniy Dushistov   [PATCH] ufs: make...
734

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
735
  	
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
736
737
  	UFSD("ENTER
  ");
6cfd01484   Christoph Hellwig   push BKL down int...
738

ee3ffd6c1   Evgeniy Dushistov   [PATCH] ufs: make...
739
  	ufs_put_cstotal(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
740
741
  	size = uspi->s_cssize;
  	blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift;
e295cfcb2   Evgeniy Dushistov   [PATCH] ufs: fix ...
742
  	base = space = (char*) sbi->s_csp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
743
744
745
746
  	for (i = 0; i < blks; i += uspi->s_fpb) {
  		size = uspi->s_bsize;
  		if (i + uspi->s_fpb > blks)
  			size = (blks - i) * uspi->s_fsize;
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
747

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
748
  		ubh = ubh_bread(sb, uspi->s_csaddr + i, size);
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
749

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
  		ubh_memcpyubh (ubh, space, size);
  		space += size;
  		ubh_mark_buffer_uptodate (ubh, 1);
  		ubh_mark_buffer_dirty (ubh);
  		ubh_brelse (ubh);
  	}
  	for (i = 0; i < sbi->s_cg_loaded; i++) {
  		ufs_put_cylinder (sb, i);
  		kfree (sbi->s_ucpi[i]);
  	}
  	for (; i < UFS_MAX_GROUP_LOADED; i++) 
  		kfree (sbi->s_ucpi[i]);
  	for (i = 0; i < uspi->s_ncg; i++) 
  		brelse (sbi->s_ucg[i]);
  	kfree (sbi->s_ucg);
  	kfree (base);
6cfd01484   Christoph Hellwig   push BKL down int...
766

abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
767
768
  	UFSD("EXIT
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
769
  }
7bd54ef72   Artem Bityutskiy   fs/ufs: re-arrang...
770
771
772
773
774
775
776
777
  static int ufs_sync_fs(struct super_block *sb, int wait)
  {
  	struct ufs_sb_private_info * uspi;
  	struct ufs_super_block_first * usb1;
  	struct ufs_super_block_third * usb3;
  	unsigned flags;
  
  	lock_ufs(sb);
b6963327e   Marco Stornelli   ufs: drop lock/un...
778
  	mutex_lock(&UFS_SB(sb)->s_lock);
7bd54ef72   Artem Bityutskiy   fs/ufs: re-arrang...
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
  
  	UFSD("ENTER
  ");
  
  	flags = UFS_SB(sb)->s_flags;
  	uspi = UFS_SB(sb)->s_uspi;
  	usb1 = ubh_get_usb_first(uspi);
  	usb3 = ubh_get_usb_third(uspi);
  
  	usb1->fs_time = cpu_to_fs32(sb, get_seconds());
  	if ((flags & UFS_ST_MASK) == UFS_ST_SUN  ||
  	    (flags & UFS_ST_MASK) == UFS_ST_SUNOS ||
  	    (flags & UFS_ST_MASK) == UFS_ST_SUNx86)
  		ufs_set_fs_state(sb, usb1, usb3,
  				UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time));
  	ufs_put_cstotal(sb);
7bd54ef72   Artem Bityutskiy   fs/ufs: re-arrang...
795
796
797
  
  	UFSD("EXIT
  ");
b6963327e   Marco Stornelli   ufs: drop lock/un...
798
  	mutex_unlock(&UFS_SB(sb)->s_lock);
7bd54ef72   Artem Bityutskiy   fs/ufs: re-arrang...
799
800
801
802
  	unlock_ufs(sb);
  
  	return 0;
  }
9e9ad5f40   Artem Bityutskiy   fs/ufs: get rid o...
803
  static void delayed_sync_fs(struct work_struct *work)
7bd54ef72   Artem Bityutskiy   fs/ufs: re-arrang...
804
  {
9e9ad5f40   Artem Bityutskiy   fs/ufs: get rid o...
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
  	struct ufs_sb_info *sbi;
  
  	sbi = container_of(work, struct ufs_sb_info, sync_work.work);
  
  	spin_lock(&sbi->work_lock);
  	sbi->work_queued = 0;
  	spin_unlock(&sbi->work_lock);
  
  	ufs_sync_fs(sbi->sb, 1);
  }
  
  void ufs_mark_sb_dirty(struct super_block *sb)
  {
  	struct ufs_sb_info *sbi = UFS_SB(sb);
  	unsigned long delay;
  
  	spin_lock(&sbi->work_lock);
  	if (!sbi->work_queued) {
  		delay = msecs_to_jiffies(dirty_writeback_interval * 10);
  		queue_delayed_work(system_long_wq, &sbi->sync_work, delay);
  		sbi->work_queued = 1;
  	}
  	spin_unlock(&sbi->work_lock);
7bd54ef72   Artem Bityutskiy   fs/ufs: re-arrang...
828
829
830
831
832
833
834
835
836
837
838
  }
  
  static void ufs_put_super(struct super_block *sb)
  {
  	struct ufs_sb_info * sbi = UFS_SB(sb);
  
  	UFSD("ENTER
  ");
  
  	if (!(sb->s_flags & MS_RDONLY))
  		ufs_put_super_internal(sb);
9e9ad5f40   Artem Bityutskiy   fs/ufs: get rid o...
839
  	cancel_delayed_work_sync(&sbi->sync_work);
7bd54ef72   Artem Bityutskiy   fs/ufs: re-arrang...
840
841
842
843
844
845
846
847
848
  
  	ubh_brelse_uspi (sbi->s_uspi);
  	kfree (sbi->s_uspi);
  	kfree (sbi);
  	sb->s_fs_info = NULL;
  	UFSD("EXIT
  ");
  	return;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
849
850
851
852
853
854
855
  static int ufs_fill_super(struct super_block *sb, void *data, int silent)
  {
  	struct ufs_sb_info * sbi;
  	struct ufs_sb_private_info * uspi;
  	struct ufs_super_block_first * usb1;
  	struct ufs_super_block_second * usb2;
  	struct ufs_super_block_third * usb3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
856
857
858
859
  	struct ufs_buffer_head * ubh;	
  	struct inode *inode;
  	unsigned block_size, super_block_size;
  	unsigned flags;
7b4ee73e2   Evgeniy   [PATCH] ufs cleanup
860
  	unsigned super_block_offset;
9e6766cc8   Duane Griffin   ufs: validate max...
861
  	unsigned maxsymlen;
b55c460da   David Howells   iget: stop UFS fr...
862
  	int ret = -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
863
864
865
866
867
  
  	uspi = NULL;
  	ubh = NULL;
  	flags = 0;
  	
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
868
869
  	UFSD("ENTER
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
870
  		
f8314dc60   Panagiotis Issaris   [PATCH] fs: Conve...
871
  	sbi = kzalloc(sizeof(struct ufs_sb_info), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
872
873
874
  	if (!sbi)
  		goto failed_nomem;
  	sb->s_fs_info = sbi;
9e9ad5f40   Artem Bityutskiy   fs/ufs: get rid o...
875
  	sbi->sb = sb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
876

abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
877
878
  	UFSD("flag %u
  ", (int)(sb->s_flags & MS_RDONLY));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
879
880
881
882
883
884
885
886
887
  	
  #ifndef CONFIG_UFS_FS_WRITE
  	if (!(sb->s_flags & MS_RDONLY)) {
  		printk("ufs was compiled with read-only support, "
  		"can't be mounted as read-write
  ");
  		goto failed;
  	}
  #endif
788257d61   Arnd Bergmann   ufs: remove the BKL
888
  	mutex_init(&sbi->mutex);
b6963327e   Marco Stornelli   ufs: drop lock/un...
889
  	mutex_init(&sbi->s_lock);
9e9ad5f40   Artem Bityutskiy   fs/ufs: get rid o...
890
891
  	spin_lock_init(&sbi->work_lock);
  	INIT_DELAYED_WORK(&sbi->sync_work, delayed_sync_fs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
  	/*
  	 * Set default mount options
  	 * Parse mount options
  	 */
  	sbi->s_mount_opt = 0;
  	ufs_set_opt (sbi->s_mount_opt, ONERROR_LOCK);
  	if (!ufs_parse_options ((char *) data, &sbi->s_mount_opt)) {
  		printk("wrong mount options
  ");
  		goto failed;
  	}
  	if (!(sbi->s_mount_opt & UFS_MOUNT_UFSTYPE)) {
  		if (!silent)
  			printk("You didn't specify the type of your ufs filesystem
  
  "
  			"mount -t ufs -o ufstype="
c690a7225   Michael Owen   typo patch for fs...
909
910
911
  			"sun|sunx86|44bsd|ufs2|5xbsd|old|hp|nextstep|nextstep-cd|openstep ...
  
  "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
912
913
914
915
916
  			">>>WARNING<<< Wrong ufstype may corrupt your filesystem, "
  			"default is ufstype=old
  ");
  		ufs_set_opt (sbi->s_mount_opt, UFSTYPE_OLD);
  	}
252e211e9   Mark   Add in SunOS 4.1....
917
918
  	uspi = kzalloc(sizeof(struct ufs_sb_private_info), GFP_KERNEL);
  	sbi->s_uspi = uspi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
919
920
  	if (!uspi)
  		goto failed;
f336953bf   Evgeniy Dushistov   [PATCH] ufs: rest...
921
  	uspi->s_dirblksize = UFS_SECTOR_SIZE;
7b4ee73e2   Evgeniy   [PATCH] ufs cleanup
922
  	super_block_offset=UFS_SBLOCK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
923
924
925
  	/* Keep 2Gig file limit. Some UFS variants need to override 
  	   this but as I don't know which I'll let those in the know loosen
  	   the rules */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
926
927
  	switch (sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) {
  	case UFS_MOUNT_UFSTYPE_44BSD:
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
928
929
  		UFSD("ufstype=44bsd
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
930
931
932
933
934
935
936
937
  		uspi->s_fsize = block_size = 512;
  		uspi->s_fmask = ~(512 - 1);
  		uspi->s_fshift = 9;
  		uspi->s_sbsize = super_block_size = 1536;
  		uspi->s_sbbase = 0;
  		flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD;
  		break;
  	case UFS_MOUNT_UFSTYPE_UFS2:
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
938
939
  		UFSD("ufstype=ufs2
  ");
7b4ee73e2   Evgeniy   [PATCH] ufs cleanup
940
  		super_block_offset=SBLOCK_UFS2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
941
942
943
944
945
946
  		uspi->s_fsize = block_size = 512;
  		uspi->s_fmask = ~(512 - 1);
  		uspi->s_fshift = 9;
  		uspi->s_sbsize = super_block_size = 1536;
  		uspi->s_sbbase =  0;
  		flags |= UFS_TYPE_UFS2 | UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
947
948
949
  		break;
  		
  	case UFS_MOUNT_UFSTYPE_SUN:
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
950
951
  		UFSD("ufstype=sun
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
952
953
954
955
956
  		uspi->s_fsize = block_size = 1024;
  		uspi->s_fmask = ~(1024 - 1);
  		uspi->s_fshift = 10;
  		uspi->s_sbsize = super_block_size = 2048;
  		uspi->s_sbbase = 0;
252e211e9   Mark   Add in SunOS 4.1....
957
  		uspi->s_maxsymlinklen = 0; /* Not supported on disk */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
958
959
  		flags |= UFS_DE_OLD | UFS_UID_EFT | UFS_ST_SUN | UFS_CG_SUN;
  		break;
252e211e9   Mark   Add in SunOS 4.1....
960
961
962
963
964
965
966
967
968
969
970
971
  	case UFS_MOUNT_UFSTYPE_SUNOS:
  		UFSD(("ufstype=sunos
  "))
  		uspi->s_fsize = block_size = 1024;
  		uspi->s_fmask = ~(1024 - 1);
  		uspi->s_fshift = 10;
  		uspi->s_sbsize = 2048;
  		super_block_size = 2048;
  		uspi->s_sbbase = 0;
  		uspi->s_maxsymlinklen = 0; /* Not supported on disk */
  		flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_SUNOS | UFS_CG_SUN;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
972
  	case UFS_MOUNT_UFSTYPE_SUNx86:
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
973
974
  		UFSD("ufstype=sunx86
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
975
976
977
978
979
  		uspi->s_fsize = block_size = 1024;
  		uspi->s_fmask = ~(1024 - 1);
  		uspi->s_fshift = 10;
  		uspi->s_sbsize = super_block_size = 2048;
  		uspi->s_sbbase = 0;
252e211e9   Mark   Add in SunOS 4.1....
980
  		uspi->s_maxsymlinklen = 0; /* Not supported on disk */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
981
982
983
984
  		flags |= UFS_DE_OLD | UFS_UID_EFT | UFS_ST_SUNx86 | UFS_CG_SUN;
  		break;
  
  	case UFS_MOUNT_UFSTYPE_OLD:
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
985
986
  		UFSD("ufstype=old
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
  		uspi->s_fsize = block_size = 1024;
  		uspi->s_fmask = ~(1024 - 1);
  		uspi->s_fshift = 10;
  		uspi->s_sbsize = super_block_size = 2048;
  		uspi->s_sbbase = 0;
  		flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD;
  		if (!(sb->s_flags & MS_RDONLY)) {
  			if (!silent)
  				printk(KERN_INFO "ufstype=old is supported read-only
  ");
  			sb->s_flags |= MS_RDONLY;
  		}
  		break;
  	
  	case UFS_MOUNT_UFSTYPE_NEXTSTEP:
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
1002
1003
  		UFSD("ufstype=nextstep
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1004
1005
1006
1007
1008
  		uspi->s_fsize = block_size = 1024;
  		uspi->s_fmask = ~(1024 - 1);
  		uspi->s_fshift = 10;
  		uspi->s_sbsize = super_block_size = 2048;
  		uspi->s_sbbase = 0;
0c664f974   Evgeniy Dushistov   ufs: fix nexstep ...
1009
  		uspi->s_dirblksize = 1024;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
  		flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD;
  		if (!(sb->s_flags & MS_RDONLY)) {
  			if (!silent)
  				printk(KERN_INFO "ufstype=nextstep is supported read-only
  ");
  			sb->s_flags |= MS_RDONLY;
  		}
  		break;
  	
  	case UFS_MOUNT_UFSTYPE_NEXTSTEP_CD:
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
1020
1021
  		UFSD("ufstype=nextstep-cd
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1022
1023
1024
1025
1026
  		uspi->s_fsize = block_size = 2048;
  		uspi->s_fmask = ~(2048 - 1);
  		uspi->s_fshift = 11;
  		uspi->s_sbsize = super_block_size = 2048;
  		uspi->s_sbbase = 0;
0c664f974   Evgeniy Dushistov   ufs: fix nexstep ...
1027
  		uspi->s_dirblksize = 1024;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
  		flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD;
  		if (!(sb->s_flags & MS_RDONLY)) {
  			if (!silent)
  				printk(KERN_INFO "ufstype=nextstep-cd is supported read-only
  ");
  			sb->s_flags |= MS_RDONLY;
  		}
  		break;
  	
  	case UFS_MOUNT_UFSTYPE_OPENSTEP:
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
1038
1039
  		UFSD("ufstype=openstep
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1040
1041
1042
1043
1044
  		uspi->s_fsize = block_size = 1024;
  		uspi->s_fmask = ~(1024 - 1);
  		uspi->s_fshift = 10;
  		uspi->s_sbsize = super_block_size = 2048;
  		uspi->s_sbbase = 0;
f336953bf   Evgeniy Dushistov   [PATCH] ufs: rest...
1045
  		uspi->s_dirblksize = 1024;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
  		flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD;
  		if (!(sb->s_flags & MS_RDONLY)) {
  			if (!silent)
  				printk(KERN_INFO "ufstype=openstep is supported read-only
  ");
  			sb->s_flags |= MS_RDONLY;
  		}
  		break;
  	
  	case UFS_MOUNT_UFSTYPE_HP:
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
1056
1057
  		UFSD("ufstype=hp
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
  		uspi->s_fsize = block_size = 1024;
  		uspi->s_fmask = ~(1024 - 1);
  		uspi->s_fshift = 10;
  		uspi->s_sbsize = super_block_size = 2048;
  		uspi->s_sbbase = 0;
  		flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD;
  		if (!(sb->s_flags & MS_RDONLY)) {
  			if (!silent)
  				printk(KERN_INFO "ufstype=hp is supported read-only
  ");
  			sb->s_flags |= MS_RDONLY;
   		}
   		break;
  	default:
  		if (!silent)
  			printk("unknown ufstype
  ");
  		goto failed;
  	}
  	
  again:	
  	if (!sb_set_blocksize(sb, block_size)) {
  		printk(KERN_ERR "UFS: failed to set blocksize
  ");
  		goto failed;
  	}
  
  	/*
  	 * read ufs super block from device
  	 */
7b4ee73e2   Evgeniy   [PATCH] ufs cleanup
1088
1089
1090
  
  	ubh = ubh_bread_uspi(uspi, sb, uspi->s_sbbase + super_block_offset/block_size, super_block_size);
  	
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1091
1092
  	if (!ubh) 
              goto failed;
7b4ee73e2   Evgeniy   [PATCH] ufs cleanup
1093
1094
1095
  	usb1 = ubh_get_usb_first(uspi);
  	usb2 = ubh_get_usb_second(uspi);
  	usb3 = ubh_get_usb_third(uspi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1096

252e211e9   Mark   Add in SunOS 4.1....
1097
1098
1099
1100
1101
1102
1103
  	/* Sort out mod used on SunOS 4.1.3 for fs_state */
  	uspi->s_postblformat = fs32_to_cpu(sb, usb3->fs_postblformat);
  	if (((flags & UFS_ST_MASK) == UFS_ST_SUNOS) &&
  	    (uspi->s_postblformat != UFS_42POSTBLFMT)) {
  		flags &= ~UFS_ST_MASK;
  		flags |=  UFS_ST_SUN;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1104
1105
1106
1107
1108
1109
  	/*
  	 * Check ufs magic number
  	 */
  	sbi->s_bytesex = BYTESEX_LE;
  	switch ((uspi->fs_magic = fs32_to_cpu(sb, usb3->fs_magic))) {
  		case UFS_MAGIC:
d27d7a9a7   Thomas Stewart   ufs: permit mount...
1110
  		case UFS_MAGIC_BW:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1111
1112
1113
1114
1115
1116
1117
1118
1119
  		case UFS2_MAGIC:
  		case UFS_MAGIC_LFN:
  	        case UFS_MAGIC_FEA:
  	        case UFS_MAGIC_4GB:
  			goto magic_found;
  	}
  	sbi->s_bytesex = BYTESEX_BE;
  	switch ((uspi->fs_magic = fs32_to_cpu(sb, usb3->fs_magic))) {
  		case UFS_MAGIC:
d27d7a9a7   Thomas Stewart   ufs: permit mount...
1120
  		case UFS_MAGIC_BW:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
1148
1149
1150
  		case UFS2_MAGIC:
  		case UFS_MAGIC_LFN:
  	        case UFS_MAGIC_FEA:
  	        case UFS_MAGIC_4GB:
  			goto magic_found;
  	}
  
  	if ((((sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_NEXTSTEP) 
  	  || ((sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_NEXTSTEP_CD) 
  	  || ((sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_OPENSTEP)) 
  	  && uspi->s_sbbase < 256) {
  		ubh_brelse_uspi(uspi);
  		ubh = NULL;
  		uspi->s_sbbase += 8;
  		goto again;
  	}
  	if (!silent)
  		printk("ufs_read_super: bad magic number
  ");
  	goto failed;
  
  magic_found:
  	/*
  	 * Check block and fragment sizes
  	 */
  	uspi->s_bsize = fs32_to_cpu(sb, usb1->fs_bsize);
  	uspi->s_fsize = fs32_to_cpu(sb, usb1->fs_fsize);
  	uspi->s_sbsize = fs32_to_cpu(sb, usb1->fs_sbsize);
  	uspi->s_fmask = fs32_to_cpu(sb, usb1->fs_fmask);
  	uspi->s_fshift = fs32_to_cpu(sb, usb1->fs_fshift);
9e8c4273e   vignesh babu   is_power_of_2: uf...
1151
  	if (!is_power_of_2(uspi->s_fsize)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
  		printk(KERN_ERR "ufs_read_super: fragment size %u is not a power of 2
  ",
  			uspi->s_fsize);
  			goto failed;
  	}
  	if (uspi->s_fsize < 512) {
  		printk(KERN_ERR "ufs_read_super: fragment size %u is too small
  ",
  			uspi->s_fsize);
  		goto failed;
  	}
  	if (uspi->s_fsize > 4096) {
  		printk(KERN_ERR "ufs_read_super: fragment size %u is too large
  ",
  			uspi->s_fsize);
  		goto failed;
  	}
9e8c4273e   vignesh babu   is_power_of_2: uf...
1169
  	if (!is_power_of_2(uspi->s_bsize)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
  		printk(KERN_ERR "ufs_read_super: block size %u is not a power of 2
  ",
  			uspi->s_bsize);
  		goto failed;
  	}
  	if (uspi->s_bsize < 4096) {
  		printk(KERN_ERR "ufs_read_super: block size %u is too small
  ",
  			uspi->s_bsize);
  		goto failed;
  	}
  	if (uspi->s_bsize / uspi->s_fsize > 8) {
  		printk(KERN_ERR "ufs_read_super: too many fragments per block (%u)
  ",
  			uspi->s_bsize / uspi->s_fsize);
  		goto failed;
  	}
  	if (uspi->s_fsize != block_size || uspi->s_sbsize != super_block_size) {
  		ubh_brelse_uspi(uspi);
  		ubh = NULL;
  		block_size = uspi->s_fsize;
  		super_block_size = uspi->s_sbsize;
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
1192
1193
  		UFSD("another value of block_size or super_block_size %u, %u
  ", block_size, super_block_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1194
1195
  		goto again;
  	}
f664f1f9b   Andrew Morton   revert "ufs: Fix ...
1196
  	sbi->s_flags = flags;/*after that line some functions use s_flags*/
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
1197
  	ufs_print_super_stuff(sb, usb1, usb2, usb3);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1198
1199
1200
1201
1202
  
  	/*
  	 * Check, if file system was correctly unmounted.
  	 * If not, make it read only.
  	 */
f664f1f9b   Andrew Morton   revert "ufs: Fix ...
1203
1204
1205
1206
1207
1208
  	if (((flags & UFS_ST_MASK) == UFS_ST_44BSD) ||
  	  ((flags & UFS_ST_MASK) == UFS_ST_OLD) ||
  	  (((flags & UFS_ST_MASK) == UFS_ST_SUN ||
  	    (flags & UFS_ST_MASK) == UFS_ST_SUNOS ||
  	  (flags & UFS_ST_MASK) == UFS_ST_SUNx86) &&
  	  (ufs_get_fs_state(sb, usb1, usb3) == (UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time))))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1209
1210
  		switch(usb1->fs_clean) {
  		case UFS_FSCLEAN:
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
1211
1212
  			UFSD("fs is clean
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1213
1214
  			break;
  		case UFS_FSSTABLE:
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
1215
1216
  			UFSD("fs is stable
  ");
b3a0fd4d8   Alex Viskovatoff   fs/ufs: recognize...
1217
1218
1219
1220
  			break;
  		case UFS_FSLOG:
  			UFSD("fs is logging fs
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1221
1222
  			break;
  		case UFS_FSOSF1:
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
1223
1224
  			UFSD("fs is DEC OSF/1
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
  			break;
  		case UFS_FSACTIVE:
  			printk("ufs_read_super: fs is active
  ");
  			sb->s_flags |= MS_RDONLY;
  			break;
  		case UFS_FSBAD:
  			printk("ufs_read_super: fs is bad
  ");
  			sb->s_flags |= MS_RDONLY;
  			break;
  		default:
  			printk("ufs_read_super: can't grok fs_clean 0x%x
  ", usb1->fs_clean);
  			sb->s_flags |= MS_RDONLY;
  			break;
  		}
ee3ffd6c1   Evgeniy Dushistov   [PATCH] ufs: make...
1242
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1243
1244
1245
1246
1247
1248
1249
1250
1251
  		printk("ufs_read_super: fs needs fsck
  ");
  		sb->s_flags |= MS_RDONLY;
  	}
  
  	/*
  	 * Read ufs_super_block into internal data structures
  	 */
  	sb->s_op = &ufs_super_ops;
f3e2a520f   Alexey Dobriyan   ufs: NFS support
1252
  	sb->s_export_op = &ufs_export_ops;
123e9caf1   Christoph Hellwig   quota: explicitly...
1253

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
  	sb->s_magic = fs32_to_cpu(sb, usb3->fs_magic);
  
  	uspi->s_sblkno = fs32_to_cpu(sb, usb1->fs_sblkno);
  	uspi->s_cblkno = fs32_to_cpu(sb, usb1->fs_cblkno);
  	uspi->s_iblkno = fs32_to_cpu(sb, usb1->fs_iblkno);
  	uspi->s_dblkno = fs32_to_cpu(sb, usb1->fs_dblkno);
  	uspi->s_cgoffset = fs32_to_cpu(sb, usb1->fs_cgoffset);
  	uspi->s_cgmask = fs32_to_cpu(sb, usb1->fs_cgmask);
  
  	if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
647b7e87b   Evgeniy Dushistov   [PATCH] ufs: one ...
1264
1265
1266
  		uspi->s_u2_size  = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size);
  		uspi->s_u2_dsize = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize);
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
  		uspi->s_size  =  fs32_to_cpu(sb, usb1->fs_size);
  		uspi->s_dsize =  fs32_to_cpu(sb, usb1->fs_dsize);
  	}
  
  	uspi->s_ncg = fs32_to_cpu(sb, usb1->fs_ncg);
  	/* s_bsize already set */
  	/* s_fsize already set */
  	uspi->s_fpb = fs32_to_cpu(sb, usb1->fs_frag);
  	uspi->s_minfree = fs32_to_cpu(sb, usb1->fs_minfree);
  	uspi->s_bmask = fs32_to_cpu(sb, usb1->fs_bmask);
  	uspi->s_fmask = fs32_to_cpu(sb, usb1->fs_fmask);
  	uspi->s_bshift = fs32_to_cpu(sb, usb1->fs_bshift);
  	uspi->s_fshift = fs32_to_cpu(sb, usb1->fs_fshift);
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
1280
1281
  	UFSD("uspi->s_bshift = %d,uspi->s_fshift = %d", uspi->s_bshift,
  		uspi->s_fshift);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
  	uspi->s_fpbshift = fs32_to_cpu(sb, usb1->fs_fragshift);
  	uspi->s_fsbtodb = fs32_to_cpu(sb, usb1->fs_fsbtodb);
  	/* s_sbsize already set */
  	uspi->s_csmask = fs32_to_cpu(sb, usb1->fs_csmask);
  	uspi->s_csshift = fs32_to_cpu(sb, usb1->fs_csshift);
  	uspi->s_nindir = fs32_to_cpu(sb, usb1->fs_nindir);
  	uspi->s_inopb = fs32_to_cpu(sb, usb1->fs_inopb);
  	uspi->s_nspf = fs32_to_cpu(sb, usb1->fs_nspf);
  	uspi->s_npsect = ufs_get_fs_npsect(sb, usb1, usb3);
  	uspi->s_interleave = fs32_to_cpu(sb, usb1->fs_interleave);
  	uspi->s_trackskew = fs32_to_cpu(sb, usb1->fs_trackskew);
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
1293
1294
1295
1296
1297
  
  	if (uspi->fs_magic == UFS2_MAGIC)
  		uspi->s_csaddr = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_csaddr);
  	else
  		uspi->s_csaddr = fs32_to_cpu(sb, usb1->fs_csaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1298
1299
1300
1301
1302
1303
1304
  	uspi->s_cssize = fs32_to_cpu(sb, usb1->fs_cssize);
  	uspi->s_cgsize = fs32_to_cpu(sb, usb1->fs_cgsize);
  	uspi->s_ntrak = fs32_to_cpu(sb, usb1->fs_ntrak);
  	uspi->s_nsect = fs32_to_cpu(sb, usb1->fs_nsect);
  	uspi->s_spc = fs32_to_cpu(sb, usb1->fs_spc);
  	uspi->s_ipg = fs32_to_cpu(sb, usb1->fs_ipg);
  	uspi->s_fpg = fs32_to_cpu(sb, usb1->fs_fpg);
647b7e87b   Evgeniy Dushistov   [PATCH] ufs: one ...
1305
1306
  	uspi->s_cpc = fs32_to_cpu(sb, usb2->fs_un.fs_u1.fs_cpc);
  	uspi->s_contigsumsize = fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_contigsumsize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1307
1308
  	uspi->s_qbmask = ufs_get_fs_qbmask(sb, usb3);
  	uspi->s_qfmask = ufs_get_fs_qfmask(sb, usb3);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1309
1310
1311
1312
1313
1314
1315
1316
  	uspi->s_nrpos = fs32_to_cpu(sb, usb3->fs_nrpos);
  	uspi->s_postbloff = fs32_to_cpu(sb, usb3->fs_postbloff);
  	uspi->s_rotbloff = fs32_to_cpu(sb, usb3->fs_rotbloff);
  
  	/*
  	 * Compute another frequently used values
  	 */
  	uspi->s_fpbmask = uspi->s_fpb - 1;
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
1317
  	if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1318
  		uspi->s_apbshift = uspi->s_bshift - 3;
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
1319
  	else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1320
  		uspi->s_apbshift = uspi->s_bshift - 2;
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
1321

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
  	uspi->s_2apbshift = uspi->s_apbshift * 2;
  	uspi->s_3apbshift = uspi->s_apbshift * 3;
  	uspi->s_apb = 1 << uspi->s_apbshift;
  	uspi->s_2apb = 1 << uspi->s_2apbshift;
  	uspi->s_3apb = 1 << uspi->s_3apbshift;
  	uspi->s_apbmask = uspi->s_apb - 1;
  	uspi->s_nspfshift = uspi->s_fshift - UFS_SECTOR_BITS;
  	uspi->s_nspb = uspi->s_nspf << uspi->s_fpbshift;
  	uspi->s_inopf = uspi->s_inopb >> uspi->s_fpbshift;
  	uspi->s_bpf = uspi->s_fsize << 3;
  	uspi->s_bpfshift = uspi->s_fshift + 3;
  	uspi->s_bpfmask = uspi->s_bpf - 1;
90b315af1   Evgeniy Dushistov   ufs: fix symlink ...
1334
1335
  	if ((sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_44BSD ||
  	    (sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_UFS2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1336
  		uspi->s_maxsymlinklen =
647b7e87b   Evgeniy Dushistov   [PATCH] ufs: one ...
1337
  		    fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_maxsymlinklen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1338

9e6766cc8   Duane Griffin   ufs: validate max...
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
  	if (uspi->fs_magic == UFS2_MAGIC)
  		maxsymlen = 2 * 4 * (UFS_NDADDR + UFS_NINDIR);
  	else
  		maxsymlen = 4 * (UFS_NDADDR + UFS_NINDIR);
  	if (uspi->s_maxsymlinklen > maxsymlen) {
  		ufs_warning(sb, __func__, "ufs_read_super: excessive maximum "
  			    "fast symlink size (%u)
  ", uspi->s_maxsymlinklen);
  		uspi->s_maxsymlinklen = maxsymlen;
  	}
8de527787   Al Viro   vfs: check i_nlin...
1349
  	sb->s_max_links = UFS_LINK_MAX;
9e6766cc8   Duane Griffin   ufs: validate max...
1350

b55c460da   David Howells   iget: stop UFS fr...
1351
1352
1353
  	inode = ufs_iget(sb, UFS_ROOTINO);
  	if (IS_ERR(inode)) {
  		ret = PTR_ERR(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1354
  		goto failed;
b55c460da   David Howells   iget: stop UFS fr...
1355
  	}
48fde701a   Al Viro   switch open-coded...
1356
  	sb->s_root = d_make_root(inode);
b55c460da   David Howells   iget: stop UFS fr...
1357
1358
  	if (!sb->s_root) {
  		ret = -ENOMEM;
48fde701a   Al Viro   switch open-coded...
1359
  		goto failed;
b55c460da   David Howells   iget: stop UFS fr...
1360
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1361

ee3ffd6c1   Evgeniy Dushistov   [PATCH] ufs: make...
1362
  	ufs_setup_cstotal(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1363
1364
1365
1366
1367
1368
  	/*
  	 * Read cylinder group structures
  	 */
  	if (!(sb->s_flags & MS_RDONLY))
  		if (!ufs_read_cylinder_structures(sb))
  			goto failed;
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
1369
1370
  	UFSD("EXIT
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1371
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1372
  failed:
f99d49adf   Jesper Juhl   [PATCH] kfree cle...
1373
1374
1375
1376
  	if (ubh)
  		ubh_brelse_uspi (uspi);
  	kfree (uspi);
  	kfree(sbi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1377
  	sb->s_fs_info = NULL;
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
1378
1379
  	UFSD("EXIT (FAILED)
  ");
b55c460da   David Howells   iget: stop UFS fr...
1380
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1381
1382
  
  failed_nomem:
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
1383
1384
  	UFSD("EXIT (NOMEM)
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1385
1386
  	return -ENOMEM;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1387
1388
1389
1390
1391
1392
1393
  static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
  {
  	struct ufs_sb_private_info * uspi;
  	struct ufs_super_block_first * usb1;
  	struct ufs_super_block_third * usb3;
  	unsigned new_mount_opt, ufstype;
  	unsigned flags;
337eb00a2   Alessio Igor Bogani   Push BKL down int...
1394

788257d61   Arnd Bergmann   ufs: remove the BKL
1395
  	lock_ufs(sb);
b6963327e   Marco Stornelli   ufs: drop lock/un...
1396
  	mutex_lock(&UFS_SB(sb)->s_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1397
1398
  	uspi = UFS_SB(sb)->s_uspi;
  	flags = UFS_SB(sb)->s_flags;
7b4ee73e2   Evgeniy   [PATCH] ufs cleanup
1399
1400
  	usb1 = ubh_get_usb_first(uspi);
  	usb3 = ubh_get_usb_third(uspi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1401
1402
1403
1404
1405
1406
1407
1408
  	
  	/*
  	 * Allow the "check" option to be passed as a remount option.
  	 * It is not possible to change ufstype option during remount
  	 */
  	ufstype = UFS_SB(sb)->s_mount_opt & UFS_MOUNT_UFSTYPE;
  	new_mount_opt = 0;
  	ufs_set_opt (new_mount_opt, ONERROR_LOCK);
bbd6851a3   Al Viro   Push lock_super()...
1409
  	if (!ufs_parse_options (data, &new_mount_opt)) {
b6963327e   Marco Stornelli   ufs: drop lock/un...
1410
  		mutex_unlock(&UFS_SB(sb)->s_lock);
788257d61   Arnd Bergmann   ufs: remove the BKL
1411
  		unlock_ufs(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1412
  		return -EINVAL;
bbd6851a3   Al Viro   Push lock_super()...
1413
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1414
1415
  	if (!(new_mount_opt & UFS_MOUNT_UFSTYPE)) {
  		new_mount_opt |= ufstype;
ee3ffd6c1   Evgeniy Dushistov   [PATCH] ufs: make...
1416
  	} else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1417
1418
  		printk("ufstype can't be changed during remount
  ");
b6963327e   Marco Stornelli   ufs: drop lock/un...
1419
  		mutex_unlock(&UFS_SB(sb)->s_lock);
788257d61   Arnd Bergmann   ufs: remove the BKL
1420
  		unlock_ufs(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1421
1422
1423
1424
1425
  		return -EINVAL;
  	}
  
  	if ((*mount_flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
  		UFS_SB(sb)->s_mount_opt = new_mount_opt;
b6963327e   Marco Stornelli   ufs: drop lock/un...
1426
  		mutex_unlock(&UFS_SB(sb)->s_lock);
788257d61   Arnd Bergmann   ufs: remove the BKL
1427
  		unlock_ufs(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1428
1429
1430
1431
1432
1433
1434
  		return 0;
  	}
  	
  	/*
  	 * fs was mouted as rw, remounting ro
  	 */
  	if (*mount_flags & MS_RDONLY) {
ee3ffd6c1   Evgeniy Dushistov   [PATCH] ufs: make...
1435
  		ufs_put_super_internal(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1436
1437
  		usb1->fs_time = cpu_to_fs32(sb, get_seconds());
  		if ((flags & UFS_ST_MASK) == UFS_ST_SUN
252e211e9   Mark   Add in SunOS 4.1....
1438
  		  || (flags & UFS_ST_MASK) == UFS_ST_SUNOS
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1439
1440
1441
  		  || (flags & UFS_ST_MASK) == UFS_ST_SUNx86) 
  			ufs_set_fs_state(sb, usb1, usb3,
  				UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time));
9695ef16e   Evgeniy Dushistov   [PATCH] ufs: wron...
1442
  		ubh_mark_buffer_dirty (USPI_UBH(uspi));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1443
  		sb->s_flags |= MS_RDONLY;
ee3ffd6c1   Evgeniy Dushistov   [PATCH] ufs: make...
1444
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1445
1446
1447
  	/*
  	 * fs was mounted as ro, remounting rw
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1448
1449
1450
1451
  #ifndef CONFIG_UFS_FS_WRITE
  		printk("ufs was compiled with read-only support, "
  		"can't be mounted as read-write
  ");
b6963327e   Marco Stornelli   ufs: drop lock/un...
1452
  		mutex_unlock(&UFS_SB(sb)->s_lock);
788257d61   Arnd Bergmann   ufs: remove the BKL
1453
  		unlock_ufs(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1454
1455
1456
  		return -EINVAL;
  #else
  		if (ufstype != UFS_MOUNT_UFSTYPE_SUN && 
252e211e9   Mark   Add in SunOS 4.1....
1457
  		    ufstype != UFS_MOUNT_UFSTYPE_SUNOS &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1458
  		    ufstype != UFS_MOUNT_UFSTYPE_44BSD &&
cbcae39fa   Evgeniy Dushistov   [PATCH] ufs2 writ...
1459
1460
  		    ufstype != UFS_MOUNT_UFSTYPE_SUNx86 &&
  		    ufstype != UFS_MOUNT_UFSTYPE_UFS2) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1461
1462
  			printk("this ufstype is read-only supported
  ");
b6963327e   Marco Stornelli   ufs: drop lock/un...
1463
  			mutex_unlock(&UFS_SB(sb)->s_lock);
788257d61   Arnd Bergmann   ufs: remove the BKL
1464
  			unlock_ufs(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1465
1466
  			return -EINVAL;
  		}
ee3ffd6c1   Evgeniy Dushistov   [PATCH] ufs: make...
1467
  		if (!ufs_read_cylinder_structures(sb)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1468
1469
  			printk("failed during remounting
  ");
b6963327e   Marco Stornelli   ufs: drop lock/un...
1470
  			mutex_unlock(&UFS_SB(sb)->s_lock);
788257d61   Arnd Bergmann   ufs: remove the BKL
1471
  			unlock_ufs(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1472
1473
1474
1475
1476
1477
  			return -EPERM;
  		}
  		sb->s_flags &= ~MS_RDONLY;
  #endif
  	}
  	UFS_SB(sb)->s_mount_opt = new_mount_opt;
b6963327e   Marco Stornelli   ufs: drop lock/un...
1478
  	mutex_unlock(&UFS_SB(sb)->s_lock);
788257d61   Arnd Bergmann   ufs: remove the BKL
1479
  	unlock_ufs(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1480
1481
  	return 0;
  }
34c80b1d9   Al Viro   vfs: switch ->sho...
1482
  static int ufs_show_options(struct seq_file *seq, struct dentry *root)
2a9807c0d   Evgeniy Dushistov   ufs: implement sh...
1483
  {
34c80b1d9   Al Viro   vfs: switch ->sho...
1484
  	struct ufs_sb_info *sbi = UFS_SB(root->d_sb);
2a9807c0d   Evgeniy Dushistov   ufs: implement sh...
1485
  	unsigned mval = sbi->s_mount_opt & UFS_MOUNT_UFSTYPE;
a447c0932   Steven Whitehouse   vfs: Use const fo...
1486
  	const struct match_token *tp = tokens;
2a9807c0d   Evgeniy Dushistov   ufs: implement sh...
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
  
  	while (tp->token != Opt_onerror_panic && tp->token != mval)
  		++tp;
  	BUG_ON(tp->token == Opt_onerror_panic);
  	seq_printf(seq, ",%s", tp->pattern);
  
  	mval = sbi->s_mount_opt & UFS_MOUNT_ONERROR;
  	while (tp->token != Opt_err && tp->token != mval)
  		++tp;
  	BUG_ON(tp->token == Opt_err);
  	seq_printf(seq, ",%s", tp->pattern);
  
  	return 0;
  }
647b7e87b   Evgeniy Dushistov   [PATCH] ufs: one ...
1501
  static int ufs_statfs(struct dentry *dentry, struct kstatfs *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1502
  {
726c33422   David Howells   [PATCH] VFS: Perm...
1503
  	struct super_block *sb = dentry->d_sb;
647b7e87b   Evgeniy Dushistov   [PATCH] ufs: one ...
1504
1505
1506
1507
1508
  	struct ufs_sb_private_info *uspi= UFS_SB(sb)->s_uspi;
  	unsigned  flags = UFS_SB(sb)->s_flags;
  	struct ufs_super_block_first *usb1;
  	struct ufs_super_block_second *usb2;
  	struct ufs_super_block_third *usb3;
41d577aa3   Coly Li   fs/ufs: return f_...
1509
  	u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1510

788257d61   Arnd Bergmann   ufs: remove the BKL
1511
  	lock_ufs(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1512

647b7e87b   Evgeniy Dushistov   [PATCH] ufs: one ...
1513
1514
1515
  	usb1 = ubh_get_usb_first(uspi);
  	usb2 = ubh_get_usb_second(uspi);
  	usb3 = ubh_get_usb_third(uspi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1516
  	
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1517
1518
  	if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
  		buf->f_type = UFS2_MAGIC;
647b7e87b   Evgeniy Dushistov   [PATCH] ufs: one ...
1519
  		buf->f_blocks = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize);
647b7e87b   Evgeniy Dushistov   [PATCH] ufs: one ...
1520
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1521
1522
  		buf->f_type = UFS_MAGIC;
  		buf->f_blocks = uspi->s_dsize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1523
  	}
ee3ffd6c1   Evgeniy Dushistov   [PATCH] ufs: make...
1524
1525
1526
  	buf->f_bfree = ufs_blkstofrags(uspi->cs_total.cs_nbfree) +
  		uspi->cs_total.cs_nffree;
  	buf->f_ffree = uspi->cs_total.cs_nifree;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1527
1528
1529
1530
1531
  	buf->f_bsize = sb->s_blocksize;
  	buf->f_bavail = (buf->f_bfree > (((long)buf->f_blocks / 100) * uspi->s_minfree))
  		? (buf->f_bfree - (((long)buf->f_blocks / 100) * uspi->s_minfree)) : 0;
  	buf->f_files = uspi->s_ncg * uspi->s_ipg;
  	buf->f_namelen = UFS_MAXNAMLEN;
41d577aa3   Coly Li   fs/ufs: return f_...
1532
1533
  	buf->f_fsid.val[0] = (u32)id;
  	buf->f_fsid.val[1] = (u32)(id >> 32);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1534

788257d61   Arnd Bergmann   ufs: remove the BKL
1535
  	unlock_ufs(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1536
1537
1538
  
  	return 0;
  }
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
1539
  static struct kmem_cache * ufs_inode_cachep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1540
1541
1542
1543
  
  static struct inode *ufs_alloc_inode(struct super_block *sb)
  {
  	struct ufs_inode_info *ei;
788257d61   Arnd Bergmann   ufs: remove the BKL
1544
  	ei = (struct ufs_inode_info *)kmem_cache_alloc(ufs_inode_cachep, GFP_NOFS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1545
1546
1547
1548
1549
  	if (!ei)
  		return NULL;
  	ei->vfs_inode.i_version = 1;
  	return &ei->vfs_inode;
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
1550
  static void ufs_i_callback(struct rcu_head *head)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1551
  {
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
1552
  	struct inode *inode = container_of(head, struct inode, i_rcu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1553
1554
  	kmem_cache_free(ufs_inode_cachep, UFS_I(inode));
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
1555
1556
1557
1558
  static void ufs_destroy_inode(struct inode *inode)
  {
  	call_rcu(&inode->i_rcu, ufs_i_callback);
  }
51cc50685   Alexey Dobriyan   SL*B: drop kmem c...
1559
  static void init_once(void *foo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1560
1561
  {
  	struct ufs_inode_info *ei = (struct ufs_inode_info *) foo;
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
1562
  	inode_init_once(&ei->vfs_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1563
  }
20c2df83d   Paul Mundt   mm: Remove slab d...
1564

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1565
1566
1567
1568
  static int init_inodecache(void)
  {
  	ufs_inode_cachep = kmem_cache_create("ufs_inode_cache",
  					     sizeof(struct ufs_inode_info),
fffb60f93   Paul Jackson   [PATCH] cpuset me...
1569
1570
  					     0, (SLAB_RECLAIM_ACCOUNT|
  						SLAB_MEM_SPREAD),
20c2df83d   Paul Mundt   mm: Remove slab d...
1571
  					     init_once);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1572
1573
1574
1575
1576
1577
1578
  	if (ufs_inode_cachep == NULL)
  		return -ENOMEM;
  	return 0;
  }
  
  static void destroy_inodecache(void)
  {
8c0a85377   Kirill A. Shutemov   fs: push rcu_barr...
1579
1580
1581
1582
1583
  	/*
  	 * Make sure all delayed rcu free inodes are flushed before we
  	 * destroy cache.
  	 */
  	rcu_barrier();
1a1d92c10   Alexey Dobriyan   [PATCH] Really ig...
1584
  	kmem_cache_destroy(ufs_inode_cachep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1585
  }
ee9b6d61a   Josef 'Jeff' Sipek   [PATCH] Mark stru...
1586
  static const struct super_operations ufs_super_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1587
1588
  	.alloc_inode	= ufs_alloc_inode,
  	.destroy_inode	= ufs_destroy_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1589
  	.write_inode	= ufs_write_inode,
58e8268c7   Al Viro   switch ufs to ->e...
1590
  	.evict_inode	= ufs_evict_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1591
  	.put_super	= ufs_put_super,
8c8006564   Christoph Hellwig   ufs: add ->sync_fs
1592
  	.sync_fs	= ufs_sync_fs,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1593
1594
  	.statfs		= ufs_statfs,
  	.remount_fs	= ufs_remount,
2a9807c0d   Evgeniy Dushistov   ufs: implement sh...
1595
  	.show_options   = ufs_show_options,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1596
  };
152a08366   Al Viro   new helper: mount...
1597
1598
  static struct dentry *ufs_mount(struct file_system_type *fs_type,
  	int flags, const char *dev_name, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1599
  {
152a08366   Al Viro   new helper: mount...
1600
  	return mount_bdev(fs_type, flags, dev_name, data, ufs_fill_super);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1601
1602
1603
1604
1605
  }
  
  static struct file_system_type ufs_fs_type = {
  	.owner		= THIS_MODULE,
  	.name		= "ufs",
152a08366   Al Viro   new helper: mount...
1606
  	.mount		= ufs_mount,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1607
1608
1609
  	.kill_sb	= kill_block_super,
  	.fs_flags	= FS_REQUIRES_DEV,
  };
7f78e0351   Eric W. Biederman   fs: Limit sys_mou...
1610
  MODULE_ALIAS_FS("ufs");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
  
  static int __init init_ufs_fs(void)
  {
  	int err = init_inodecache();
  	if (err)
  		goto out1;
  	err = register_filesystem(&ufs_fs_type);
  	if (err)
  		goto out;
  	return 0;
  out:
  	destroy_inodecache();
  out1:
  	return err;
  }
  
  static void __exit exit_ufs_fs(void)
  {
  	unregister_filesystem(&ufs_fs_type);
  	destroy_inodecache();
  }
  
  module_init(init_ufs_fs)
  module_exit(exit_ufs_fs)
  MODULE_LICENSE("GPL");