Blame view

fs/udf/super.c 60.7 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
  /*
   * super.c
   *
   * PURPOSE
   *  Super block routines for the OSTA-UDF(tm) filesystem.
   *
   * DESCRIPTION
   *  OSTA-UDF(tm) = Optical Storage Technology Association
   *  Universal Disk Format.
   *
   *  This code is based on version 2.00 of the UDF specification,
   *  and revision 3 of the ECMA 167 standard [equivalent to ISO 13346].
   *    http://www.osta.org/
   *    http://www.ecma.ch/
   *    http://www.iso.org/
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
   * COPYRIGHT
   *  This file is distributed under the terms of the GNU General Public
   *  License (GPL). Copies of the GPL can be obtained from:
   *    ftp://prep.ai.mit.edu/pub/gnu/GPL
   *  Each contributing author retains all rights to their own work.
   *
   *  (C) 1998 Dave Boynton
   *  (C) 1998-2004 Ben Fennema
   *  (C) 2000 Stelias Computing Inc
   *
   * HISTORY
   *
   *  09/24/98 dgb  changed to allow compiling outside of kernel, and
   *                added some debugging.
   *  10/01/98 dgb  updated to allow (some) possibility of compiling w/2.0.34
   *  10/16/98      attempting some multi-session support
   *  10/17/98      added freespace count for "df"
   *  11/11/98 gr   added novrs option
   *  11/26/98 dgb  added fileset,anchor mount options
3a71fc5de   Marcin Slusarz   udf: fix coding s...
36
37
   *  12/06/98 blf  really hosed things royally. vat/sparing support. sequenced
   *                vol descs. rewrote option handling based on isofs
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
39
   *  12/20/98      find the free space bitmap (if it exists)
   */
cb00ea352   Cyrill Gorcunov   UDF: coding style...
40
  #include "udfdecl.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
44
45
46
47
48
49
  #include <linux/blkdev.h>
  #include <linux/slab.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/parser.h>
  #include <linux/stat.h>
  #include <linux/cdrom.h>
  #include <linux/nls.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
  #include <linux/buffer_head.h>
  #include <linux/vfs.h>
  #include <linux/vmalloc.h>
dc5d39be6   Marcin Slusarz   udf: convert UDF_...
53
  #include <linux/errno.h>
6da80894c   Miklos Szeredi   mount options: fi...
54
55
  #include <linux/mount.h>
  #include <linux/seq_file.h>
01b954a36   Marcin Slusarz   udf: convert udf_...
56
  #include <linux/bitmap.h>
f845fced9   Bob Copeland   udf: use crc_itu_...
57
  #include <linux/crc-itu-t.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
  #include <asm/byteorder.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  #include "udf_sb.h"
  #include "udf_i.h"
  
  #include <linux/init.h>
  #include <asm/uaccess.h>
  
  #define VDS_POS_PRIMARY_VOL_DESC	0
  #define VDS_POS_UNALLOC_SPACE_DESC	1
  #define VDS_POS_LOGICAL_VOL_DESC	2
  #define VDS_POS_PARTITION_DESC		3
  #define VDS_POS_IMP_USE_VOL_DESC	4
  #define VDS_POS_VOL_DESC_PTR		5
  #define VDS_POS_TERMINATING_DESC	6
  #define VDS_POS_LENGTH			7
6da80894c   Miklos Szeredi   mount options: fi...
73
  #define UDF_DEFAULT_BLOCKSIZE 2048
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
76
  /* These are the "meat" - everything else is stuffing */
  static int udf_fill_super(struct super_block *, void *, int);
  static void udf_put_super(struct super_block *);
146bca72c   Jan Kara   udf: Don't write ...
77
  static int udf_sync_fs(struct super_block *, int);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
  static int udf_remount_fs(struct super_block *, int *, char *);
5ca4e4be8   Pekka Enberg   Remove struct typ...
79
  static void udf_load_logicalvolint(struct super_block *, struct kernel_extent_ad);
5ca4e4be8   Pekka Enberg   Remove struct typ...
80
81
  static int udf_find_fileset(struct super_block *, struct kernel_lb_addr *,
  			    struct kernel_lb_addr *);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
82
  static void udf_load_fileset(struct super_block *, struct buffer_head *,
5ca4e4be8   Pekka Enberg   Remove struct typ...
83
  			     struct kernel_lb_addr *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
85
86
  static void udf_open_lvid(struct super_block *);
  static void udf_close_lvid(struct super_block *);
  static unsigned int udf_count_free(struct super_block *);
726c33422   David Howells   [PATCH] VFS: Perm...
87
  static int udf_statfs(struct dentry *, struct kstatfs *);
34c80b1d9   Al Viro   vfs: switch ->sho...
88
  static int udf_show_options(struct seq_file *, struct dentry *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89

6c79e987d   Marcin Slusarz   udf: remove some ...
90
91
  struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct udf_sb_info *sbi)
  {
4b11111ab   Marcin Slusarz   udf: fix coding s...
92
93
  	struct logicalVolIntegrityDesc *lvid =
  		(struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data;
6c79e987d   Marcin Slusarz   udf: remove some ...
94
  	__u32 number_of_partitions = le32_to_cpu(lvid->numOfPartitions);
4b11111ab   Marcin Slusarz   udf: fix coding s...
95
96
  	__u32 offset = number_of_partitions * 2 *
  				sizeof(uint32_t)/sizeof(uint8_t);
6c79e987d   Marcin Slusarz   udf: remove some ...
97
98
  	return (struct logicalVolIntegrityDescImpUse *)&(lvid->impUse[offset]);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
  /* UDF filesystem type */
152a08366   Al Viro   new helper: mount...
100
101
  static struct dentry *udf_mount(struct file_system_type *fs_type,
  		      int flags, const char *dev_name, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
  {
152a08366   Al Viro   new helper: mount...
103
  	return mount_bdev(fs_type, flags, dev_name, data, udf_fill_super);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
105
106
  }
  
  static struct file_system_type udf_fstype = {
28de7948a   Cyrill Gorcunov   UDF: coding style...
107
108
  	.owner		= THIS_MODULE,
  	.name		= "udf",
152a08366   Al Viro   new helper: mount...
109
  	.mount		= udf_mount,
28de7948a   Cyrill Gorcunov   UDF: coding style...
110
111
  	.kill_sb	= kill_block_super,
  	.fs_flags	= FS_REQUIRES_DEV,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
  };
cb00ea352   Cyrill Gorcunov   UDF: coding style...
113
  static struct kmem_cache *udf_inode_cachep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
115
116
117
  
  static struct inode *udf_alloc_inode(struct super_block *sb)
  {
  	struct udf_inode_info *ei;
3a71fc5de   Marcin Slusarz   udf: fix coding s...
118
  	ei = kmem_cache_alloc(udf_inode_cachep, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
120
  	if (!ei)
  		return NULL;
95f8797f4   Dan Bastone   [PATCH] initializ...
121
122
123
124
125
126
  
  	ei->i_unique = 0;
  	ei->i_lenExtents = 0;
  	ei->i_next_alloc_block = 0;
  	ei->i_next_alloc_goal = 0;
  	ei->i_strat4096 = 0;
4d0fb621d   Alessio Igor Bogani   udf: Replace bkl ...
127
  	init_rwsem(&ei->i_data_sem);
95f8797f4   Dan Bastone   [PATCH] initializ...
128

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
130
  	return &ei->vfs_inode;
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
131
  static void udf_i_callback(struct rcu_head *head)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
  {
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
133
  	struct inode *inode = container_of(head, struct inode, i_rcu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
  	kmem_cache_free(udf_inode_cachep, UDF_I(inode));
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
136
137
138
139
  static void udf_destroy_inode(struct inode *inode)
  {
  	call_rcu(&inode->i_rcu, udf_i_callback);
  }
51cc50685   Alexey Dobriyan   SL*B: drop kmem c...
140
  static void init_once(void *foo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
  {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
142
  	struct udf_inode_info *ei = (struct udf_inode_info *)foo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143

a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
144
145
  	ei->i_ext.i_data = NULL;
  	inode_init_once(&ei->vfs_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
147
148
149
150
151
  }
  
  static int init_inodecache(void)
  {
  	udf_inode_cachep = kmem_cache_create("udf_inode_cache",
  					     sizeof(struct udf_inode_info),
cb00ea352   Cyrill Gorcunov   UDF: coding style...
152
153
  					     0, (SLAB_RECLAIM_ACCOUNT |
  						 SLAB_MEM_SPREAD),
20c2df83d   Paul Mundt   mm: Remove slab d...
154
  					     init_once);
28de7948a   Cyrill Gorcunov   UDF: coding style...
155
  	if (!udf_inode_cachep)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
157
158
159
160
161
  		return -ENOMEM;
  	return 0;
  }
  
  static void destroy_inodecache(void)
  {
1a1d92c10   Alexey Dobriyan   [PATCH] Really ig...
162
  	kmem_cache_destroy(udf_inode_cachep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
165
  }
  
  /* Superblock operations */
ee9b6d61a   Josef 'Jeff' Sipek   [PATCH] Mark stru...
166
  static const struct super_operations udf_sb_ops = {
28de7948a   Cyrill Gorcunov   UDF: coding style...
167
168
169
  	.alloc_inode	= udf_alloc_inode,
  	.destroy_inode	= udf_destroy_inode,
  	.write_inode	= udf_write_inode,
3aac2b62e   Al Viro   switch udf to ->e...
170
  	.evict_inode	= udf_evict_inode,
28de7948a   Cyrill Gorcunov   UDF: coding style...
171
  	.put_super	= udf_put_super,
146bca72c   Jan Kara   udf: Don't write ...
172
  	.sync_fs	= udf_sync_fs,
28de7948a   Cyrill Gorcunov   UDF: coding style...
173
174
  	.statfs		= udf_statfs,
  	.remount_fs	= udf_remount_fs,
6da80894c   Miklos Szeredi   mount options: fi...
175
  	.show_options	= udf_show_options,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
  };
cb00ea352   Cyrill Gorcunov   UDF: coding style...
177
  struct udf_options {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
179
180
181
182
183
184
185
186
187
  	unsigned char novrs;
  	unsigned int blocksize;
  	unsigned int session;
  	unsigned int lastblock;
  	unsigned int anchor;
  	unsigned int volume;
  	unsigned short partition;
  	unsigned int fileset;
  	unsigned int rootdir;
  	unsigned int flags;
faa17292f   Al Viro   udf: propagate um...
188
  	umode_t umask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
190
  	gid_t gid;
  	uid_t uid;
faa17292f   Al Viro   udf: propagate um...
191
192
  	umode_t fmode;
  	umode_t dmode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
194
195
196
197
198
  	struct nls_table *nls_map;
  };
  
  static int __init init_udf_fs(void)
  {
  	int err;
28de7948a   Cyrill Gorcunov   UDF: coding style...
199

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
201
202
203
204
205
  	err = init_inodecache();
  	if (err)
  		goto out1;
  	err = register_filesystem(&udf_fstype);
  	if (err)
  		goto out;
28de7948a   Cyrill Gorcunov   UDF: coding style...
206

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
  	return 0;
28de7948a   Cyrill Gorcunov   UDF: coding style...
208
209
  
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
  	destroy_inodecache();
28de7948a   Cyrill Gorcunov   UDF: coding style...
211
212
  
  out1:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
214
215
216
217
218
219
220
221
222
  	return err;
  }
  
  static void __exit exit_udf_fs(void)
  {
  	unregister_filesystem(&udf_fstype);
  	destroy_inodecache();
  }
  
  module_init(init_udf_fs)
28de7948a   Cyrill Gorcunov   UDF: coding style...
223
  module_exit(exit_udf_fs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224

dc5d39be6   Marcin Slusarz   udf: convert UDF_...
225
226
227
228
229
230
231
  static int udf_sb_alloc_partition_maps(struct super_block *sb, u32 count)
  {
  	struct udf_sb_info *sbi = UDF_SB(sb);
  
  	sbi->s_partmaps = kcalloc(count, sizeof(struct udf_part_map),
  				  GFP_KERNEL);
  	if (!sbi->s_partmaps) {
8076c363d   Joe Perches   udf: Rename udf_e...
232
233
234
  		udf_err(sb, "Unable to allocate space for %d partition maps
  ",
  			count);
dc5d39be6   Marcin Slusarz   udf: convert UDF_...
235
236
237
238
239
240
241
  		sbi->s_partitions = 0;
  		return -ENOMEM;
  	}
  
  	sbi->s_partitions = count;
  	return 0;
  }
34c80b1d9   Al Viro   vfs: switch ->sho...
242
  static int udf_show_options(struct seq_file *seq, struct dentry *root)
6da80894c   Miklos Szeredi   mount options: fi...
243
  {
34c80b1d9   Al Viro   vfs: switch ->sho...
244
  	struct super_block *sb = root->d_sb;
6da80894c   Miklos Szeredi   mount options: fi...
245
246
247
248
  	struct udf_sb_info *sbi = UDF_SB(sb);
  
  	if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT))
  		seq_puts(seq, ",nostrict");
1197e4dfc   Clemens Ladisch   udf: use hardware...
249
  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_BLOCKSIZE_SET))
6da80894c   Miklos Szeredi   mount options: fi...
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
  		seq_printf(seq, ",bs=%lu", sb->s_blocksize);
  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_UNHIDE))
  		seq_puts(seq, ",unhide");
  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_UNDELETE))
  		seq_puts(seq, ",undelete");
  	if (!UDF_QUERY_FLAG(sb, UDF_FLAG_USE_AD_IN_ICB))
  		seq_puts(seq, ",noadinicb");
  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_USE_SHORT_AD))
  		seq_puts(seq, ",shortad");
  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_UID_FORGET))
  		seq_puts(seq, ",uid=forget");
  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_UID_IGNORE))
  		seq_puts(seq, ",uid=ignore");
  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_GID_FORGET))
  		seq_puts(seq, ",gid=forget");
  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_GID_IGNORE))
  		seq_puts(seq, ",gid=ignore");
  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_UID_SET))
  		seq_printf(seq, ",uid=%u", sbi->s_uid);
  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_GID_SET))
  		seq_printf(seq, ",gid=%u", sbi->s_gid);
  	if (sbi->s_umask != 0)
faa17292f   Al Viro   udf: propagate um...
272
  		seq_printf(seq, ",umask=%ho", sbi->s_umask);
87bc730c0   Marcin Slusarz   udf: fix default ...
273
  	if (sbi->s_fmode != UDF_INVALID_MODE)
faa17292f   Al Viro   udf: propagate um...
274
  		seq_printf(seq, ",mode=%ho", sbi->s_fmode);
87bc730c0   Marcin Slusarz   udf: fix default ...
275
  	if (sbi->s_dmode != UDF_INVALID_MODE)
faa17292f   Al Viro   udf: propagate um...
276
  		seq_printf(seq, ",dmode=%ho", sbi->s_dmode);
6da80894c   Miklos Szeredi   mount options: fi...
277
278
279
280
  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_SESSION_SET))
  		seq_printf(seq, ",session=%u", sbi->s_session);
  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_LASTBLOCK_SET))
  		seq_printf(seq, ",lastblock=%u", sbi->s_last_block);
403460051   Jan Kara   udf: Try anchor i...
281
282
  	if (sbi->s_anchor != 0)
  		seq_printf(seq, ",anchor=%u", sbi->s_anchor);
6da80894c   Miklos Szeredi   mount options: fi...
283
284
285
286
287
288
289
290
291
292
293
  	/*
  	 * volume, partition, fileset and rootdir seem to be ignored
  	 * currently
  	 */
  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8))
  		seq_puts(seq, ",utf8");
  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP) && sbi->s_nls_map)
  		seq_printf(seq, ",iocharset=%s", sbi->s_nls_map->charset);
  
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
294
295
296
297
298
299
300
301
302
303
304
  /*
   * udf_parse_options
   *
   * PURPOSE
   *	Parse mount options.
   *
   * DESCRIPTION
   *	The following mount options are supported:
   *
   *	gid=		Set the default group.
   *	umask=		Set the default umask.
7ac9bcd5d   Marcin Slusarz   udf: implement mo...
305
306
   *	mode=		Set the default file permissions.
   *	dmode=		Set the default directory permissions.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
308
309
310
311
312
313
314
315
316
317
318
319
   *	uid=		Set the default user.
   *	bs=		Set the block size.
   *	unhide		Show otherwise hidden files.
   *	undelete	Show deleted files in lists.
   *	adinicb		Embed data in the inode (default)
   *	noadinicb	Don't embed data in the inode
   *	shortad		Use short ad's
   *	longad		Use long ad's (default)
   *	nostrict	Unset strict conformance
   *	iocharset=	Set the NLS character set
   *
   *	The remaining are for debugging and disaster recovery:
   *
28de7948a   Cyrill Gorcunov   UDF: coding style...
320
   *	novrs		Skip volume sequence recognition
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
   *
   *	The following expect a offset from 0.
   *
   *	session=	Set the CDROM session (default= last session)
   *	anchor=		Override standard anchor location. (default= 256)
   *	volume=		Override the VolumeDesc location. (unused)
   *	partition=	Override the PartitionDesc location. (unused)
   *	lastblock=	Set the last block of the filesystem/
   *
   *	The following expect a offset from the partition root.
   *
   *	fileset=	Override the fileset block location. (unused)
   *	rootdir=	Override the root directory location. (unused)
   *		WARNING: overriding the rootdir to a non-directory may
   *		yield highly unpredictable results.
   *
   * PRE-CONDITIONS
   *	options		Pointer to mount options string.
   *	uopts		Pointer to mount options variable.
   *
   * POST-CONDITIONS
   *	<return>	1	Mount options parsed okay.
   *	<return>	0	Error parsing mount options.
   *
   * HISTORY
   *	July 1, 1997 - Andrew E. Mileski
   *	Written, tested, and released.
   */
28de7948a   Cyrill Gorcunov   UDF: coding style...
349

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
351
352
353
354
355
  enum {
  	Opt_novrs, Opt_nostrict, Opt_bs, Opt_unhide, Opt_undelete,
  	Opt_noadinicb, Opt_adinicb, Opt_shortad, Opt_longad,
  	Opt_gid, Opt_uid, Opt_umask, Opt_session, Opt_lastblock,
  	Opt_anchor, Opt_volume, Opt_partition, Opt_fileset,
  	Opt_rootdir, Opt_utf8, Opt_iocharset,
7ac9bcd5d   Marcin Slusarz   udf: implement mo...
356
357
  	Opt_err, Opt_uforget, Opt_uignore, Opt_gforget, Opt_gignore,
  	Opt_fmode, Opt_dmode
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
  };
a447c0932   Steven Whitehouse   vfs: Use const fo...
359
  static const match_table_t tokens = {
28de7948a   Cyrill Gorcunov   UDF: coding style...
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
  	{Opt_novrs,	"novrs"},
  	{Opt_nostrict,	"nostrict"},
  	{Opt_bs,	"bs=%u"},
  	{Opt_unhide,	"unhide"},
  	{Opt_undelete,	"undelete"},
  	{Opt_noadinicb,	"noadinicb"},
  	{Opt_adinicb,	"adinicb"},
  	{Opt_shortad,	"shortad"},
  	{Opt_longad,	"longad"},
  	{Opt_uforget,	"uid=forget"},
  	{Opt_uignore,	"uid=ignore"},
  	{Opt_gforget,	"gid=forget"},
  	{Opt_gignore,	"gid=ignore"},
  	{Opt_gid,	"gid=%u"},
  	{Opt_uid,	"uid=%u"},
  	{Opt_umask,	"umask=%o"},
  	{Opt_session,	"session=%u"},
  	{Opt_lastblock,	"lastblock=%u"},
  	{Opt_anchor,	"anchor=%u"},
  	{Opt_volume,	"volume=%u"},
  	{Opt_partition,	"partition=%u"},
  	{Opt_fileset,	"fileset=%u"},
  	{Opt_rootdir,	"rootdir=%u"},
  	{Opt_utf8,	"utf8"},
  	{Opt_iocharset,	"iocharset=%s"},
7ac9bcd5d   Marcin Slusarz   udf: implement mo...
385
386
  	{Opt_fmode,     "mode=%o"},
  	{Opt_dmode,     "dmode=%o"},
28de7948a   Cyrill Gorcunov   UDF: coding style...
387
  	{Opt_err,	NULL}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388
  };
6da80894c   Miklos Szeredi   mount options: fi...
389
390
  static int udf_parse_options(char *options, struct udf_options *uopt,
  			     bool remount)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
392
393
394
395
  {
  	char *p;
  	int option;
  
  	uopt->novrs = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
397
398
399
400
401
402
403
404
405
406
  	uopt->partition = 0xFFFF;
  	uopt->session = 0xFFFFFFFF;
  	uopt->lastblock = 0;
  	uopt->anchor = 0;
  	uopt->volume = 0xFFFFFFFF;
  	uopt->rootdir = 0xFFFFFFFF;
  	uopt->fileset = 0xFFFFFFFF;
  	uopt->nls_map = NULL;
  
  	if (!options)
  		return 1;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
407
  	while ((p = strsep(&options, ",")) != NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408
409
410
411
412
413
  		substring_t args[MAX_OPT_ARGS];
  		int token;
  		if (!*p)
  			continue;
  
  		token = match_token(p, tokens, args);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
414
415
416
  		switch (token) {
  		case Opt_novrs:
  			uopt->novrs = 1;
4136801ae   Clemens Ladisch   udf: fix novrs mo...
417
  			break;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
418
419
420
421
  		case Opt_bs:
  			if (match_int(&args[0], &option))
  				return 0;
  			uopt->blocksize = option;
1197e4dfc   Clemens Ladisch   udf: use hardware...
422
  			uopt->flags |= (1 << UDF_FLAG_BLOCKSIZE_SET);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
  			break;
  		case Opt_unhide:
  			uopt->flags |= (1 << UDF_FLAG_UNHIDE);
  			break;
  		case Opt_undelete:
  			uopt->flags |= (1 << UDF_FLAG_UNDELETE);
  			break;
  		case Opt_noadinicb:
  			uopt->flags &= ~(1 << UDF_FLAG_USE_AD_IN_ICB);
  			break;
  		case Opt_adinicb:
  			uopt->flags |= (1 << UDF_FLAG_USE_AD_IN_ICB);
  			break;
  		case Opt_shortad:
  			uopt->flags |= (1 << UDF_FLAG_USE_SHORT_AD);
  			break;
  		case Opt_longad:
  			uopt->flags &= ~(1 << UDF_FLAG_USE_SHORT_AD);
  			break;
  		case Opt_gid:
  			if (match_int(args, &option))
  				return 0;
  			uopt->gid = option;
ca76d2d80   Cyrill Gorcunov   UDF: fix UID and ...
446
  			uopt->flags |= (1 << UDF_FLAG_GID_SET);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
447
448
449
450
451
  			break;
  		case Opt_uid:
  			if (match_int(args, &option))
  				return 0;
  			uopt->uid = option;
ca76d2d80   Cyrill Gorcunov   UDF: fix UID and ...
452
  			uopt->flags |= (1 << UDF_FLAG_UID_SET);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
453
454
455
456
457
458
459
460
461
462
463
464
465
  			break;
  		case Opt_umask:
  			if (match_octal(args, &option))
  				return 0;
  			uopt->umask = option;
  			break;
  		case Opt_nostrict:
  			uopt->flags &= ~(1 << UDF_FLAG_STRICT);
  			break;
  		case Opt_session:
  			if (match_int(args, &option))
  				return 0;
  			uopt->session = option;
6da80894c   Miklos Szeredi   mount options: fi...
466
467
  			if (!remount)
  				uopt->flags |= (1 << UDF_FLAG_SESSION_SET);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
468
469
470
471
472
  			break;
  		case Opt_lastblock:
  			if (match_int(args, &option))
  				return 0;
  			uopt->lastblock = option;
6da80894c   Miklos Szeredi   mount options: fi...
473
474
  			if (!remount)
  				uopt->flags |= (1 << UDF_FLAG_LASTBLOCK_SET);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
  			break;
  		case Opt_anchor:
  			if (match_int(args, &option))
  				return 0;
  			uopt->anchor = option;
  			break;
  		case Opt_volume:
  			if (match_int(args, &option))
  				return 0;
  			uopt->volume = option;
  			break;
  		case Opt_partition:
  			if (match_int(args, &option))
  				return 0;
  			uopt->partition = option;
  			break;
  		case Opt_fileset:
  			if (match_int(args, &option))
  				return 0;
  			uopt->fileset = option;
  			break;
  		case Opt_rootdir:
  			if (match_int(args, &option))
  				return 0;
  			uopt->rootdir = option;
  			break;
  		case Opt_utf8:
  			uopt->flags |= (1 << UDF_FLAG_UTF8);
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
504
  #ifdef CONFIG_UDF_NLS
cb00ea352   Cyrill Gorcunov   UDF: coding style...
505
506
507
508
  		case Opt_iocharset:
  			uopt->nls_map = load_nls(args[0].from);
  			uopt->flags |= (1 << UDF_FLAG_NLS_MAP);
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
  #endif
cb00ea352   Cyrill Gorcunov   UDF: coding style...
510
511
512
513
514
515
516
517
518
519
520
521
  		case Opt_uignore:
  			uopt->flags |= (1 << UDF_FLAG_UID_IGNORE);
  			break;
  		case Opt_uforget:
  			uopt->flags |= (1 << UDF_FLAG_UID_FORGET);
  			break;
  		case Opt_gignore:
  			uopt->flags |= (1 << UDF_FLAG_GID_IGNORE);
  			break;
  		case Opt_gforget:
  			uopt->flags |= (1 << UDF_FLAG_GID_FORGET);
  			break;
7ac9bcd5d   Marcin Slusarz   udf: implement mo...
522
523
524
525
526
527
528
529
530
531
  		case Opt_fmode:
  			if (match_octal(args, &option))
  				return 0;
  			uopt->fmode = option & 0777;
  			break;
  		case Opt_dmode:
  			if (match_octal(args, &option))
  				return 0;
  			uopt->dmode = option & 0777;
  			break;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
532
  		default:
78ace70c4   Joe Perches   udf: Convert prin...
533
534
  			pr_err("bad mount option \"%s\" or missing value
  ", p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
536
537
538
539
  			return 0;
  		}
  	}
  	return 1;
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
540
  static int udf_remount_fs(struct super_block *sb, int *flags, char *options)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541
542
  {
  	struct udf_options uopt;
6c79e987d   Marcin Slusarz   udf: remove some ...
543
  	struct udf_sb_info *sbi = UDF_SB(sb);
c79d967de   Christoph Hellwig   quota: move remou...
544
  	int error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545

6c79e987d   Marcin Slusarz   udf: remove some ...
546
547
548
549
  	uopt.flags = sbi->s_flags;
  	uopt.uid   = sbi->s_uid;
  	uopt.gid   = sbi->s_gid;
  	uopt.umask = sbi->s_umask;
7ac9bcd5d   Marcin Slusarz   udf: implement mo...
550
551
  	uopt.fmode = sbi->s_fmode;
  	uopt.dmode = sbi->s_dmode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
552

6da80894c   Miklos Szeredi   mount options: fi...
553
  	if (!udf_parse_options(options, &uopt, true))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
  		return -EINVAL;
c03cad241   Jan Kara   udf: Protect defa...
555
  	write_lock(&sbi->s_cred_lock);
6c79e987d   Marcin Slusarz   udf: remove some ...
556
557
558
559
  	sbi->s_flags = uopt.flags;
  	sbi->s_uid   = uopt.uid;
  	sbi->s_gid   = uopt.gid;
  	sbi->s_umask = uopt.umask;
7ac9bcd5d   Marcin Slusarz   udf: implement mo...
560
561
  	sbi->s_fmode = uopt.fmode;
  	sbi->s_dmode = uopt.dmode;
c03cad241   Jan Kara   udf: Protect defa...
562
  	write_unlock(&sbi->s_cred_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
563

6c79e987d   Marcin Slusarz   udf: remove some ...
564
565
  	if (sbi->s_lvid_bh) {
  		int write_rev = le16_to_cpu(udf_sb_lvidiu(sbi)->minUDFWriteRev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
566
567
568
  		if (write_rev > UDF_MAX_WRITE_VERSION)
  			*flags |= MS_RDONLY;
  	}
c79d967de   Christoph Hellwig   quota: move remou...
569
570
  	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
  		goto out_unlock;
363504628   Jan Kara   udf: Remove dead ...
571
  	if (*flags & MS_RDONLY)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
572
  		udf_close_lvid(sb);
363504628   Jan Kara   udf: Remove dead ...
573
  	else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
574
  		udf_open_lvid(sb);
c79d967de   Christoph Hellwig   quota: move remou...
575
  out_unlock:
c79d967de   Christoph Hellwig   quota: move remou...
576
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
577
  }
403460051   Jan Kara   udf: Try anchor i...
578
579
580
  /* Check Volume Structure Descriptors (ECMA 167 2/9.1) */
  /* We also check any "CD-ROM Volume Descriptor Set" (ECMA 167 2/8.3.1) */
  static loff_t udf_check_vsd(struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
581
582
  {
  	struct volStructDesc *vsd = NULL;
f4bcbbd92   Sebastian Manciulea   udf: Fix handling...
583
  	loff_t sector = 32768;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
584
585
  	int sectorsize;
  	struct buffer_head *bh = NULL;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
586
587
  	int nsr02 = 0;
  	int nsr03 = 0;
6c79e987d   Marcin Slusarz   udf: remove some ...
588
  	struct udf_sb_info *sbi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
589

6c79e987d   Marcin Slusarz   udf: remove some ...
590
  	sbi = UDF_SB(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
591
592
593
594
  	if (sb->s_blocksize < sizeof(struct volStructDesc))
  		sectorsize = sizeof(struct volStructDesc);
  	else
  		sectorsize = sb->s_blocksize;
6c79e987d   Marcin Slusarz   udf: remove some ...
595
  	sector += (sbi->s_session << sb->s_blocksize_bits);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
596
597
598
  
  	udf_debug("Starting at sector %u (%ld byte sectors)
  ",
706047a79   Sebastian Manciulea   udf: Fix compilat...
599
600
  		  (unsigned int)(sector >> sb->s_blocksize_bits),
  		  sb->s_blocksize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601
  	/* Process the sequence (if applicable) */
cb00ea352   Cyrill Gorcunov   UDF: coding style...
602
  	for (; !nsr02 && !nsr03; sector += sectorsize) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603
604
605
606
607
608
609
  		/* Read a block */
  		bh = udf_tread(sb, sector >> sb->s_blocksize_bits);
  		if (!bh)
  			break;
  
  		/* Look for ISO  descriptors */
  		vsd = (struct volStructDesc *)(bh->b_data +
3a71fc5de   Marcin Slusarz   udf: fix coding s...
610
  					      (sector & (sb->s_blocksize - 1)));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
611

cb00ea352   Cyrill Gorcunov   UDF: coding style...
612
  		if (vsd->stdIdent[0] == 0) {
3bf25cb40   Jan Kara   udf: use get_bh()
613
  			brelse(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
614
  			break;
3a71fc5de   Marcin Slusarz   udf: fix coding s...
615
616
  		} else if (!strncmp(vsd->stdIdent, VSD_STD_ID_CD001,
  				    VSD_STD_ID_LEN)) {
cb00ea352   Cyrill Gorcunov   UDF: coding style...
617
618
619
620
621
622
  			switch (vsd->structType) {
  			case 0:
  				udf_debug("ISO9660 Boot Record found
  ");
  				break;
  			case 1:
a983f368f   Joe Perches   udf: Neaten udf_d...
623
624
  				udf_debug("ISO9660 Primary Volume Descriptor found
  ");
cb00ea352   Cyrill Gorcunov   UDF: coding style...
625
626
  				break;
  			case 2:
a983f368f   Joe Perches   udf: Neaten udf_d...
627
628
  				udf_debug("ISO9660 Supplementary Volume Descriptor found
  ");
cb00ea352   Cyrill Gorcunov   UDF: coding style...
629
630
  				break;
  			case 3:
a983f368f   Joe Perches   udf: Neaten udf_d...
631
632
  				udf_debug("ISO9660 Volume Partition Descriptor found
  ");
cb00ea352   Cyrill Gorcunov   UDF: coding style...
633
634
  				break;
  			case 255:
a983f368f   Joe Perches   udf: Neaten udf_d...
635
636
  				udf_debug("ISO9660 Volume Descriptor Set Terminator found
  ");
cb00ea352   Cyrill Gorcunov   UDF: coding style...
637
638
639
640
641
642
  				break;
  			default:
  				udf_debug("ISO9660 VRS (%u) found
  ",
  					  vsd->structType);
  				break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643
  			}
3a71fc5de   Marcin Slusarz   udf: fix coding s...
644
645
646
647
648
  		} else if (!strncmp(vsd->stdIdent, VSD_STD_ID_BEA01,
  				    VSD_STD_ID_LEN))
  			; /* nothing */
  		else if (!strncmp(vsd->stdIdent, VSD_STD_ID_TEA01,
  				    VSD_STD_ID_LEN)) {
3bf25cb40   Jan Kara   udf: use get_bh()
649
  			brelse(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
  			break;
3a71fc5de   Marcin Slusarz   udf: fix coding s...
651
652
  		} else if (!strncmp(vsd->stdIdent, VSD_STD_ID_NSR02,
  				    VSD_STD_ID_LEN))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653
  			nsr02 = sector;
3a71fc5de   Marcin Slusarz   udf: fix coding s...
654
655
  		else if (!strncmp(vsd->stdIdent, VSD_STD_ID_NSR03,
  				    VSD_STD_ID_LEN))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
656
  			nsr03 = sector;
3bf25cb40   Jan Kara   udf: use get_bh()
657
  		brelse(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658
659
660
661
662
663
  	}
  
  	if (nsr03)
  		return nsr03;
  	else if (nsr02)
  		return nsr02;
6c79e987d   Marcin Slusarz   udf: remove some ...
664
  	else if (sector - (sbi->s_session << sb->s_blocksize_bits) == 32768)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
665
666
667
668
  		return -1;
  	else
  		return 0;
  }
3a71fc5de   Marcin Slusarz   udf: fix coding s...
669
  static int udf_find_fileset(struct super_block *sb,
5ca4e4be8   Pekka Enberg   Remove struct typ...
670
671
  			    struct kernel_lb_addr *fileset,
  			    struct kernel_lb_addr *root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
672
673
674
675
  {
  	struct buffer_head *bh = NULL;
  	long lastblock;
  	uint16_t ident;
6c79e987d   Marcin Slusarz   udf: remove some ...
676
  	struct udf_sb_info *sbi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
677
678
  
  	if (fileset->logicalBlockNum != 0xFFFFFFFF ||
cb00ea352   Cyrill Gorcunov   UDF: coding style...
679
  	    fileset->partitionReferenceNum != 0xFFFF) {
97e961fdb   Pekka Enberg   Fix the udf code ...
680
  		bh = udf_read_ptagged(sb, fileset, 0, &ident);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681

28de7948a   Cyrill Gorcunov   UDF: coding style...
682
  		if (!bh) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
683
  			return 1;
28de7948a   Cyrill Gorcunov   UDF: coding style...
684
  		} else if (ident != TAG_IDENT_FSD) {
3bf25cb40   Jan Kara   udf: use get_bh()
685
  			brelse(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
687
  			return 1;
  		}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
688

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
689
  	}
6c79e987d   Marcin Slusarz   udf: remove some ...
690
  	sbi = UDF_SB(sb);
3a71fc5de   Marcin Slusarz   udf: fix coding s...
691
692
  	if (!bh) {
  		/* Search backwards through the partitions */
5ca4e4be8   Pekka Enberg   Remove struct typ...
693
  		struct kernel_lb_addr newfileset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
694

28de7948a   Cyrill Gorcunov   UDF: coding style...
695
  /* --> cvg: FIXME - is it reasonable? */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
696
  		return 1;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
697

6c79e987d   Marcin Slusarz   udf: remove some ...
698
  		for (newfileset.partitionReferenceNum = sbi->s_partitions - 1;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
699
700
701
702
  		     (newfileset.partitionReferenceNum != 0xFFFF &&
  		      fileset->logicalBlockNum == 0xFFFFFFFF &&
  		      fileset->partitionReferenceNum == 0xFFFF);
  		     newfileset.partitionReferenceNum--) {
6c79e987d   Marcin Slusarz   udf: remove some ...
703
704
705
  			lastblock = sbi->s_partmaps
  					[newfileset.partitionReferenceNum]
  						.s_partition_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706
  			newfileset.logicalBlockNum = 0;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
707
  			do {
97e961fdb   Pekka Enberg   Fix the udf code ...
708
  				bh = udf_read_ptagged(sb, &newfileset, 0,
3a71fc5de   Marcin Slusarz   udf: fix coding s...
709
  						      &ident);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
710
711
  				if (!bh) {
  					newfileset.logicalBlockNum++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
712
713
  					continue;
  				}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
714
715
  				switch (ident) {
  				case TAG_IDENT_SBD:
28de7948a   Cyrill Gorcunov   UDF: coding style...
716
717
  				{
  					struct spaceBitmapDesc *sp;
4b11111ab   Marcin Slusarz   udf: fix coding s...
718
719
  					sp = (struct spaceBitmapDesc *)
  								bh->b_data;
28de7948a   Cyrill Gorcunov   UDF: coding style...
720
721
  					newfileset.logicalBlockNum += 1 +
  						((le32_to_cpu(sp->numOfBytes) +
4b11111ab   Marcin Slusarz   udf: fix coding s...
722
723
  						  sizeof(struct spaceBitmapDesc)
  						  - 1) >> sb->s_blocksize_bits);
28de7948a   Cyrill Gorcunov   UDF: coding style...
724
725
726
  					brelse(bh);
  					break;
  				}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
727
  				case TAG_IDENT_FSD:
28de7948a   Cyrill Gorcunov   UDF: coding style...
728
729
  					*fileset = newfileset;
  					break;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
730
  				default:
28de7948a   Cyrill Gorcunov   UDF: coding style...
731
732
733
734
  					newfileset.logicalBlockNum++;
  					brelse(bh);
  					bh = NULL;
  					break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
735
  				}
28de7948a   Cyrill Gorcunov   UDF: coding style...
736
737
738
  			} while (newfileset.logicalBlockNum < lastblock &&
  				 fileset->logicalBlockNum == 0xFFFFFFFF &&
  				 fileset->partitionReferenceNum == 0xFFFF);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
739
740
741
742
  		}
  	}
  
  	if ((fileset->logicalBlockNum != 0xFFFFFFFF ||
cb00ea352   Cyrill Gorcunov   UDF: coding style...
743
  	     fileset->partitionReferenceNum != 0xFFFF) && bh) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
745
  		udf_debug("Fileset at block=%d, partition=%d
  ",
cb00ea352   Cyrill Gorcunov   UDF: coding style...
746
747
  			  fileset->logicalBlockNum,
  			  fileset->partitionReferenceNum);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
748

6c79e987d   Marcin Slusarz   udf: remove some ...
749
  		sbi->s_partition = fileset->partitionReferenceNum;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
750
  		udf_load_fileset(sb, bh, root);
3bf25cb40   Jan Kara   udf: use get_bh()
751
  		brelse(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752
753
754
755
  		return 0;
  	}
  	return 1;
  }
c0eb31ed1   Jan Kara   udf: Cleanup volu...
756
  static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
757
758
  {
  	struct primaryVolDesc *pvoldesc;
ba9aadd80   Marcin Slusarz   udf: reduce stack...
759
  	struct ustr *instr, *outstr;
c0eb31ed1   Jan Kara   udf: Cleanup volu...
760
761
  	struct buffer_head *bh;
  	uint16_t ident;
ba9aadd80   Marcin Slusarz   udf: reduce stack...
762
763
764
765
766
767
768
769
770
  	int ret = 1;
  
  	instr = kmalloc(sizeof(struct ustr), GFP_NOFS);
  	if (!instr)
  		return 1;
  
  	outstr = kmalloc(sizeof(struct ustr), GFP_NOFS);
  	if (!outstr)
  		goto out1;
c0eb31ed1   Jan Kara   udf: Cleanup volu...
771
772
773
  
  	bh = udf_read_tagged(sb, block, block, &ident);
  	if (!bh)
ba9aadd80   Marcin Slusarz   udf: reduce stack...
774
  		goto out2;
c0eb31ed1   Jan Kara   udf: Cleanup volu...
775
  	BUG_ON(ident != TAG_IDENT_PVD);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
776
777
  
  	pvoldesc = (struct primaryVolDesc *)bh->b_data;
56774805d   Marcin Slusarz   udf: convert udf_...
778
779
  	if (udf_disk_stamp_to_time(&UDF_SB(sb)->s_record_time,
  			      pvoldesc->recordingDateAndTime)) {
af15a298a   Marcin Slusarz   udf: remove unnee...
780
  #ifdef UDFFS_DEBUG
5ca4e4be8   Pekka Enberg   Remove struct typ...
781
  		struct timestamp *ts = &pvoldesc->recordingDateAndTime;
a983f368f   Joe Perches   udf: Neaten udf_d...
782
783
  		udf_debug("recording time %04u/%02u/%02u %02u:%02u (%x)
  ",
af15a298a   Marcin Slusarz   udf: remove unnee...
784
785
786
  			  le16_to_cpu(ts->year), ts->month, ts->day, ts->hour,
  			  ts->minute, le16_to_cpu(ts->typeAndTimezone));
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
787
  	}
ba9aadd80   Marcin Slusarz   udf: reduce stack...
788
789
790
791
  	if (!udf_build_ustr(instr, pvoldesc->volIdent, 32))
  		if (udf_CS0toUTF8(outstr, instr)) {
  			strncpy(UDF_SB(sb)->s_volume_ident, outstr->u_name,
  				outstr->u_len > 31 ? 31 : outstr->u_len);
4b11111ab   Marcin Slusarz   udf: fix coding s...
792
793
  			udf_debug("volIdent[] = '%s'
  ",
a983f368f   Joe Perches   udf: Neaten udf_d...
794
  				  UDF_SB(sb)->s_volume_ident);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
795
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
796

ba9aadd80   Marcin Slusarz   udf: reduce stack...
797
798
799
800
  	if (!udf_build_ustr(instr, pvoldesc->volSetIdent, 128))
  		if (udf_CS0toUTF8(outstr, instr))
  			udf_debug("volSetIdent[] = '%s'
  ", outstr->u_name);
c0eb31ed1   Jan Kara   udf: Cleanup volu...
801
802
  
  	brelse(bh);
ba9aadd80   Marcin Slusarz   udf: reduce stack...
803
804
805
806
807
808
  	ret = 0;
  out2:
  	kfree(outstr);
  out1:
  	kfree(instr);
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
809
  }
3080a74ea   Namjae Jeon   udf: Skip mirror ...
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
  struct inode *udf_find_metadata_inode_efe(struct super_block *sb,
  					u32 meta_file_loc, u32 partition_num)
  {
  	struct kernel_lb_addr addr;
  	struct inode *metadata_fe;
  
  	addr.logicalBlockNum = meta_file_loc;
  	addr.partitionReferenceNum = partition_num;
  
  	metadata_fe = udf_iget(sb, &addr);
  
  	if (metadata_fe == NULL)
  		udf_warn(sb, "metadata inode efe not found
  ");
  	else if (UDF_I(metadata_fe)->i_alloc_type != ICBTAG_FLAG_AD_SHORT) {
  		udf_warn(sb, "metadata inode efe does not have short allocation descriptors!
  ");
  		iput(metadata_fe);
  		metadata_fe = NULL;
  	}
  
  	return metadata_fe;
  }
bfb257a59   Jan Kara   udf: Add read-onl...
833
834
835
836
837
  static int udf_load_metadata_files(struct super_block *sb, int partition)
  {
  	struct udf_sb_info *sbi = UDF_SB(sb);
  	struct udf_part_map *map;
  	struct udf_meta_data *mdata;
5ca4e4be8   Pekka Enberg   Remove struct typ...
838
  	struct kernel_lb_addr addr;
bfb257a59   Jan Kara   udf: Add read-onl...
839
840
841
842
843
  
  	map = &sbi->s_partmaps[partition];
  	mdata = &map->s_type_specific.s_metadata;
  
  	/* metadata address */
bfb257a59   Jan Kara   udf: Add read-onl...
844
845
  	udf_debug("Metadata file location: block = %d part = %d
  ",
3080a74ea   Namjae Jeon   udf: Skip mirror ...
846
  		  mdata->s_meta_file_loc, map->s_partition_num);
bfb257a59   Jan Kara   udf: Add read-onl...
847

3080a74ea   Namjae Jeon   udf: Skip mirror ...
848
849
  	mdata->s_metadata_fe = udf_find_metadata_inode_efe(sb,
  		mdata->s_meta_file_loc, map->s_partition_num);
bfb257a59   Jan Kara   udf: Add read-onl...
850
851
  
  	if (mdata->s_metadata_fe == NULL) {
3080a74ea   Namjae Jeon   udf: Skip mirror ...
852
853
854
855
  		/* mirror file entry */
  		udf_debug("Mirror metadata file location: block = %d part = %d
  ",
  			  mdata->s_mirror_file_loc, map->s_partition_num);
bfb257a59   Jan Kara   udf: Add read-onl...
856

3080a74ea   Namjae Jeon   udf: Skip mirror ...
857
858
  		mdata->s_mirror_fe = udf_find_metadata_inode_efe(sb,
  			mdata->s_mirror_file_loc, map->s_partition_num);
bfb257a59   Jan Kara   udf: Add read-onl...
859

3080a74ea   Namjae Jeon   udf: Skip mirror ...
860
861
862
  		if (mdata->s_mirror_fe == NULL) {
  			udf_err(sb, "Both metadata and mirror metadata inode efe can not found
  ");
bfb257a59   Jan Kara   udf: Add read-onl...
863
  			goto error_exit;
3080a74ea   Namjae Jeon   udf: Skip mirror ...
864
  		}
bfb257a59   Jan Kara   udf: Add read-onl...
865
866
867
868
869
870
871
872
873
874
875
876
877
  	}
  
  	/*
  	 * bitmap file entry
  	 * Note:
  	 * Load only if bitmap file location differs from 0xFFFFFFFF (DCN-5102)
  	*/
  	if (mdata->s_bitmap_file_loc != 0xFFFFFFFF) {
  		addr.logicalBlockNum = mdata->s_bitmap_file_loc;
  		addr.partitionReferenceNum = map->s_partition_num;
  
  		udf_debug("Bitmap file location: block = %d part = %d
  ",
a983f368f   Joe Perches   udf: Neaten udf_d...
878
  			  addr.logicalBlockNum, addr.partitionReferenceNum);
bfb257a59   Jan Kara   udf: Add read-onl...
879

97e961fdb   Pekka Enberg   Fix the udf code ...
880
  		mdata->s_bitmap_fe = udf_iget(sb, &addr);
bfb257a59   Jan Kara   udf: Add read-onl...
881
882
883
  
  		if (mdata->s_bitmap_fe == NULL) {
  			if (sb->s_flags & MS_RDONLY)
a40ecd7b3   Joe Perches   udf: Rename udf_w...
884
885
  				udf_warn(sb, "bitmap inode efe not found but it's ok since the disc is mounted read-only
  ");
bfb257a59   Jan Kara   udf: Add read-onl...
886
  			else {
8076c363d   Joe Perches   udf: Rename udf_e...
887
888
  				udf_err(sb, "bitmap inode efe not found and attempted read-write mount
  ");
bfb257a59   Jan Kara   udf: Add read-onl...
889
890
891
892
893
894
895
896
897
898
899
900
901
  				goto error_exit;
  			}
  		}
  	}
  
  	udf_debug("udf_load_metadata_files Ok
  ");
  
  	return 0;
  
  error_exit:
  	return 1;
  }
28de7948a   Cyrill Gorcunov   UDF: coding style...
902
  static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh,
5ca4e4be8   Pekka Enberg   Remove struct typ...
903
  			     struct kernel_lb_addr *root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
904
905
906
907
908
909
  {
  	struct fileSetDesc *fset;
  
  	fset = (struct fileSetDesc *)bh->b_data;
  
  	*root = lelb_to_cpu(fset->rootDirectoryICB.extLocation);
6c79e987d   Marcin Slusarz   udf: remove some ...
910
  	UDF_SB(sb)->s_serial_number = le16_to_cpu(fset->descTag.tagSerialNum);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
911

cb00ea352   Cyrill Gorcunov   UDF: coding style...
912
913
914
  	udf_debug("Rootdir at block=%d, partition=%d
  ",
  		  root->logicalBlockNum, root->partitionReferenceNum);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
915
  }
883cb9d18   Marcin Slusarz   udf: move calcula...
916
917
918
  int udf_compute_nr_groups(struct super_block *sb, u32 partition)
  {
  	struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition];
8dee00bb7   Julia Lawall   fs/udf: Use DIV_R...
919
920
921
  	return DIV_ROUND_UP(map->s_partition_len +
  			    (sizeof(struct spaceBitmapDesc) << 3),
  			    sb->s_blocksize * 8);
883cb9d18   Marcin Slusarz   udf: move calcula...
922
  }
66e1da3f4   Marcin Slusarz   udf: convert macr...
923
924
  static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index)
  {
66e1da3f4   Marcin Slusarz   udf: convert macr...
925
926
927
  	struct udf_bitmap *bitmap;
  	int nr_groups;
  	int size;
883cb9d18   Marcin Slusarz   udf: move calcula...
928
  	nr_groups = udf_compute_nr_groups(sb, index);
66e1da3f4   Marcin Slusarz   udf: convert macr...
929
930
931
932
  	size = sizeof(struct udf_bitmap) +
  		(sizeof(struct buffer_head *) * nr_groups);
  
  	if (size <= PAGE_SIZE)
ed2ae6f69   Joe Perches   fs/udf: Use vzalloc
933
  		bitmap = kzalloc(size, GFP_KERNEL);
66e1da3f4   Marcin Slusarz   udf: convert macr...
934
  	else
ed2ae6f69   Joe Perches   fs/udf: Use vzalloc
935
  		bitmap = vzalloc(size); /* TODO: get rid of vzalloc */
66e1da3f4   Marcin Slusarz   udf: convert macr...
936
937
  
  	if (bitmap == NULL) {
8076c363d   Joe Perches   udf: Rename udf_e...
938
939
940
  		udf_err(sb, "Unable to allocate space for bitmap and %d buffer_head pointers
  ",
  			nr_groups);
66e1da3f4   Marcin Slusarz   udf: convert macr...
941
942
  		return NULL;
  	}
66e1da3f4   Marcin Slusarz   udf: convert macr...
943
944
945
946
  	bitmap->s_block_bitmap = (struct buffer_head **)(bitmap + 1);
  	bitmap->s_nr_groups = nr_groups;
  	return bitmap;
  }
3fb38dfa0   Jan Kara   udf: Move filling...
947
948
  static int udf_fill_partdesc_info(struct super_block *sb,
  		struct partitionDesc *p, int p_index)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
949
  {
6c79e987d   Marcin Slusarz   udf: remove some ...
950
  	struct udf_part_map *map;
165923fa4   Marcin Slusarz   udf: super.c reor...
951
  	struct udf_sb_info *sbi = UDF_SB(sb);
3fb38dfa0   Jan Kara   udf: Move filling...
952
  	struct partitionHeaderDesc *phd;
165923fa4   Marcin Slusarz   udf: super.c reor...
953

3fb38dfa0   Jan Kara   udf: Move filling...
954
  	map = &sbi->s_partmaps[p_index];
165923fa4   Marcin Slusarz   udf: super.c reor...
955
956
957
958
959
960
961
962
963
964
965
966
  
  	map->s_partition_len = le32_to_cpu(p->partitionLength); /* blocks */
  	map->s_partition_root = le32_to_cpu(p->partitionStartingLocation);
  
  	if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_READ_ONLY))
  		map->s_partition_flags |= UDF_PART_FLAG_READ_ONLY;
  	if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_WRITE_ONCE))
  		map->s_partition_flags |= UDF_PART_FLAG_WRITE_ONCE;
  	if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_REWRITABLE))
  		map->s_partition_flags |= UDF_PART_FLAG_REWRITABLE;
  	if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_OVERWRITABLE))
  		map->s_partition_flags |= UDF_PART_FLAG_OVERWRITABLE;
a983f368f   Joe Perches   udf: Neaten udf_d...
967
968
969
970
  	udf_debug("Partition (%d type %x) starts at physical %d, block length %d
  ",
  		  p_index, map->s_partition_type,
  		  map->s_partition_root, map->s_partition_len);
165923fa4   Marcin Slusarz   udf: super.c reor...
971
972
973
  
  	if (strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR02) &&
  	    strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR03))
3fb38dfa0   Jan Kara   udf: Move filling...
974
  		return 0;
165923fa4   Marcin Slusarz   udf: super.c reor...
975
976
977
  
  	phd = (struct partitionHeaderDesc *)p->partitionContentsUse;
  	if (phd->unallocSpaceTable.extLength) {
5ca4e4be8   Pekka Enberg   Remove struct typ...
978
  		struct kernel_lb_addr loc = {
165923fa4   Marcin Slusarz   udf: super.c reor...
979
980
  			.logicalBlockNum = le32_to_cpu(
  				phd->unallocSpaceTable.extPosition),
3fb38dfa0   Jan Kara   udf: Move filling...
981
  			.partitionReferenceNum = p_index,
165923fa4   Marcin Slusarz   udf: super.c reor...
982
  		};
97e961fdb   Pekka Enberg   Fix the udf code ...
983
  		map->s_uspace.s_table = udf_iget(sb, &loc);
165923fa4   Marcin Slusarz   udf: super.c reor...
984
985
986
  		if (!map->s_uspace.s_table) {
  			udf_debug("cannot load unallocSpaceTable (part %d)
  ",
a983f368f   Joe Perches   udf: Neaten udf_d...
987
  				  p_index);
3fb38dfa0   Jan Kara   udf: Move filling...
988
  			return 1;
165923fa4   Marcin Slusarz   udf: super.c reor...
989
990
991
992
  		}
  		map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_TABLE;
  		udf_debug("unallocSpaceTable (part %d) @ %ld
  ",
a983f368f   Joe Perches   udf: Neaten udf_d...
993
  			  p_index, map->s_uspace.s_table->i_ino);
165923fa4   Marcin Slusarz   udf: super.c reor...
994
995
996
  	}
  
  	if (phd->unallocSpaceBitmap.extLength) {
3fb38dfa0   Jan Kara   udf: Move filling...
997
998
999
  		struct udf_bitmap *bitmap = udf_sb_alloc_bitmap(sb, p_index);
  		if (!bitmap)
  			return 1;
165923fa4   Marcin Slusarz   udf: super.c reor...
1000
  		map->s_uspace.s_bitmap = bitmap;
2e0838fd0   Jan Kara   udf: Improve erro...
1001
  		bitmap->s_extLength = le32_to_cpu(
165923fa4   Marcin Slusarz   udf: super.c reor...
1002
  				phd->unallocSpaceBitmap.extLength);
2e0838fd0   Jan Kara   udf: Improve erro...
1003
  		bitmap->s_extPosition = le32_to_cpu(
165923fa4   Marcin Slusarz   udf: super.c reor...
1004
  				phd->unallocSpaceBitmap.extPosition);
2e0838fd0   Jan Kara   udf: Improve erro...
1005
  		map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_BITMAP;
a983f368f   Joe Perches   udf: Neaten udf_d...
1006
1007
1008
  		udf_debug("unallocSpaceBitmap (part %d) @ %d
  ",
  			  p_index, bitmap->s_extPosition);
165923fa4   Marcin Slusarz   udf: super.c reor...
1009
1010
1011
  	}
  
  	if (phd->partitionIntegrityTable.extLength)
3fb38dfa0   Jan Kara   udf: Move filling...
1012
1013
  		udf_debug("partitionIntegrityTable (part %d)
  ", p_index);
165923fa4   Marcin Slusarz   udf: super.c reor...
1014
1015
  
  	if (phd->freedSpaceTable.extLength) {
5ca4e4be8   Pekka Enberg   Remove struct typ...
1016
  		struct kernel_lb_addr loc = {
165923fa4   Marcin Slusarz   udf: super.c reor...
1017
1018
  			.logicalBlockNum = le32_to_cpu(
  				phd->freedSpaceTable.extPosition),
3fb38dfa0   Jan Kara   udf: Move filling...
1019
  			.partitionReferenceNum = p_index,
165923fa4   Marcin Slusarz   udf: super.c reor...
1020
  		};
97e961fdb   Pekka Enberg   Fix the udf code ...
1021
  		map->s_fspace.s_table = udf_iget(sb, &loc);
165923fa4   Marcin Slusarz   udf: super.c reor...
1022
  		if (!map->s_fspace.s_table) {
3fb38dfa0   Jan Kara   udf: Move filling...
1023
1024
  			udf_debug("cannot load freedSpaceTable (part %d)
  ",
a983f368f   Joe Perches   udf: Neaten udf_d...
1025
  				  p_index);
3fb38dfa0   Jan Kara   udf: Move filling...
1026
  			return 1;
165923fa4   Marcin Slusarz   udf: super.c reor...
1027
1028
1029
1030
1031
  		}
  
  		map->s_partition_flags |= UDF_PART_FLAG_FREED_TABLE;
  		udf_debug("freedSpaceTable (part %d) @ %ld
  ",
a983f368f   Joe Perches   udf: Neaten udf_d...
1032
  			  p_index, map->s_fspace.s_table->i_ino);
165923fa4   Marcin Slusarz   udf: super.c reor...
1033
1034
1035
  	}
  
  	if (phd->freedSpaceBitmap.extLength) {
3fb38dfa0   Jan Kara   udf: Move filling...
1036
1037
1038
  		struct udf_bitmap *bitmap = udf_sb_alloc_bitmap(sb, p_index);
  		if (!bitmap)
  			return 1;
165923fa4   Marcin Slusarz   udf: super.c reor...
1039
  		map->s_fspace.s_bitmap = bitmap;
2e0838fd0   Jan Kara   udf: Improve erro...
1040
  		bitmap->s_extLength = le32_to_cpu(
165923fa4   Marcin Slusarz   udf: super.c reor...
1041
  				phd->freedSpaceBitmap.extLength);
2e0838fd0   Jan Kara   udf: Improve erro...
1042
  		bitmap->s_extPosition = le32_to_cpu(
165923fa4   Marcin Slusarz   udf: super.c reor...
1043
  				phd->freedSpaceBitmap.extPosition);
2e0838fd0   Jan Kara   udf: Improve erro...
1044
  		map->s_partition_flags |= UDF_PART_FLAG_FREED_BITMAP;
a983f368f   Joe Perches   udf: Neaten udf_d...
1045
1046
1047
  		udf_debug("freedSpaceBitmap (part %d) @ %d
  ",
  			  p_index, bitmap->s_extPosition);
165923fa4   Marcin Slusarz   udf: super.c reor...
1048
  	}
3fb38dfa0   Jan Kara   udf: Move filling...
1049
1050
  	return 0;
  }
e971b0b9e   Jan Kara   udf: Try harder w...
1051
1052
  static void udf_find_vat_block(struct super_block *sb, int p_index,
  			       int type1_index, sector_t start_block)
38b74a53e   Jan Kara   udf: Move process...
1053
1054
1055
  {
  	struct udf_sb_info *sbi = UDF_SB(sb);
  	struct udf_part_map *map = &sbi->s_partmaps[p_index];
e971b0b9e   Jan Kara   udf: Try harder w...
1056
  	sector_t vat_block;
5ca4e4be8   Pekka Enberg   Remove struct typ...
1057
  	struct kernel_lb_addr ino;
e971b0b9e   Jan Kara   udf: Try harder w...
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
  
  	/*
  	 * VAT file entry is in the last recorded block. Some broken disks have
  	 * it a few blocks before so try a bit harder...
  	 */
  	ino.partitionReferenceNum = type1_index;
  	for (vat_block = start_block;
  	     vat_block >= map->s_partition_root &&
  	     vat_block >= start_block - 3 &&
  	     !sbi->s_vat_inode; vat_block--) {
  		ino.logicalBlockNum = vat_block - map->s_partition_root;
  		sbi->s_vat_inode = udf_iget(sb, &ino);
  	}
  }
  
  static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
  {
  	struct udf_sb_info *sbi = UDF_SB(sb);
  	struct udf_part_map *map = &sbi->s_partmaps[p_index];
fa5e08156   Jan Kara   udf: Handle VAT p...
1077
1078
1079
1080
  	struct buffer_head *bh = NULL;
  	struct udf_inode_info *vati;
  	uint32_t pos;
  	struct virtualAllocationTable20 *vat20;
4bf17af0d   Jan Kara   udf: Fix loading ...
1081
  	sector_t blocks = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits;
38b74a53e   Jan Kara   udf: Move process...
1082

e971b0b9e   Jan Kara   udf: Try harder w...
1083
  	udf_find_vat_block(sb, p_index, type1_index, sbi->s_last_block);
4bf17af0d   Jan Kara   udf: Fix loading ...
1084
1085
  	if (!sbi->s_vat_inode &&
  	    sbi->s_last_block != blocks - 1) {
78ace70c4   Joe Perches   udf: Convert prin...
1086
1087
1088
1089
  		pr_notice("Failed to read VAT inode from the last recorded block (%lu), retrying with the last block of the device (%lu).
  ",
  			  (unsigned long)sbi->s_last_block,
  			  (unsigned long)blocks - 1);
e971b0b9e   Jan Kara   udf: Try harder w...
1090
  		udf_find_vat_block(sb, p_index, type1_index, blocks - 1);
4bf17af0d   Jan Kara   udf: Fix loading ...
1091
  	}
38b74a53e   Jan Kara   udf: Move process...
1092
1093
1094
1095
  	if (!sbi->s_vat_inode)
  		return 1;
  
  	if (map->s_partition_type == UDF_VIRTUAL_MAP15) {
47c9358a0   Sebastian Manciulea   udf: Fix bug in V...
1096
  		map->s_type_specific.s_virtual.s_start_offset = 0;
38b74a53e   Jan Kara   udf: Move process...
1097
1098
1099
  		map->s_type_specific.s_virtual.s_num_entries =
  			(sbi->s_vat_inode->i_size - 36) >> 2;
  	} else if (map->s_partition_type == UDF_VIRTUAL_MAP20) {
fa5e08156   Jan Kara   udf: Handle VAT p...
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
  		vati = UDF_I(sbi->s_vat_inode);
  		if (vati->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
  			pos = udf_block_map(sbi->s_vat_inode, 0);
  			bh = sb_bread(sb, pos);
  			if (!bh)
  				return 1;
  			vat20 = (struct virtualAllocationTable20 *)bh->b_data;
  		} else {
  			vat20 = (struct virtualAllocationTable20 *)
  							vati->i_ext.i_data;
  		}
38b74a53e   Jan Kara   udf: Move process...
1111

38b74a53e   Jan Kara   udf: Move process...
1112
  		map->s_type_specific.s_virtual.s_start_offset =
47c9358a0   Sebastian Manciulea   udf: Fix bug in V...
1113
  			le16_to_cpu(vat20->lengthHeader);
38b74a53e   Jan Kara   udf: Move process...
1114
1115
1116
1117
1118
1119
1120
1121
  		map->s_type_specific.s_virtual.s_num_entries =
  			(sbi->s_vat_inode->i_size -
  				map->s_type_specific.s_virtual.
  					s_start_offset) >> 2;
  		brelse(bh);
  	}
  	return 0;
  }
3fb38dfa0   Jan Kara   udf: Move filling...
1122
1123
1124
1125
1126
1127
  static int udf_load_partdesc(struct super_block *sb, sector_t block)
  {
  	struct buffer_head *bh;
  	struct partitionDesc *p;
  	struct udf_part_map *map;
  	struct udf_sb_info *sbi = UDF_SB(sb);
38b74a53e   Jan Kara   udf: Move process...
1128
  	int i, type1_idx;
3fb38dfa0   Jan Kara   udf: Move filling...
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
  	uint16_t partitionNumber;
  	uint16_t ident;
  	int ret = 0;
  
  	bh = udf_read_tagged(sb, block, block, &ident);
  	if (!bh)
  		return 1;
  	if (ident != TAG_IDENT_PD)
  		goto out_bh;
  
  	p = (struct partitionDesc *)bh->b_data;
  	partitionNumber = le16_to_cpu(p->partitionNumber);
38b74a53e   Jan Kara   udf: Move process...
1141

bfb257a59   Jan Kara   udf: Add read-onl...
1142
  	/* First scan for TYPE1, SPARABLE and METADATA partitions */
3fb38dfa0   Jan Kara   udf: Move filling...
1143
1144
1145
1146
1147
  	for (i = 0; i < sbi->s_partitions; i++) {
  		map = &sbi->s_partmaps[i];
  		udf_debug("Searching map: (%d == %d)
  ",
  			  map->s_partition_num, partitionNumber);
38b74a53e   Jan Kara   udf: Move process...
1148
1149
1150
  		if (map->s_partition_num == partitionNumber &&
  		    (map->s_partition_type == UDF_TYPE1_MAP15 ||
  		     map->s_partition_type == UDF_SPARABLE_MAP15))
3fb38dfa0   Jan Kara   udf: Move filling...
1151
1152
  			break;
  	}
38b74a53e   Jan Kara   udf: Move process...
1153
  	if (i >= sbi->s_partitions) {
3fb38dfa0   Jan Kara   udf: Move filling...
1154
1155
1156
1157
1158
  		udf_debug("Partition (%d) not found in partition map
  ",
  			  partitionNumber);
  		goto out_bh;
  	}
165923fa4   Marcin Slusarz   udf: super.c reor...
1159

3fb38dfa0   Jan Kara   udf: Move filling...
1160
  	ret = udf_fill_partdesc_info(sb, p, i);
38b74a53e   Jan Kara   udf: Move process...
1161
1162
  
  	/*
bfb257a59   Jan Kara   udf: Add read-onl...
1163
1164
  	 * Now rescan for VIRTUAL or METADATA partitions when SPARABLE and
  	 * PHYSICAL partitions are already set up
38b74a53e   Jan Kara   udf: Move process...
1165
1166
1167
1168
1169
1170
1171
  	 */
  	type1_idx = i;
  	for (i = 0; i < sbi->s_partitions; i++) {
  		map = &sbi->s_partmaps[i];
  
  		if (map->s_partition_num == partitionNumber &&
  		    (map->s_partition_type == UDF_VIRTUAL_MAP15 ||
bfb257a59   Jan Kara   udf: Add read-onl...
1172
1173
  		     map->s_partition_type == UDF_VIRTUAL_MAP20 ||
  		     map->s_partition_type == UDF_METADATA_MAP25))
38b74a53e   Jan Kara   udf: Move process...
1174
1175
1176
1177
1178
1179
1180
1181
1182
  			break;
  	}
  
  	if (i >= sbi->s_partitions)
  		goto out_bh;
  
  	ret = udf_fill_partdesc_info(sb, p, i);
  	if (ret)
  		goto out_bh;
bfb257a59   Jan Kara   udf: Add read-onl...
1183
1184
1185
  	if (map->s_partition_type == UDF_METADATA_MAP25) {
  		ret = udf_load_metadata_files(sb, i);
  		if (ret) {
78ace70c4   Joe Perches   udf: Convert prin...
1186
1187
1188
  			udf_err(sb, "error loading MetaData partition map %d
  ",
  				i);
bfb257a59   Jan Kara   udf: Add read-onl...
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
  			goto out_bh;
  		}
  	} else {
  		ret = udf_load_vat(sb, i, type1_idx);
  		if (ret)
  			goto out_bh;
  		/*
  		 * Mark filesystem read-only if we have a partition with
  		 * virtual map since we don't handle writing to it (we
  		 * overwrite blocks instead of relocating them).
  		 */
  		sb->s_flags |= MS_RDONLY;
78ace70c4   Joe Perches   udf: Convert prin...
1201
1202
  		pr_notice("Filesystem marked read-only because writing to pseudooverwrite partition is not implemented
  ");
bfb257a59   Jan Kara   udf: Add read-onl...
1203
  	}
c0eb31ed1   Jan Kara   udf: Cleanup volu...
1204
  out_bh:
2e0838fd0   Jan Kara   udf: Improve erro...
1205
  	/* In case loading failed, we handle cleanup in udf_fill_super */
c0eb31ed1   Jan Kara   udf: Cleanup volu...
1206
1207
  	brelse(bh);
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1208
  }
c0eb31ed1   Jan Kara   udf: Cleanup volu...
1209
  static int udf_load_logicalvol(struct super_block *sb, sector_t block,
5ca4e4be8   Pekka Enberg   Remove struct typ...
1210
  			       struct kernel_lb_addr *fileset)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1211
1212
1213
1214
  {
  	struct logicalVolDesc *lvd;
  	int i, j, offset;
  	uint8_t type;
6c79e987d   Marcin Slusarz   udf: remove some ...
1215
  	struct udf_sb_info *sbi = UDF_SB(sb);
4b11111ab   Marcin Slusarz   udf: fix coding s...
1216
  	struct genericPartitionMap *gpm;
c0eb31ed1   Jan Kara   udf: Cleanup volu...
1217
1218
1219
  	uint16_t ident;
  	struct buffer_head *bh;
  	int ret = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1220

c0eb31ed1   Jan Kara   udf: Cleanup volu...
1221
1222
1223
1224
  	bh = udf_read_tagged(sb, block, block, &ident);
  	if (!bh)
  		return 1;
  	BUG_ON(ident != TAG_IDENT_LVD);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1225
  	lvd = (struct logicalVolDesc *)bh->b_data;
dc5d39be6   Marcin Slusarz   udf: convert UDF_...
1226
  	i = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps));
c0eb31ed1   Jan Kara   udf: Cleanup volu...
1227
1228
1229
1230
  	if (i != 0) {
  		ret = i;
  		goto out_bh;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1231

cb00ea352   Cyrill Gorcunov   UDF: coding style...
1232
  	for (i = 0, offset = 0;
6c79e987d   Marcin Slusarz   udf: remove some ...
1233
  	     i < sbi->s_partitions && offset < le32_to_cpu(lvd->mapTableLength);
4b11111ab   Marcin Slusarz   udf: fix coding s...
1234
1235
1236
1237
1238
  	     i++, offset += gpm->partitionMapLength) {
  		struct udf_part_map *map = &sbi->s_partmaps[i];
  		gpm = (struct genericPartitionMap *)
  				&(lvd->partitionMaps[offset]);
  		type = gpm->partitionMapType;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1239
  		if (type == 1) {
4b11111ab   Marcin Slusarz   udf: fix coding s...
1240
1241
  			struct genericPartitionMap1 *gpm1 =
  				(struct genericPartitionMap1 *)gpm;
6c79e987d   Marcin Slusarz   udf: remove some ...
1242
1243
1244
1245
  			map->s_partition_type = UDF_TYPE1_MAP15;
  			map->s_volumeseqnum = le16_to_cpu(gpm1->volSeqNum);
  			map->s_partition_num = le16_to_cpu(gpm1->partitionNum);
  			map->s_partition_func = NULL;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1246
  		} else if (type == 2) {
4b11111ab   Marcin Slusarz   udf: fix coding s...
1247
1248
1249
1250
1251
1252
1253
  			struct udfPartitionMap2 *upm2 =
  						(struct udfPartitionMap2 *)gpm;
  			if (!strncmp(upm2->partIdent.ident, UDF_ID_VIRTUAL,
  						strlen(UDF_ID_VIRTUAL))) {
  				u16 suf =
  					le16_to_cpu(((__le16 *)upm2->partIdent.
  							identSuffix)[0]);
c82a12750   Jan Kara   udf: Fix detectio...
1254
  				if (suf < 0x0200) {
4b11111ab   Marcin Slusarz   udf: fix coding s...
1255
1256
1257
1258
  					map->s_partition_type =
  							UDF_VIRTUAL_MAP15;
  					map->s_partition_func =
  							udf_get_pblock_virt15;
c82a12750   Jan Kara   udf: Fix detectio...
1259
  				} else {
4b11111ab   Marcin Slusarz   udf: fix coding s...
1260
1261
1262
1263
  					map->s_partition_type =
  							UDF_VIRTUAL_MAP20;
  					map->s_partition_func =
  							udf_get_pblock_virt20;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1264
  				}
4b11111ab   Marcin Slusarz   udf: fix coding s...
1265
1266
1267
  			} else if (!strncmp(upm2->partIdent.ident,
  						UDF_ID_SPARABLE,
  						strlen(UDF_ID_SPARABLE))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1268
  				uint32_t loc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1269
  				struct sparingTable *st;
4b11111ab   Marcin Slusarz   udf: fix coding s...
1270
1271
  				struct sparablePartitionMap *spm =
  					(struct sparablePartitionMap *)gpm;
28de7948a   Cyrill Gorcunov   UDF: coding style...
1272

6c79e987d   Marcin Slusarz   udf: remove some ...
1273
  				map->s_partition_type = UDF_SPARABLE_MAP15;
4b11111ab   Marcin Slusarz   udf: fix coding s...
1274
1275
  				map->s_type_specific.s_sparing.s_packet_len =
  						le16_to_cpu(spm->packetLength);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1276
  				for (j = 0; j < spm->numSparingTables; j++) {
4b11111ab   Marcin Slusarz   udf: fix coding s...
1277
1278
1279
1280
1281
1282
1283
1284
  					struct buffer_head *bh2;
  
  					loc = le32_to_cpu(
  						spm->locSparingTable[j]);
  					bh2 = udf_read_tagged(sb, loc, loc,
  							     &ident);
  					map->s_type_specific.s_sparing.
  							s_spar_map[j] = bh2;
165923fa4   Marcin Slusarz   udf: super.c reor...
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
  					if (bh2 == NULL)
  						continue;
  
  					st = (struct sparingTable *)bh2->b_data;
  					if (ident != 0 || strncmp(
  						st->sparingIdent.ident,
  						UDF_ID_SPARING,
  						strlen(UDF_ID_SPARING))) {
  						brelse(bh2);
  						map->s_type_specific.s_sparing.
  							s_spar_map[j] = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1296
1297
  					}
  				}
6c79e987d   Marcin Slusarz   udf: remove some ...
1298
  				map->s_partition_func = udf_get_pblock_spar15;
bfb257a59   Jan Kara   udf: Add read-onl...
1299
1300
1301
1302
1303
1304
1305
1306
  			} else if (!strncmp(upm2->partIdent.ident,
  						UDF_ID_METADATA,
  						strlen(UDF_ID_METADATA))) {
  				struct udf_meta_data *mdata =
  					&map->s_type_specific.s_metadata;
  				struct metadataPartitionMap *mdm =
  						(struct metadataPartitionMap *)
  						&(lvd->partitionMaps[offset]);
a983f368f   Joe Perches   udf: Neaten udf_d...
1307
1308
1309
  				udf_debug("Parsing Logical vol part %d type %d  id=%s
  ",
  					  i, type, UDF_ID_METADATA);
bfb257a59   Jan Kara   udf: Add read-onl...
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
  
  				map->s_partition_type = UDF_METADATA_MAP25;
  				map->s_partition_func = udf_get_pblock_meta25;
  
  				mdata->s_meta_file_loc   =
  					le32_to_cpu(mdm->metadataFileLoc);
  				mdata->s_mirror_file_loc =
  					le32_to_cpu(mdm->metadataMirrorFileLoc);
  				mdata->s_bitmap_file_loc =
  					le32_to_cpu(mdm->metadataBitmapFileLoc);
  				mdata->s_alloc_unit_size =
  					le32_to_cpu(mdm->allocUnitSize);
  				mdata->s_align_unit_size =
  					le16_to_cpu(mdm->alignUnitSize);
ed47a7d00   Jan Kara   udf: Cleanup meta...
1324
1325
  				if (mdm->flags & 0x01)
  					mdata->s_flags |= MF_DUPLICATE_MD;
bfb257a59   Jan Kara   udf: Add read-onl...
1326
1327
1328
  
  				udf_debug("Metadata Ident suffix=0x%x
  ",
a983f368f   Joe Perches   udf: Neaten udf_d...
1329
1330
  					  le16_to_cpu(*(__le16 *)
  						      mdm->partIdent.identSuffix));
bfb257a59   Jan Kara   udf: Add read-onl...
1331
1332
  				udf_debug("Metadata part num=%d
  ",
a983f368f   Joe Perches   udf: Neaten udf_d...
1333
  					  le16_to_cpu(mdm->partitionNum));
bfb257a59   Jan Kara   udf: Add read-onl...
1334
1335
  				udf_debug("Metadata part alloc unit size=%d
  ",
a983f368f   Joe Perches   udf: Neaten udf_d...
1336
  					  le32_to_cpu(mdm->allocUnitSize));
bfb257a59   Jan Kara   udf: Add read-onl...
1337
1338
  				udf_debug("Metadata file loc=%d
  ",
a983f368f   Joe Perches   udf: Neaten udf_d...
1339
  					  le32_to_cpu(mdm->metadataFileLoc));
bfb257a59   Jan Kara   udf: Add read-onl...
1340
1341
  				udf_debug("Mirror file loc=%d
  ",
a983f368f   Joe Perches   udf: Neaten udf_d...
1342
  					  le32_to_cpu(mdm->metadataMirrorFileLoc));
bfb257a59   Jan Kara   udf: Add read-onl...
1343
1344
  				udf_debug("Bitmap file loc=%d
  ",
a983f368f   Joe Perches   udf: Neaten udf_d...
1345
  					  le32_to_cpu(mdm->metadataBitmapFileLoc));
ed47a7d00   Jan Kara   udf: Cleanup meta...
1346
1347
1348
  				udf_debug("Flags: %d %d
  ",
  					  mdata->s_flags, mdm->flags);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1349
  			} else {
3a71fc5de   Marcin Slusarz   udf: fix coding s...
1350
1351
1352
  				udf_debug("Unknown ident: %s
  ",
  					  upm2->partIdent.ident);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1353
1354
  				continue;
  			}
6c79e987d   Marcin Slusarz   udf: remove some ...
1355
1356
  			map->s_volumeseqnum = le16_to_cpu(upm2->volSeqNum);
  			map->s_partition_num = le16_to_cpu(upm2->partitionNum);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1357
1358
1359
  		}
  		udf_debug("Partition (%d:%d) type %d on volume %d
  ",
a983f368f   Joe Perches   udf: Neaten udf_d...
1360
  			  i, map->s_partition_num, type, map->s_volumeseqnum);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1361
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1362
  	if (fileset) {
5ca4e4be8   Pekka Enberg   Remove struct typ...
1363
  		struct long_ad *la = (struct long_ad *)&(lvd->logicalVolContentsUse[0]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1364
1365
  
  		*fileset = lelb_to_cpu(la->extLocation);
a983f368f   Joe Perches   udf: Neaten udf_d...
1366
1367
1368
  		udf_debug("FileSet found in LogicalVolDesc at block=%d, partition=%d
  ",
  			  fileset->logicalBlockNum,
28de7948a   Cyrill Gorcunov   UDF: coding style...
1369
  			  fileset->partitionReferenceNum);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1370
1371
1372
  	}
  	if (lvd->integritySeqExt.extLength)
  		udf_load_logicalvolint(sb, leea_to_cpu(lvd->integritySeqExt));
28de7948a   Cyrill Gorcunov   UDF: coding style...
1373

c0eb31ed1   Jan Kara   udf: Cleanup volu...
1374
1375
1376
  out_bh:
  	brelse(bh);
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1377
1378
1379
1380
1381
1382
  }
  
  /*
   * udf_load_logicalvolint
   *
   */
5ca4e4be8   Pekka Enberg   Remove struct typ...
1383
  static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_ad loc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1384
1385
1386
  {
  	struct buffer_head *bh = NULL;
  	uint16_t ident;
6c79e987d   Marcin Slusarz   udf: remove some ...
1387
1388
  	struct udf_sb_info *sbi = UDF_SB(sb);
  	struct logicalVolIntegrityDesc *lvid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1389
1390
  
  	while (loc.extLength > 0 &&
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1391
1392
1393
  	       (bh = udf_read_tagged(sb, loc.extLocation,
  				     loc.extLocation, &ident)) &&
  	       ident == TAG_IDENT_LVID) {
6c79e987d   Marcin Slusarz   udf: remove some ...
1394
1395
  		sbi->s_lvid_bh = bh;
  		lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1396

6c79e987d   Marcin Slusarz   udf: remove some ...
1397
  		if (lvid->nextIntegrityExt.extLength)
3a71fc5de   Marcin Slusarz   udf: fix coding s...
1398
  			udf_load_logicalvolint(sb,
6c79e987d   Marcin Slusarz   udf: remove some ...
1399
  				leea_to_cpu(lvid->nextIntegrityExt));
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1400

6c79e987d   Marcin Slusarz   udf: remove some ...
1401
  		if (sbi->s_lvid_bh != bh)
3bf25cb40   Jan Kara   udf: use get_bh()
1402
  			brelse(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1403
  		loc.extLength -= sb->s_blocksize;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1404
  		loc.extLocation++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1405
  	}
6c79e987d   Marcin Slusarz   udf: remove some ...
1406
  	if (sbi->s_lvid_bh != bh)
3bf25cb40   Jan Kara   udf: use get_bh()
1407
  		brelse(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
  }
  
  /*
   * udf_process_sequence
   *
   * PURPOSE
   *	Process a main/reserve volume descriptor sequence.
   *
   * PRE-CONDITIONS
   *	sb			Pointer to _locked_ superblock.
   *	block			First block of first extent of the sequence.
   *	lastblock		Lastblock of first extent of the sequence.
   *
   * HISTORY
   *	July 1, 1997 - Andrew E. Mileski
   *	Written, tested, and released.
   */
200a3592c   Jan Kara   udf: Mark udf_pro...
1425
  static noinline int udf_process_sequence(struct super_block *sb, long block,
5ca4e4be8   Pekka Enberg   Remove struct typ...
1426
  				long lastblock, struct kernel_lb_addr *fileset)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1427
1428
1429
  {
  	struct buffer_head *bh = NULL;
  	struct udf_vds_record vds[VDS_POS_LENGTH];
4b11111ab   Marcin Slusarz   udf: fix coding s...
1430
  	struct udf_vds_record *curr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1431
1432
  	struct generic_desc *gd;
  	struct volDescPtr *vdp;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1433
  	int done = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1434
1435
1436
1437
1438
  	uint32_t vdsn;
  	uint16_t ident;
  	long next_s = 0, next_e = 0;
  
  	memset(vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH);
c0eb31ed1   Jan Kara   udf: Cleanup volu...
1439
1440
1441
1442
  	/*
  	 * Read the main descriptor sequence and find which descriptors
  	 * are in it.
  	 */
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1443
  	for (; (!done && block <= lastblock); block++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1444
1445
  
  		bh = udf_read_tagged(sb, block, block, &ident);
c0eb31ed1   Jan Kara   udf: Cleanup volu...
1446
  		if (!bh) {
78ace70c4   Joe Perches   udf: Convert prin...
1447
1448
1449
1450
  			udf_err(sb,
  				"Block %llu of volume descriptor sequence is corrupted or we could not read it
  ",
  				(unsigned long long)block);
c0eb31ed1   Jan Kara   udf: Cleanup volu...
1451
1452
  			return 1;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1453
1454
1455
1456
  
  		/* Process each descriptor (ISO 13346 3/8.3-8.4) */
  		gd = (struct generic_desc *)bh->b_data;
  		vdsn = le32_to_cpu(gd->volDescSeqNum);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1457
  		switch (ident) {
28de7948a   Cyrill Gorcunov   UDF: coding style...
1458
  		case TAG_IDENT_PVD: /* ISO 13346 3/10.1 */
4b11111ab   Marcin Slusarz   udf: fix coding s...
1459
1460
1461
1462
  			curr = &vds[VDS_POS_PRIMARY_VOL_DESC];
  			if (vdsn >= curr->volDescSeqNum) {
  				curr->volDescSeqNum = vdsn;
  				curr->block = block;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1463
1464
  			}
  			break;
28de7948a   Cyrill Gorcunov   UDF: coding style...
1465
  		case TAG_IDENT_VDP: /* ISO 13346 3/10.3 */
4b11111ab   Marcin Slusarz   udf: fix coding s...
1466
1467
1468
1469
  			curr = &vds[VDS_POS_VOL_DESC_PTR];
  			if (vdsn >= curr->volDescSeqNum) {
  				curr->volDescSeqNum = vdsn;
  				curr->block = block;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1470
1471
  
  				vdp = (struct volDescPtr *)bh->b_data;
4b11111ab   Marcin Slusarz   udf: fix coding s...
1472
1473
1474
1475
  				next_s = le32_to_cpu(
  					vdp->nextVolDescSeqExt.extLocation);
  				next_e = le32_to_cpu(
  					vdp->nextVolDescSeqExt.extLength);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1476
1477
1478
1479
  				next_e = next_e >> sb->s_blocksize_bits;
  				next_e += next_s;
  			}
  			break;
28de7948a   Cyrill Gorcunov   UDF: coding style...
1480
  		case TAG_IDENT_IUVD: /* ISO 13346 3/10.4 */
4b11111ab   Marcin Slusarz   udf: fix coding s...
1481
1482
1483
1484
  			curr = &vds[VDS_POS_IMP_USE_VOL_DESC];
  			if (vdsn >= curr->volDescSeqNum) {
  				curr->volDescSeqNum = vdsn;
  				curr->block = block;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1485
1486
  			}
  			break;
28de7948a   Cyrill Gorcunov   UDF: coding style...
1487
  		case TAG_IDENT_PD: /* ISO 13346 3/10.5 */
4b11111ab   Marcin Slusarz   udf: fix coding s...
1488
1489
1490
  			curr = &vds[VDS_POS_PARTITION_DESC];
  			if (!curr->block)
  				curr->block = block;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1491
  			break;
28de7948a   Cyrill Gorcunov   UDF: coding style...
1492
  		case TAG_IDENT_LVD: /* ISO 13346 3/10.6 */
4b11111ab   Marcin Slusarz   udf: fix coding s...
1493
1494
1495
1496
  			curr = &vds[VDS_POS_LOGICAL_VOL_DESC];
  			if (vdsn >= curr->volDescSeqNum) {
  				curr->volDescSeqNum = vdsn;
  				curr->block = block;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1497
1498
  			}
  			break;
28de7948a   Cyrill Gorcunov   UDF: coding style...
1499
  		case TAG_IDENT_USD: /* ISO 13346 3/10.8 */
4b11111ab   Marcin Slusarz   udf: fix coding s...
1500
1501
1502
1503
  			curr = &vds[VDS_POS_UNALLOC_SPACE_DESC];
  			if (vdsn >= curr->volDescSeqNum) {
  				curr->volDescSeqNum = vdsn;
  				curr->block = block;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1504
1505
  			}
  			break;
28de7948a   Cyrill Gorcunov   UDF: coding style...
1506
  		case TAG_IDENT_TD: /* ISO 13346 3/10.9 */
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1507
1508
1509
1510
1511
  			vds[VDS_POS_TERMINATING_DESC].block = block;
  			if (next_e) {
  				block = next_s;
  				lastblock = next_e;
  				next_s = next_e = 0;
4b11111ab   Marcin Slusarz   udf: fix coding s...
1512
  			} else
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1513
1514
  				done = 1;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1515
  		}
3bf25cb40   Jan Kara   udf: use get_bh()
1516
  		brelse(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1517
  	}
c0eb31ed1   Jan Kara   udf: Cleanup volu...
1518
1519
1520
1521
1522
  	/*
  	 * Now read interesting descriptors again and process them
  	 * in a suitable order
  	 */
  	if (!vds[VDS_POS_PRIMARY_VOL_DESC].block) {
78ace70c4   Joe Perches   udf: Convert prin...
1523
1524
  		udf_err(sb, "Primary Volume Descriptor not found!
  ");
c0eb31ed1   Jan Kara   udf: Cleanup volu...
1525
1526
1527
1528
  		return 1;
  	}
  	if (udf_load_pvoldesc(sb, vds[VDS_POS_PRIMARY_VOL_DESC].block))
  		return 1;
165923fa4   Marcin Slusarz   udf: super.c reor...
1529

c0eb31ed1   Jan Kara   udf: Cleanup volu...
1530
1531
1532
  	if (vds[VDS_POS_LOGICAL_VOL_DESC].block && udf_load_logicalvol(sb,
  	    vds[VDS_POS_LOGICAL_VOL_DESC].block, fileset))
  		return 1;
165923fa4   Marcin Slusarz   udf: super.c reor...
1533

c0eb31ed1   Jan Kara   udf: Cleanup volu...
1534
1535
1536
1537
1538
1539
1540
1541
1542
  	if (vds[VDS_POS_PARTITION_DESC].block) {
  		/*
  		 * We rescan the whole descriptor sequence to find
  		 * partition descriptor blocks and process them.
  		 */
  		for (block = vds[VDS_POS_PARTITION_DESC].block;
  		     block < vds[VDS_POS_TERMINATING_DESC].block;
  		     block++)
  			if (udf_load_partdesc(sb, block))
165923fa4   Marcin Slusarz   udf: super.c reor...
1543
  				return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1544
1545
1546
1547
  	}
  
  	return 0;
  }
403460051   Jan Kara   udf: Try anchor i...
1548
1549
  static int udf_load_sequence(struct super_block *sb, struct buffer_head *bh,
  			     struct kernel_lb_addr *fileset)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1550
  {
403460051   Jan Kara   udf: Try anchor i...
1551
1552
  	struct anchorVolDescPtr *anchor;
  	long main_s, main_e, reserve_s, reserve_e;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1553

403460051   Jan Kara   udf: Try anchor i...
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
  	anchor = (struct anchorVolDescPtr *)bh->b_data;
  
  	/* Locate the main sequence */
  	main_s = le32_to_cpu(anchor->mainVolDescSeqExt.extLocation);
  	main_e = le32_to_cpu(anchor->mainVolDescSeqExt.extLength);
  	main_e = main_e >> sb->s_blocksize_bits;
  	main_e += main_s;
  
  	/* Locate the reserve sequence */
  	reserve_s = le32_to_cpu(anchor->reserveVolDescSeqExt.extLocation);
  	reserve_e = le32_to_cpu(anchor->reserveVolDescSeqExt.extLength);
  	reserve_e = reserve_e >> sb->s_blocksize_bits;
  	reserve_e += reserve_s;
  
  	/* Process the main & reserve sequences */
  	/* responsible for finding the PartitionDesc(s) */
  	if (!udf_process_sequence(sb, main_s, main_e, fileset))
  		return 1;
  	return !udf_process_sequence(sb, reserve_s, reserve_e, fileset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1573
  }
403460051   Jan Kara   udf: Try anchor i...
1574
1575
1576
1577
1578
1579
  /*
   * Check whether there is an anchor block in the given block and
   * load Volume Descriptor Sequence if so.
   */
  static int udf_check_anchor_block(struct super_block *sb, sector_t block,
  				  struct kernel_lb_addr *fileset)
1197e4dfc   Clemens Ladisch   udf: use hardware...
1580
  {
403460051   Jan Kara   udf: Try anchor i...
1581
1582
1583
  	struct buffer_head *bh;
  	uint16_t ident;
  	int ret;
1197e4dfc   Clemens Ladisch   udf: use hardware...
1584

403460051   Jan Kara   udf: Try anchor i...
1585
1586
1587
  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV) &&
  	    udf_fixed_to_variable(block) >=
  	    sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits)
1197e4dfc   Clemens Ladisch   udf: use hardware...
1588
  		return 0;
403460051   Jan Kara   udf: Try anchor i...
1589
1590
1591
  
  	bh = udf_read_tagged(sb, block, block, &ident);
  	if (!bh)
1197e4dfc   Clemens Ladisch   udf: use hardware...
1592
  		return 0;
403460051   Jan Kara   udf: Try anchor i...
1593
1594
  	if (ident != TAG_IDENT_AVDP) {
  		brelse(bh);
1197e4dfc   Clemens Ladisch   udf: use hardware...
1595
1596
  		return 0;
  	}
403460051   Jan Kara   udf: Try anchor i...
1597
1598
1599
  	ret = udf_load_sequence(sb, bh, fileset);
  	brelse(bh);
  	return ret;
1197e4dfc   Clemens Ladisch   udf: use hardware...
1600
  }
403460051   Jan Kara   udf: Try anchor i...
1601
1602
1603
  /* Search for an anchor volume descriptor pointer */
  static sector_t udf_scan_anchors(struct super_block *sb, sector_t lastblock,
  				 struct kernel_lb_addr *fileset)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1604
  {
403460051   Jan Kara   udf: Try anchor i...
1605
  	sector_t last[6];
38b74a53e   Jan Kara   udf: Move process...
1606
  	int i;
403460051   Jan Kara   udf: Try anchor i...
1607
1608
  	struct udf_sb_info *sbi = UDF_SB(sb);
  	int last_count = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1609

403460051   Jan Kara   udf: Try anchor i...
1610
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
1636
1637
  	/* First try user provided anchor */
  	if (sbi->s_anchor) {
  		if (udf_check_anchor_block(sb, sbi->s_anchor, fileset))
  			return lastblock;
  	}
  	/*
  	 * according to spec, anchor is in either:
  	 *     block 256
  	 *     lastblock-256
  	 *     lastblock
  	 *  however, if the disc isn't closed, it could be 512.
  	 */
  	if (udf_check_anchor_block(sb, sbi->s_session + 256, fileset))
  		return lastblock;
  	/*
  	 * The trouble is which block is the last one. Drives often misreport
  	 * this so we try various possibilities.
  	 */
  	last[last_count++] = lastblock;
  	if (lastblock >= 1)
  		last[last_count++] = lastblock - 1;
  	last[last_count++] = lastblock + 1;
  	if (lastblock >= 2)
  		last[last_count++] = lastblock - 2;
  	if (lastblock >= 150)
  		last[last_count++] = lastblock - 150;
  	if (lastblock >= 152)
  		last[last_count++] = lastblock - 152;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1638

403460051   Jan Kara   udf: Try anchor i...
1639
1640
1641
  	for (i = 0; i < last_count; i++) {
  		if (last[i] >= sb->s_bdev->bd_inode->i_size >>
  				sb->s_blocksize_bits)
28f7c4d41   Marcin Slusarz   udf: improve read...
1642
  			continue;
403460051   Jan Kara   udf: Try anchor i...
1643
1644
1645
  		if (udf_check_anchor_block(sb, last[i], fileset))
  			return last[i];
  		if (last[i] < 256)
28f7c4d41   Marcin Slusarz   udf: improve read...
1646
  			continue;
403460051   Jan Kara   udf: Try anchor i...
1647
1648
1649
  		if (udf_check_anchor_block(sb, last[i] - 256, fileset))
  			return last[i];
  	}
28f7c4d41   Marcin Slusarz   udf: improve read...
1650

403460051   Jan Kara   udf: Try anchor i...
1651
1652
1653
1654
1655
  	/* Finally try block 512 in case media is open */
  	if (udf_check_anchor_block(sb, sbi->s_session + 512, fileset))
  		return last[0];
  	return 0;
  }
28f7c4d41   Marcin Slusarz   udf: improve read...
1656

403460051   Jan Kara   udf: Try anchor i...
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
  /*
   * Find an anchor volume descriptor and load Volume Descriptor Sequence from
   * area specified by it. The function expects sbi->s_lastblock to be the last
   * block on the media.
   *
   * Return 1 if ok, 0 if not found.
   *
   */
  static int udf_find_anchor(struct super_block *sb,
  			   struct kernel_lb_addr *fileset)
  {
  	sector_t lastblock;
  	struct udf_sb_info *sbi = UDF_SB(sb);
28f7c4d41   Marcin Slusarz   udf: improve read...
1670

403460051   Jan Kara   udf: Try anchor i...
1671
1672
1673
  	lastblock = udf_scan_anchors(sb, sbi->s_last_block, fileset);
  	if (lastblock)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1674

403460051   Jan Kara   udf: Try anchor i...
1675
1676
1677
1678
1679
1680
1681
1682
  	/* No anchor found? Try VARCONV conversion of block numbers */
  	UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
  	/* Firstly, we try to not convert number of the last block */
  	lastblock = udf_scan_anchors(sb,
  				udf_variable_to_fixed(sbi->s_last_block),
  				fileset);
  	if (lastblock)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1683

403460051   Jan Kara   udf: Try anchor i...
1684
1685
1686
1687
1688
1689
  	/* Secondly, we try with converted number of the last block */
  	lastblock = udf_scan_anchors(sb, sbi->s_last_block, fileset);
  	if (!lastblock) {
  		/* VARCONV didn't help. Clear it. */
  		UDF_CLEAR_FLAG(sb, UDF_FLAG_VARCONV);
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1690
  	}
403460051   Jan Kara   udf: Try anchor i...
1691
1692
1693
1694
  out:
  	sbi->s_last_block = lastblock;
  	return 1;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1695

403460051   Jan Kara   udf: Try anchor i...
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
  /*
   * Check Volume Structure Descriptor, find Anchor block and load Volume
   * Descriptor Sequence
   */
  static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt,
  			int silent, struct kernel_lb_addr *fileset)
  {
  	struct udf_sb_info *sbi = UDF_SB(sb);
  	loff_t nsr_off;
  
  	if (!sb_set_blocksize(sb, uopt->blocksize)) {
  		if (!silent)
78ace70c4   Joe Perches   udf: Convert prin...
1708
1709
  			udf_warn(sb, "Bad block size
  ");
403460051   Jan Kara   udf: Try anchor i...
1710
1711
1712
1713
1714
1715
1716
1717
  		return 0;
  	}
  	sbi->s_last_block = uopt->lastblock;
  	if (!uopt->novrs) {
  		/* Check that it is NSR02 compliant */
  		nsr_off = udf_check_vsd(sb);
  		if (!nsr_off) {
  			if (!silent)
78ace70c4   Joe Perches   udf: Convert prin...
1718
1719
  				udf_warn(sb, "No VRS found
  ");
403460051   Jan Kara   udf: Try anchor i...
1720
1721
1722
  			return 0;
  		}
  		if (nsr_off == -1)
a983f368f   Joe Perches   udf: Neaten udf_d...
1723
1724
  			udf_debug("Failed to read byte 32768. Assuming open disc. Skipping validity check
  ");
403460051   Jan Kara   udf: Try anchor i...
1725
1726
1727
1728
1729
  		if (!sbi->s_last_block)
  			sbi->s_last_block = udf_get_last_block(sb);
  	} else {
  		udf_debug("Validity check skipped because of novrs option
  ");
28f7c4d41   Marcin Slusarz   udf: improve read...
1730
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1731

403460051   Jan Kara   udf: Try anchor i...
1732
1733
1734
1735
  	/* Look for anchor block and load Volume Descriptor Sequence */
  	sbi->s_anchor = uopt->anchor;
  	if (!udf_find_anchor(sb, fileset)) {
  		if (!silent)
78ace70c4   Joe Perches   udf: Convert prin...
1736
1737
  			udf_warn(sb, "No anchor found
  ");
403460051   Jan Kara   udf: Try anchor i...
1738
1739
1740
  		return 0;
  	}
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1741
1742
1743
1744
  }
  
  static void udf_open_lvid(struct super_block *sb)
  {
6c79e987d   Marcin Slusarz   udf: remove some ...
1745
1746
  	struct udf_sb_info *sbi = UDF_SB(sb);
  	struct buffer_head *bh = sbi->s_lvid_bh;
165923fa4   Marcin Slusarz   udf: super.c reor...
1747
1748
  	struct logicalVolIntegrityDesc *lvid;
  	struct logicalVolIntegrityDescImpUse *lvidiu;
146bca72c   Jan Kara   udf: Don't write ...
1749

165923fa4   Marcin Slusarz   udf: super.c reor...
1750
1751
  	if (!bh)
  		return;
949f4a7c0   Jan Kara   udf: Protect all ...
1752
1753
  
  	mutex_lock(&sbi->s_alloc_mutex);
165923fa4   Marcin Slusarz   udf: super.c reor...
1754
1755
1756
1757
1758
1759
1760
  	lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
  	lvidiu = udf_sb_lvidiu(sbi);
  
  	lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
  	lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
  	udf_time_to_disk_stamp(&lvid->recordingDateAndTime,
  				CURRENT_TIME);
146bca72c   Jan Kara   udf: Don't write ...
1761
  	lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN);
165923fa4   Marcin Slusarz   udf: super.c reor...
1762
1763
  
  	lvid->descTag.descCRC = cpu_to_le16(
5ca4e4be8   Pekka Enberg   Remove struct typ...
1764
  		crc_itu_t(0, (char *)lvid + sizeof(struct tag),
f845fced9   Bob Copeland   udf: use crc_itu_...
1765
  			le16_to_cpu(lvid->descTag.descCRCLength)));
165923fa4   Marcin Slusarz   udf: super.c reor...
1766
1767
1768
  
  	lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
  	mark_buffer_dirty(bh);
146bca72c   Jan Kara   udf: Don't write ...
1769
  	sbi->s_lvid_dirty = 0;
949f4a7c0   Jan Kara   udf: Protect all ...
1770
  	mutex_unlock(&sbi->s_alloc_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1771
1772
1773
1774
  }
  
  static void udf_close_lvid(struct super_block *sb)
  {
6c79e987d   Marcin Slusarz   udf: remove some ...
1775
1776
1777
  	struct udf_sb_info *sbi = UDF_SB(sb);
  	struct buffer_head *bh = sbi->s_lvid_bh;
  	struct logicalVolIntegrityDesc *lvid;
165923fa4   Marcin Slusarz   udf: super.c reor...
1778
  	struct logicalVolIntegrityDescImpUse *lvidiu;
28de7948a   Cyrill Gorcunov   UDF: coding style...
1779

6c79e987d   Marcin Slusarz   udf: remove some ...
1780
1781
  	if (!bh)
  		return;
949f4a7c0   Jan Kara   udf: Protect all ...
1782
  	mutex_lock(&sbi->s_alloc_mutex);
6c79e987d   Marcin Slusarz   udf: remove some ...
1783
  	lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
165923fa4   Marcin Slusarz   udf: super.c reor...
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
  	lvidiu = udf_sb_lvidiu(sbi);
  	lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
  	lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
  	udf_time_to_disk_stamp(&lvid->recordingDateAndTime, CURRENT_TIME);
  	if (UDF_MAX_WRITE_VERSION > le16_to_cpu(lvidiu->maxUDFWriteRev))
  		lvidiu->maxUDFWriteRev = cpu_to_le16(UDF_MAX_WRITE_VERSION);
  	if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFReadRev))
  		lvidiu->minUDFReadRev = cpu_to_le16(sbi->s_udfrev);
  	if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFWriteRev))
  		lvidiu->minUDFWriteRev = cpu_to_le16(sbi->s_udfrev);
  	lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE);
  
  	lvid->descTag.descCRC = cpu_to_le16(
5ca4e4be8   Pekka Enberg   Remove struct typ...
1797
  			crc_itu_t(0, (char *)lvid + sizeof(struct tag),
f845fced9   Bob Copeland   udf: use crc_itu_...
1798
  				le16_to_cpu(lvid->descTag.descCRCLength)));
165923fa4   Marcin Slusarz   udf: super.c reor...
1799
1800
  
  	lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
853a0c25b   Jan Kara   udf: Mark LVID bu...
1801
1802
1803
1804
1805
1806
  	/*
  	 * We set buffer uptodate unconditionally here to avoid spurious
  	 * warnings from mark_buffer_dirty() when previous EIO has marked
  	 * the buffer as !uptodate
  	 */
  	set_buffer_uptodate(bh);
165923fa4   Marcin Slusarz   udf: super.c reor...
1807
  	mark_buffer_dirty(bh);
146bca72c   Jan Kara   udf: Don't write ...
1808
  	sbi->s_lvid_dirty = 0;
949f4a7c0   Jan Kara   udf: Protect all ...
1809
  	mutex_unlock(&sbi->s_alloc_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1810
  }
d664b6af6   Jan Kara   udf: Move handlin...
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
  u64 lvid_get_unique_id(struct super_block *sb)
  {
  	struct buffer_head *bh;
  	struct udf_sb_info *sbi = UDF_SB(sb);
  	struct logicalVolIntegrityDesc *lvid;
  	struct logicalVolHeaderDesc *lvhd;
  	u64 uniqueID;
  	u64 ret;
  
  	bh = sbi->s_lvid_bh;
  	if (!bh)
  		return 0;
  
  	lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
  	lvhd = (struct logicalVolHeaderDesc *)lvid->logicalVolContentsUse;
  
  	mutex_lock(&sbi->s_alloc_mutex);
  	ret = uniqueID = le64_to_cpu(lvhd->uniqueID);
  	if (!(++uniqueID & 0xFFFFFFFF))
  		uniqueID += 16;
  	lvhd->uniqueID = cpu_to_le64(uniqueID);
  	mutex_unlock(&sbi->s_alloc_mutex);
  	mark_buffer_dirty(bh);
  
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1836
  }
66e1da3f4   Marcin Slusarz   udf: convert macr...
1837
1838
1839
1840
  static void udf_sb_free_bitmap(struct udf_bitmap *bitmap)
  {
  	int i;
  	int nr_groups = bitmap->s_nr_groups;
4b11111ab   Marcin Slusarz   udf: fix coding s...
1841
1842
  	int size = sizeof(struct udf_bitmap) + (sizeof(struct buffer_head *) *
  						nr_groups);
66e1da3f4   Marcin Slusarz   udf: convert macr...
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
  
  	for (i = 0; i < nr_groups; i++)
  		if (bitmap->s_block_bitmap[i])
  			brelse(bitmap->s_block_bitmap[i]);
  
  	if (size <= PAGE_SIZE)
  		kfree(bitmap);
  	else
  		vfree(bitmap);
  }
2e0838fd0   Jan Kara   udf: Improve erro...
1853
1854
1855
  static void udf_free_partition(struct udf_part_map *map)
  {
  	int i;
bfb257a59   Jan Kara   udf: Add read-onl...
1856
  	struct udf_meta_data *mdata;
2e0838fd0   Jan Kara   udf: Improve erro...
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
  
  	if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE)
  		iput(map->s_uspace.s_table);
  	if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE)
  		iput(map->s_fspace.s_table);
  	if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP)
  		udf_sb_free_bitmap(map->s_uspace.s_bitmap);
  	if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP)
  		udf_sb_free_bitmap(map->s_fspace.s_bitmap);
  	if (map->s_partition_type == UDF_SPARABLE_MAP15)
  		for (i = 0; i < 4; i++)
  			brelse(map->s_type_specific.s_sparing.s_spar_map[i]);
bfb257a59   Jan Kara   udf: Add read-onl...
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
  	else if (map->s_partition_type == UDF_METADATA_MAP25) {
  		mdata = &map->s_type_specific.s_metadata;
  		iput(mdata->s_metadata_fe);
  		mdata->s_metadata_fe = NULL;
  
  		iput(mdata->s_mirror_fe);
  		mdata->s_mirror_fe = NULL;
  
  		iput(mdata->s_bitmap_fe);
  		mdata->s_bitmap_fe = NULL;
  	}
2e0838fd0   Jan Kara   udf: Improve erro...
1880
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1881
1882
1883
  static int udf_fill_super(struct super_block *sb, void *options, int silent)
  {
  	int i;
403460051   Jan Kara   udf: Try anchor i...
1884
  	int ret;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1885
  	struct inode *inode = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1886
  	struct udf_options uopt;
5ca4e4be8   Pekka Enberg   Remove struct typ...
1887
  	struct kernel_lb_addr rootdir, fileset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1888
1889
1890
1891
1892
1893
  	struct udf_sb_info *sbi;
  
  	uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT);
  	uopt.uid = -1;
  	uopt.gid = -1;
  	uopt.umask = 0;
87bc730c0   Marcin Slusarz   udf: fix default ...
1894
1895
  	uopt.fmode = UDF_INVALID_MODE;
  	uopt.dmode = UDF_INVALID_MODE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1896

6c79e987d   Marcin Slusarz   udf: remove some ...
1897
  	sbi = kzalloc(sizeof(struct udf_sb_info), GFP_KERNEL);
9db9f9e31   Alessio Igor Bogani   udf: Remove unnec...
1898
  	if (!sbi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1899
  		return -ENOMEM;
28de7948a   Cyrill Gorcunov   UDF: coding style...
1900

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1901
  	sb->s_fs_info = sbi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1902

1e7933def   Ingo Molnar   [PATCH] sem2mutex...
1903
  	mutex_init(&sbi->s_alloc_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1904

6da80894c   Miklos Szeredi   mount options: fi...
1905
  	if (!udf_parse_options((char *)options, &uopt, false))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1906
1907
1908
  		goto error_out;
  
  	if (uopt.flags & (1 << UDF_FLAG_UTF8) &&
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1909
  	    uopt.flags & (1 << UDF_FLAG_NLS_MAP)) {
8076c363d   Joe Perches   udf: Rename udf_e...
1910
1911
  		udf_err(sb, "utf8 cannot be combined with iocharset
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1912
1913
1914
  		goto error_out;
  	}
  #ifdef CONFIG_UDF_NLS
cb00ea352   Cyrill Gorcunov   UDF: coding style...
1915
  	if ((uopt.flags & (1 << UDF_FLAG_NLS_MAP)) && !uopt.nls_map) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
  		uopt.nls_map = load_nls_default();
  		if (!uopt.nls_map)
  			uopt.flags &= ~(1 << UDF_FLAG_NLS_MAP);
  		else
  			udf_debug("Using default NLS map
  ");
  	}
  #endif
  	if (!(uopt.flags & (1 << UDF_FLAG_NLS_MAP)))
  		uopt.flags |= (1 << UDF_FLAG_UTF8);
  
  	fileset.logicalBlockNum = 0xFFFFFFFF;
  	fileset.partitionReferenceNum = 0xFFFF;
6c79e987d   Marcin Slusarz   udf: remove some ...
1929
1930
1931
1932
  	sbi->s_flags = uopt.flags;
  	sbi->s_uid = uopt.uid;
  	sbi->s_gid = uopt.gid;
  	sbi->s_umask = uopt.umask;
7ac9bcd5d   Marcin Slusarz   udf: implement mo...
1933
1934
  	sbi->s_fmode = uopt.fmode;
  	sbi->s_dmode = uopt.dmode;
6c79e987d   Marcin Slusarz   udf: remove some ...
1935
  	sbi->s_nls_map = uopt.nls_map;
c03cad241   Jan Kara   udf: Protect defa...
1936
  	rwlock_init(&sbi->s_cred_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1937

cb00ea352   Cyrill Gorcunov   UDF: coding style...
1938
  	if (uopt.session == 0xFFFFFFFF)
6c79e987d   Marcin Slusarz   udf: remove some ...
1939
  		sbi->s_session = udf_get_last_session(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1940
  	else
6c79e987d   Marcin Slusarz   udf: remove some ...
1941
  		sbi->s_session = uopt.session;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1942

6c79e987d   Marcin Slusarz   udf: remove some ...
1943
1944
  	udf_debug("Multi-session=%d
  ", sbi->s_session);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1945

403460051   Jan Kara   udf: Try anchor i...
1946
1947
1948
  	/* Fill in the rest of the superblock */
  	sb->s_op = &udf_sb_ops;
  	sb->s_export_op = &udf_export_ops;
123e9caf1   Christoph Hellwig   quota: explicitly...
1949

403460051   Jan Kara   udf: Try anchor i...
1950
1951
1952
  	sb->s_dirt = 0;
  	sb->s_magic = UDF_SUPER_MAGIC;
  	sb->s_time_gran = 1000;
1197e4dfc   Clemens Ladisch   udf: use hardware...
1953
  	if (uopt.flags & (1 << UDF_FLAG_BLOCKSIZE_SET)) {
403460051   Jan Kara   udf: Try anchor i...
1954
  		ret = udf_load_vrs(sb, &uopt, silent, &fileset);
1197e4dfc   Clemens Ladisch   udf: use hardware...
1955
  	} else {
e1defc4ff   Martin K. Petersen   block: Do away wi...
1956
  		uopt.blocksize = bdev_logical_block_size(sb->s_bdev);
403460051   Jan Kara   udf: Try anchor i...
1957
1958
  		ret = udf_load_vrs(sb, &uopt, silent, &fileset);
  		if (!ret && uopt.blocksize != UDF_DEFAULT_BLOCKSIZE) {
1197e4dfc   Clemens Ladisch   udf: use hardware...
1959
  			if (!silent)
78ace70c4   Joe Perches   udf: Convert prin...
1960
1961
1962
  				pr_notice("Rescanning with blocksize %d
  ",
  					  UDF_DEFAULT_BLOCKSIZE);
1197e4dfc   Clemens Ladisch   udf: use hardware...
1963
  			uopt.blocksize = UDF_DEFAULT_BLOCKSIZE;
403460051   Jan Kara   udf: Try anchor i...
1964
  			ret = udf_load_vrs(sb, &uopt, silent, &fileset);
1197e4dfc   Clemens Ladisch   udf: use hardware...
1965
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1966
  	}
403460051   Jan Kara   udf: Try anchor i...
1967
  	if (!ret) {
78ace70c4   Joe Perches   udf: Convert prin...
1968
1969
  		udf_warn(sb, "No partition found (1)
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1970
1971
  		goto error_out;
  	}
6c79e987d   Marcin Slusarz   udf: remove some ...
1972
1973
  	udf_debug("Lastblock=%d
  ", sbi->s_last_block);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1974

6c79e987d   Marcin Slusarz   udf: remove some ...
1975
  	if (sbi->s_lvid_bh) {
4b11111ab   Marcin Slusarz   udf: fix coding s...
1976
1977
  		struct logicalVolIntegrityDescImpUse *lvidiu =
  							udf_sb_lvidiu(sbi);
6c79e987d   Marcin Slusarz   udf: remove some ...
1978
1979
  		uint16_t minUDFReadRev = le16_to_cpu(lvidiu->minUDFReadRev);
  		uint16_t minUDFWriteRev = le16_to_cpu(lvidiu->minUDFWriteRev);
4b11111ab   Marcin Slusarz   udf: fix coding s...
1980
1981
  		/* uint16_t maxUDFWriteRev =
  				le16_to_cpu(lvidiu->maxUDFWriteRev); */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1982

cb00ea352   Cyrill Gorcunov   UDF: coding style...
1983
  		if (minUDFReadRev > UDF_MAX_READ_VERSION) {
78ace70c4   Joe Perches   udf: Convert prin...
1984
1985
1986
1987
  			udf_err(sb, "minUDFReadRev=%x (max is %x)
  ",
  				le16_to_cpu(lvidiu->minUDFReadRev),
  				UDF_MAX_READ_VERSION);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1988
  			goto error_out;
4b11111ab   Marcin Slusarz   udf: fix coding s...
1989
  		} else if (minUDFWriteRev > UDF_MAX_WRITE_VERSION)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1990
  			sb->s_flags |= MS_RDONLY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1991

6c79e987d   Marcin Slusarz   udf: remove some ...
1992
  		sbi->s_udfrev = minUDFWriteRev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1993
1994
1995
1996
1997
1998
  
  		if (minUDFReadRev >= UDF_VERS_USE_EXTENDED_FE)
  			UDF_SET_FLAG(sb, UDF_FLAG_USE_EXTENDED_FE);
  		if (minUDFReadRev >= UDF_VERS_USE_STREAMS)
  			UDF_SET_FLAG(sb, UDF_FLAG_USE_STREAMS);
  	}
6c79e987d   Marcin Slusarz   udf: remove some ...
1999
  	if (!sbi->s_partitions) {
78ace70c4   Joe Perches   udf: Convert prin...
2000
2001
  		udf_warn(sb, "No partition found (2)
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2002
2003
  		goto error_out;
  	}
4b11111ab   Marcin Slusarz   udf: fix coding s...
2004
2005
  	if (sbi->s_partmaps[sbi->s_partition].s_partition_flags &
  			UDF_PART_FLAG_READ_ONLY) {
78ace70c4   Joe Perches   udf: Convert prin...
2006
2007
  		pr_notice("Partition marked readonly; forcing readonly mount
  ");
39b3f6d6e   Eric Sandeen   [PATCH] mount udf...
2008
  		sb->s_flags |= MS_RDONLY;
c1a26e7d4   Peter Osterlund   [PATCH] UDF: Fix ...
2009
  	}
39b3f6d6e   Eric Sandeen   [PATCH] mount udf...
2010

cb00ea352   Cyrill Gorcunov   UDF: coding style...
2011
  	if (udf_find_fileset(sb, &fileset, &rootdir)) {
78ace70c4   Joe Perches   udf: Convert prin...
2012
2013
  		udf_warn(sb, "No fileset found
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2014
2015
  		goto error_out;
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2016
  	if (!silent) {
5ca4e4be8   Pekka Enberg   Remove struct typ...
2017
  		struct timestamp ts;
56774805d   Marcin Slusarz   udf: convert udf_...
2018
  		udf_time_to_disk_stamp(&ts, sbi->s_record_time);
78ace70c4   Joe Perches   udf: Convert prin...
2019
2020
2021
2022
  		udf_info("Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)
  ",
  			 sbi->s_volume_ident,
  			 le16_to_cpu(ts.year), ts.month, ts.day,
56774805d   Marcin Slusarz   udf: convert udf_...
2023
  			 ts.hour, ts.minute, le16_to_cpu(ts.typeAndTimezone));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2024
2025
2026
2027
2028
2029
2030
  	}
  	if (!(sb->s_flags & MS_RDONLY))
  		udf_open_lvid(sb);
  
  	/* Assign the root inode */
  	/* assign inodes by physical block number */
  	/* perhaps it's not extensible enough, but for now ... */
97e961fdb   Pekka Enberg   Fix the udf code ...
2031
  	inode = udf_iget(sb, &rootdir);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2032
  	if (!inode) {
78ace70c4   Joe Perches   udf: Convert prin...
2033
2034
  		udf_err(sb, "Error in udf_iget, block=%d, partition=%d
  ",
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2035
  		       rootdir.logicalBlockNum, rootdir.partitionReferenceNum);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2036
2037
2038
2039
2040
  		goto error_out;
  	}
  
  	/* Allocate a dentry for the root inode */
  	sb->s_root = d_alloc_root(inode);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2041
  	if (!sb->s_root) {
78ace70c4   Joe Perches   udf: Convert prin...
2042
2043
  		udf_err(sb, "Couldn't allocate root dentry
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2044
2045
2046
  		iput(inode);
  		goto error_out;
  	}
31170b6ad   Jan Kara   udf: support file...
2047
  	sb->s_maxbytes = MAX_LFS_FILESIZE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2048
  	return 0;
28de7948a   Cyrill Gorcunov   UDF: coding style...
2049
  error_out:
6c79e987d   Marcin Slusarz   udf: remove some ...
2050
2051
  	if (sbi->s_vat_inode)
  		iput(sbi->s_vat_inode);
2e0838fd0   Jan Kara   udf: Improve erro...
2052
2053
2054
  	if (sbi->s_partitions)
  		for (i = 0; i < sbi->s_partitions; i++)
  			udf_free_partition(&sbi->s_partmaps[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2055
2056
  #ifdef CONFIG_UDF_NLS
  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
6c79e987d   Marcin Slusarz   udf: remove some ...
2057
  		unload_nls(sbi->s_nls_map);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2058
2059
2060
  #endif
  	if (!(sb->s_flags & MS_RDONLY))
  		udf_close_lvid(sb);
6c79e987d   Marcin Slusarz   udf: remove some ...
2061
2062
2063
  	brelse(sbi->s_lvid_bh);
  
  	kfree(sbi->s_partmaps);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2064
2065
  	kfree(sbi);
  	sb->s_fs_info = NULL;
28de7948a   Cyrill Gorcunov   UDF: coding style...
2066

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2067
2068
  	return -EINVAL;
  }
8076c363d   Joe Perches   udf: Rename udf_e...
2069
2070
  void _udf_err(struct super_block *sb, const char *function,
  	      const char *fmt, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2071
  {
c2bff36c2   Joe Perches   udf: Neaten loggi...
2072
  	struct va_format vaf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2073
  	va_list args;
c2bff36c2   Joe Perches   udf: Neaten loggi...
2074
2075
  	/* mark sb error */
  	if (!(sb->s_flags & MS_RDONLY))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2076
  		sb->s_dirt = 1;
c2bff36c2   Joe Perches   udf: Neaten loggi...
2077

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2078
  	va_start(args, fmt);
c2bff36c2   Joe Perches   udf: Neaten loggi...
2079
2080
2081
2082
2083
  
  	vaf.fmt = fmt;
  	vaf.va = &args;
  
  	pr_err("error (device %s): %s: %pV", sb->s_id, function, &vaf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2084
  	va_end(args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2085
  }
a40ecd7b3   Joe Perches   udf: Rename udf_w...
2086
2087
  void _udf_warn(struct super_block *sb, const char *function,
  	       const char *fmt, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2088
  {
c2bff36c2   Joe Perches   udf: Neaten loggi...
2089
  	struct va_format vaf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2090
  	va_list args;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2091
  	va_start(args, fmt);
c2bff36c2   Joe Perches   udf: Neaten loggi...
2092
2093
2094
2095
2096
  
  	vaf.fmt = fmt;
  	vaf.va = &args;
  
  	pr_warn("warning (device %s): %s: %pV", sb->s_id, function, &vaf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2097
  	va_end(args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2098
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2099
  static void udf_put_super(struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2100
2101
  {
  	int i;
6c79e987d   Marcin Slusarz   udf: remove some ...
2102
  	struct udf_sb_info *sbi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2103

6c79e987d   Marcin Slusarz   udf: remove some ...
2104
  	sbi = UDF_SB(sb);
6cfd01484   Christoph Hellwig   push BKL down int...
2105

6c79e987d   Marcin Slusarz   udf: remove some ...
2106
2107
  	if (sbi->s_vat_inode)
  		iput(sbi->s_vat_inode);
2e0838fd0   Jan Kara   udf: Improve erro...
2108
2109
2110
  	if (sbi->s_partitions)
  		for (i = 0; i < sbi->s_partitions; i++)
  			udf_free_partition(&sbi->s_partmaps[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2111
2112
  #ifdef CONFIG_UDF_NLS
  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
6c79e987d   Marcin Slusarz   udf: remove some ...
2113
  		unload_nls(sbi->s_nls_map);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2114
2115
2116
  #endif
  	if (!(sb->s_flags & MS_RDONLY))
  		udf_close_lvid(sb);
6c79e987d   Marcin Slusarz   udf: remove some ...
2117
2118
  	brelse(sbi->s_lvid_bh);
  	kfree(sbi->s_partmaps);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2119
2120
2121
  	kfree(sb->s_fs_info);
  	sb->s_fs_info = NULL;
  }
146bca72c   Jan Kara   udf: Don't write ...
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
  static int udf_sync_fs(struct super_block *sb, int wait)
  {
  	struct udf_sb_info *sbi = UDF_SB(sb);
  
  	mutex_lock(&sbi->s_alloc_mutex);
  	if (sbi->s_lvid_dirty) {
  		/*
  		 * Blockdevice will be synced later so we don't have to submit
  		 * the buffer for IO
  		 */
  		mark_buffer_dirty(sbi->s_lvid_bh);
  		sb->s_dirt = 0;
  		sbi->s_lvid_dirty = 0;
  	}
  	mutex_unlock(&sbi->s_alloc_mutex);
  
  	return 0;
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2140
  static int udf_statfs(struct dentry *dentry, struct kstatfs *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2141
  {
726c33422   David Howells   [PATCH] VFS: Perm...
2142
  	struct super_block *sb = dentry->d_sb;
6c79e987d   Marcin Slusarz   udf: remove some ...
2143
2144
  	struct udf_sb_info *sbi = UDF_SB(sb);
  	struct logicalVolIntegrityDescImpUse *lvidiu;
557f5a146   Coly Li   udf: return f_fsi...
2145
  	u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
6c79e987d   Marcin Slusarz   udf: remove some ...
2146
2147
2148
2149
2150
  
  	if (sbi->s_lvid_bh != NULL)
  		lvidiu = udf_sb_lvidiu(sbi);
  	else
  		lvidiu = NULL;
726c33422   David Howells   [PATCH] VFS: Perm...
2151

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2152
2153
  	buf->f_type = UDF_SUPER_MAGIC;
  	buf->f_bsize = sb->s_blocksize;
6c79e987d   Marcin Slusarz   udf: remove some ...
2154
  	buf->f_blocks = sbi->s_partmaps[sbi->s_partition].s_partition_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2155
2156
  	buf->f_bfree = udf_count_free(sb);
  	buf->f_bavail = buf->f_bfree;
6c79e987d   Marcin Slusarz   udf: remove some ...
2157
2158
2159
  	buf->f_files = (lvidiu != NULL ? (le32_to_cpu(lvidiu->numFiles) +
  					  le32_to_cpu(lvidiu->numDirs)) : 0)
  			+ buf->f_bfree;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2160
  	buf->f_ffree = buf->f_bfree;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2161
  	buf->f_namelen = UDF_NAME_LEN - 2;
557f5a146   Coly Li   udf: return f_fsi...
2162
2163
  	buf->f_fsid.val[0] = (u32)id;
  	buf->f_fsid.val[1] = (u32)(id >> 32);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2164
2165
2166
  
  	return 0;
  }
4b11111ab   Marcin Slusarz   udf: fix coding s...
2167
2168
  static unsigned int udf_count_free_bitmap(struct super_block *sb,
  					  struct udf_bitmap *bitmap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2169
2170
2171
2172
2173
  {
  	struct buffer_head *bh = NULL;
  	unsigned int accum = 0;
  	int index;
  	int block = 0, newblock;
5ca4e4be8   Pekka Enberg   Remove struct typ...
2174
  	struct kernel_lb_addr loc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2175
  	uint32_t bytes;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2176
2177
2178
  	uint8_t *ptr;
  	uint16_t ident;
  	struct spaceBitmapDesc *bm;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2179
  	loc.logicalBlockNum = bitmap->s_extPosition;
6c79e987d   Marcin Slusarz   udf: remove some ...
2180
  	loc.partitionReferenceNum = UDF_SB(sb)->s_partition;
97e961fdb   Pekka Enberg   Fix the udf code ...
2181
  	bh = udf_read_ptagged(sb, &loc, 0, &ident);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2182

cb00ea352   Cyrill Gorcunov   UDF: coding style...
2183
  	if (!bh) {
78ace70c4   Joe Perches   udf: Convert prin...
2184
2185
  		udf_err(sb, "udf_count_free failed
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2186
  		goto out;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2187
  	} else if (ident != TAG_IDENT_SBD) {
3bf25cb40   Jan Kara   udf: use get_bh()
2188
  		brelse(bh);
78ace70c4   Joe Perches   udf: Convert prin...
2189
2190
  		udf_err(sb, "udf_count_free failed
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2191
2192
2193
2194
2195
  		goto out;
  	}
  
  	bm = (struct spaceBitmapDesc *)bh->b_data;
  	bytes = le32_to_cpu(bm->numOfBytes);
28de7948a   Cyrill Gorcunov   UDF: coding style...
2196
2197
  	index = sizeof(struct spaceBitmapDesc); /* offset in first block only */
  	ptr = (uint8_t *)bh->b_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2198

cb00ea352   Cyrill Gorcunov   UDF: coding style...
2199
  	while (bytes > 0) {
01b954a36   Marcin Slusarz   udf: convert udf_...
2200
2201
2202
2203
  		u32 cur_bytes = min_t(u32, bytes, sb->s_blocksize - index);
  		accum += bitmap_weight((const unsigned long *)(ptr + index),
  					cur_bytes * 8);
  		bytes -= cur_bytes;
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2204
  		if (bytes) {
3bf25cb40   Jan Kara   udf: use get_bh()
2205
  			brelse(bh);
97e961fdb   Pekka Enberg   Fix the udf code ...
2206
  			newblock = udf_get_lb_pblock(sb, &loc, ++block);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2207
  			bh = udf_tread(sb, newblock);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2208
  			if (!bh) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2209
2210
2211
2212
2213
  				udf_debug("read failed
  ");
  				goto out;
  			}
  			index = 0;
28de7948a   Cyrill Gorcunov   UDF: coding style...
2214
  			ptr = (uint8_t *)bh->b_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2215
2216
  		}
  	}
3bf25cb40   Jan Kara   udf: use get_bh()
2217
  	brelse(bh);
28de7948a   Cyrill Gorcunov   UDF: coding style...
2218
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2219
2220
  	return accum;
  }
4b11111ab   Marcin Slusarz   udf: fix coding s...
2221
2222
  static unsigned int udf_count_free_table(struct super_block *sb,
  					 struct inode *table)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2223
2224
  {
  	unsigned int accum = 0;
ff116fc8d   Jan Kara   UDF: introduce st...
2225
  	uint32_t elen;
5ca4e4be8   Pekka Enberg   Remove struct typ...
2226
  	struct kernel_lb_addr eloc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2227
  	int8_t etype;
ff116fc8d   Jan Kara   UDF: introduce st...
2228
  	struct extent_position epos;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2229

d1668fe39   Jan Kara   udf: Remove BKL f...
2230
  	mutex_lock(&UDF_SB(sb)->s_alloc_mutex);
c0b344385   Marcin Slusarz   udf: remove UDF_I...
2231
  	epos.block = UDF_I(table)->i_location;
ff116fc8d   Jan Kara   UDF: introduce st...
2232
2233
  	epos.offset = sizeof(struct unallocSpaceEntry);
  	epos.bh = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2234

3a71fc5de   Marcin Slusarz   udf: fix coding s...
2235
  	while ((etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2236
  		accum += (elen >> table->i_sb->s_blocksize_bits);
3a71fc5de   Marcin Slusarz   udf: fix coding s...
2237

3bf25cb40   Jan Kara   udf: use get_bh()
2238
  	brelse(epos.bh);
d1668fe39   Jan Kara   udf: Remove BKL f...
2239
  	mutex_unlock(&UDF_SB(sb)->s_alloc_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2240
2241
2242
  
  	return accum;
  }
cb00ea352   Cyrill Gorcunov   UDF: coding style...
2243
2244
  
  static unsigned int udf_count_free(struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2245
2246
  {
  	unsigned int accum = 0;
6c79e987d   Marcin Slusarz   udf: remove some ...
2247
2248
  	struct udf_sb_info *sbi;
  	struct udf_part_map *map;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2249

6c79e987d   Marcin Slusarz   udf: remove some ...
2250
2251
  	sbi = UDF_SB(sb);
  	if (sbi->s_lvid_bh) {
4b11111ab   Marcin Slusarz   udf: fix coding s...
2252
2253
2254
  		struct logicalVolIntegrityDesc *lvid =
  			(struct logicalVolIntegrityDesc *)
  			sbi->s_lvid_bh->b_data;
6c79e987d   Marcin Slusarz   udf: remove some ...
2255
  		if (le32_to_cpu(lvid->numOfPartitions) > sbi->s_partition) {
4b11111ab   Marcin Slusarz   udf: fix coding s...
2256
2257
  			accum = le32_to_cpu(
  					lvid->freeSpaceTable[sbi->s_partition]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2258
2259
2260
2261
2262
2263
2264
  			if (accum == 0xFFFFFFFF)
  				accum = 0;
  		}
  	}
  
  	if (accum)
  		return accum;
6c79e987d   Marcin Slusarz   udf: remove some ...
2265
2266
  	map = &sbi->s_partmaps[sbi->s_partition];
  	if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) {
28de7948a   Cyrill Gorcunov   UDF: coding style...
2267
  		accum += udf_count_free_bitmap(sb,
6c79e987d   Marcin Slusarz   udf: remove some ...
2268
  					       map->s_uspace.s_bitmap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2269
  	}
6c79e987d   Marcin Slusarz   udf: remove some ...
2270
  	if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) {
28de7948a   Cyrill Gorcunov   UDF: coding style...
2271
  		accum += udf_count_free_bitmap(sb,
6c79e987d   Marcin Slusarz   udf: remove some ...
2272
  					       map->s_fspace.s_bitmap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2273
2274
2275
  	}
  	if (accum)
  		return accum;
6c79e987d   Marcin Slusarz   udf: remove some ...
2276
  	if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) {
28de7948a   Cyrill Gorcunov   UDF: coding style...
2277
  		accum += udf_count_free_table(sb,
6c79e987d   Marcin Slusarz   udf: remove some ...
2278
  					      map->s_uspace.s_table);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2279
  	}
6c79e987d   Marcin Slusarz   udf: remove some ...
2280
  	if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) {
28de7948a   Cyrill Gorcunov   UDF: coding style...
2281
  		accum += udf_count_free_table(sb,
6c79e987d   Marcin Slusarz   udf: remove some ...
2282
  					      map->s_fspace.s_table);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2283
2284
2285
2286
  	}
  
  	return accum;
  }