15ce34554SBagas Sanjaya // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * super.c
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * PURPOSE
61da177e4SLinus Torvalds * Super block routines for the OSTA-UDF(tm) filesystem.
71da177e4SLinus Torvalds *
81da177e4SLinus Torvalds * DESCRIPTION
91da177e4SLinus Torvalds * OSTA-UDF(tm) = Optical Storage Technology Association
101da177e4SLinus Torvalds * Universal Disk Format.
111da177e4SLinus Torvalds *
121da177e4SLinus Torvalds * This code is based on version 2.00 of the UDF specification,
131da177e4SLinus Torvalds * and revision 3 of the ECMA 167 standard [equivalent to ISO 13346].
141da177e4SLinus Torvalds * http://www.osta.org/
15248727a4SAlexander A. Klimov * https://www.ecma.ch/
16248727a4SAlexander A. Klimov * https://www.iso.org/
171da177e4SLinus Torvalds *
181da177e4SLinus Torvalds * COPYRIGHT
191da177e4SLinus Torvalds * (C) 1998 Dave Boynton
201da177e4SLinus Torvalds * (C) 1998-2004 Ben Fennema
211da177e4SLinus Torvalds * (C) 2000 Stelias Computing Inc
221da177e4SLinus Torvalds *
231da177e4SLinus Torvalds * HISTORY
241da177e4SLinus Torvalds *
251da177e4SLinus Torvalds * 09/24/98 dgb changed to allow compiling outside of kernel, and
261da177e4SLinus Torvalds * added some debugging.
271da177e4SLinus Torvalds * 10/01/98 dgb updated to allow (some) possibility of compiling w/2.0.34
281da177e4SLinus Torvalds * 10/16/98 attempting some multi-session support
291da177e4SLinus Torvalds * 10/17/98 added freespace count for "df"
301da177e4SLinus Torvalds * 11/11/98 gr added novrs option
311da177e4SLinus Torvalds * 11/26/98 dgb added fileset,anchor mount options
323a71fc5dSMarcin Slusarz * 12/06/98 blf really hosed things royally. vat/sparing support. sequenced
333a71fc5dSMarcin Slusarz * vol descs. rewrote option handling based on isofs
341da177e4SLinus Torvalds * 12/20/98 find the free space bitmap (if it exists)
351da177e4SLinus Torvalds */
361da177e4SLinus Torvalds
371da177e4SLinus Torvalds #include "udfdecl.h"
381da177e4SLinus Torvalds
391da177e4SLinus Torvalds #include <linux/blkdev.h>
401da177e4SLinus Torvalds #include <linux/slab.h>
411da177e4SLinus Torvalds #include <linux/kernel.h>
421da177e4SLinus Torvalds #include <linux/module.h>
431da177e4SLinus Torvalds #include <linux/parser.h>
441da177e4SLinus Torvalds #include <linux/stat.h>
451da177e4SLinus Torvalds #include <linux/cdrom.h>
461da177e4SLinus Torvalds #include <linux/nls.h>
471da177e4SLinus Torvalds #include <linux/vfs.h>
481da177e4SLinus Torvalds #include <linux/vmalloc.h>
49dc5d39beSMarcin Slusarz #include <linux/errno.h>
506da80894SMiklos Szeredi #include <linux/mount.h>
516da80894SMiklos Szeredi #include <linux/seq_file.h>
5201b954a3SMarcin Slusarz #include <linux/bitmap.h>
53f845fcedSBob Copeland #include <linux/crc-itu-t.h>
541df2ae31SJan Kara #include <linux/log2.h>
551da177e4SLinus Torvalds #include <asm/byteorder.h>
56a48fc69fSJan Kara #include <linux/iversion.h>
571da177e4SLinus Torvalds
581da177e4SLinus Torvalds #include "udf_sb.h"
591da177e4SLinus Torvalds #include "udf_i.h"
601da177e4SLinus Torvalds
611da177e4SLinus Torvalds #include <linux/init.h>
62e973606cSFabian Frederick #include <linux/uaccess.h>
631da177e4SLinus Torvalds
644b8d4252SJan Kara enum {
654b8d4252SJan Kara VDS_POS_PRIMARY_VOL_DESC,
664b8d4252SJan Kara VDS_POS_UNALLOC_SPACE_DESC,
674b8d4252SJan Kara VDS_POS_LOGICAL_VOL_DESC,
684b8d4252SJan Kara VDS_POS_IMP_USE_VOL_DESC,
694b8d4252SJan Kara VDS_POS_LENGTH
704b8d4252SJan Kara };
711da177e4SLinus Torvalds
7244499602SPeter A. Felvegi #define VSD_FIRST_SECTOR_OFFSET 32768
7344499602SPeter A. Felvegi #define VSD_MAX_SECTOR_OFFSET 0x800000
7444499602SPeter A. Felvegi
75a47241cdSAlden Tondettar /*
76a47241cdSAlden Tondettar * Maximum number of Terminating Descriptor / Logical Volume Integrity
77a47241cdSAlden Tondettar * Descriptor redirections. The chosen numbers are arbitrary - just that we
78a47241cdSAlden Tondettar * hopefully don't limit any real use of rewritten inode on write-once media
79a47241cdSAlden Tondettar * but avoid looping for too long on corrupted media.
80a47241cdSAlden Tondettar */
81a47241cdSAlden Tondettar #define UDF_MAX_TD_NESTING 64
82a47241cdSAlden Tondettar #define UDF_MAX_LVID_NESTING 1000
83a47241cdSAlden Tondettar
848de52778SAl Viro enum { UDF_MAX_LINKS = 0xffff };
85c2efd13aSJan Kara /*
86c2efd13aSJan Kara * We limit filesize to 4TB. This is arbitrary as the on-disk format supports
87c2efd13aSJan Kara * more but because the file space is described by a linked list of extents,
88c2efd13aSJan Kara * each of which can have at most 1GB, the creation and handling of extents
89c2efd13aSJan Kara * gets unusably slow beyond certain point...
90c2efd13aSJan Kara */
91c2efd13aSJan Kara #define UDF_MAX_FILESIZE (1ULL << 42)
928de52778SAl Viro
931da177e4SLinus Torvalds /* These are the "meat" - everything else is stuffing */
941da177e4SLinus Torvalds static int udf_fill_super(struct super_block *, void *, int);
951da177e4SLinus Torvalds static void udf_put_super(struct super_block *);
96146bca72SJan Kara static int udf_sync_fs(struct super_block *, int);
971da177e4SLinus Torvalds static int udf_remount_fs(struct super_block *, int *, char *);
985ca4e4beSPekka Enberg static void udf_load_logicalvolint(struct super_block *, struct kernel_extent_ad);
991da177e4SLinus Torvalds static void udf_open_lvid(struct super_block *);
1001da177e4SLinus Torvalds static void udf_close_lvid(struct super_block *);
1011da177e4SLinus Torvalds static unsigned int udf_count_free(struct super_block *);
102726c3342SDavid Howells static int udf_statfs(struct dentry *, struct kstatfs *);
10334c80b1dSAl Viro static int udf_show_options(struct seq_file *, struct dentry *);
1041da177e4SLinus Torvalds
udf_sb_lvidiu(struct super_block * sb)10569d75671SJan Kara struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct super_block *sb)
1066c79e987SMarcin Slusarz {
10769d75671SJan Kara struct logicalVolIntegrityDesc *lvid;
10869d75671SJan Kara unsigned int partnum;
10969d75671SJan Kara unsigned int offset;
11069d75671SJan Kara
11169d75671SJan Kara if (!UDF_SB(sb)->s_lvid_bh)
11269d75671SJan Kara return NULL;
11369d75671SJan Kara lvid = (struct logicalVolIntegrityDesc *)UDF_SB(sb)->s_lvid_bh->b_data;
11469d75671SJan Kara partnum = le32_to_cpu(lvid->numOfPartitions);
11569d75671SJan Kara /* The offset is to skip freeSpaceTable and sizeTable arrays */
11669d75671SJan Kara offset = partnum * 2 * sizeof(uint32_t);
117781d2a9aSJan Kara return (struct logicalVolIntegrityDescImpUse *)
118781d2a9aSJan Kara (((uint8_t *)(lvid + 1)) + offset);
1196c79e987SMarcin Slusarz }
1206c79e987SMarcin Slusarz
1211da177e4SLinus Torvalds /* UDF filesystem type */
udf_mount(struct file_system_type * fs_type,int flags,const char * dev_name,void * data)122152a0836SAl Viro static struct dentry *udf_mount(struct file_system_type *fs_type,
123152a0836SAl Viro int flags, const char *dev_name, void *data)
1241da177e4SLinus Torvalds {
125152a0836SAl Viro return mount_bdev(fs_type, flags, dev_name, data, udf_fill_super);
1261da177e4SLinus Torvalds }
1271da177e4SLinus Torvalds
1281da177e4SLinus Torvalds static struct file_system_type udf_fstype = {
1291da177e4SLinus Torvalds .owner = THIS_MODULE,
1301da177e4SLinus Torvalds .name = "udf",
131152a0836SAl Viro .mount = udf_mount,
1321da177e4SLinus Torvalds .kill_sb = kill_block_super,
1331da177e4SLinus Torvalds .fs_flags = FS_REQUIRES_DEV,
1341da177e4SLinus Torvalds };
1353e64fe5bSEric W. Biederman MODULE_ALIAS_FS("udf");
1361da177e4SLinus Torvalds
137e18b890bSChristoph Lameter static struct kmem_cache *udf_inode_cachep;
1381da177e4SLinus Torvalds
udf_alloc_inode(struct super_block * sb)1391da177e4SLinus Torvalds static struct inode *udf_alloc_inode(struct super_block *sb)
1401da177e4SLinus Torvalds {
1411da177e4SLinus Torvalds struct udf_inode_info *ei;
142fd60b288SMuchun Song ei = alloc_inode_sb(sb, udf_inode_cachep, GFP_KERNEL);
1431da177e4SLinus Torvalds if (!ei)
1441da177e4SLinus Torvalds return NULL;
14595f8797fSDan Bastone
14695f8797fSDan Bastone ei->i_unique = 0;
14795f8797fSDan Bastone ei->i_lenExtents = 0;
148ab9a3a73SSteven J. Magnani ei->i_lenStreams = 0;
14995f8797fSDan Bastone ei->i_next_alloc_block = 0;
15095f8797fSDan Bastone ei->i_next_alloc_goal = 0;
15195f8797fSDan Bastone ei->i_strat4096 = 0;
152ab9a3a73SSteven J. Magnani ei->i_streamdir = 0;
153fc8033a3SJan Kara ei->i_hidden = 0;
1544d0fb621SAlessio Igor Bogani init_rwsem(&ei->i_data_sem);
15599600051SNamjae Jeon ei->cached_extent.lstart = -1;
15699600051SNamjae Jeon spin_lock_init(&ei->i_extent_cache_lock);
157a48fc69fSJan Kara inode_set_iversion(&ei->vfs_inode, 1);
15895f8797fSDan Bastone
1591da177e4SLinus Torvalds return &ei->vfs_inode;
1601da177e4SLinus Torvalds }
1611da177e4SLinus Torvalds
udf_free_in_core_inode(struct inode * inode)162a78bb383SAl Viro static void udf_free_in_core_inode(struct inode *inode)
163fa0d7e3dSNick Piggin {
164fa0d7e3dSNick Piggin kmem_cache_free(udf_inode_cachep, UDF_I(inode));
165fa0d7e3dSNick Piggin }
166fa0d7e3dSNick Piggin
init_once(void * foo)16751cc5068SAlexey Dobriyan static void init_once(void *foo)
1681da177e4SLinus Torvalds {
1690dafb7e6SLi zeming struct udf_inode_info *ei = foo;
1701da177e4SLinus Torvalds
171382a2287SJan Kara ei->i_data = NULL;
1721da177e4SLinus Torvalds inode_init_once(&ei->vfs_inode);
1731da177e4SLinus Torvalds }
1741da177e4SLinus Torvalds
init_inodecache(void)17553ea18deSFabian Frederick static int __init init_inodecache(void)
1761da177e4SLinus Torvalds {
1771da177e4SLinus Torvalds udf_inode_cachep = kmem_cache_create("udf_inode_cache",
1781da177e4SLinus Torvalds sizeof(struct udf_inode_info),
179fffb60f9SPaul Jackson 0, (SLAB_RECLAIM_ACCOUNT |
1805d097056SVladimir Davydov SLAB_MEM_SPREAD |
1815d097056SVladimir Davydov SLAB_ACCOUNT),
18220c2df83SPaul Mundt init_once);
18328de7948SCyrill Gorcunov if (!udf_inode_cachep)
1841da177e4SLinus Torvalds return -ENOMEM;
1851da177e4SLinus Torvalds return 0;
1861da177e4SLinus Torvalds }
1871da177e4SLinus Torvalds
destroy_inodecache(void)1881da177e4SLinus Torvalds static void destroy_inodecache(void)
1891da177e4SLinus Torvalds {
1908c0a8537SKirill A. Shutemov /*
1918c0a8537SKirill A. Shutemov * Make sure all delayed rcu free inodes are flushed before we
1928c0a8537SKirill A. Shutemov * destroy cache.
1938c0a8537SKirill A. Shutemov */
1948c0a8537SKirill A. Shutemov rcu_barrier();
1951a1d92c1SAlexey Dobriyan kmem_cache_destroy(udf_inode_cachep);
1961da177e4SLinus Torvalds }
1971da177e4SLinus Torvalds
1981da177e4SLinus Torvalds /* Superblock operations */
199ee9b6d61SJosef 'Jeff' Sipek static const struct super_operations udf_sb_ops = {
2001da177e4SLinus Torvalds .alloc_inode = udf_alloc_inode,
201a78bb383SAl Viro .free_inode = udf_free_in_core_inode,
2021da177e4SLinus Torvalds .write_inode = udf_write_inode,
2033aac2b62SAl Viro .evict_inode = udf_evict_inode,
2041da177e4SLinus Torvalds .put_super = udf_put_super,
205146bca72SJan Kara .sync_fs = udf_sync_fs,
2061da177e4SLinus Torvalds .statfs = udf_statfs,
2071da177e4SLinus Torvalds .remount_fs = udf_remount_fs,
2086da80894SMiklos Szeredi .show_options = udf_show_options,
2091da177e4SLinus Torvalds };
2101da177e4SLinus Torvalds
211cb00ea35SCyrill Gorcunov struct udf_options {
2121da177e4SLinus Torvalds unsigned char novrs;
2131da177e4SLinus Torvalds unsigned int blocksize;
2141da177e4SLinus Torvalds unsigned int session;
2151da177e4SLinus Torvalds unsigned int lastblock;
2161da177e4SLinus Torvalds unsigned int anchor;
2171da177e4SLinus Torvalds unsigned int flags;
218faa17292SAl Viro umode_t umask;
219c2ba138aSEric W. Biederman kgid_t gid;
220c2ba138aSEric W. Biederman kuid_t uid;
221faa17292SAl Viro umode_t fmode;
222faa17292SAl Viro umode_t dmode;
2231da177e4SLinus Torvalds struct nls_table *nls_map;
2241da177e4SLinus Torvalds };
2251da177e4SLinus Torvalds
init_udf_fs(void)2261da177e4SLinus Torvalds static int __init init_udf_fs(void)
2271da177e4SLinus Torvalds {
2281da177e4SLinus Torvalds int err;
22928de7948SCyrill Gorcunov
2301da177e4SLinus Torvalds err = init_inodecache();
2311da177e4SLinus Torvalds if (err)
2321da177e4SLinus Torvalds goto out1;
2331da177e4SLinus Torvalds err = register_filesystem(&udf_fstype);
2341da177e4SLinus Torvalds if (err)
2351da177e4SLinus Torvalds goto out;
23628de7948SCyrill Gorcunov
2371da177e4SLinus Torvalds return 0;
23828de7948SCyrill Gorcunov
2391da177e4SLinus Torvalds out:
2401da177e4SLinus Torvalds destroy_inodecache();
24128de7948SCyrill Gorcunov
2421da177e4SLinus Torvalds out1:
2431da177e4SLinus Torvalds return err;
2441da177e4SLinus Torvalds }
2451da177e4SLinus Torvalds
exit_udf_fs(void)2461da177e4SLinus Torvalds static void __exit exit_udf_fs(void)
2471da177e4SLinus Torvalds {
2481da177e4SLinus Torvalds unregister_filesystem(&udf_fstype);
2491da177e4SLinus Torvalds destroy_inodecache();
2501da177e4SLinus Torvalds }
2511da177e4SLinus Torvalds
udf_sb_alloc_partition_maps(struct super_block * sb,u32 count)252dc5d39beSMarcin Slusarz static int udf_sb_alloc_partition_maps(struct super_block *sb, u32 count)
253dc5d39beSMarcin Slusarz {
254dc5d39beSMarcin Slusarz struct udf_sb_info *sbi = UDF_SB(sb);
255dc5d39beSMarcin Slusarz
256033c9da0SMarkus Elfring sbi->s_partmaps = kcalloc(count, sizeof(*sbi->s_partmaps), GFP_KERNEL);
257dc5d39beSMarcin Slusarz if (!sbi->s_partmaps) {
258dc5d39beSMarcin Slusarz sbi->s_partitions = 0;
259dc5d39beSMarcin Slusarz return -ENOMEM;
260dc5d39beSMarcin Slusarz }
261dc5d39beSMarcin Slusarz
262dc5d39beSMarcin Slusarz sbi->s_partitions = count;
263dc5d39beSMarcin Slusarz return 0;
264dc5d39beSMarcin Slusarz }
265dc5d39beSMarcin Slusarz
udf_sb_free_bitmap(struct udf_bitmap * bitmap)266bff943afSJan Kara static void udf_sb_free_bitmap(struct udf_bitmap *bitmap)
267bff943afSJan Kara {
268bff943afSJan Kara int i;
269bff943afSJan Kara int nr_groups = bitmap->s_nr_groups;
270bff943afSJan Kara
271bff943afSJan Kara for (i = 0; i < nr_groups; i++)
27257053b3bSJan Kara if (!IS_ERR_OR_NULL(bitmap->s_block_bitmap[i]))
273bff943afSJan Kara brelse(bitmap->s_block_bitmap[i]);
274bff943afSJan Kara
2751d5cfdb0STetsuo Handa kvfree(bitmap);
276bff943afSJan Kara }
277bff943afSJan Kara
udf_free_partition(struct udf_part_map * map)278bff943afSJan Kara static void udf_free_partition(struct udf_part_map *map)
279bff943afSJan Kara {
280bff943afSJan Kara int i;
281bff943afSJan Kara struct udf_meta_data *mdata;
282bff943afSJan Kara
283bff943afSJan Kara if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE)
284bff943afSJan Kara iput(map->s_uspace.s_table);
285bff943afSJan Kara if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP)
286bff943afSJan Kara udf_sb_free_bitmap(map->s_uspace.s_bitmap);
287bff943afSJan Kara if (map->s_partition_type == UDF_SPARABLE_MAP15)
288bff943afSJan Kara for (i = 0; i < 4; i++)
289bff943afSJan Kara brelse(map->s_type_specific.s_sparing.s_spar_map[i]);
290bff943afSJan Kara else if (map->s_partition_type == UDF_METADATA_MAP25) {
291bff943afSJan Kara mdata = &map->s_type_specific.s_metadata;
292bff943afSJan Kara iput(mdata->s_metadata_fe);
293bff943afSJan Kara mdata->s_metadata_fe = NULL;
294bff943afSJan Kara
295bff943afSJan Kara iput(mdata->s_mirror_fe);
296bff943afSJan Kara mdata->s_mirror_fe = NULL;
297bff943afSJan Kara
298bff943afSJan Kara iput(mdata->s_bitmap_fe);
299bff943afSJan Kara mdata->s_bitmap_fe = NULL;
300bff943afSJan Kara }
301bff943afSJan Kara }
302bff943afSJan Kara
udf_sb_free_partitions(struct super_block * sb)303bff943afSJan Kara static void udf_sb_free_partitions(struct super_block *sb)
304bff943afSJan Kara {
305bff943afSJan Kara struct udf_sb_info *sbi = UDF_SB(sb);
306bff943afSJan Kara int i;
307ba2eb866SMarkus Elfring
308ba2eb866SMarkus Elfring if (!sbi->s_partmaps)
3091b1baff6SNamjae Jeon return;
310bff943afSJan Kara for (i = 0; i < sbi->s_partitions; i++)
311bff943afSJan Kara udf_free_partition(&sbi->s_partmaps[i]);
312bff943afSJan Kara kfree(sbi->s_partmaps);
313bff943afSJan Kara sbi->s_partmaps = NULL;
314bff943afSJan Kara }
315bff943afSJan Kara
udf_show_options(struct seq_file * seq,struct dentry * root)31634c80b1dSAl Viro static int udf_show_options(struct seq_file *seq, struct dentry *root)
3176da80894SMiklos Szeredi {
31834c80b1dSAl Viro struct super_block *sb = root->d_sb;
3196da80894SMiklos Szeredi struct udf_sb_info *sbi = UDF_SB(sb);
3206da80894SMiklos Szeredi
3216da80894SMiklos Szeredi if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT))
3226da80894SMiklos Szeredi seq_puts(seq, ",nostrict");
3231197e4dfSClemens Ladisch if (UDF_QUERY_FLAG(sb, UDF_FLAG_BLOCKSIZE_SET))
3246da80894SMiklos Szeredi seq_printf(seq, ",bs=%lu", sb->s_blocksize);
3256da80894SMiklos Szeredi if (UDF_QUERY_FLAG(sb, UDF_FLAG_UNHIDE))
3266da80894SMiklos Szeredi seq_puts(seq, ",unhide");
3276da80894SMiklos Szeredi if (UDF_QUERY_FLAG(sb, UDF_FLAG_UNDELETE))
3286da80894SMiklos Szeredi seq_puts(seq, ",undelete");
3296da80894SMiklos Szeredi if (!UDF_QUERY_FLAG(sb, UDF_FLAG_USE_AD_IN_ICB))
3306da80894SMiklos Szeredi seq_puts(seq, ",noadinicb");
3316da80894SMiklos Szeredi if (UDF_QUERY_FLAG(sb, UDF_FLAG_USE_SHORT_AD))
3326da80894SMiklos Szeredi seq_puts(seq, ",shortad");
3336da80894SMiklos Szeredi if (UDF_QUERY_FLAG(sb, UDF_FLAG_UID_FORGET))
3346da80894SMiklos Szeredi seq_puts(seq, ",uid=forget");
3356da80894SMiklos Szeredi if (UDF_QUERY_FLAG(sb, UDF_FLAG_GID_FORGET))
3366da80894SMiklos Szeredi seq_puts(seq, ",gid=forget");
3376da80894SMiklos Szeredi if (UDF_QUERY_FLAG(sb, UDF_FLAG_UID_SET))
338c2ba138aSEric W. Biederman seq_printf(seq, ",uid=%u", from_kuid(&init_user_ns, sbi->s_uid));
3396da80894SMiklos Szeredi if (UDF_QUERY_FLAG(sb, UDF_FLAG_GID_SET))
340c2ba138aSEric W. Biederman seq_printf(seq, ",gid=%u", from_kgid(&init_user_ns, sbi->s_gid));
3416da80894SMiklos Szeredi if (sbi->s_umask != 0)
342faa17292SAl Viro seq_printf(seq, ",umask=%ho", sbi->s_umask);
34387bc730cSMarcin Slusarz if (sbi->s_fmode != UDF_INVALID_MODE)
344faa17292SAl Viro seq_printf(seq, ",mode=%ho", sbi->s_fmode);
34587bc730cSMarcin Slusarz if (sbi->s_dmode != UDF_INVALID_MODE)
346faa17292SAl Viro seq_printf(seq, ",dmode=%ho", sbi->s_dmode);
3476da80894SMiklos Szeredi if (UDF_QUERY_FLAG(sb, UDF_FLAG_SESSION_SET))
348fcbf7637SSteve Magnani seq_printf(seq, ",session=%d", sbi->s_session);
3496da80894SMiklos Szeredi if (UDF_QUERY_FLAG(sb, UDF_FLAG_LASTBLOCK_SET))
3506da80894SMiklos Szeredi seq_printf(seq, ",lastblock=%u", sbi->s_last_block);
35140346005SJan Kara if (sbi->s_anchor != 0)
35240346005SJan Kara seq_printf(seq, ",anchor=%u", sbi->s_anchor);
353b6453334SPali Rohár if (sbi->s_nls_map)
3546da80894SMiklos Szeredi seq_printf(seq, ",iocharset=%s", sbi->s_nls_map->charset);
355b6453334SPali Rohár else
356b6453334SPali Rohár seq_puts(seq, ",iocharset=utf8");
3576da80894SMiklos Szeredi
3586da80894SMiklos Szeredi return 0;
3596da80894SMiklos Szeredi }
3606da80894SMiklos Szeredi
3611da177e4SLinus Torvalds /*
3621da177e4SLinus Torvalds * udf_parse_options
3631da177e4SLinus Torvalds *
3641da177e4SLinus Torvalds * PURPOSE
3651da177e4SLinus Torvalds * Parse mount options.
3661da177e4SLinus Torvalds *
3671da177e4SLinus Torvalds * DESCRIPTION
3681da177e4SLinus Torvalds * The following mount options are supported:
3691da177e4SLinus Torvalds *
3701da177e4SLinus Torvalds * gid= Set the default group.
3711da177e4SLinus Torvalds * umask= Set the default umask.
3727ac9bcd5SMarcin Slusarz * mode= Set the default file permissions.
3737ac9bcd5SMarcin Slusarz * dmode= Set the default directory permissions.
3741da177e4SLinus Torvalds * uid= Set the default user.
3751da177e4SLinus Torvalds * bs= Set the block size.
3761da177e4SLinus Torvalds * unhide Show otherwise hidden files.
3771da177e4SLinus Torvalds * undelete Show deleted files in lists.
3781da177e4SLinus Torvalds * adinicb Embed data in the inode (default)
3791da177e4SLinus Torvalds * noadinicb Don't embed data in the inode
3801da177e4SLinus Torvalds * shortad Use short ad's
3811da177e4SLinus Torvalds * longad Use long ad's (default)
3821da177e4SLinus Torvalds * nostrict Unset strict conformance
3831da177e4SLinus Torvalds * iocharset= Set the NLS character set
3841da177e4SLinus Torvalds *
3851da177e4SLinus Torvalds * The remaining are for debugging and disaster recovery:
3861da177e4SLinus Torvalds *
3871da177e4SLinus Torvalds * novrs Skip volume sequence recognition
3881da177e4SLinus Torvalds *
3891da177e4SLinus Torvalds * The following expect a offset from 0.
3901da177e4SLinus Torvalds *
3911da177e4SLinus Torvalds * session= Set the CDROM session (default= last session)
3921da177e4SLinus Torvalds * anchor= Override standard anchor location. (default= 256)
3931da177e4SLinus Torvalds * volume= Override the VolumeDesc location. (unused)
3941da177e4SLinus Torvalds * partition= Override the PartitionDesc location. (unused)
3951da177e4SLinus Torvalds * lastblock= Set the last block of the filesystem/
3961da177e4SLinus Torvalds *
3971da177e4SLinus Torvalds * The following expect a offset from the partition root.
3981da177e4SLinus Torvalds *
3991da177e4SLinus Torvalds * fileset= Override the fileset block location. (unused)
4001da177e4SLinus Torvalds * rootdir= Override the root directory location. (unused)
4011da177e4SLinus Torvalds * WARNING: overriding the rootdir to a non-directory may
4021da177e4SLinus Torvalds * yield highly unpredictable results.
4031da177e4SLinus Torvalds *
4041da177e4SLinus Torvalds * PRE-CONDITIONS
4051da177e4SLinus Torvalds * options Pointer to mount options string.
4061da177e4SLinus Torvalds * uopts Pointer to mount options variable.
4071da177e4SLinus Torvalds *
4081da177e4SLinus Torvalds * POST-CONDITIONS
4091da177e4SLinus Torvalds * <return> 1 Mount options parsed okay.
4101da177e4SLinus Torvalds * <return> 0 Error parsing mount options.
4111da177e4SLinus Torvalds *
4121da177e4SLinus Torvalds * HISTORY
4131da177e4SLinus Torvalds * July 1, 1997 - Andrew E. Mileski
4141da177e4SLinus Torvalds * Written, tested, and released.
4151da177e4SLinus Torvalds */
41628de7948SCyrill Gorcunov
4171da177e4SLinus Torvalds enum {
4181da177e4SLinus Torvalds Opt_novrs, Opt_nostrict, Opt_bs, Opt_unhide, Opt_undelete,
4191da177e4SLinus Torvalds Opt_noadinicb, Opt_adinicb, Opt_shortad, Opt_longad,
4201da177e4SLinus Torvalds Opt_gid, Opt_uid, Opt_umask, Opt_session, Opt_lastblock,
4211da177e4SLinus Torvalds Opt_anchor, Opt_volume, Opt_partition, Opt_fileset,
4221da177e4SLinus Torvalds Opt_rootdir, Opt_utf8, Opt_iocharset,
4237ac9bcd5SMarcin Slusarz Opt_err, Opt_uforget, Opt_uignore, Opt_gforget, Opt_gignore,
4247ac9bcd5SMarcin Slusarz Opt_fmode, Opt_dmode
4251da177e4SLinus Torvalds };
4261da177e4SLinus Torvalds
427a447c093SSteven Whitehouse static const match_table_t tokens = {
4281da177e4SLinus Torvalds {Opt_novrs, "novrs"},
4291da177e4SLinus Torvalds {Opt_nostrict, "nostrict"},
4301da177e4SLinus Torvalds {Opt_bs, "bs=%u"},
4311da177e4SLinus Torvalds {Opt_unhide, "unhide"},
4321da177e4SLinus Torvalds {Opt_undelete, "undelete"},
4331da177e4SLinus Torvalds {Opt_noadinicb, "noadinicb"},
4341da177e4SLinus Torvalds {Opt_adinicb, "adinicb"},
4351da177e4SLinus Torvalds {Opt_shortad, "shortad"},
4361da177e4SLinus Torvalds {Opt_longad, "longad"},
4374d6660ebSPhillip Susi {Opt_uforget, "uid=forget"},
4384d6660ebSPhillip Susi {Opt_uignore, "uid=ignore"},
4394d6660ebSPhillip Susi {Opt_gforget, "gid=forget"},
4404d6660ebSPhillip Susi {Opt_gignore, "gid=ignore"},
4411da177e4SLinus Torvalds {Opt_gid, "gid=%u"},
4421da177e4SLinus Torvalds {Opt_uid, "uid=%u"},
4431da177e4SLinus Torvalds {Opt_umask, "umask=%o"},
4441da177e4SLinus Torvalds {Opt_session, "session=%u"},
4451da177e4SLinus Torvalds {Opt_lastblock, "lastblock=%u"},
4461da177e4SLinus Torvalds {Opt_anchor, "anchor=%u"},
4471da177e4SLinus Torvalds {Opt_volume, "volume=%u"},
4481da177e4SLinus Torvalds {Opt_partition, "partition=%u"},
4491da177e4SLinus Torvalds {Opt_fileset, "fileset=%u"},
4501da177e4SLinus Torvalds {Opt_rootdir, "rootdir=%u"},
4511da177e4SLinus Torvalds {Opt_utf8, "utf8"},
4521da177e4SLinus Torvalds {Opt_iocharset, "iocharset=%s"},
4537ac9bcd5SMarcin Slusarz {Opt_fmode, "mode=%o"},
4547ac9bcd5SMarcin Slusarz {Opt_dmode, "dmode=%o"},
4551da177e4SLinus Torvalds {Opt_err, NULL}
4561da177e4SLinus Torvalds };
4571da177e4SLinus Torvalds
udf_parse_options(char * options,struct udf_options * uopt,bool remount)4586da80894SMiklos Szeredi static int udf_parse_options(char *options, struct udf_options *uopt,
4596da80894SMiklos Szeredi bool remount)
4601da177e4SLinus Torvalds {
4611da177e4SLinus Torvalds char *p;
4621da177e4SLinus Torvalds int option;
4633a9a3aa8SBingJing Chang unsigned int uv;
4641da177e4SLinus Torvalds
4651da177e4SLinus Torvalds uopt->novrs = 0;
4661da177e4SLinus Torvalds uopt->session = 0xFFFFFFFF;
4671da177e4SLinus Torvalds uopt->lastblock = 0;
4681da177e4SLinus Torvalds uopt->anchor = 0;
4691da177e4SLinus Torvalds
4701da177e4SLinus Torvalds if (!options)
4711da177e4SLinus Torvalds return 1;
4721da177e4SLinus Torvalds
473cb00ea35SCyrill Gorcunov while ((p = strsep(&options, ",")) != NULL) {
4741da177e4SLinus Torvalds substring_t args[MAX_OPT_ARGS];
4751da177e4SLinus Torvalds int token;
4768c6915aeSFabian Frederick unsigned n;
4771da177e4SLinus Torvalds if (!*p)
4781da177e4SLinus Torvalds continue;
4791da177e4SLinus Torvalds
4801da177e4SLinus Torvalds token = match_token(p, tokens, args);
481cb00ea35SCyrill Gorcunov switch (token) {
4821da177e4SLinus Torvalds case Opt_novrs:
4831da177e4SLinus Torvalds uopt->novrs = 1;
4844136801aSClemens Ladisch break;
4851da177e4SLinus Torvalds case Opt_bs:
4861da177e4SLinus Torvalds if (match_int(&args[0], &option))
4871da177e4SLinus Torvalds return 0;
4888c6915aeSFabian Frederick n = option;
4898c6915aeSFabian Frederick if (n != 512 && n != 1024 && n != 2048 && n != 4096)
4908c6915aeSFabian Frederick return 0;
4918c6915aeSFabian Frederick uopt->blocksize = n;
4921197e4dfSClemens Ladisch uopt->flags |= (1 << UDF_FLAG_BLOCKSIZE_SET);
4931da177e4SLinus Torvalds break;
4941da177e4SLinus Torvalds case Opt_unhide:
4951da177e4SLinus Torvalds uopt->flags |= (1 << UDF_FLAG_UNHIDE);
4961da177e4SLinus Torvalds break;
4971da177e4SLinus Torvalds case Opt_undelete:
4981da177e4SLinus Torvalds uopt->flags |= (1 << UDF_FLAG_UNDELETE);
4991da177e4SLinus Torvalds break;
5001da177e4SLinus Torvalds case Opt_noadinicb:
5011da177e4SLinus Torvalds uopt->flags &= ~(1 << UDF_FLAG_USE_AD_IN_ICB);
5021da177e4SLinus Torvalds break;
5031da177e4SLinus Torvalds case Opt_adinicb:
5041da177e4SLinus Torvalds uopt->flags |= (1 << UDF_FLAG_USE_AD_IN_ICB);
5051da177e4SLinus Torvalds break;
5061da177e4SLinus Torvalds case Opt_shortad:
5071da177e4SLinus Torvalds uopt->flags |= (1 << UDF_FLAG_USE_SHORT_AD);
5081da177e4SLinus Torvalds break;
5091da177e4SLinus Torvalds case Opt_longad:
5101da177e4SLinus Torvalds uopt->flags &= ~(1 << UDF_FLAG_USE_SHORT_AD);
5111da177e4SLinus Torvalds break;
5121da177e4SLinus Torvalds case Opt_gid:
5133a9a3aa8SBingJing Chang if (match_uint(args, &uv))
5141da177e4SLinus Torvalds return 0;
5153a9a3aa8SBingJing Chang uopt->gid = make_kgid(current_user_ns(), uv);
516c2ba138aSEric W. Biederman if (!gid_valid(uopt->gid))
517c2ba138aSEric W. Biederman return 0;
518ca76d2d8SCyrill Gorcunov uopt->flags |= (1 << UDF_FLAG_GID_SET);
5191da177e4SLinus Torvalds break;
5201da177e4SLinus Torvalds case Opt_uid:
5213a9a3aa8SBingJing Chang if (match_uint(args, &uv))
5221da177e4SLinus Torvalds return 0;
5233a9a3aa8SBingJing Chang uopt->uid = make_kuid(current_user_ns(), uv);
524c2ba138aSEric W. Biederman if (!uid_valid(uopt->uid))
525c2ba138aSEric W. Biederman return 0;
526ca76d2d8SCyrill Gorcunov uopt->flags |= (1 << UDF_FLAG_UID_SET);
5271da177e4SLinus Torvalds break;
5281da177e4SLinus Torvalds case Opt_umask:
5291da177e4SLinus Torvalds if (match_octal(args, &option))
5301da177e4SLinus Torvalds return 0;
5311da177e4SLinus Torvalds uopt->umask = option;
5321da177e4SLinus Torvalds break;
5331da177e4SLinus Torvalds case Opt_nostrict:
5341da177e4SLinus Torvalds uopt->flags &= ~(1 << UDF_FLAG_STRICT);
5351da177e4SLinus Torvalds break;
5361da177e4SLinus Torvalds case Opt_session:
5371da177e4SLinus Torvalds if (match_int(args, &option))
5381da177e4SLinus Torvalds return 0;
5391da177e4SLinus Torvalds uopt->session = option;
5406da80894SMiklos Szeredi if (!remount)
5416da80894SMiklos Szeredi uopt->flags |= (1 << UDF_FLAG_SESSION_SET);
5421da177e4SLinus Torvalds break;
5431da177e4SLinus Torvalds case Opt_lastblock:
5441da177e4SLinus Torvalds if (match_int(args, &option))
5451da177e4SLinus Torvalds return 0;
5461da177e4SLinus Torvalds uopt->lastblock = option;
5476da80894SMiklos Szeredi if (!remount)
5486da80894SMiklos Szeredi uopt->flags |= (1 << UDF_FLAG_LASTBLOCK_SET);
5491da177e4SLinus Torvalds break;
5501da177e4SLinus Torvalds case Opt_anchor:
5511da177e4SLinus Torvalds if (match_int(args, &option))
5521da177e4SLinus Torvalds return 0;
5531da177e4SLinus Torvalds uopt->anchor = option;
5541da177e4SLinus Torvalds break;
5551da177e4SLinus Torvalds case Opt_volume:
5561da177e4SLinus Torvalds case Opt_partition:
5571da177e4SLinus Torvalds case Opt_fileset:
5581da177e4SLinus Torvalds case Opt_rootdir:
559f0c4a817SJan Kara /* Ignored (never implemented properly) */
5601da177e4SLinus Torvalds break;
5611da177e4SLinus Torvalds case Opt_utf8:
562b6453334SPali Rohár if (!remount) {
563b6453334SPali Rohár unload_nls(uopt->nls_map);
564b6453334SPali Rohár uopt->nls_map = NULL;
565b6453334SPali Rohár }
5661da177e4SLinus Torvalds break;
5671da177e4SLinus Torvalds case Opt_iocharset:
568785dffe1SChengguang Xu if (!remount) {
569785dffe1SChengguang Xu unload_nls(uopt->nls_map);
570b6453334SPali Rohár uopt->nls_map = NULL;
571b6453334SPali Rohár }
572b6453334SPali Rohár /* When nls_map is not loaded then UTF-8 is used */
573b6453334SPali Rohár if (!remount && strcmp(args[0].from, "utf8") != 0) {
5741da177e4SLinus Torvalds uopt->nls_map = load_nls(args[0].from);
575b6453334SPali Rohár if (!uopt->nls_map) {
576b6453334SPali Rohár pr_err("iocharset %s not found\n",
577b6453334SPali Rohár args[0].from);
578b6453334SPali Rohár return 0;
579b6453334SPali Rohár }
580785dffe1SChengguang Xu }
5811da177e4SLinus Torvalds break;
5824d6660ebSPhillip Susi case Opt_uforget:
5834d6660ebSPhillip Susi uopt->flags |= (1 << UDF_FLAG_UID_FORGET);
5844d6660ebSPhillip Susi break;
58570260e44SJan Kara case Opt_uignore:
5864d6660ebSPhillip Susi case Opt_gignore:
58770260e44SJan Kara /* These options are superseeded by uid=<number> */
5884d6660ebSPhillip Susi break;
5894d6660ebSPhillip Susi case Opt_gforget:
5904d6660ebSPhillip Susi uopt->flags |= (1 << UDF_FLAG_GID_FORGET);
5914d6660ebSPhillip Susi break;
5927ac9bcd5SMarcin Slusarz case Opt_fmode:
5937ac9bcd5SMarcin Slusarz if (match_octal(args, &option))
5947ac9bcd5SMarcin Slusarz return 0;
5957ac9bcd5SMarcin Slusarz uopt->fmode = option & 0777;
5967ac9bcd5SMarcin Slusarz break;
5977ac9bcd5SMarcin Slusarz case Opt_dmode:
5987ac9bcd5SMarcin Slusarz if (match_octal(args, &option))
5997ac9bcd5SMarcin Slusarz return 0;
6007ac9bcd5SMarcin Slusarz uopt->dmode = option & 0777;
6017ac9bcd5SMarcin Slusarz break;
6021da177e4SLinus Torvalds default:
60378ace70cSJoe Perches pr_err("bad mount option \"%s\" or missing value\n", p);
6041da177e4SLinus Torvalds return 0;
6051da177e4SLinus Torvalds }
6061da177e4SLinus Torvalds }
6071da177e4SLinus Torvalds return 1;
6081da177e4SLinus Torvalds }
6091da177e4SLinus Torvalds
udf_remount_fs(struct super_block * sb,int * flags,char * options)610cb00ea35SCyrill Gorcunov static int udf_remount_fs(struct super_block *sb, int *flags, char *options)
6111da177e4SLinus Torvalds {
6121da177e4SLinus Torvalds struct udf_options uopt;
6136c79e987SMarcin Slusarz struct udf_sb_info *sbi = UDF_SB(sb);
614c79d967dSChristoph Hellwig int error = 0;
615a9ad01bcSJan Kara
616a9ad01bcSJan Kara if (!(*flags & SB_RDONLY) && UDF_QUERY_FLAG(sb, UDF_FLAG_RW_INCOMPAT))
617a9ad01bcSJan Kara return -EACCES;
6181da177e4SLinus Torvalds
61902b9984dSTheodore Ts'o sync_filesystem(sb);
620e729eac6SJan Kara
6216c79e987SMarcin Slusarz uopt.flags = sbi->s_flags;
6226c79e987SMarcin Slusarz uopt.uid = sbi->s_uid;
6236c79e987SMarcin Slusarz uopt.gid = sbi->s_gid;
6246c79e987SMarcin Slusarz uopt.umask = sbi->s_umask;
6257ac9bcd5SMarcin Slusarz uopt.fmode = sbi->s_fmode;
6267ac9bcd5SMarcin Slusarz uopt.dmode = sbi->s_dmode;
627785dffe1SChengguang Xu uopt.nls_map = NULL;
6281da177e4SLinus Torvalds
6296da80894SMiklos Szeredi if (!udf_parse_options(options, &uopt, true))
6301da177e4SLinus Torvalds return -EINVAL;
6311da177e4SLinus Torvalds
632c03cad24SJan Kara write_lock(&sbi->s_cred_lock);
6336c79e987SMarcin Slusarz sbi->s_flags = uopt.flags;
6346c79e987SMarcin Slusarz sbi->s_uid = uopt.uid;
6356c79e987SMarcin Slusarz sbi->s_gid = uopt.gid;
6366c79e987SMarcin Slusarz sbi->s_umask = uopt.umask;
6377ac9bcd5SMarcin Slusarz sbi->s_fmode = uopt.fmode;
6387ac9bcd5SMarcin Slusarz sbi->s_dmode = uopt.dmode;
639c03cad24SJan Kara write_unlock(&sbi->s_cred_lock);
6401da177e4SLinus Torvalds
6411751e8a6SLinus Torvalds if ((bool)(*flags & SB_RDONLY) == sb_rdonly(sb))
642c79d967dSChristoph Hellwig goto out_unlock;
643c79d967dSChristoph Hellwig
6441751e8a6SLinus Torvalds if (*flags & SB_RDONLY)
6451da177e4SLinus Torvalds udf_close_lvid(sb);
64636350462SJan Kara else
6471da177e4SLinus Torvalds udf_open_lvid(sb);
6481da177e4SLinus Torvalds
649c79d967dSChristoph Hellwig out_unlock:
650c79d967dSChristoph Hellwig return error;
6511da177e4SLinus Torvalds }
6521da177e4SLinus Torvalds
653ba54aef0SSteven J. Magnani /*
654ba54aef0SSteven J. Magnani * Check VSD descriptor. Returns -1 in case we are at the end of volume
655ba54aef0SSteven J. Magnani * recognition area, 0 if the descriptor is valid but non-interesting, 1 if
656ba54aef0SSteven J. Magnani * we found one of NSR descriptors we are looking for.
657ba54aef0SSteven J. Magnani */
identify_vsd(const struct volStructDesc * vsd)658ba54aef0SSteven J. Magnani static int identify_vsd(const struct volStructDesc *vsd)
659ba54aef0SSteven J. Magnani {
660ba54aef0SSteven J. Magnani int ret = 0;
661ba54aef0SSteven J. Magnani
662ba54aef0SSteven J. Magnani if (!memcmp(vsd->stdIdent, VSD_STD_ID_CD001, VSD_STD_ID_LEN)) {
663ba54aef0SSteven J. Magnani switch (vsd->structType) {
664ba54aef0SSteven J. Magnani case 0:
665ba54aef0SSteven J. Magnani udf_debug("ISO9660 Boot Record found\n");
666ba54aef0SSteven J. Magnani break;
667ba54aef0SSteven J. Magnani case 1:
668ba54aef0SSteven J. Magnani udf_debug("ISO9660 Primary Volume Descriptor found\n");
669ba54aef0SSteven J. Magnani break;
670ba54aef0SSteven J. Magnani case 2:
671ba54aef0SSteven J. Magnani udf_debug("ISO9660 Supplementary Volume Descriptor found\n");
672ba54aef0SSteven J. Magnani break;
673ba54aef0SSteven J. Magnani case 3:
674ba54aef0SSteven J. Magnani udf_debug("ISO9660 Volume Partition Descriptor found\n");
675ba54aef0SSteven J. Magnani break;
676ba54aef0SSteven J. Magnani case 255:
677ba54aef0SSteven J. Magnani udf_debug("ISO9660 Volume Descriptor Set Terminator found\n");
678ba54aef0SSteven J. Magnani break;
679ba54aef0SSteven J. Magnani default:
680ba54aef0SSteven J. Magnani udf_debug("ISO9660 VRS (%u) found\n", vsd->structType);
681ba54aef0SSteven J. Magnani break;
682ba54aef0SSteven J. Magnani }
683ba54aef0SSteven J. Magnani } else if (!memcmp(vsd->stdIdent, VSD_STD_ID_BEA01, VSD_STD_ID_LEN))
684ba54aef0SSteven J. Magnani ; /* ret = 0 */
685ba54aef0SSteven J. Magnani else if (!memcmp(vsd->stdIdent, VSD_STD_ID_NSR02, VSD_STD_ID_LEN))
686ba54aef0SSteven J. Magnani ret = 1;
687ba54aef0SSteven J. Magnani else if (!memcmp(vsd->stdIdent, VSD_STD_ID_NSR03, VSD_STD_ID_LEN))
688ba54aef0SSteven J. Magnani ret = 1;
689ba54aef0SSteven J. Magnani else if (!memcmp(vsd->stdIdent, VSD_STD_ID_BOOT2, VSD_STD_ID_LEN))
690ba54aef0SSteven J. Magnani ; /* ret = 0 */
691ba54aef0SSteven J. Magnani else if (!memcmp(vsd->stdIdent, VSD_STD_ID_CDW02, VSD_STD_ID_LEN))
692ba54aef0SSteven J. Magnani ; /* ret = 0 */
693ba54aef0SSteven J. Magnani else {
694ba54aef0SSteven J. Magnani /* TEA01 or invalid id : end of volume recognition area */
695ba54aef0SSteven J. Magnani ret = -1;
696ba54aef0SSteven J. Magnani }
697ba54aef0SSteven J. Magnani
698ba54aef0SSteven J. Magnani return ret;
699ba54aef0SSteven J. Magnani }
700ba54aef0SSteven J. Magnani
701ba54aef0SSteven J. Magnani /*
702ba54aef0SSteven J. Magnani * Check Volume Structure Descriptors (ECMA 167 2/9.1)
703ba54aef0SSteven J. Magnani * We also check any "CD-ROM Volume Descriptor Set" (ECMA 167 2/8.3.1)
704ba54aef0SSteven J. Magnani * @return 1 if NSR02 or NSR03 found,
705ba54aef0SSteven J. Magnani * -1 if first sector read error, 0 otherwise
706ba54aef0SSteven J. Magnani */
udf_check_vsd(struct super_block * sb)707ba54aef0SSteven J. Magnani static int udf_check_vsd(struct super_block *sb)
7081da177e4SLinus Torvalds {
7091da177e4SLinus Torvalds struct volStructDesc *vsd = NULL;
71044499602SPeter A. Felvegi loff_t sector = VSD_FIRST_SECTOR_OFFSET;
7111da177e4SLinus Torvalds int sectorsize;
7121da177e4SLinus Torvalds struct buffer_head *bh = NULL;
713ba54aef0SSteven J. Magnani int nsr = 0;
7146c79e987SMarcin Slusarz struct udf_sb_info *sbi;
7155cdc4a69Slianzhi chang loff_t session_offset;
7161da177e4SLinus Torvalds
7176c79e987SMarcin Slusarz sbi = UDF_SB(sb);
7181da177e4SLinus Torvalds if (sb->s_blocksize < sizeof(struct volStructDesc))
7191da177e4SLinus Torvalds sectorsize = sizeof(struct volStructDesc);
7201da177e4SLinus Torvalds else
7211da177e4SLinus Torvalds sectorsize = sb->s_blocksize;
7221da177e4SLinus Torvalds
7235cdc4a69Slianzhi chang session_offset = (loff_t)sbi->s_session << sb->s_blocksize_bits;
7245cdc4a69Slianzhi chang sector += session_offset;
7251da177e4SLinus Torvalds
726fcbf7637SSteve Magnani udf_debug("Starting at sector %u (%lu byte sectors)\n",
727706047a7SSebastian Manciulea (unsigned int)(sector >> sb->s_blocksize_bits),
728706047a7SSebastian Manciulea sb->s_blocksize);
72944499602SPeter A. Felvegi /* Process the sequence (if applicable). The hard limit on the sector
73044499602SPeter A. Felvegi * offset is arbitrary, hopefully large enough so that all valid UDF
73144499602SPeter A. Felvegi * filesystems will be recognised. There is no mention of an upper
73244499602SPeter A. Felvegi * bound to the size of the volume recognition area in the standard.
73344499602SPeter A. Felvegi * The limit will prevent the code to read all the sectors of a
73444499602SPeter A. Felvegi * specially crafted image (like a bluray disc full of CD001 sectors),
73544499602SPeter A. Felvegi * potentially causing minutes or even hours of uninterruptible I/O
73644499602SPeter A. Felvegi * activity. This actually happened with uninitialised SSD partitions
73744499602SPeter A. Felvegi * (all 0xFF) before the check for the limit and all valid IDs were
73844499602SPeter A. Felvegi * added */
739ba54aef0SSteven J. Magnani for (; !nsr && sector < VSD_MAX_SECTOR_OFFSET; sector += sectorsize) {
7401da177e4SLinus Torvalds /* Read a block */
741101ee137SJan Kara bh = sb_bread(sb, sector >> sb->s_blocksize_bits);
7421da177e4SLinus Torvalds if (!bh)
7431da177e4SLinus Torvalds break;
7441da177e4SLinus Torvalds
7451da177e4SLinus Torvalds vsd = (struct volStructDesc *)(bh->b_data +
74628de7948SCyrill Gorcunov (sector & (sb->s_blocksize - 1)));
747ba54aef0SSteven J. Magnani nsr = identify_vsd(vsd);
7486fbacb85SSteven J. Magnani /* Found NSR or end? */
7496fbacb85SSteven J. Magnani if (nsr) {
7506fbacb85SSteven J. Magnani brelse(bh);
7516fbacb85SSteven J. Magnani break;
7526fbacb85SSteven J. Magnani }
7536fbacb85SSteven J. Magnani /*
7546fbacb85SSteven J. Magnani * Special handling for improperly formatted VRS (e.g., Win10)
7556fbacb85SSteven J. Magnani * where components are separated by 2048 bytes even though
7566fbacb85SSteven J. Magnani * sectors are 4K
7576fbacb85SSteven J. Magnani */
7586fbacb85SSteven J. Magnani if (sb->s_blocksize == 4096) {
7596fbacb85SSteven J. Magnani nsr = identify_vsd(vsd + 1);
7606fbacb85SSteven J. Magnani /* Ignore unknown IDs... */
7616fbacb85SSteven J. Magnani if (nsr < 0)
7626fbacb85SSteven J. Magnani nsr = 0;
7636fbacb85SSteven J. Magnani }
7643bf25cb4SJan Kara brelse(bh);
7651da177e4SLinus Torvalds }
7661da177e4SLinus Torvalds
767ba54aef0SSteven J. Magnani if (nsr > 0)
768ba54aef0SSteven J. Magnani return 1;
7695cdc4a69Slianzhi chang else if (!bh && sector - session_offset == VSD_FIRST_SECTOR_OFFSET)
7701da177e4SLinus Torvalds return -1;
7711da177e4SLinus Torvalds else
7721da177e4SLinus Torvalds return 0;
7731da177e4SLinus Torvalds }
7741da177e4SLinus Torvalds
udf_verify_domain_identifier(struct super_block * sb,struct regid * ident,char * dname)7758b47ea6cSJan Kara static int udf_verify_domain_identifier(struct super_block *sb,
7768b47ea6cSJan Kara struct regid *ident, char *dname)
7778b47ea6cSJan Kara {
778871b9b14SPali Rohár struct domainIdentSuffix *suffix;
7798b47ea6cSJan Kara
7808b47ea6cSJan Kara if (memcmp(ident->ident, UDF_ID_COMPLIANT, strlen(UDF_ID_COMPLIANT))) {
7818b47ea6cSJan Kara udf_warn(sb, "Not OSTA UDF compliant %s descriptor.\n", dname);
7828b47ea6cSJan Kara goto force_ro;
7838b47ea6cSJan Kara }
78449be68c4SPali Rohár if (ident->flags & ENTITYID_FLAGS_DIRTY) {
7858b47ea6cSJan Kara udf_warn(sb, "Possibly not OSTA UDF compliant %s descriptor.\n",
7868b47ea6cSJan Kara dname);
7878b47ea6cSJan Kara goto force_ro;
7888b47ea6cSJan Kara }
789871b9b14SPali Rohár suffix = (struct domainIdentSuffix *)ident->identSuffix;
790871b9b14SPali Rohár if ((suffix->domainFlags & DOMAIN_FLAGS_HARD_WRITE_PROTECT) ||
791871b9b14SPali Rohár (suffix->domainFlags & DOMAIN_FLAGS_SOFT_WRITE_PROTECT)) {
7928b47ea6cSJan Kara if (!sb_rdonly(sb)) {
7938b47ea6cSJan Kara udf_warn(sb, "Descriptor for %s marked write protected."
7948b47ea6cSJan Kara " Forcing read only mount.\n", dname);
7958b47ea6cSJan Kara }
7968b47ea6cSJan Kara goto force_ro;
7978b47ea6cSJan Kara }
7988b47ea6cSJan Kara return 0;
7998b47ea6cSJan Kara
8008b47ea6cSJan Kara force_ro:
8018b47ea6cSJan Kara if (!sb_rdonly(sb))
8028b47ea6cSJan Kara return -EACCES;
8038b47ea6cSJan Kara UDF_SET_FLAG(sb, UDF_FLAG_RW_INCOMPAT);
8048b47ea6cSJan Kara return 0;
8058b47ea6cSJan Kara }
8068b47ea6cSJan Kara
udf_load_fileset(struct super_block * sb,struct fileSetDesc * fset,struct kernel_lb_addr * root)8078b47ea6cSJan Kara static int udf_load_fileset(struct super_block *sb, struct fileSetDesc *fset,
8088b47ea6cSJan Kara struct kernel_lb_addr *root)
8098b47ea6cSJan Kara {
8108b47ea6cSJan Kara int ret;
8118b47ea6cSJan Kara
8128b47ea6cSJan Kara ret = udf_verify_domain_identifier(sb, &fset->domainIdent, "file set");
8138b47ea6cSJan Kara if (ret < 0)
8148b47ea6cSJan Kara return ret;
8158b47ea6cSJan Kara
8168b47ea6cSJan Kara *root = lelb_to_cpu(fset->rootDirectoryICB.extLocation);
8178b47ea6cSJan Kara UDF_SB(sb)->s_serial_number = le16_to_cpu(fset->descTag.tagSerialNum);
8188b47ea6cSJan Kara
8198b47ea6cSJan Kara udf_debug("Rootdir at block=%u, partition=%u\n",
8208b47ea6cSJan Kara root->logicalBlockNum, root->partitionReferenceNum);
8218b47ea6cSJan Kara return 0;
8228b47ea6cSJan Kara }
8238b47ea6cSJan Kara
udf_find_fileset(struct super_block * sb,struct kernel_lb_addr * fileset,struct kernel_lb_addr * root)8243a71fc5dSMarcin Slusarz static int udf_find_fileset(struct super_block *sb,
8255ca4e4beSPekka Enberg struct kernel_lb_addr *fileset,
8265ca4e4beSPekka Enberg struct kernel_lb_addr *root)
8271da177e4SLinus Torvalds {
8280dafb7e6SLi zeming struct buffer_head *bh;
8291da177e4SLinus Torvalds uint16_t ident;
8302dee5aacSJan Kara int ret;
8311da177e4SLinus Torvalds
8322dee5aacSJan Kara if (fileset->logicalBlockNum == 0xFFFFFFFF &&
8332dee5aacSJan Kara fileset->partitionReferenceNum == 0xFFFF)
8342dee5aacSJan Kara return -EINVAL;
8352dee5aacSJan Kara
83697e961fdSPekka Enberg bh = udf_read_ptagged(sb, fileset, 0, &ident);
8372dee5aacSJan Kara if (!bh)
8382dee5aacSJan Kara return -EIO;
8392dee5aacSJan Kara if (ident != TAG_IDENT_FSD) {
8403bf25cb4SJan Kara brelse(bh);
8412dee5aacSJan Kara return -EINVAL;
8421da177e4SLinus Torvalds }
8431da177e4SLinus Torvalds
844fcbf7637SSteve Magnani udf_debug("Fileset at block=%u, partition=%u\n",
8452dee5aacSJan Kara fileset->logicalBlockNum, fileset->partitionReferenceNum);
8461da177e4SLinus Torvalds
84782c82ab6SJan Kara UDF_SB(sb)->s_partition = fileset->partitionReferenceNum;
8482dee5aacSJan Kara ret = udf_load_fileset(sb, (struct fileSetDesc *)bh->b_data, root);
8493bf25cb4SJan Kara brelse(bh);
8502dee5aacSJan Kara return ret;
8511da177e4SLinus Torvalds }
8521da177e4SLinus Torvalds
853d759bfa4SJan Kara /*
854d759bfa4SJan Kara * Load primary Volume Descriptor Sequence
855d759bfa4SJan Kara *
856d759bfa4SJan Kara * Return <0 on error, 0 on success. -EAGAIN is special meaning next sequence
857d759bfa4SJan Kara * should be tried.
858d759bfa4SJan Kara */
udf_load_pvoldesc(struct super_block * sb,sector_t block)859c0eb31edSJan Kara static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
8601da177e4SLinus Torvalds {
8611da177e4SLinus Torvalds struct primaryVolDesc *pvoldesc;
8629293fcfbSAndrew Gabbasov uint8_t *outstr;
863c0eb31edSJan Kara struct buffer_head *bh;
864c0eb31edSJan Kara uint16_t ident;
865aa9f6661SJing Xiangfeng int ret;
8660220eddaSDeepa Dinamani struct timestamp *ts;
867ba9aadd8SMarcin Slusarz
8689293fcfbSAndrew Gabbasov outstr = kmalloc(128, GFP_NOFS);
869ba9aadd8SMarcin Slusarz if (!outstr)
8709293fcfbSAndrew Gabbasov return -ENOMEM;
871c0eb31edSJan Kara
872c0eb31edSJan Kara bh = udf_read_tagged(sb, block, block, &ident);
873d759bfa4SJan Kara if (!bh) {
874d759bfa4SJan Kara ret = -EAGAIN;
875ba9aadd8SMarcin Slusarz goto out2;
876d759bfa4SJan Kara }
877ba9aadd8SMarcin Slusarz
878d759bfa4SJan Kara if (ident != TAG_IDENT_PVD) {
879d759bfa4SJan Kara ret = -EIO;
880d759bfa4SJan Kara goto out_bh;
881d759bfa4SJan Kara }
8821da177e4SLinus Torvalds
8831da177e4SLinus Torvalds pvoldesc = (struct primaryVolDesc *)bh->b_data;
8841da177e4SLinus Torvalds
8850220eddaSDeepa Dinamani udf_disk_stamp_to_time(&UDF_SB(sb)->s_record_time,
8860220eddaSDeepa Dinamani pvoldesc->recordingDateAndTime);
8870220eddaSDeepa Dinamani ts = &pvoldesc->recordingDateAndTime;
888a983f368SJoe Perches udf_debug("recording time %04u/%02u/%02u %02u:%02u (%x)\n",
889af15a298SMarcin Slusarz le16_to_cpu(ts->year), ts->month, ts->day, ts->hour,
890af15a298SMarcin Slusarz ts->minute, le16_to_cpu(ts->typeAndTimezone));
8911da177e4SLinus Torvalds
892e966fc8dSJan Kara ret = udf_dstrCS0toChar(sb, outstr, 31, pvoldesc->volIdent, 32);
893b54e41f5SJan Kara if (ret < 0) {
894b54e41f5SJan Kara strcpy(UDF_SB(sb)->s_volume_ident, "InvalidName");
895b54e41f5SJan Kara pr_warn("incorrect volume identification, setting to "
896b54e41f5SJan Kara "'InvalidName'\n");
897b54e41f5SJan Kara } else {
8989293fcfbSAndrew Gabbasov strncpy(UDF_SB(sb)->s_volume_ident, outstr, ret);
899b54e41f5SJan Kara }
900e9d4cf41SFabian Frederick udf_debug("volIdent[] = '%s'\n", UDF_SB(sb)->s_volume_ident);
9011da177e4SLinus Torvalds
902e966fc8dSJan Kara ret = udf_dstrCS0toChar(sb, outstr, 127, pvoldesc->volSetIdent, 128);
903b54e41f5SJan Kara if (ret < 0) {
904b54e41f5SJan Kara ret = 0;
905e9d4cf41SFabian Frederick goto out_bh;
906b54e41f5SJan Kara }
9079293fcfbSAndrew Gabbasov outstr[ret] = 0;
9089293fcfbSAndrew Gabbasov udf_debug("volSetIdent[] = '%s'\n", outstr);
909c0eb31edSJan Kara
910ba9aadd8SMarcin Slusarz ret = 0;
911d759bfa4SJan Kara out_bh:
912d759bfa4SJan Kara brelse(bh);
913ba9aadd8SMarcin Slusarz out2:
914ba9aadd8SMarcin Slusarz kfree(outstr);
915ba9aadd8SMarcin Slusarz return ret;
9161da177e4SLinus Torvalds }
9171da177e4SLinus Torvalds
udf_find_metadata_inode_efe(struct super_block * sb,u32 meta_file_loc,u32 partition_ref)9183080a74eSNamjae Jeon struct inode *udf_find_metadata_inode_efe(struct super_block *sb,
9197888824bSAlden Tondettar u32 meta_file_loc, u32 partition_ref)
9203080a74eSNamjae Jeon {
9213080a74eSNamjae Jeon struct kernel_lb_addr addr;
9223080a74eSNamjae Jeon struct inode *metadata_fe;
9233080a74eSNamjae Jeon
9243080a74eSNamjae Jeon addr.logicalBlockNum = meta_file_loc;
9257888824bSAlden Tondettar addr.partitionReferenceNum = partition_ref;
9263080a74eSNamjae Jeon
9276174c2ebSJan Kara metadata_fe = udf_iget_special(sb, &addr);
9283080a74eSNamjae Jeon
9296d3d5e86SJan Kara if (IS_ERR(metadata_fe)) {
9303080a74eSNamjae Jeon udf_warn(sb, "metadata inode efe not found\n");
9316d3d5e86SJan Kara return metadata_fe;
9326d3d5e86SJan Kara }
9336d3d5e86SJan Kara if (UDF_I(metadata_fe)->i_alloc_type != ICBTAG_FLAG_AD_SHORT) {
9343080a74eSNamjae Jeon udf_warn(sb, "metadata inode efe does not have short allocation descriptors!\n");
9353080a74eSNamjae Jeon iput(metadata_fe);
9366d3d5e86SJan Kara return ERR_PTR(-EIO);
9373080a74eSNamjae Jeon }
9383080a74eSNamjae Jeon
9393080a74eSNamjae Jeon return metadata_fe;
9403080a74eSNamjae Jeon }
9413080a74eSNamjae Jeon
udf_load_metadata_files(struct super_block * sb,int partition,int type1_index)9427888824bSAlden Tondettar static int udf_load_metadata_files(struct super_block *sb, int partition,
9437888824bSAlden Tondettar int type1_index)
944bfb257a5SJan Kara {
945bfb257a5SJan Kara struct udf_sb_info *sbi = UDF_SB(sb);
946bfb257a5SJan Kara struct udf_part_map *map;
947bfb257a5SJan Kara struct udf_meta_data *mdata;
9485ca4e4beSPekka Enberg struct kernel_lb_addr addr;
9496d3d5e86SJan Kara struct inode *fe;
950bfb257a5SJan Kara
951bfb257a5SJan Kara map = &sbi->s_partmaps[partition];
952bfb257a5SJan Kara mdata = &map->s_type_specific.s_metadata;
9537888824bSAlden Tondettar mdata->s_phys_partition_ref = type1_index;
954bfb257a5SJan Kara
955bfb257a5SJan Kara /* metadata address */
956fcbf7637SSteve Magnani udf_debug("Metadata file location: block = %u part = %u\n",
9577888824bSAlden Tondettar mdata->s_meta_file_loc, mdata->s_phys_partition_ref);
958bfb257a5SJan Kara
9596d3d5e86SJan Kara fe = udf_find_metadata_inode_efe(sb, mdata->s_meta_file_loc,
9607888824bSAlden Tondettar mdata->s_phys_partition_ref);
9616d3d5e86SJan Kara if (IS_ERR(fe)) {
962bfb257a5SJan Kara /* mirror file entry */
963fcbf7637SSteve Magnani udf_debug("Mirror metadata file location: block = %u part = %u\n",
9647888824bSAlden Tondettar mdata->s_mirror_file_loc, mdata->s_phys_partition_ref);
965bfb257a5SJan Kara
9666d3d5e86SJan Kara fe = udf_find_metadata_inode_efe(sb, mdata->s_mirror_file_loc,
9677888824bSAlden Tondettar mdata->s_phys_partition_ref);
968bfb257a5SJan Kara
9696d3d5e86SJan Kara if (IS_ERR(fe)) {
9703080a74eSNamjae Jeon udf_err(sb, "Both metadata and mirror metadata inode efe can not found\n");
9716d3d5e86SJan Kara return PTR_ERR(fe);
9723080a74eSNamjae Jeon }
9736d3d5e86SJan Kara mdata->s_mirror_fe = fe;
9746d3d5e86SJan Kara } else
9756d3d5e86SJan Kara mdata->s_metadata_fe = fe;
9766d3d5e86SJan Kara
977bfb257a5SJan Kara
978bfb257a5SJan Kara /*
979bfb257a5SJan Kara * bitmap file entry
980bfb257a5SJan Kara * Note:
981bfb257a5SJan Kara * Load only if bitmap file location differs from 0xFFFFFFFF (DCN-5102)
982bfb257a5SJan Kara */
983bfb257a5SJan Kara if (mdata->s_bitmap_file_loc != 0xFFFFFFFF) {
984bfb257a5SJan Kara addr.logicalBlockNum = mdata->s_bitmap_file_loc;
9857888824bSAlden Tondettar addr.partitionReferenceNum = mdata->s_phys_partition_ref;
986bfb257a5SJan Kara
987fcbf7637SSteve Magnani udf_debug("Bitmap file location: block = %u part = %u\n",
988bfb257a5SJan Kara addr.logicalBlockNum, addr.partitionReferenceNum);
989bfb257a5SJan Kara
9906174c2ebSJan Kara fe = udf_iget_special(sb, &addr);
9916d3d5e86SJan Kara if (IS_ERR(fe)) {
992bc98a42cSDavid Howells if (sb_rdonly(sb))
993a40ecd7bSJoe Perches udf_warn(sb, "bitmap inode efe not found but it's ok since the disc is mounted read-only\n");
994bfb257a5SJan Kara else {
9958076c363SJoe Perches udf_err(sb, "bitmap inode efe not found and attempted read-write mount\n");
9966d3d5e86SJan Kara return PTR_ERR(fe);
997bfb257a5SJan Kara }
9986d3d5e86SJan Kara } else
9996d3d5e86SJan Kara mdata->s_bitmap_fe = fe;
1000bfb257a5SJan Kara }
1001bfb257a5SJan Kara
1002bfb257a5SJan Kara udf_debug("udf_load_metadata_files Ok\n");
1003bfb257a5SJan Kara return 0;
1004bfb257a5SJan Kara }
1005bfb257a5SJan Kara
udf_compute_nr_groups(struct super_block * sb,u32 partition)1006883cb9d1SMarcin Slusarz int udf_compute_nr_groups(struct super_block *sb, u32 partition)
1007883cb9d1SMarcin Slusarz {
1008883cb9d1SMarcin Slusarz struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition];
10098dee00bbSJulia Lawall return DIV_ROUND_UP(map->s_partition_len +
10108dee00bbSJulia Lawall (sizeof(struct spaceBitmapDesc) << 3),
10118dee00bbSJulia Lawall sb->s_blocksize * 8);
1012883cb9d1SMarcin Slusarz }
1013883cb9d1SMarcin Slusarz
udf_sb_alloc_bitmap(struct super_block * sb,u32 index)101466e1da3fSMarcin Slusarz static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index)
101566e1da3fSMarcin Slusarz {
101666e1da3fSMarcin Slusarz struct udf_bitmap *bitmap;
1017256ccb9bSDenis Efremov int nr_groups = udf_compute_nr_groups(sb, index);
101866e1da3fSMarcin Slusarz
1019256ccb9bSDenis Efremov bitmap = kvzalloc(struct_size(bitmap, s_block_bitmap, nr_groups),
1020256ccb9bSDenis Efremov GFP_KERNEL);
1021ba2eb866SMarkus Elfring if (!bitmap)
102266e1da3fSMarcin Slusarz return NULL;
102366e1da3fSMarcin Slusarz
102466e1da3fSMarcin Slusarz bitmap->s_nr_groups = nr_groups;
102566e1da3fSMarcin Slusarz return bitmap;
102666e1da3fSMarcin Slusarz }
102766e1da3fSMarcin Slusarz
check_partition_desc(struct super_block * sb,struct partitionDesc * p,struct udf_part_map * map)1028b085fbe2SJan Kara static int check_partition_desc(struct super_block *sb,
1029b085fbe2SJan Kara struct partitionDesc *p,
1030b085fbe2SJan Kara struct udf_part_map *map)
1031b085fbe2SJan Kara {
1032b085fbe2SJan Kara bool umap, utable, fmap, ftable;
1033b085fbe2SJan Kara struct partitionHeaderDesc *phd;
1034b085fbe2SJan Kara
1035b085fbe2SJan Kara switch (le32_to_cpu(p->accessType)) {
1036b085fbe2SJan Kara case PD_ACCESS_TYPE_READ_ONLY:
1037b085fbe2SJan Kara case PD_ACCESS_TYPE_WRITE_ONCE:
1038b085fbe2SJan Kara case PD_ACCESS_TYPE_NONE:
1039b085fbe2SJan Kara goto force_ro;
1040b085fbe2SJan Kara }
1041b085fbe2SJan Kara
1042b085fbe2SJan Kara /* No Partition Header Descriptor? */
1043b085fbe2SJan Kara if (strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR02) &&
1044b085fbe2SJan Kara strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR03))
1045b085fbe2SJan Kara goto force_ro;
1046b085fbe2SJan Kara
1047b085fbe2SJan Kara phd = (struct partitionHeaderDesc *)p->partitionContentsUse;
1048b085fbe2SJan Kara utable = phd->unallocSpaceTable.extLength;
1049b085fbe2SJan Kara umap = phd->unallocSpaceBitmap.extLength;
1050b085fbe2SJan Kara ftable = phd->freedSpaceTable.extLength;
1051b085fbe2SJan Kara fmap = phd->freedSpaceBitmap.extLength;
1052b085fbe2SJan Kara
1053b085fbe2SJan Kara /* No allocation info? */
1054b085fbe2SJan Kara if (!utable && !umap && !ftable && !fmap)
1055b085fbe2SJan Kara goto force_ro;
1056b085fbe2SJan Kara
1057b085fbe2SJan Kara /* We don't support blocks that require erasing before overwrite */
1058b085fbe2SJan Kara if (ftable || fmap)
1059b085fbe2SJan Kara goto force_ro;
1060b085fbe2SJan Kara /* UDF 2.60: 2.3.3 - no mixing of tables & bitmaps, no VAT. */
1061b085fbe2SJan Kara if (utable && umap)
1062b085fbe2SJan Kara goto force_ro;
1063b085fbe2SJan Kara
1064b085fbe2SJan Kara if (map->s_partition_type == UDF_VIRTUAL_MAP15 ||
106557debb81SPali Rohár map->s_partition_type == UDF_VIRTUAL_MAP20 ||
106657debb81SPali Rohár map->s_partition_type == UDF_METADATA_MAP25)
1067b085fbe2SJan Kara goto force_ro;
1068b085fbe2SJan Kara
1069b085fbe2SJan Kara return 0;
1070b085fbe2SJan Kara force_ro:
1071b085fbe2SJan Kara if (!sb_rdonly(sb))
1072b085fbe2SJan Kara return -EACCES;
1073b085fbe2SJan Kara UDF_SET_FLAG(sb, UDF_FLAG_RW_INCOMPAT);
1074b085fbe2SJan Kara return 0;
1075b085fbe2SJan Kara }
1076b085fbe2SJan Kara
udf_fill_partdesc_info(struct super_block * sb,struct partitionDesc * p,int p_index)10773fb38dfaSJan Kara static int udf_fill_partdesc_info(struct super_block *sb,
10783fb38dfaSJan Kara struct partitionDesc *p, int p_index)
10793fb38dfaSJan Kara {
10803fb38dfaSJan Kara struct udf_part_map *map;
10813fb38dfaSJan Kara struct udf_sb_info *sbi = UDF_SB(sb);
10823fb38dfaSJan Kara struct partitionHeaderDesc *phd;
1083a5633076SJan Kara u32 sum;
1084b085fbe2SJan Kara int err;
10853fb38dfaSJan Kara
10863fb38dfaSJan Kara map = &sbi->s_partmaps[p_index];
10873fb38dfaSJan Kara
10883fb38dfaSJan Kara map->s_partition_len = le32_to_cpu(p->partitionLength); /* blocks */
10893fb38dfaSJan Kara map->s_partition_root = le32_to_cpu(p->partitionStartingLocation);
1090a5633076SJan Kara if (check_add_overflow(map->s_partition_root, map->s_partition_len,
1091a5633076SJan Kara &sum)) {
1092a5633076SJan Kara udf_err(sb, "Partition %d has invalid location %u + %u\n",
1093a5633076SJan Kara p_index, map->s_partition_root, map->s_partition_len);
1094a5633076SJan Kara return -EFSCORRUPTED;
1095a5633076SJan Kara }
10963fb38dfaSJan Kara
10973fb38dfaSJan Kara if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_READ_ONLY))
10983fb38dfaSJan Kara map->s_partition_flags |= UDF_PART_FLAG_READ_ONLY;
10993fb38dfaSJan Kara if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_WRITE_ONCE))
11003fb38dfaSJan Kara map->s_partition_flags |= UDF_PART_FLAG_WRITE_ONCE;
11013fb38dfaSJan Kara if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_REWRITABLE))
11023fb38dfaSJan Kara map->s_partition_flags |= UDF_PART_FLAG_REWRITABLE;
11033fb38dfaSJan Kara if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_OVERWRITABLE))
11043fb38dfaSJan Kara map->s_partition_flags |= UDF_PART_FLAG_OVERWRITABLE;
11053fb38dfaSJan Kara
1106fcbf7637SSteve Magnani udf_debug("Partition (%d type %x) starts at physical %u, block length %u\n",
1107a983f368SJoe Perches p_index, map->s_partition_type,
1108a983f368SJoe Perches map->s_partition_root, map->s_partition_len);
11093fb38dfaSJan Kara
1110b085fbe2SJan Kara err = check_partition_desc(sb, p, map);
1111b085fbe2SJan Kara if (err)
1112b085fbe2SJan Kara return err;
1113b085fbe2SJan Kara
1114b085fbe2SJan Kara /*
1115b085fbe2SJan Kara * Skip loading allocation info it we cannot ever write to the fs.
1116b085fbe2SJan Kara * This is a correctness thing as we may have decided to force ro mount
1117b085fbe2SJan Kara * to avoid allocation info we don't support.
1118b085fbe2SJan Kara */
1119b085fbe2SJan Kara if (UDF_QUERY_FLAG(sb, UDF_FLAG_RW_INCOMPAT))
11203fb38dfaSJan Kara return 0;
11213fb38dfaSJan Kara
11223fb38dfaSJan Kara phd = (struct partitionHeaderDesc *)p->partitionContentsUse;
11233fb38dfaSJan Kara if (phd->unallocSpaceTable.extLength) {
11245ca4e4beSPekka Enberg struct kernel_lb_addr loc = {
11253fb38dfaSJan Kara .logicalBlockNum = le32_to_cpu(
11263fb38dfaSJan Kara phd->unallocSpaceTable.extPosition),
11273fb38dfaSJan Kara .partitionReferenceNum = p_index,
11283fb38dfaSJan Kara };
11296d3d5e86SJan Kara struct inode *inode;
11303fb38dfaSJan Kara
11316174c2ebSJan Kara inode = udf_iget_special(sb, &loc);
11326d3d5e86SJan Kara if (IS_ERR(inode)) {
11333fb38dfaSJan Kara udf_debug("cannot load unallocSpaceTable (part %d)\n",
11343fb38dfaSJan Kara p_index);
11356d3d5e86SJan Kara return PTR_ERR(inode);
11363fb38dfaSJan Kara }
11376d3d5e86SJan Kara map->s_uspace.s_table = inode;
11383fb38dfaSJan Kara map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_TABLE;
1139fcbf7637SSteve Magnani udf_debug("unallocSpaceTable (part %d) @ %lu\n",
11403fb38dfaSJan Kara p_index, map->s_uspace.s_table->i_ino);
11413fb38dfaSJan Kara }
11423fb38dfaSJan Kara
11433fb38dfaSJan Kara if (phd->unallocSpaceBitmap.extLength) {
11443fb38dfaSJan Kara struct udf_bitmap *bitmap = udf_sb_alloc_bitmap(sb, p_index);
11453fb38dfaSJan Kara if (!bitmap)
1146d759bfa4SJan Kara return -ENOMEM;
11473fb38dfaSJan Kara map->s_uspace.s_bitmap = bitmap;
11483fb38dfaSJan Kara bitmap->s_extPosition = le32_to_cpu(
11493fb38dfaSJan Kara phd->unallocSpaceBitmap.extPosition);
11503fb38dfaSJan Kara map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_BITMAP;
1151a5633076SJan Kara /* Check whether math over bitmap won't overflow. */
1152a5633076SJan Kara if (check_add_overflow(map->s_partition_len,
1153a5633076SJan Kara sizeof(struct spaceBitmapDesc) << 3,
1154a5633076SJan Kara &sum)) {
1155a5633076SJan Kara udf_err(sb, "Partition %d is too long (%u)\n", p_index,
1156a5633076SJan Kara map->s_partition_len);
1157a5633076SJan Kara return -EFSCORRUPTED;
1158a5633076SJan Kara }
1159fcbf7637SSteve Magnani udf_debug("unallocSpaceBitmap (part %d) @ %u\n",
1160a983f368SJoe Perches p_index, bitmap->s_extPosition);
11613fb38dfaSJan Kara }
11623fb38dfaSJan Kara
11633fb38dfaSJan Kara return 0;
11643fb38dfaSJan Kara }
11653fb38dfaSJan Kara
udf_find_vat_block(struct super_block * sb,int p_index,int type1_index,sector_t start_block)1166e971b0b9SJan Kara static void udf_find_vat_block(struct super_block *sb, int p_index,
1167e971b0b9SJan Kara int type1_index, sector_t start_block)
1168e971b0b9SJan Kara {
1169e971b0b9SJan Kara struct udf_sb_info *sbi = UDF_SB(sb);
1170e971b0b9SJan Kara struct udf_part_map *map = &sbi->s_partmaps[p_index];
1171e971b0b9SJan Kara sector_t vat_block;
1172e971b0b9SJan Kara struct kernel_lb_addr ino;
11736d3d5e86SJan Kara struct inode *inode;
1174e971b0b9SJan Kara
1175e971b0b9SJan Kara /*
1176e971b0b9SJan Kara * VAT file entry is in the last recorded block. Some broken disks have
1177e971b0b9SJan Kara * it a few blocks before so try a bit harder...
1178e971b0b9SJan Kara */
1179e971b0b9SJan Kara ino.partitionReferenceNum = type1_index;
1180e971b0b9SJan Kara for (vat_block = start_block;
1181e971b0b9SJan Kara vat_block >= map->s_partition_root &&
11826d3d5e86SJan Kara vat_block >= start_block - 3; vat_block--) {
1183e971b0b9SJan Kara ino.logicalBlockNum = vat_block - map->s_partition_root;
11846174c2ebSJan Kara inode = udf_iget_special(sb, &ino);
11856d3d5e86SJan Kara if (!IS_ERR(inode)) {
11866d3d5e86SJan Kara sbi->s_vat_inode = inode;
11876d3d5e86SJan Kara break;
11886d3d5e86SJan Kara }
1189e971b0b9SJan Kara }
1190e971b0b9SJan Kara }
1191e971b0b9SJan Kara
udf_load_vat(struct super_block * sb,int p_index,int type1_index)119238b74a53SJan Kara static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
119338b74a53SJan Kara {
119438b74a53SJan Kara struct udf_sb_info *sbi = UDF_SB(sb);
119538b74a53SJan Kara struct udf_part_map *map = &sbi->s_partmaps[p_index];
1196fa5e0815SJan Kara struct buffer_head *bh = NULL;
1197fa5e0815SJan Kara struct udf_inode_info *vati;
1198fa5e0815SJan Kara struct virtualAllocationTable20 *vat20;
1199e4ae4735SChristoph Hellwig sector_t blocks = sb_bdev_nr_blocks(sb);
120038b74a53SJan Kara
1201e971b0b9SJan Kara udf_find_vat_block(sb, p_index, type1_index, sbi->s_last_block);
12024bf17af0SJan Kara if (!sbi->s_vat_inode &&
12034bf17af0SJan Kara sbi->s_last_block != blocks - 1) {
120478ace70cSJoe Perches pr_notice("Failed to read VAT inode from the last recorded block (%lu), retrying with the last block of the device (%lu).\n",
12054bf17af0SJan Kara (unsigned long)sbi->s_last_block,
12064bf17af0SJan Kara (unsigned long)blocks - 1);
1207e971b0b9SJan Kara udf_find_vat_block(sb, p_index, type1_index, blocks - 1);
12084bf17af0SJan Kara }
120938b74a53SJan Kara if (!sbi->s_vat_inode)
1210d759bfa4SJan Kara return -EIO;
121138b74a53SJan Kara
121238b74a53SJan Kara if (map->s_partition_type == UDF_VIRTUAL_MAP15) {
121347c9358aSSebastian Manciulea map->s_type_specific.s_virtual.s_start_offset = 0;
121438b74a53SJan Kara map->s_type_specific.s_virtual.s_num_entries =
121538b74a53SJan Kara (sbi->s_vat_inode->i_size - 36) >> 2;
121638b74a53SJan Kara } else if (map->s_partition_type == UDF_VIRTUAL_MAP20) {
1217fa5e0815SJan Kara vati = UDF_I(sbi->s_vat_inode);
1218fa5e0815SJan Kara if (vati->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
121908931b78SJan Kara int err = 0;
122008931b78SJan Kara
122108931b78SJan Kara bh = udf_bread(sbi->s_vat_inode, 0, 0, &err);
122208931b78SJan Kara if (!bh) {
122308931b78SJan Kara if (!err)
122408931b78SJan Kara err = -EFSCORRUPTED;
122508931b78SJan Kara return err;
122608931b78SJan Kara }
1227fa5e0815SJan Kara vat20 = (struct virtualAllocationTable20 *)bh->b_data;
1228fa5e0815SJan Kara } else {
1229fa5e0815SJan Kara vat20 = (struct virtualAllocationTable20 *)
1230382a2287SJan Kara vati->i_data;
1231fa5e0815SJan Kara }
1232fa5e0815SJan Kara
123338b74a53SJan Kara map->s_type_specific.s_virtual.s_start_offset =
123447c9358aSSebastian Manciulea le16_to_cpu(vat20->lengthHeader);
123538b74a53SJan Kara map->s_type_specific.s_virtual.s_num_entries =
123638b74a53SJan Kara (sbi->s_vat_inode->i_size -
123738b74a53SJan Kara map->s_type_specific.s_virtual.
123838b74a53SJan Kara s_start_offset) >> 2;
123938b74a53SJan Kara brelse(bh);
124038b74a53SJan Kara }
124138b74a53SJan Kara return 0;
124238b74a53SJan Kara }
124338b74a53SJan Kara
1244d759bfa4SJan Kara /*
1245d759bfa4SJan Kara * Load partition descriptor block
1246d759bfa4SJan Kara *
1247d759bfa4SJan Kara * Returns <0 on error, 0 on success, -EAGAIN is special - try next descriptor
1248d759bfa4SJan Kara * sequence.
1249d759bfa4SJan Kara */
udf_load_partdesc(struct super_block * sb,sector_t block)1250c0eb31edSJan Kara static int udf_load_partdesc(struct super_block *sb, sector_t block)
12511da177e4SLinus Torvalds {
1252c0eb31edSJan Kara struct buffer_head *bh;
1253c0eb31edSJan Kara struct partitionDesc *p;
12546c79e987SMarcin Slusarz struct udf_part_map *map;
1255165923faSMarcin Slusarz struct udf_sb_info *sbi = UDF_SB(sb);
125638b74a53SJan Kara int i, type1_idx;
1257c0eb31edSJan Kara uint16_t partitionNumber;
1258c0eb31edSJan Kara uint16_t ident;
1259d759bfa4SJan Kara int ret;
12601da177e4SLinus Torvalds
1261c0eb31edSJan Kara bh = udf_read_tagged(sb, block, block, &ident);
1262c0eb31edSJan Kara if (!bh)
1263d759bfa4SJan Kara return -EAGAIN;
1264d759bfa4SJan Kara if (ident != TAG_IDENT_PD) {
1265d759bfa4SJan Kara ret = 0;
1266c0eb31edSJan Kara goto out_bh;
1267d759bfa4SJan Kara }
1268c0eb31edSJan Kara
1269c0eb31edSJan Kara p = (struct partitionDesc *)bh->b_data;
1270c0eb31edSJan Kara partitionNumber = le16_to_cpu(p->partitionNumber);
127138b74a53SJan Kara
12727888824bSAlden Tondettar /* First scan for TYPE1 and SPARABLE partitions */
12736c79e987SMarcin Slusarz for (i = 0; i < sbi->s_partitions; i++) {
12746c79e987SMarcin Slusarz map = &sbi->s_partmaps[i];
1275fcbf7637SSteve Magnani udf_debug("Searching map: (%u == %u)\n",
1276165923faSMarcin Slusarz map->s_partition_num, partitionNumber);
127738b74a53SJan Kara if (map->s_partition_num == partitionNumber &&
127838b74a53SJan Kara (map->s_partition_type == UDF_TYPE1_MAP15 ||
127938b74a53SJan Kara map->s_partition_type == UDF_SPARABLE_MAP15))
1280165923faSMarcin Slusarz break;
1281165923faSMarcin Slusarz }
12821da177e4SLinus Torvalds
128338b74a53SJan Kara if (i >= sbi->s_partitions) {
1284fcbf7637SSteve Magnani udf_debug("Partition (%u) not found in partition map\n",
1285165923faSMarcin Slusarz partitionNumber);
1286d759bfa4SJan Kara ret = 0;
1287c0eb31edSJan Kara goto out_bh;
1288165923faSMarcin Slusarz }
12891da177e4SLinus Torvalds
12903fb38dfaSJan Kara ret = udf_fill_partdesc_info(sb, p, i);
1291d759bfa4SJan Kara if (ret < 0)
1292d759bfa4SJan Kara goto out_bh;
129338b74a53SJan Kara
129438b74a53SJan Kara /*
1295bfb257a5SJan Kara * Now rescan for VIRTUAL or METADATA partitions when SPARABLE and
1296bfb257a5SJan Kara * PHYSICAL partitions are already set up
129738b74a53SJan Kara */
129838b74a53SJan Kara type1_idx = i;
129944499602SPeter A. Felvegi map = NULL; /* supress 'maybe used uninitialized' warning */
130038b74a53SJan Kara for (i = 0; i < sbi->s_partitions; i++) {
130138b74a53SJan Kara map = &sbi->s_partmaps[i];
130238b74a53SJan Kara
130338b74a53SJan Kara if (map->s_partition_num == partitionNumber &&
130438b74a53SJan Kara (map->s_partition_type == UDF_VIRTUAL_MAP15 ||
1305bfb257a5SJan Kara map->s_partition_type == UDF_VIRTUAL_MAP20 ||
1306bfb257a5SJan Kara map->s_partition_type == UDF_METADATA_MAP25))
130738b74a53SJan Kara break;
130838b74a53SJan Kara }
130938b74a53SJan Kara
1310d759bfa4SJan Kara if (i >= sbi->s_partitions) {
1311d759bfa4SJan Kara ret = 0;
131238b74a53SJan Kara goto out_bh;
1313d759bfa4SJan Kara }
131438b74a53SJan Kara
131538b74a53SJan Kara ret = udf_fill_partdesc_info(sb, p, i);
1316d759bfa4SJan Kara if (ret < 0)
131738b74a53SJan Kara goto out_bh;
1318bfb257a5SJan Kara
1319bfb257a5SJan Kara if (map->s_partition_type == UDF_METADATA_MAP25) {
13207888824bSAlden Tondettar ret = udf_load_metadata_files(sb, i, type1_idx);
1321d759bfa4SJan Kara if (ret < 0) {
132278ace70cSJoe Perches udf_err(sb, "error loading MetaData partition map %d\n",
132378ace70cSJoe Perches i);
1324bfb257a5SJan Kara goto out_bh;
1325bfb257a5SJan Kara }
1326bfb257a5SJan Kara } else {
1327e729eac6SJan Kara /*
1328e729eac6SJan Kara * If we have a partition with virtual map, we don't handle
1329e729eac6SJan Kara * writing to it (we overwrite blocks instead of relocating
1330e729eac6SJan Kara * them).
1331e729eac6SJan Kara */
1332bc98a42cSDavid Howells if (!sb_rdonly(sb)) {
1333e729eac6SJan Kara ret = -EACCES;
1334e729eac6SJan Kara goto out_bh;
1335e729eac6SJan Kara }
1336a9ad01bcSJan Kara UDF_SET_FLAG(sb, UDF_FLAG_RW_INCOMPAT);
1337bfb257a5SJan Kara ret = udf_load_vat(sb, i, type1_idx);
1338d759bfa4SJan Kara if (ret < 0)
1339bfb257a5SJan Kara goto out_bh;
1340bfb257a5SJan Kara }
1341d759bfa4SJan Kara ret = 0;
1342c0eb31edSJan Kara out_bh:
13432e0838fdSJan Kara /* In case loading failed, we handle cleanup in udf_fill_super */
1344c0eb31edSJan Kara brelse(bh);
1345c0eb31edSJan Kara return ret;
13461da177e4SLinus Torvalds }
13471da177e4SLinus Torvalds
udf_load_sparable_map(struct super_block * sb,struct udf_part_map * map,struct sparablePartitionMap * spm)13481df2ae31SJan Kara static int udf_load_sparable_map(struct super_block *sb,
13491df2ae31SJan Kara struct udf_part_map *map,
13501df2ae31SJan Kara struct sparablePartitionMap *spm)
13511df2ae31SJan Kara {
13521df2ae31SJan Kara uint32_t loc;
13531df2ae31SJan Kara uint16_t ident;
13541df2ae31SJan Kara struct sparingTable *st;
13551df2ae31SJan Kara struct udf_sparing_data *sdata = &map->s_type_specific.s_sparing;
13561df2ae31SJan Kara int i;
13571df2ae31SJan Kara struct buffer_head *bh;
13581df2ae31SJan Kara
13591df2ae31SJan Kara map->s_partition_type = UDF_SPARABLE_MAP15;
13601df2ae31SJan Kara sdata->s_packet_len = le16_to_cpu(spm->packetLength);
13611df2ae31SJan Kara if (!is_power_of_2(sdata->s_packet_len)) {
13621df2ae31SJan Kara udf_err(sb, "error loading logical volume descriptor: "
13631df2ae31SJan Kara "Invalid packet length %u\n",
13641df2ae31SJan Kara (unsigned)sdata->s_packet_len);
13651df2ae31SJan Kara return -EIO;
13661df2ae31SJan Kara }
13671df2ae31SJan Kara if (spm->numSparingTables > 4) {
13681df2ae31SJan Kara udf_err(sb, "error loading logical volume descriptor: "
13691df2ae31SJan Kara "Too many sparing tables (%d)\n",
13701df2ae31SJan Kara (int)spm->numSparingTables);
13711df2ae31SJan Kara return -EIO;
13721df2ae31SJan Kara }
137344ac6b82SJan Kara if (le32_to_cpu(spm->sizeSparingTable) > sb->s_blocksize) {
137444ac6b82SJan Kara udf_err(sb, "error loading logical volume descriptor: "
137544ac6b82SJan Kara "Too big sparing table size (%u)\n",
137644ac6b82SJan Kara le32_to_cpu(spm->sizeSparingTable));
137744ac6b82SJan Kara return -EIO;
137844ac6b82SJan Kara }
13791df2ae31SJan Kara
13801df2ae31SJan Kara for (i = 0; i < spm->numSparingTables; i++) {
13811df2ae31SJan Kara loc = le32_to_cpu(spm->locSparingTable[i]);
13821df2ae31SJan Kara bh = udf_read_tagged(sb, loc, loc, &ident);
13831df2ae31SJan Kara if (!bh)
13841df2ae31SJan Kara continue;
13851df2ae31SJan Kara
13861df2ae31SJan Kara st = (struct sparingTable *)bh->b_data;
13871df2ae31SJan Kara if (ident != 0 ||
13881df2ae31SJan Kara strncmp(st->sparingIdent.ident, UDF_ID_SPARING,
13891df2ae31SJan Kara strlen(UDF_ID_SPARING)) ||
13901df2ae31SJan Kara sizeof(*st) + le16_to_cpu(st->reallocationTableLen) >
13911df2ae31SJan Kara sb->s_blocksize) {
13921df2ae31SJan Kara brelse(bh);
13931df2ae31SJan Kara continue;
13941df2ae31SJan Kara }
13951df2ae31SJan Kara
13961df2ae31SJan Kara sdata->s_spar_map[i] = bh;
13971df2ae31SJan Kara }
13981df2ae31SJan Kara map->s_partition_func = udf_get_pblock_spar15;
13991df2ae31SJan Kara return 0;
14001df2ae31SJan Kara }
14011df2ae31SJan Kara
udf_load_logicalvol(struct super_block * sb,sector_t block,struct kernel_lb_addr * fileset)1402c0eb31edSJan Kara static int udf_load_logicalvol(struct super_block *sb, sector_t block,
14035ca4e4beSPekka Enberg struct kernel_lb_addr *fileset)
14041da177e4SLinus Torvalds {
14051da177e4SLinus Torvalds struct logicalVolDesc *lvd;
14061df2ae31SJan Kara int i, offset;
14071da177e4SLinus Torvalds uint8_t type;
14086c79e987SMarcin Slusarz struct udf_sb_info *sbi = UDF_SB(sb);
14094b11111aSMarcin Slusarz struct genericPartitionMap *gpm;
1410c0eb31edSJan Kara uint16_t ident;
1411c0eb31edSJan Kara struct buffer_head *bh;
1412adee11b2SJan Kara unsigned int table_len;
1413d759bfa4SJan Kara int ret;
14141da177e4SLinus Torvalds
1415c0eb31edSJan Kara bh = udf_read_tagged(sb, block, block, &ident);
1416c0eb31edSJan Kara if (!bh)
1417d759bfa4SJan Kara return -EAGAIN;
1418c0eb31edSJan Kara BUG_ON(ident != TAG_IDENT_LVD);
14191da177e4SLinus Torvalds lvd = (struct logicalVolDesc *)bh->b_data;
1420adee11b2SJan Kara table_len = le32_to_cpu(lvd->mapTableLength);
142157b9655dSJan Kara if (table_len > sb->s_blocksize - sizeof(*lvd)) {
1422adee11b2SJan Kara udf_err(sb, "error loading logical volume descriptor: "
1423adee11b2SJan Kara "Partition table too long (%u > %lu)\n", table_len,
1424adee11b2SJan Kara sb->s_blocksize - sizeof(*lvd));
1425d759bfa4SJan Kara ret = -EIO;
1426adee11b2SJan Kara goto out_bh;
1427adee11b2SJan Kara }
14281da177e4SLinus Torvalds
14292dee5aacSJan Kara ret = udf_verify_domain_identifier(sb, &lvd->domainIdent,
14302dee5aacSJan Kara "logical volume");
14312dee5aacSJan Kara if (ret)
14322dee5aacSJan Kara goto out_bh;
1433cb14d340SJan Kara ret = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps));
1434cb14d340SJan Kara if (ret)
1435c0eb31edSJan Kara goto out_bh;
14361da177e4SLinus Torvalds
14371da177e4SLinus Torvalds for (i = 0, offset = 0;
1438adee11b2SJan Kara i < sbi->s_partitions && offset < table_len;
14394b11111aSMarcin Slusarz i++, offset += gpm->partitionMapLength) {
14406c79e987SMarcin Slusarz struct udf_part_map *map = &sbi->s_partmaps[i];
14414b11111aSMarcin Slusarz gpm = (struct genericPartitionMap *)
14424b11111aSMarcin Slusarz &(lvd->partitionMaps[offset]);
14434b11111aSMarcin Slusarz type = gpm->partitionMapType;
1444cb00ea35SCyrill Gorcunov if (type == 1) {
14454b11111aSMarcin Slusarz struct genericPartitionMap1 *gpm1 =
14464b11111aSMarcin Slusarz (struct genericPartitionMap1 *)gpm;
14476c79e987SMarcin Slusarz map->s_partition_type = UDF_TYPE1_MAP15;
14486c79e987SMarcin Slusarz map->s_volumeseqnum = le16_to_cpu(gpm1->volSeqNum);
14496c79e987SMarcin Slusarz map->s_partition_num = le16_to_cpu(gpm1->partitionNum);
14506c79e987SMarcin Slusarz map->s_partition_func = NULL;
1451cb00ea35SCyrill Gorcunov } else if (type == 2) {
14524b11111aSMarcin Slusarz struct udfPartitionMap2 *upm2 =
14534b11111aSMarcin Slusarz (struct udfPartitionMap2 *)gpm;
14544b11111aSMarcin Slusarz if (!strncmp(upm2->partIdent.ident, UDF_ID_VIRTUAL,
14554b11111aSMarcin Slusarz strlen(UDF_ID_VIRTUAL))) {
14564b11111aSMarcin Slusarz u16 suf =
14574b11111aSMarcin Slusarz le16_to_cpu(((__le16 *)upm2->partIdent.
14584b11111aSMarcin Slusarz identSuffix)[0]);
1459c82a1275SJan Kara if (suf < 0x0200) {
14604b11111aSMarcin Slusarz map->s_partition_type =
14614b11111aSMarcin Slusarz UDF_VIRTUAL_MAP15;
14624b11111aSMarcin Slusarz map->s_partition_func =
14634b11111aSMarcin Slusarz udf_get_pblock_virt15;
1464c82a1275SJan Kara } else {
14654b11111aSMarcin Slusarz map->s_partition_type =
14664b11111aSMarcin Slusarz UDF_VIRTUAL_MAP20;
14674b11111aSMarcin Slusarz map->s_partition_func =
14684b11111aSMarcin Slusarz udf_get_pblock_virt20;
14691da177e4SLinus Torvalds }
14704b11111aSMarcin Slusarz } else if (!strncmp(upm2->partIdent.ident,
14714b11111aSMarcin Slusarz UDF_ID_SPARABLE,
14724b11111aSMarcin Slusarz strlen(UDF_ID_SPARABLE))) {
1473d759bfa4SJan Kara ret = udf_load_sparable_map(sb, map,
1474d759bfa4SJan Kara (struct sparablePartitionMap *)gpm);
1475d759bfa4SJan Kara if (ret < 0)
14761df2ae31SJan Kara goto out_bh;
1477bfb257a5SJan Kara } else if (!strncmp(upm2->partIdent.ident,
1478bfb257a5SJan Kara UDF_ID_METADATA,
1479bfb257a5SJan Kara strlen(UDF_ID_METADATA))) {
1480bfb257a5SJan Kara struct udf_meta_data *mdata =
1481bfb257a5SJan Kara &map->s_type_specific.s_metadata;
1482bfb257a5SJan Kara struct metadataPartitionMap *mdm =
1483bfb257a5SJan Kara (struct metadataPartitionMap *)
1484bfb257a5SJan Kara &(lvd->partitionMaps[offset]);
1485fcbf7637SSteve Magnani udf_debug("Parsing Logical vol part %d type %u id=%s\n",
1486a983f368SJoe Perches i, type, UDF_ID_METADATA);
1487bfb257a5SJan Kara
1488bfb257a5SJan Kara map->s_partition_type = UDF_METADATA_MAP25;
1489bfb257a5SJan Kara map->s_partition_func = udf_get_pblock_meta25;
1490bfb257a5SJan Kara
1491bfb257a5SJan Kara mdata->s_meta_file_loc =
1492bfb257a5SJan Kara le32_to_cpu(mdm->metadataFileLoc);
1493bfb257a5SJan Kara mdata->s_mirror_file_loc =
1494bfb257a5SJan Kara le32_to_cpu(mdm->metadataMirrorFileLoc);
1495bfb257a5SJan Kara mdata->s_bitmap_file_loc =
1496bfb257a5SJan Kara le32_to_cpu(mdm->metadataBitmapFileLoc);
1497bfb257a5SJan Kara mdata->s_alloc_unit_size =
1498bfb257a5SJan Kara le32_to_cpu(mdm->allocUnitSize);
1499bfb257a5SJan Kara mdata->s_align_unit_size =
1500bfb257a5SJan Kara le16_to_cpu(mdm->alignUnitSize);
1501ed47a7d0SJan Kara if (mdm->flags & 0x01)
1502ed47a7d0SJan Kara mdata->s_flags |= MF_DUPLICATE_MD;
1503bfb257a5SJan Kara
1504bfb257a5SJan Kara udf_debug("Metadata Ident suffix=0x%x\n",
1505a983f368SJoe Perches le16_to_cpu(*(__le16 *)
1506a983f368SJoe Perches mdm->partIdent.identSuffix));
1507fcbf7637SSteve Magnani udf_debug("Metadata part num=%u\n",
1508bfb257a5SJan Kara le16_to_cpu(mdm->partitionNum));
1509fcbf7637SSteve Magnani udf_debug("Metadata part alloc unit size=%u\n",
1510bfb257a5SJan Kara le32_to_cpu(mdm->allocUnitSize));
1511fcbf7637SSteve Magnani udf_debug("Metadata file loc=%u\n",
1512bfb257a5SJan Kara le32_to_cpu(mdm->metadataFileLoc));
1513fcbf7637SSteve Magnani udf_debug("Mirror file loc=%u\n",
1514bfb257a5SJan Kara le32_to_cpu(mdm->metadataMirrorFileLoc));
1515fcbf7637SSteve Magnani udf_debug("Bitmap file loc=%u\n",
1516bfb257a5SJan Kara le32_to_cpu(mdm->metadataBitmapFileLoc));
1517fcbf7637SSteve Magnani udf_debug("Flags: %d %u\n",
1518ed47a7d0SJan Kara mdata->s_flags, mdm->flags);
1519cb00ea35SCyrill Gorcunov } else {
15203a71fc5dSMarcin Slusarz udf_debug("Unknown ident: %s\n",
15213a71fc5dSMarcin Slusarz upm2->partIdent.ident);
15221da177e4SLinus Torvalds continue;
15231da177e4SLinus Torvalds }
15246c79e987SMarcin Slusarz map->s_volumeseqnum = le16_to_cpu(upm2->volSeqNum);
15256c79e987SMarcin Slusarz map->s_partition_num = le16_to_cpu(upm2->partitionNum);
15261da177e4SLinus Torvalds }
1527fcbf7637SSteve Magnani udf_debug("Partition (%d:%u) type %u on volume %u\n",
1528a983f368SJoe Perches i, map->s_partition_num, type, map->s_volumeseqnum);
15291da177e4SLinus Torvalds }
15301da177e4SLinus Torvalds
1531cb00ea35SCyrill Gorcunov if (fileset) {
15325ca4e4beSPekka Enberg struct long_ad *la = (struct long_ad *)&(lvd->logicalVolContentsUse[0]);
15331da177e4SLinus Torvalds
15341da177e4SLinus Torvalds *fileset = lelb_to_cpu(la->extLocation);
1535fcbf7637SSteve Magnani udf_debug("FileSet found in LogicalVolDesc at block=%u, partition=%u\n",
1536a983f368SJoe Perches fileset->logicalBlockNum,
153728de7948SCyrill Gorcunov fileset->partitionReferenceNum);
15381da177e4SLinus Torvalds }
15391da177e4SLinus Torvalds if (lvd->integritySeqExt.extLength)
15401da177e4SLinus Torvalds udf_load_logicalvolint(sb, leea_to_cpu(lvd->integritySeqExt));
1541d759bfa4SJan Kara ret = 0;
15424f5edd82SSteve Magnani
15434f5edd82SSteve Magnani if (!sbi->s_lvid_bh) {
15444f5edd82SSteve Magnani /* We can't generate unique IDs without a valid LVID */
15454f5edd82SSteve Magnani if (sb_rdonly(sb)) {
15464f5edd82SSteve Magnani UDF_SET_FLAG(sb, UDF_FLAG_RW_INCOMPAT);
15474f5edd82SSteve Magnani } else {
15484f5edd82SSteve Magnani udf_warn(sb, "Damaged or missing LVID, forcing "
15494f5edd82SSteve Magnani "readonly mount\n");
15504f5edd82SSteve Magnani ret = -EACCES;
15514f5edd82SSteve Magnani }
15524f5edd82SSteve Magnani }
1553c0eb31edSJan Kara out_bh:
1554c0eb31edSJan Kara brelse(bh);
1555c0eb31edSJan Kara return ret;
15561da177e4SLinus Torvalds }
15571da177e4SLinus Torvalds
15581da177e4SLinus Torvalds /*
1559a47241cdSAlden Tondettar * Find the prevailing Logical Volume Integrity Descriptor.
15601da177e4SLinus Torvalds */
udf_load_logicalvolint(struct super_block * sb,struct kernel_extent_ad loc)15615ca4e4beSPekka Enberg static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_ad loc)
15621da177e4SLinus Torvalds {
1563a47241cdSAlden Tondettar struct buffer_head *bh, *final_bh;
15641da177e4SLinus Torvalds uint16_t ident;
15656c79e987SMarcin Slusarz struct udf_sb_info *sbi = UDF_SB(sb);
15666c79e987SMarcin Slusarz struct logicalVolIntegrityDesc *lvid;
1567a47241cdSAlden Tondettar int indirections = 0;
1568781d2a9aSJan Kara u32 parts, impuselen;
15691da177e4SLinus Torvalds
1570a47241cdSAlden Tondettar while (++indirections <= UDF_MAX_LVID_NESTING) {
1571a47241cdSAlden Tondettar final_bh = NULL;
15721da177e4SLinus Torvalds while (loc.extLength > 0 &&
15731da177e4SLinus Torvalds (bh = udf_read_tagged(sb, loc.extLocation,
1574a47241cdSAlden Tondettar loc.extLocation, &ident))) {
1575a47241cdSAlden Tondettar if (ident != TAG_IDENT_LVID) {
15763bf25cb4SJan Kara brelse(bh);
1577a47241cdSAlden Tondettar break;
1578a47241cdSAlden Tondettar }
1579a47241cdSAlden Tondettar
1580a47241cdSAlden Tondettar brelse(final_bh);
1581a47241cdSAlden Tondettar final_bh = bh;
1582a47241cdSAlden Tondettar
15831da177e4SLinus Torvalds loc.extLength -= sb->s_blocksize;
15841da177e4SLinus Torvalds loc.extLocation++;
15851da177e4SLinus Torvalds }
1586a47241cdSAlden Tondettar
1587a47241cdSAlden Tondettar if (!final_bh)
1588a47241cdSAlden Tondettar return;
1589a47241cdSAlden Tondettar
1590a47241cdSAlden Tondettar brelse(sbi->s_lvid_bh);
1591a47241cdSAlden Tondettar sbi->s_lvid_bh = final_bh;
1592a47241cdSAlden Tondettar
1593a47241cdSAlden Tondettar lvid = (struct logicalVolIntegrityDesc *)final_bh->b_data;
1594a47241cdSAlden Tondettar if (lvid->nextIntegrityExt.extLength == 0)
1595781d2a9aSJan Kara goto check;
1596a47241cdSAlden Tondettar
1597a47241cdSAlden Tondettar loc = leea_to_cpu(lvid->nextIntegrityExt);
15981da177e4SLinus Torvalds }
15991da177e4SLinus Torvalds
1600a47241cdSAlden Tondettar udf_warn(sb, "Too many LVID indirections (max %u), ignoring.\n",
1601a47241cdSAlden Tondettar UDF_MAX_LVID_NESTING);
1602781d2a9aSJan Kara out_err:
1603a47241cdSAlden Tondettar brelse(sbi->s_lvid_bh);
1604a47241cdSAlden Tondettar sbi->s_lvid_bh = NULL;
1605781d2a9aSJan Kara return;
1606781d2a9aSJan Kara check:
1607781d2a9aSJan Kara parts = le32_to_cpu(lvid->numOfPartitions);
1608781d2a9aSJan Kara impuselen = le32_to_cpu(lvid->lengthOfImpUse);
1609781d2a9aSJan Kara if (parts >= sb->s_blocksize || impuselen >= sb->s_blocksize ||
1610781d2a9aSJan Kara sizeof(struct logicalVolIntegrityDesc) + impuselen +
1611781d2a9aSJan Kara 2 * parts * sizeof(u32) > sb->s_blocksize) {
1612781d2a9aSJan Kara udf_warn(sb, "Corrupted LVID (parts=%u, impuselen=%u), "
1613781d2a9aSJan Kara "ignoring.\n", parts, impuselen);
1614781d2a9aSJan Kara goto out_err;
1615781d2a9aSJan Kara }
1616a47241cdSAlden Tondettar }
1617a47241cdSAlden Tondettar
16187b78fd02SJan Kara /*
16197b78fd02SJan Kara * Step for reallocation of table of partition descriptor sequence numbers.
16207b78fd02SJan Kara * Must be power of 2.
16217b78fd02SJan Kara */
16227b78fd02SJan Kara #define PART_DESC_ALLOC_STEP 32
16237b78fd02SJan Kara
1624ee4af50cSJan Kara struct part_desc_seq_scan_data {
1625ee4af50cSJan Kara struct udf_vds_record rec;
1626ee4af50cSJan Kara u32 partnum;
1627ee4af50cSJan Kara };
1628ee4af50cSJan Kara
16297b78fd02SJan Kara struct desc_seq_scan_data {
16307b78fd02SJan Kara struct udf_vds_record vds[VDS_POS_LENGTH];
16317b78fd02SJan Kara unsigned int size_part_descs;
1632ee4af50cSJan Kara unsigned int num_part_descs;
1633ee4af50cSJan Kara struct part_desc_seq_scan_data *part_descs_loc;
16347b78fd02SJan Kara };
16357b78fd02SJan Kara
handle_partition_descriptor(struct buffer_head * bh,struct desc_seq_scan_data * data)16367b78fd02SJan Kara static struct udf_vds_record *handle_partition_descriptor(
16377b78fd02SJan Kara struct buffer_head *bh,
16387b78fd02SJan Kara struct desc_seq_scan_data *data)
16397b78fd02SJan Kara {
16407b78fd02SJan Kara struct partitionDesc *desc = (struct partitionDesc *)bh->b_data;
16417b78fd02SJan Kara int partnum;
1642ee4af50cSJan Kara int i;
16437b78fd02SJan Kara
16447b78fd02SJan Kara partnum = le16_to_cpu(desc->partitionNumber);
1645ee4af50cSJan Kara for (i = 0; i < data->num_part_descs; i++)
1646ee4af50cSJan Kara if (partnum == data->part_descs_loc[i].partnum)
1647ee4af50cSJan Kara return &(data->part_descs_loc[i].rec);
1648ee4af50cSJan Kara if (data->num_part_descs >= data->size_part_descs) {
1649ee4af50cSJan Kara struct part_desc_seq_scan_data *new_loc;
16507b78fd02SJan Kara unsigned int new_size = ALIGN(partnum, PART_DESC_ALLOC_STEP);
16517b78fd02SJan Kara
16526396bb22SKees Cook new_loc = kcalloc(new_size, sizeof(*new_loc), GFP_KERNEL);
16537b78fd02SJan Kara if (!new_loc)
16547b78fd02SJan Kara return ERR_PTR(-ENOMEM);
16557b78fd02SJan Kara memcpy(new_loc, data->part_descs_loc,
16567b78fd02SJan Kara data->size_part_descs * sizeof(*new_loc));
16577b78fd02SJan Kara kfree(data->part_descs_loc);
16587b78fd02SJan Kara data->part_descs_loc = new_loc;
16597b78fd02SJan Kara data->size_part_descs = new_size;
16607b78fd02SJan Kara }
1661ee4af50cSJan Kara return &(data->part_descs_loc[data->num_part_descs++].rec);
16627b78fd02SJan Kara }
16637b78fd02SJan Kara
16647b78fd02SJan Kara
get_volume_descriptor_record(uint16_t ident,struct buffer_head * bh,struct desc_seq_scan_data * data)16657b78fd02SJan Kara static struct udf_vds_record *get_volume_descriptor_record(uint16_t ident,
16667b78fd02SJan Kara struct buffer_head *bh, struct desc_seq_scan_data *data)
166718cf4781SJan Kara {
166818cf4781SJan Kara switch (ident) {
166918cf4781SJan Kara case TAG_IDENT_PVD: /* ISO 13346 3/10.1 */
16707b78fd02SJan Kara return &(data->vds[VDS_POS_PRIMARY_VOL_DESC]);
167118cf4781SJan Kara case TAG_IDENT_IUVD: /* ISO 13346 3/10.4 */
16727b78fd02SJan Kara return &(data->vds[VDS_POS_IMP_USE_VOL_DESC]);
167318cf4781SJan Kara case TAG_IDENT_LVD: /* ISO 13346 3/10.6 */
16747b78fd02SJan Kara return &(data->vds[VDS_POS_LOGICAL_VOL_DESC]);
167518cf4781SJan Kara case TAG_IDENT_USD: /* ISO 13346 3/10.8 */
16767b78fd02SJan Kara return &(data->vds[VDS_POS_UNALLOC_SPACE_DESC]);
16777b78fd02SJan Kara case TAG_IDENT_PD: /* ISO 13346 3/10.5 */
16787b78fd02SJan Kara return handle_partition_descriptor(bh, data);
167918cf4781SJan Kara }
168018cf4781SJan Kara return NULL;
168118cf4781SJan Kara }
1682e7a4eb86SVegard Nossum
1683e7a4eb86SVegard Nossum /*
16841da177e4SLinus Torvalds * Process a main/reserve volume descriptor sequence.
1685d759bfa4SJan Kara * @block First block of first extent of the sequence.
1686d759bfa4SJan Kara * @lastblock Lastblock of first extent of the sequence.
1687d759bfa4SJan Kara * @fileset There we store extent containing root fileset
16881da177e4SLinus Torvalds *
1689d759bfa4SJan Kara * Returns <0 on error, 0 on success. -EAGAIN is special - try next descriptor
1690d759bfa4SJan Kara * sequence
16911da177e4SLinus Torvalds */
udf_process_sequence(struct super_block * sb,sector_t block,sector_t lastblock,struct kernel_lb_addr * fileset)1692d759bfa4SJan Kara static noinline int udf_process_sequence(
1693d759bfa4SJan Kara struct super_block *sb,
1694d759bfa4SJan Kara sector_t block, sector_t lastblock,
1695d759bfa4SJan Kara struct kernel_lb_addr *fileset)
16961da177e4SLinus Torvalds {
16971da177e4SLinus Torvalds struct buffer_head *bh = NULL;
16984b11111aSMarcin Slusarz struct udf_vds_record *curr;
16991da177e4SLinus Torvalds struct generic_desc *gd;
17001da177e4SLinus Torvalds struct volDescPtr *vdp;
17012b8f9421SFabian Frederick bool done = false;
17021da177e4SLinus Torvalds uint32_t vdsn;
17031da177e4SLinus Torvalds uint16_t ident;
1704d759bfa4SJan Kara int ret;
1705e7a4eb86SVegard Nossum unsigned int indirections = 0;
17067b78fd02SJan Kara struct desc_seq_scan_data data;
17077b78fd02SJan Kara unsigned int i;
17081da177e4SLinus Torvalds
17097b78fd02SJan Kara memset(data.vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH);
17107b78fd02SJan Kara data.size_part_descs = PART_DESC_ALLOC_STEP;
1711ee4af50cSJan Kara data.num_part_descs = 0;
17126396bb22SKees Cook data.part_descs_loc = kcalloc(data.size_part_descs,
17136396bb22SKees Cook sizeof(*data.part_descs_loc),
17146396bb22SKees Cook GFP_KERNEL);
17157b78fd02SJan Kara if (!data.part_descs_loc)
17167b78fd02SJan Kara return -ENOMEM;
17171da177e4SLinus Torvalds
1718c0eb31edSJan Kara /*
1719c0eb31edSJan Kara * Read the main descriptor sequence and find which descriptors
1720c0eb31edSJan Kara * are in it.
1721c0eb31edSJan Kara */
1722cb00ea35SCyrill Gorcunov for (; (!done && block <= lastblock); block++) {
17231da177e4SLinus Torvalds bh = udf_read_tagged(sb, block, block, &ident);
172467621675SJan Kara if (!bh)
172567621675SJan Kara break;
17261da177e4SLinus Torvalds
17271da177e4SLinus Torvalds /* Process each descriptor (ISO 13346 3/8.3-8.4) */
17281da177e4SLinus Torvalds gd = (struct generic_desc *)bh->b_data;
17291da177e4SLinus Torvalds vdsn = le32_to_cpu(gd->volDescSeqNum);
1730cb00ea35SCyrill Gorcunov switch (ident) {
17311da177e4SLinus Torvalds case TAG_IDENT_VDP: /* ISO 13346 3/10.3 */
17327b568cbaSJan Kara if (++indirections > UDF_MAX_TD_NESTING) {
17337b568cbaSJan Kara udf_err(sb, "too many Volume Descriptor "
17347b568cbaSJan Kara "Pointers (max %u supported)\n",
17357b568cbaSJan Kara UDF_MAX_TD_NESTING);
17367b568cbaSJan Kara brelse(bh);
1737a7be300dSJan Kara ret = -EIO;
1738a7be300dSJan Kara goto out;
17397b568cbaSJan Kara }
17401da177e4SLinus Torvalds
17411da177e4SLinus Torvalds vdp = (struct volDescPtr *)bh->b_data;
17427b568cbaSJan Kara block = le32_to_cpu(vdp->nextVolDescSeqExt.extLocation);
17437b568cbaSJan Kara lastblock = le32_to_cpu(
17447b568cbaSJan Kara vdp->nextVolDescSeqExt.extLength) >>
17457b568cbaSJan Kara sb->s_blocksize_bits;
17467b568cbaSJan Kara lastblock += block - 1;
17477b568cbaSJan Kara /* For loop is going to increment 'block' again */
17487b568cbaSJan Kara block--;
17491da177e4SLinus Torvalds break;
175018cf4781SJan Kara case TAG_IDENT_PVD: /* ISO 13346 3/10.1 */
17511da177e4SLinus Torvalds case TAG_IDENT_IUVD: /* ISO 13346 3/10.4 */
175218cf4781SJan Kara case TAG_IDENT_LVD: /* ISO 13346 3/10.6 */
175318cf4781SJan Kara case TAG_IDENT_USD: /* ISO 13346 3/10.8 */
17547b78fd02SJan Kara case TAG_IDENT_PD: /* ISO 13346 3/10.5 */
17557b78fd02SJan Kara curr = get_volume_descriptor_record(ident, bh, &data);
17567b78fd02SJan Kara if (IS_ERR(curr)) {
17577b78fd02SJan Kara brelse(bh);
1758a7be300dSJan Kara ret = PTR_ERR(curr);
1759a7be300dSJan Kara goto out;
17607b78fd02SJan Kara }
17617b78fd02SJan Kara /* Descriptor we don't care about? */
17627b78fd02SJan Kara if (!curr)
17637b78fd02SJan Kara break;
17644b11111aSMarcin Slusarz if (vdsn >= curr->volDescSeqNum) {
17654b11111aSMarcin Slusarz curr->volDescSeqNum = vdsn;
17664b11111aSMarcin Slusarz curr->block = block;
17671da177e4SLinus Torvalds }
17681da177e4SLinus Torvalds break;
17691da177e4SLinus Torvalds case TAG_IDENT_TD: /* ISO 13346 3/10.9 */
17702b8f9421SFabian Frederick done = true;
17711da177e4SLinus Torvalds break;
17721da177e4SLinus Torvalds }
17733bf25cb4SJan Kara brelse(bh);
17741da177e4SLinus Torvalds }
1775c0eb31edSJan Kara /*
1776c0eb31edSJan Kara * Now read interesting descriptors again and process them
1777c0eb31edSJan Kara * in a suitable order
1778c0eb31edSJan Kara */
17797b78fd02SJan Kara if (!data.vds[VDS_POS_PRIMARY_VOL_DESC].block) {
178078ace70cSJoe Perches udf_err(sb, "Primary Volume Descriptor not found!\n");
1781a7be300dSJan Kara ret = -EAGAIN;
1782a7be300dSJan Kara goto out;
1783c0eb31edSJan Kara }
17847b78fd02SJan Kara ret = udf_load_pvoldesc(sb, data.vds[VDS_POS_PRIMARY_VOL_DESC].block);
1785d759bfa4SJan Kara if (ret < 0)
1786a7be300dSJan Kara goto out;
1787165923faSMarcin Slusarz
17887b78fd02SJan Kara if (data.vds[VDS_POS_LOGICAL_VOL_DESC].block) {
1789d759bfa4SJan Kara ret = udf_load_logicalvol(sb,
17907b78fd02SJan Kara data.vds[VDS_POS_LOGICAL_VOL_DESC].block,
1791d759bfa4SJan Kara fileset);
1792d759bfa4SJan Kara if (ret < 0)
1793a7be300dSJan Kara goto out;
1794d759bfa4SJan Kara }
17951da177e4SLinus Torvalds
17967b78fd02SJan Kara /* Now handle prevailing Partition Descriptors */
1797ee4af50cSJan Kara for (i = 0; i < data.num_part_descs; i++) {
1798ee4af50cSJan Kara ret = udf_load_partdesc(sb, data.part_descs_loc[i].rec.block);
1799d759bfa4SJan Kara if (ret < 0)
1800a7be300dSJan Kara goto out;
1801d759bfa4SJan Kara }
1802a7be300dSJan Kara ret = 0;
1803a7be300dSJan Kara out:
1804a7be300dSJan Kara kfree(data.part_descs_loc);
1805a7be300dSJan Kara return ret;
18061da177e4SLinus Torvalds }
18071da177e4SLinus Torvalds
1808d759bfa4SJan Kara /*
1809d759bfa4SJan Kara * Load Volume Descriptor Sequence described by anchor in bh
1810d759bfa4SJan Kara *
1811d759bfa4SJan Kara * Returns <0 on error, 0 on success
1812d759bfa4SJan Kara */
udf_load_sequence(struct super_block * sb,struct buffer_head * bh,struct kernel_lb_addr * fileset)181340346005SJan Kara static int udf_load_sequence(struct super_block *sb, struct buffer_head *bh,
181440346005SJan Kara struct kernel_lb_addr *fileset)
18151da177e4SLinus Torvalds {
18161da177e4SLinus Torvalds struct anchorVolDescPtr *anchor;
1817d759bfa4SJan Kara sector_t main_s, main_e, reserve_s, reserve_e;
1818d759bfa4SJan Kara int ret;
18191da177e4SLinus Torvalds
18201da177e4SLinus Torvalds anchor = (struct anchorVolDescPtr *)bh->b_data;
18211da177e4SLinus Torvalds
18221da177e4SLinus Torvalds /* Locate the main sequence */
182328f7c4d4SMarcin Slusarz main_s = le32_to_cpu(anchor->mainVolDescSeqExt.extLocation);
182428f7c4d4SMarcin Slusarz main_e = le32_to_cpu(anchor->mainVolDescSeqExt.extLength);
18251da177e4SLinus Torvalds main_e = main_e >> sb->s_blocksize_bits;
182691c9c9ecSJan Kara main_e += main_s - 1;
18271da177e4SLinus Torvalds
18281da177e4SLinus Torvalds /* Locate the reserve sequence */
182940346005SJan Kara reserve_s = le32_to_cpu(anchor->reserveVolDescSeqExt.extLocation);
183040346005SJan Kara reserve_e = le32_to_cpu(anchor->reserveVolDescSeqExt.extLength);
18311da177e4SLinus Torvalds reserve_e = reserve_e >> sb->s_blocksize_bits;
183291c9c9ecSJan Kara reserve_e += reserve_s - 1;
18331da177e4SLinus Torvalds
18341da177e4SLinus Torvalds /* Process the main & reserve sequences */
18351da177e4SLinus Torvalds /* responsible for finding the PartitionDesc(s) */
1836d759bfa4SJan Kara ret = udf_process_sequence(sb, main_s, main_e, fileset);
1837d759bfa4SJan Kara if (ret != -EAGAIN)
1838d759bfa4SJan Kara return ret;
1839bff943afSJan Kara udf_sb_free_partitions(sb);
1840d759bfa4SJan Kara ret = udf_process_sequence(sb, reserve_s, reserve_e, fileset);
1841d759bfa4SJan Kara if (ret < 0) {
1842bff943afSJan Kara udf_sb_free_partitions(sb);
1843d759bfa4SJan Kara /* No sequence was OK, return -EIO */
1844d759bfa4SJan Kara if (ret == -EAGAIN)
1845d759bfa4SJan Kara ret = -EIO;
1846d759bfa4SJan Kara }
1847d759bfa4SJan Kara return ret;
18481da177e4SLinus Torvalds }
18491da177e4SLinus Torvalds
185040346005SJan Kara /*
185140346005SJan Kara * Check whether there is an anchor block in the given block and
185240346005SJan Kara * load Volume Descriptor Sequence if so.
1853d759bfa4SJan Kara *
1854d759bfa4SJan Kara * Returns <0 on error, 0 on success, -EAGAIN is special - try next anchor
1855d759bfa4SJan Kara * block
185640346005SJan Kara */
udf_check_anchor_block(struct super_block * sb,sector_t block,struct kernel_lb_addr * fileset)185740346005SJan Kara static int udf_check_anchor_block(struct super_block *sb, sector_t block,
185840346005SJan Kara struct kernel_lb_addr *fileset)
185940346005SJan Kara {
186040346005SJan Kara struct buffer_head *bh;
186140346005SJan Kara uint16_t ident;
186240346005SJan Kara int ret;
186340346005SJan Kara
186440346005SJan Kara bh = udf_read_tagged(sb, block, block, &ident);
186540346005SJan Kara if (!bh)
1866d759bfa4SJan Kara return -EAGAIN;
186740346005SJan Kara if (ident != TAG_IDENT_AVDP) {
186840346005SJan Kara brelse(bh);
1869d759bfa4SJan Kara return -EAGAIN;
187040346005SJan Kara }
187140346005SJan Kara ret = udf_load_sequence(sb, bh, fileset);
187240346005SJan Kara brelse(bh);
187340346005SJan Kara return ret;
187440346005SJan Kara }
187540346005SJan Kara
1876d759bfa4SJan Kara /*
1877d759bfa4SJan Kara * Search for an anchor volume descriptor pointer.
1878d759bfa4SJan Kara *
1879d759bfa4SJan Kara * Returns < 0 on error, 0 on success. -EAGAIN is special - try next set
1880d759bfa4SJan Kara * of anchors.
1881d759bfa4SJan Kara */
udf_scan_anchors(struct super_block * sb,udf_pblk_t * lastblock,struct kernel_lb_addr * fileset)1882bd904f3cSJan Kara static int udf_scan_anchors(struct super_block *sb, udf_pblk_t *lastblock,
188340346005SJan Kara struct kernel_lb_addr *fileset)
188440346005SJan Kara {
1885bd904f3cSJan Kara udf_pblk_t last[6];
188640346005SJan Kara int i;
188740346005SJan Kara struct udf_sb_info *sbi = UDF_SB(sb);
188840346005SJan Kara int last_count = 0;
1889d759bfa4SJan Kara int ret;
189040346005SJan Kara
189140346005SJan Kara /* First try user provided anchor */
189240346005SJan Kara if (sbi->s_anchor) {
1893d759bfa4SJan Kara ret = udf_check_anchor_block(sb, sbi->s_anchor, fileset);
1894d759bfa4SJan Kara if (ret != -EAGAIN)
1895d759bfa4SJan Kara return ret;
189640346005SJan Kara }
189740346005SJan Kara /*
189840346005SJan Kara * according to spec, anchor is in either:
189940346005SJan Kara * block 256
190040346005SJan Kara * lastblock-256
190140346005SJan Kara * lastblock
190240346005SJan Kara * however, if the disc isn't closed, it could be 512.
190340346005SJan Kara */
1904d759bfa4SJan Kara ret = udf_check_anchor_block(sb, sbi->s_session + 256, fileset);
1905d759bfa4SJan Kara if (ret != -EAGAIN)
1906d759bfa4SJan Kara return ret;
190740346005SJan Kara /*
190840346005SJan Kara * The trouble is which block is the last one. Drives often misreport
190940346005SJan Kara * this so we try various possibilities.
191040346005SJan Kara */
1911d759bfa4SJan Kara last[last_count++] = *lastblock;
1912d759bfa4SJan Kara if (*lastblock >= 1)
1913d759bfa4SJan Kara last[last_count++] = *lastblock - 1;
1914d759bfa4SJan Kara last[last_count++] = *lastblock + 1;
1915d759bfa4SJan Kara if (*lastblock >= 2)
1916d759bfa4SJan Kara last[last_count++] = *lastblock - 2;
1917d759bfa4SJan Kara if (*lastblock >= 150)
1918d759bfa4SJan Kara last[last_count++] = *lastblock - 150;
1919d759bfa4SJan Kara if (*lastblock >= 152)
1920d759bfa4SJan Kara last[last_count++] = *lastblock - 152;
192140346005SJan Kara
192240346005SJan Kara for (i = 0; i < last_count; i++) {
1923e4ae4735SChristoph Hellwig if (last[i] >= sb_bdev_nr_blocks(sb))
192440346005SJan Kara continue;
1925d759bfa4SJan Kara ret = udf_check_anchor_block(sb, last[i], fileset);
1926d759bfa4SJan Kara if (ret != -EAGAIN) {
1927d759bfa4SJan Kara if (!ret)
1928d759bfa4SJan Kara *lastblock = last[i];
1929d759bfa4SJan Kara return ret;
1930d759bfa4SJan Kara }
193140346005SJan Kara if (last[i] < 256)
193240346005SJan Kara continue;
1933d759bfa4SJan Kara ret = udf_check_anchor_block(sb, last[i] - 256, fileset);
1934d759bfa4SJan Kara if (ret != -EAGAIN) {
1935d759bfa4SJan Kara if (!ret)
1936d759bfa4SJan Kara *lastblock = last[i];
1937d759bfa4SJan Kara return ret;
1938d759bfa4SJan Kara }
193940346005SJan Kara }
194040346005SJan Kara
194140346005SJan Kara /* Finally try block 512 in case media is open */
1942d759bfa4SJan Kara return udf_check_anchor_block(sb, sbi->s_session + 512, fileset);
194340346005SJan Kara }
194440346005SJan Kara
194540346005SJan Kara /*
194640346005SJan Kara * Check Volume Structure Descriptor, find Anchor block and load Volume
1947d759bfa4SJan Kara * Descriptor Sequence.
1948d759bfa4SJan Kara *
1949d759bfa4SJan Kara * Returns < 0 on error, 0 on success. -EAGAIN is special meaning anchor
1950d759bfa4SJan Kara * block was not found.
195140346005SJan Kara */
udf_load_vrs(struct super_block * sb,struct udf_options * uopt,int silent,struct kernel_lb_addr * fileset)195240346005SJan Kara static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt,
195340346005SJan Kara int silent, struct kernel_lb_addr *fileset)
195440346005SJan Kara {
195540346005SJan Kara struct udf_sb_info *sbi = UDF_SB(sb);
1956ba54aef0SSteven J. Magnani int nsr = 0;
1957d759bfa4SJan Kara int ret;
195840346005SJan Kara
195940346005SJan Kara if (!sb_set_blocksize(sb, uopt->blocksize)) {
196040346005SJan Kara if (!silent)
196178ace70cSJoe Perches udf_warn(sb, "Bad block size\n");
1962d759bfa4SJan Kara return -EINVAL;
19631da177e4SLinus Torvalds }
196440346005SJan Kara sbi->s_last_block = uopt->lastblock;
196540346005SJan Kara if (!uopt->novrs) {
196640346005SJan Kara /* Check that it is NSR02 compliant */
1967ba54aef0SSteven J. Magnani nsr = udf_check_vsd(sb);
1968ba54aef0SSteven J. Magnani if (!nsr) {
196940346005SJan Kara if (!silent)
197078ace70cSJoe Perches udf_warn(sb, "No VRS found\n");
197170f16cefSFabian Frederick return -EINVAL;
197240346005SJan Kara }
1973ba54aef0SSteven J. Magnani if (nsr == -1)
197444499602SPeter A. Felvegi udf_debug("Failed to read sector at offset %d. "
197544499602SPeter A. Felvegi "Assuming open disc. Skipping validity "
197644499602SPeter A. Felvegi "check\n", VSD_FIRST_SECTOR_OFFSET);
197740346005SJan Kara if (!sbi->s_last_block)
197840346005SJan Kara sbi->s_last_block = udf_get_last_block(sb);
197940346005SJan Kara } else {
198040346005SJan Kara udf_debug("Validity check skipped because of novrs option\n");
198140346005SJan Kara }
198240346005SJan Kara
198340346005SJan Kara /* Look for anchor block and load Volume Descriptor Sequence */
198440346005SJan Kara sbi->s_anchor = uopt->anchor;
1985101ee137SJan Kara ret = udf_scan_anchors(sb, &sbi->s_last_block, fileset);
1986d759bfa4SJan Kara if (ret < 0) {
1987d759bfa4SJan Kara if (!silent && ret == -EAGAIN)
198878ace70cSJoe Perches udf_warn(sb, "No anchor found\n");
1989d759bfa4SJan Kara return ret;
199040346005SJan Kara }
1991d759bfa4SJan Kara return 0;
199240346005SJan Kara }
19931da177e4SLinus Torvalds
udf_finalize_lvid(struct logicalVolIntegrityDesc * lvid)1994ebbd5e99SSteve Magnani static void udf_finalize_lvid(struct logicalVolIntegrityDesc *lvid)
1995ebbd5e99SSteve Magnani {
1996ebbd5e99SSteve Magnani struct timespec64 ts;
1997ebbd5e99SSteve Magnani
1998ebbd5e99SSteve Magnani ktime_get_real_ts64(&ts);
1999ebbd5e99SSteve Magnani udf_time_to_disk_stamp(&lvid->recordingDateAndTime, ts);
2000ebbd5e99SSteve Magnani lvid->descTag.descCRC = cpu_to_le16(
2001ebbd5e99SSteve Magnani crc_itu_t(0, (char *)lvid + sizeof(struct tag),
2002ebbd5e99SSteve Magnani le16_to_cpu(lvid->descTag.descCRCLength)));
2003ebbd5e99SSteve Magnani lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
2004ebbd5e99SSteve Magnani }
2005ebbd5e99SSteve Magnani
udf_open_lvid(struct super_block * sb)20061da177e4SLinus Torvalds static void udf_open_lvid(struct super_block *sb)
20071da177e4SLinus Torvalds {
20086c79e987SMarcin Slusarz struct udf_sb_info *sbi = UDF_SB(sb);
20096c79e987SMarcin Slusarz struct buffer_head *bh = sbi->s_lvid_bh;
2010165923faSMarcin Slusarz struct logicalVolIntegrityDesc *lvid;
2011165923faSMarcin Slusarz struct logicalVolIntegrityDescImpUse *lvidiu;
2012146bca72SJan Kara
2013165923faSMarcin Slusarz if (!bh)
2014165923faSMarcin Slusarz return;
201569d75671SJan Kara lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
201669d75671SJan Kara lvidiu = udf_sb_lvidiu(sb);
201769d75671SJan Kara if (!lvidiu)
201869d75671SJan Kara return;
2019949f4a7cSJan Kara
2020949f4a7cSJan Kara mutex_lock(&sbi->s_alloc_mutex);
20216c79e987SMarcin Slusarz lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
20226c79e987SMarcin Slusarz lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
2023b72e632cSJan Kara if (le32_to_cpu(lvid->integrityType) == LVID_INTEGRITY_TYPE_CLOSE)
2024146bca72SJan Kara lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN);
2025b72e632cSJan Kara else
2026b72e632cSJan Kara UDF_SET_FLAG(sb, UDF_FLAG_INCONSISTENT);
20271da177e4SLinus Torvalds
2028ebbd5e99SSteve Magnani udf_finalize_lvid(lvid);
20296c79e987SMarcin Slusarz mark_buffer_dirty(bh);
2030146bca72SJan Kara sbi->s_lvid_dirty = 0;
2031949f4a7cSJan Kara mutex_unlock(&sbi->s_alloc_mutex);
20329734c971SJan Kara /* Make opening of filesystem visible on the media immediately */
20339734c971SJan Kara sync_dirty_buffer(bh);
20341da177e4SLinus Torvalds }
20351da177e4SLinus Torvalds
udf_close_lvid(struct super_block * sb)20361da177e4SLinus Torvalds static void udf_close_lvid(struct super_block *sb)
20371da177e4SLinus Torvalds {
20386c79e987SMarcin Slusarz struct udf_sb_info *sbi = UDF_SB(sb);
20396c79e987SMarcin Slusarz struct buffer_head *bh = sbi->s_lvid_bh;
20406c79e987SMarcin Slusarz struct logicalVolIntegrityDesc *lvid;
2041165923faSMarcin Slusarz struct logicalVolIntegrityDescImpUse *lvidiu;
204228de7948SCyrill Gorcunov
20436c79e987SMarcin Slusarz if (!bh)
20446c79e987SMarcin Slusarz return;
204569d75671SJan Kara lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
204669d75671SJan Kara lvidiu = udf_sb_lvidiu(sb);
204769d75671SJan Kara if (!lvidiu)
204869d75671SJan Kara return;
20496c79e987SMarcin Slusarz
2050949f4a7cSJan Kara mutex_lock(&sbi->s_alloc_mutex);
20516c79e987SMarcin Slusarz lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
20526c79e987SMarcin Slusarz lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
20536c79e987SMarcin Slusarz if (UDF_MAX_WRITE_VERSION > le16_to_cpu(lvidiu->maxUDFWriteRev))
2054165923faSMarcin Slusarz lvidiu->maxUDFWriteRev = cpu_to_le16(UDF_MAX_WRITE_VERSION);
20556c79e987SMarcin Slusarz if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFReadRev))
20566c79e987SMarcin Slusarz lvidiu->minUDFReadRev = cpu_to_le16(sbi->s_udfrev);
20576c79e987SMarcin Slusarz if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFWriteRev))
20586c79e987SMarcin Slusarz lvidiu->minUDFWriteRev = cpu_to_le16(sbi->s_udfrev);
2059b72e632cSJan Kara if (!UDF_QUERY_FLAG(sb, UDF_FLAG_INCONSISTENT))
20606c79e987SMarcin Slusarz lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE);
20611da177e4SLinus Torvalds
2062853a0c25SJan Kara /*
2063853a0c25SJan Kara * We set buffer uptodate unconditionally here to avoid spurious
2064853a0c25SJan Kara * warnings from mark_buffer_dirty() when previous EIO has marked
2065853a0c25SJan Kara * the buffer as !uptodate
2066853a0c25SJan Kara */
2067853a0c25SJan Kara set_buffer_uptodate(bh);
2068ebbd5e99SSteve Magnani udf_finalize_lvid(lvid);
20696c79e987SMarcin Slusarz mark_buffer_dirty(bh);
2070146bca72SJan Kara sbi->s_lvid_dirty = 0;
2071949f4a7cSJan Kara mutex_unlock(&sbi->s_alloc_mutex);
20729734c971SJan Kara /* Make closing of filesystem visible on the media immediately */
20739734c971SJan Kara sync_dirty_buffer(bh);
20741da177e4SLinus Torvalds }
20751da177e4SLinus Torvalds
lvid_get_unique_id(struct super_block * sb)2076d664b6afSJan Kara u64 lvid_get_unique_id(struct super_block *sb)
2077d664b6afSJan Kara {
2078d664b6afSJan Kara struct buffer_head *bh;
2079d664b6afSJan Kara struct udf_sb_info *sbi = UDF_SB(sb);
2080d664b6afSJan Kara struct logicalVolIntegrityDesc *lvid;
2081d664b6afSJan Kara struct logicalVolHeaderDesc *lvhd;
2082d664b6afSJan Kara u64 uniqueID;
2083d664b6afSJan Kara u64 ret;
2084d664b6afSJan Kara
2085d664b6afSJan Kara bh = sbi->s_lvid_bh;
2086d664b6afSJan Kara if (!bh)
2087d664b6afSJan Kara return 0;
2088d664b6afSJan Kara
2089d664b6afSJan Kara lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
2090d664b6afSJan Kara lvhd = (struct logicalVolHeaderDesc *)lvid->logicalVolContentsUse;
2091d664b6afSJan Kara
2092d664b6afSJan Kara mutex_lock(&sbi->s_alloc_mutex);
2093d664b6afSJan Kara ret = uniqueID = le64_to_cpu(lvhd->uniqueID);
2094d664b6afSJan Kara if (!(++uniqueID & 0xFFFFFFFF))
2095d664b6afSJan Kara uniqueID += 16;
2096d664b6afSJan Kara lvhd->uniqueID = cpu_to_le64(uniqueID);
2097e8b42747SSteve Magnani udf_updated_lvid(sb);
2098d664b6afSJan Kara mutex_unlock(&sbi->s_alloc_mutex);
2099d664b6afSJan Kara
2100d664b6afSJan Kara return ret;
21011da177e4SLinus Torvalds }
21021da177e4SLinus Torvalds
udf_fill_super(struct super_block * sb,void * options,int silent)21031da177e4SLinus Torvalds static int udf_fill_super(struct super_block *sb, void *options, int silent)
21041da177e4SLinus Torvalds {
2105d759bfa4SJan Kara int ret = -EINVAL;
21061da177e4SLinus Torvalds struct inode *inode = NULL;
21071da177e4SLinus Torvalds struct udf_options uopt;
21085ca4e4beSPekka Enberg struct kernel_lb_addr rootdir, fileset;
21091da177e4SLinus Torvalds struct udf_sb_info *sbi;
21109181f8bfSJan Kara bool lvid_open = false;
21111da177e4SLinus Torvalds
21121da177e4SLinus Torvalds uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT);
2113116e5258SJan Kara /* By default we'll use overflow[ug]id when UDF inode [ug]id == -1 */
2114116e5258SJan Kara uopt.uid = make_kuid(current_user_ns(), overflowuid);
2115116e5258SJan Kara uopt.gid = make_kgid(current_user_ns(), overflowgid);
21161da177e4SLinus Torvalds uopt.umask = 0;
211787bc730cSMarcin Slusarz uopt.fmode = UDF_INVALID_MODE;
211887bc730cSMarcin Slusarz uopt.dmode = UDF_INVALID_MODE;
2119785dffe1SChengguang Xu uopt.nls_map = NULL;
21201da177e4SLinus Torvalds
2121033c9da0SMarkus Elfring sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
21229db9f9e3SAlessio Igor Bogani if (!sbi)
21231da177e4SLinus Torvalds return -ENOMEM;
212428de7948SCyrill Gorcunov
21251da177e4SLinus Torvalds sb->s_fs_info = sbi;
21261da177e4SLinus Torvalds
21271e7933deSIngo Molnar mutex_init(&sbi->s_alloc_mutex);
21281da177e4SLinus Torvalds
21296da80894SMiklos Szeredi if (!udf_parse_options((char *)options, &uopt, false))
2130fdf2657bSMarkus Elfring goto parse_options_failure;
21311da177e4SLinus Torvalds
21321da177e4SLinus Torvalds fileset.logicalBlockNum = 0xFFFFFFFF;
21331da177e4SLinus Torvalds fileset.partitionReferenceNum = 0xFFFF;
21341da177e4SLinus Torvalds
21356c79e987SMarcin Slusarz sbi->s_flags = uopt.flags;
21366c79e987SMarcin Slusarz sbi->s_uid = uopt.uid;
21376c79e987SMarcin Slusarz sbi->s_gid = uopt.gid;
21386c79e987SMarcin Slusarz sbi->s_umask = uopt.umask;
21397ac9bcd5SMarcin Slusarz sbi->s_fmode = uopt.fmode;
21407ac9bcd5SMarcin Slusarz sbi->s_dmode = uopt.dmode;
21416c79e987SMarcin Slusarz sbi->s_nls_map = uopt.nls_map;
2142c03cad24SJan Kara rwlock_init(&sbi->s_cred_lock);
21431da177e4SLinus Torvalds
21441da177e4SLinus Torvalds if (uopt.session == 0xFFFFFFFF)
21456c79e987SMarcin Slusarz sbi->s_session = udf_get_last_session(sb);
21461da177e4SLinus Torvalds else
21476c79e987SMarcin Slusarz sbi->s_session = uopt.session;
21481da177e4SLinus Torvalds
21496c79e987SMarcin Slusarz udf_debug("Multi-session=%d\n", sbi->s_session);
21501da177e4SLinus Torvalds
21511da177e4SLinus Torvalds /* Fill in the rest of the superblock */
21521da177e4SLinus Torvalds sb->s_op = &udf_sb_ops;
2153221e583aSRasmus Rohde sb->s_export_op = &udf_export_ops;
2154123e9cafSChristoph Hellwig
21551da177e4SLinus Torvalds sb->s_magic = UDF_SUPER_MAGIC;
21561da177e4SLinus Torvalds sb->s_time_gran = 1000;
21571da177e4SLinus Torvalds
215840346005SJan Kara if (uopt.flags & (1 << UDF_FLAG_BLOCKSIZE_SET)) {
215940346005SJan Kara ret = udf_load_vrs(sb, &uopt, silent, &fileset);
216040346005SJan Kara } else {
2161e1defc4fSMartin K. Petersen uopt.blocksize = bdev_logical_block_size(sb->s_bdev);
216270f16cefSFabian Frederick while (uopt.blocksize <= 4096) {
216340346005SJan Kara ret = udf_load_vrs(sb, &uopt, silent, &fileset);
216470f16cefSFabian Frederick if (ret < 0) {
216570f16cefSFabian Frederick if (!silent && ret != -EACCES) {
2166fcbf7637SSteve Magnani pr_notice("Scanning with blocksize %u failed\n",
216770f16cefSFabian Frederick uopt.blocksize);
216870f16cefSFabian Frederick }
2169dc141a40SAshish Sangwan brelse(sbi->s_lvid_bh);
2170dc141a40SAshish Sangwan sbi->s_lvid_bh = NULL;
217170f16cefSFabian Frederick /*
217270f16cefSFabian Frederick * EACCES is special - we want to propagate to
217370f16cefSFabian Frederick * upper layers that we cannot handle RW mount.
217470f16cefSFabian Frederick */
217570f16cefSFabian Frederick if (ret == -EACCES)
217670f16cefSFabian Frederick break;
217770f16cefSFabian Frederick } else
217870f16cefSFabian Frederick break;
217970f16cefSFabian Frederick
218070f16cefSFabian Frederick uopt.blocksize <<= 1;
218140346005SJan Kara }
218240346005SJan Kara }
2183d759bfa4SJan Kara if (ret < 0) {
2184d759bfa4SJan Kara if (ret == -EAGAIN) {
218578ace70cSJoe Perches udf_warn(sb, "No partition found (1)\n");
2186d759bfa4SJan Kara ret = -EINVAL;
2187d759bfa4SJan Kara }
21881da177e4SLinus Torvalds goto error_out;
21891da177e4SLinus Torvalds }
21901da177e4SLinus Torvalds
2191fcbf7637SSteve Magnani udf_debug("Lastblock=%u\n", sbi->s_last_block);
21921da177e4SLinus Torvalds
21936c79e987SMarcin Slusarz if (sbi->s_lvid_bh) {
21944b11111aSMarcin Slusarz struct logicalVolIntegrityDescImpUse *lvidiu =
219569d75671SJan Kara udf_sb_lvidiu(sb);
219669d75671SJan Kara uint16_t minUDFReadRev;
219769d75671SJan Kara uint16_t minUDFWriteRev;
21981da177e4SLinus Torvalds
219969d75671SJan Kara if (!lvidiu) {
220069d75671SJan Kara ret = -EINVAL;
220169d75671SJan Kara goto error_out;
220269d75671SJan Kara }
220369d75671SJan Kara minUDFReadRev = le16_to_cpu(lvidiu->minUDFReadRev);
220469d75671SJan Kara minUDFWriteRev = le16_to_cpu(lvidiu->minUDFWriteRev);
2205cb00ea35SCyrill Gorcunov if (minUDFReadRev > UDF_MAX_READ_VERSION) {
220678ace70cSJoe Perches udf_err(sb, "minUDFReadRev=%x (max is %x)\n",
220769d75671SJan Kara minUDFReadRev,
22081da177e4SLinus Torvalds UDF_MAX_READ_VERSION);
2209d759bfa4SJan Kara ret = -EINVAL;
22101da177e4SLinus Torvalds goto error_out;
2211a9ad01bcSJan Kara } else if (minUDFWriteRev > UDF_MAX_WRITE_VERSION) {
2212a9ad01bcSJan Kara if (!sb_rdonly(sb)) {
2213e729eac6SJan Kara ret = -EACCES;
2214e729eac6SJan Kara goto error_out;
2215e729eac6SJan Kara }
2216a9ad01bcSJan Kara UDF_SET_FLAG(sb, UDF_FLAG_RW_INCOMPAT);
2217a9ad01bcSJan Kara }
22181da177e4SLinus Torvalds
22196c79e987SMarcin Slusarz sbi->s_udfrev = minUDFWriteRev;
22201da177e4SLinus Torvalds
22211da177e4SLinus Torvalds if (minUDFReadRev >= UDF_VERS_USE_EXTENDED_FE)
22221da177e4SLinus Torvalds UDF_SET_FLAG(sb, UDF_FLAG_USE_EXTENDED_FE);
22231da177e4SLinus Torvalds if (minUDFReadRev >= UDF_VERS_USE_STREAMS)
22241da177e4SLinus Torvalds UDF_SET_FLAG(sb, UDF_FLAG_USE_STREAMS);
22251da177e4SLinus Torvalds }
22261da177e4SLinus Torvalds
22276c79e987SMarcin Slusarz if (!sbi->s_partitions) {
222878ace70cSJoe Perches udf_warn(sb, "No partition found (2)\n");
2229d759bfa4SJan Kara ret = -EINVAL;
22301da177e4SLinus Torvalds goto error_out;
22311da177e4SLinus Torvalds }
22321da177e4SLinus Torvalds
22334b11111aSMarcin Slusarz if (sbi->s_partmaps[sbi->s_partition].s_partition_flags &
2234a9ad01bcSJan Kara UDF_PART_FLAG_READ_ONLY) {
2235a9ad01bcSJan Kara if (!sb_rdonly(sb)) {
2236e729eac6SJan Kara ret = -EACCES;
2237e729eac6SJan Kara goto error_out;
2238c1a26e7dSPeter Osterlund }
2239a9ad01bcSJan Kara UDF_SET_FLAG(sb, UDF_FLAG_RW_INCOMPAT);
2240a9ad01bcSJan Kara }
224139b3f6d6SEric Sandeen
22422dee5aacSJan Kara ret = udf_find_fileset(sb, &fileset, &rootdir);
22432dee5aacSJan Kara if (ret < 0) {
224478ace70cSJoe Perches udf_warn(sb, "No fileset found\n");
22451da177e4SLinus Torvalds goto error_out;
22461da177e4SLinus Torvalds }
22471da177e4SLinus Torvalds
2248cb00ea35SCyrill Gorcunov if (!silent) {
22495ca4e4beSPekka Enberg struct timestamp ts;
225056774805SMarcin Slusarz udf_time_to_disk_stamp(&ts, sbi->s_record_time);
225178ace70cSJoe Perches udf_info("Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
225278ace70cSJoe Perches sbi->s_volume_ident,
225378ace70cSJoe Perches le16_to_cpu(ts.year), ts.month, ts.day,
225456774805SMarcin Slusarz ts.hour, ts.minute, le16_to_cpu(ts.typeAndTimezone));
22551da177e4SLinus Torvalds }
2256bc98a42cSDavid Howells if (!sb_rdonly(sb)) {
22571da177e4SLinus Torvalds udf_open_lvid(sb);
22589181f8bfSJan Kara lvid_open = true;
22599181f8bfSJan Kara }
22601da177e4SLinus Torvalds
22611da177e4SLinus Torvalds /* Assign the root inode */
22621da177e4SLinus Torvalds /* assign inodes by physical block number */
22631da177e4SLinus Torvalds /* perhaps it's not extensible enough, but for now ... */
226497e961fdSPekka Enberg inode = udf_iget(sb, &rootdir);
22656d3d5e86SJan Kara if (IS_ERR(inode)) {
2266fcbf7637SSteve Magnani udf_err(sb, "Error in udf_iget, block=%u, partition=%u\n",
22671da177e4SLinus Torvalds rootdir.logicalBlockNum, rootdir.partitionReferenceNum);
22686d3d5e86SJan Kara ret = PTR_ERR(inode);
22691da177e4SLinus Torvalds goto error_out;
22701da177e4SLinus Torvalds }
22711da177e4SLinus Torvalds
22721da177e4SLinus Torvalds /* Allocate a dentry for the root inode */
227348fde701SAl Viro sb->s_root = d_make_root(inode);
2274cb00ea35SCyrill Gorcunov if (!sb->s_root) {
227578ace70cSJoe Perches udf_err(sb, "Couldn't allocate root dentry\n");
2276d759bfa4SJan Kara ret = -ENOMEM;
22771da177e4SLinus Torvalds goto error_out;
22781da177e4SLinus Torvalds }
2279c2efd13aSJan Kara sb->s_maxbytes = UDF_MAX_FILESIZE;
22808de52778SAl Viro sb->s_max_links = UDF_MAX_LINKS;
22811da177e4SLinus Torvalds return 0;
22821da177e4SLinus Torvalds
22831da177e4SLinus Torvalds error_out:
22846c79e987SMarcin Slusarz iput(sbi->s_vat_inode);
2285fdf2657bSMarkus Elfring parse_options_failure:
2286785dffe1SChengguang Xu unload_nls(uopt.nls_map);
22879181f8bfSJan Kara if (lvid_open)
22881da177e4SLinus Torvalds udf_close_lvid(sb);
22896c79e987SMarcin Slusarz brelse(sbi->s_lvid_bh);
2290bff943afSJan Kara udf_sb_free_partitions(sb);
22911da177e4SLinus Torvalds kfree(sbi);
22921da177e4SLinus Torvalds sb->s_fs_info = NULL;
229328de7948SCyrill Gorcunov
2294d759bfa4SJan Kara return ret;
22951da177e4SLinus Torvalds }
22961da177e4SLinus Torvalds
_udf_err(struct super_block * sb,const char * function,const char * fmt,...)22978076c363SJoe Perches void _udf_err(struct super_block *sb, const char *function,
22981da177e4SLinus Torvalds const char *fmt, ...)
22991da177e4SLinus Torvalds {
2300c2bff36cSJoe Perches struct va_format vaf;
23011da177e4SLinus Torvalds va_list args;
23021da177e4SLinus Torvalds
23031da177e4SLinus Torvalds va_start(args, fmt);
2304c2bff36cSJoe Perches
2305c2bff36cSJoe Perches vaf.fmt = fmt;
2306c2bff36cSJoe Perches vaf.va = &args;
2307c2bff36cSJoe Perches
2308c2bff36cSJoe Perches pr_err("error (device %s): %s: %pV", sb->s_id, function, &vaf);
2309c2bff36cSJoe Perches
23101da177e4SLinus Torvalds va_end(args);
23111da177e4SLinus Torvalds }
23121da177e4SLinus Torvalds
_udf_warn(struct super_block * sb,const char * function,const char * fmt,...)2313a40ecd7bSJoe Perches void _udf_warn(struct super_block *sb, const char *function,
23141da177e4SLinus Torvalds const char *fmt, ...)
23151da177e4SLinus Torvalds {
2316c2bff36cSJoe Perches struct va_format vaf;
23171da177e4SLinus Torvalds va_list args;
23181da177e4SLinus Torvalds
23191da177e4SLinus Torvalds va_start(args, fmt);
2320c2bff36cSJoe Perches
2321c2bff36cSJoe Perches vaf.fmt = fmt;
2322c2bff36cSJoe Perches vaf.va = &args;
2323c2bff36cSJoe Perches
2324c2bff36cSJoe Perches pr_warn("warning (device %s): %s: %pV", sb->s_id, function, &vaf);
2325c2bff36cSJoe Perches
23261da177e4SLinus Torvalds va_end(args);
23271da177e4SLinus Torvalds }
23281da177e4SLinus Torvalds
udf_put_super(struct super_block * sb)2329cb00ea35SCyrill Gorcunov static void udf_put_super(struct super_block *sb)
23301da177e4SLinus Torvalds {
23316c79e987SMarcin Slusarz struct udf_sb_info *sbi;
23321da177e4SLinus Torvalds
23336c79e987SMarcin Slusarz sbi = UDF_SB(sb);
23346cfd0148SChristoph Hellwig
23356c79e987SMarcin Slusarz iput(sbi->s_vat_inode);
23366c79e987SMarcin Slusarz unload_nls(sbi->s_nls_map);
2337bc98a42cSDavid Howells if (!sb_rdonly(sb))
23381da177e4SLinus Torvalds udf_close_lvid(sb);
23396c79e987SMarcin Slusarz brelse(sbi->s_lvid_bh);
2340bff943afSJan Kara udf_sb_free_partitions(sb);
2341bbe48dd8SFabian Frederick mutex_destroy(&sbi->s_alloc_mutex);
23421da177e4SLinus Torvalds kfree(sb->s_fs_info);
23431da177e4SLinus Torvalds sb->s_fs_info = NULL;
23441da177e4SLinus Torvalds }
23451da177e4SLinus Torvalds
udf_sync_fs(struct super_block * sb,int wait)2346146bca72SJan Kara static int udf_sync_fs(struct super_block *sb, int wait)
2347146bca72SJan Kara {
2348146bca72SJan Kara struct udf_sb_info *sbi = UDF_SB(sb);
2349146bca72SJan Kara
2350146bca72SJan Kara mutex_lock(&sbi->s_alloc_mutex);
2351146bca72SJan Kara if (sbi->s_lvid_dirty) {
2352e8b42747SSteve Magnani struct buffer_head *bh = sbi->s_lvid_bh;
2353e8b42747SSteve Magnani struct logicalVolIntegrityDesc *lvid;
2354e8b42747SSteve Magnani
2355e8b42747SSteve Magnani lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
2356e8b42747SSteve Magnani udf_finalize_lvid(lvid);
2357e8b42747SSteve Magnani
2358146bca72SJan Kara /*
2359146bca72SJan Kara * Blockdevice will be synced later so we don't have to submit
2360146bca72SJan Kara * the buffer for IO
2361146bca72SJan Kara */
2362e8b42747SSteve Magnani mark_buffer_dirty(bh);
2363146bca72SJan Kara sbi->s_lvid_dirty = 0;
2364146bca72SJan Kara }
2365146bca72SJan Kara mutex_unlock(&sbi->s_alloc_mutex);
2366146bca72SJan Kara
2367146bca72SJan Kara return 0;
2368146bca72SJan Kara }
2369146bca72SJan Kara
udf_statfs(struct dentry * dentry,struct kstatfs * buf)2370cb00ea35SCyrill Gorcunov static int udf_statfs(struct dentry *dentry, struct kstatfs *buf)
23711da177e4SLinus Torvalds {
2372726c3342SDavid Howells struct super_block *sb = dentry->d_sb;
23736c79e987SMarcin Slusarz struct udf_sb_info *sbi = UDF_SB(sb);
23746c79e987SMarcin Slusarz struct logicalVolIntegrityDescImpUse *lvidiu;
2375557f5a14SColy Li u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
23766c79e987SMarcin Slusarz
237769d75671SJan Kara lvidiu = udf_sb_lvidiu(sb);
23781da177e4SLinus Torvalds buf->f_type = UDF_SUPER_MAGIC;
23791da177e4SLinus Torvalds buf->f_bsize = sb->s_blocksize;
23806c79e987SMarcin Slusarz buf->f_blocks = sbi->s_partmaps[sbi->s_partition].s_partition_len;
23811da177e4SLinus Torvalds buf->f_bfree = udf_count_free(sb);
23821da177e4SLinus Torvalds buf->f_bavail = buf->f_bfree;
2383356557beSJan Kara /*
2384356557beSJan Kara * Let's pretend each free block is also a free 'inode' since UDF does
2385356557beSJan Kara * not have separate preallocated table of inodes.
2386356557beSJan Kara */
23876c79e987SMarcin Slusarz buf->f_files = (lvidiu != NULL ? (le32_to_cpu(lvidiu->numFiles) +
23886c79e987SMarcin Slusarz le32_to_cpu(lvidiu->numDirs)) : 0)
23896c79e987SMarcin Slusarz + buf->f_bfree;
23901da177e4SLinus Torvalds buf->f_ffree = buf->f_bfree;
23919fba7056SAndrew Gabbasov buf->f_namelen = UDF_NAME_LEN;
23926d1349c7SAl Viro buf->f_fsid = u64_to_fsid(id);
23931da177e4SLinus Torvalds
23941da177e4SLinus Torvalds return 0;
23951da177e4SLinus Torvalds }
23961da177e4SLinus Torvalds
udf_count_free_bitmap(struct super_block * sb,struct udf_bitmap * bitmap)23974b11111aSMarcin Slusarz static unsigned int udf_count_free_bitmap(struct super_block *sb,
23984b11111aSMarcin Slusarz struct udf_bitmap *bitmap)
23991da177e4SLinus Torvalds {
24001da177e4SLinus Torvalds struct buffer_head *bh = NULL;
24011da177e4SLinus Torvalds unsigned int accum = 0;
24021da177e4SLinus Torvalds int index;
2403b490bdd6SSteve Magnani udf_pblk_t block = 0, newblock;
24045ca4e4beSPekka Enberg struct kernel_lb_addr loc;
24051da177e4SLinus Torvalds uint32_t bytes;
24061da177e4SLinus Torvalds uint8_t *ptr;
24071da177e4SLinus Torvalds uint16_t ident;
24081da177e4SLinus Torvalds struct spaceBitmapDesc *bm;
24091da177e4SLinus Torvalds
24101da177e4SLinus Torvalds loc.logicalBlockNum = bitmap->s_extPosition;
24116c79e987SMarcin Slusarz loc.partitionReferenceNum = UDF_SB(sb)->s_partition;
241297e961fdSPekka Enberg bh = udf_read_ptagged(sb, &loc, 0, &ident);
24131da177e4SLinus Torvalds
2414cb00ea35SCyrill Gorcunov if (!bh) {
241578ace70cSJoe Perches udf_err(sb, "udf_count_free failed\n");
24161da177e4SLinus Torvalds goto out;
2417cb00ea35SCyrill Gorcunov } else if (ident != TAG_IDENT_SBD) {
24183bf25cb4SJan Kara brelse(bh);
241978ace70cSJoe Perches udf_err(sb, "udf_count_free failed\n");
24201da177e4SLinus Torvalds goto out;
24211da177e4SLinus Torvalds }
24221da177e4SLinus Torvalds
24231da177e4SLinus Torvalds bm = (struct spaceBitmapDesc *)bh->b_data;
24241da177e4SLinus Torvalds bytes = le32_to_cpu(bm->numOfBytes);
24251da177e4SLinus Torvalds index = sizeof(struct spaceBitmapDesc); /* offset in first block only */
24261da177e4SLinus Torvalds ptr = (uint8_t *)bh->b_data;
24271da177e4SLinus Torvalds
2428cb00ea35SCyrill Gorcunov while (bytes > 0) {
242901b954a3SMarcin Slusarz u32 cur_bytes = min_t(u32, bytes, sb->s_blocksize - index);
243001b954a3SMarcin Slusarz accum += bitmap_weight((const unsigned long *)(ptr + index),
243101b954a3SMarcin Slusarz cur_bytes * 8);
243201b954a3SMarcin Slusarz bytes -= cur_bytes;
2433cb00ea35SCyrill Gorcunov if (bytes) {
24343bf25cb4SJan Kara brelse(bh);
243597e961fdSPekka Enberg newblock = udf_get_lb_pblock(sb, &loc, ++block);
2436101ee137SJan Kara bh = sb_bread(sb, newblock);
2437cb00ea35SCyrill Gorcunov if (!bh) {
24381da177e4SLinus Torvalds udf_debug("read failed\n");
24391da177e4SLinus Torvalds goto out;
24401da177e4SLinus Torvalds }
24411da177e4SLinus Torvalds index = 0;
24421da177e4SLinus Torvalds ptr = (uint8_t *)bh->b_data;
24431da177e4SLinus Torvalds }
24441da177e4SLinus Torvalds }
24453bf25cb4SJan Kara brelse(bh);
24461da177e4SLinus Torvalds out:
24471da177e4SLinus Torvalds return accum;
24481da177e4SLinus Torvalds }
24491da177e4SLinus Torvalds
udf_count_free_table(struct super_block * sb,struct inode * table)24504b11111aSMarcin Slusarz static unsigned int udf_count_free_table(struct super_block *sb,
24514b11111aSMarcin Slusarz struct inode *table)
24521da177e4SLinus Torvalds {
24531da177e4SLinus Torvalds unsigned int accum = 0;
2454ff116fc8SJan Kara uint32_t elen;
24555ca4e4beSPekka Enberg struct kernel_lb_addr eloc;
2456ff116fc8SJan Kara struct extent_position epos;
2457*5fc8da4dSZhao Mengmeng int8_t etype;
24581da177e4SLinus Torvalds
2459d1668fe3SJan Kara mutex_lock(&UDF_SB(sb)->s_alloc_mutex);
2460c0b34438SMarcin Slusarz epos.block = UDF_I(table)->i_location;
2461ff116fc8SJan Kara epos.offset = sizeof(struct unallocSpaceEntry);
2462ff116fc8SJan Kara epos.bh = NULL;
24631da177e4SLinus Torvalds
2464*5fc8da4dSZhao Mengmeng while (udf_next_aext(table, &epos, &eloc, &elen, &etype, 1) > 0)
24651da177e4SLinus Torvalds accum += (elen >> table->i_sb->s_blocksize_bits);
24663a71fc5dSMarcin Slusarz
24673bf25cb4SJan Kara brelse(epos.bh);
2468d1668fe3SJan Kara mutex_unlock(&UDF_SB(sb)->s_alloc_mutex);
24691da177e4SLinus Torvalds
24701da177e4SLinus Torvalds return accum;
24711da177e4SLinus Torvalds }
24721da177e4SLinus Torvalds
udf_count_free(struct super_block * sb)2473cb00ea35SCyrill Gorcunov static unsigned int udf_count_free(struct super_block *sb)
24741da177e4SLinus Torvalds {
24751da177e4SLinus Torvalds unsigned int accum = 0;
2476a4a8b99eSJan Kara struct udf_sb_info *sbi = UDF_SB(sb);
24776c79e987SMarcin Slusarz struct udf_part_map *map;
2478a4a8b99eSJan Kara unsigned int part = sbi->s_partition;
2479a4a8b99eSJan Kara int ptype = sbi->s_partmaps[part].s_partition_type;
24801da177e4SLinus Torvalds
2481a4a8b99eSJan Kara if (ptype == UDF_METADATA_MAP25) {
2482a4a8b99eSJan Kara part = sbi->s_partmaps[part].s_type_specific.s_metadata.
2483a4a8b99eSJan Kara s_phys_partition_ref;
2484a4a8b99eSJan Kara } else if (ptype == UDF_VIRTUAL_MAP15 || ptype == UDF_VIRTUAL_MAP20) {
2485a4a8b99eSJan Kara /*
2486a4a8b99eSJan Kara * Filesystems with VAT are append-only and we cannot write to
2487a4a8b99eSJan Kara * them. Let's just report 0 here.
2488a4a8b99eSJan Kara */
2489a4a8b99eSJan Kara return 0;
2490a4a8b99eSJan Kara }
2491a4a8b99eSJan Kara
24926c79e987SMarcin Slusarz if (sbi->s_lvid_bh) {
24934b11111aSMarcin Slusarz struct logicalVolIntegrityDesc *lvid =
24944b11111aSMarcin Slusarz (struct logicalVolIntegrityDesc *)
24954b11111aSMarcin Slusarz sbi->s_lvid_bh->b_data;
2496a4a8b99eSJan Kara if (le32_to_cpu(lvid->numOfPartitions) > part) {
24974b11111aSMarcin Slusarz accum = le32_to_cpu(
2498a4a8b99eSJan Kara lvid->freeSpaceTable[part]);
24991da177e4SLinus Torvalds if (accum == 0xFFFFFFFF)
25001da177e4SLinus Torvalds accum = 0;
25011da177e4SLinus Torvalds }
25021da177e4SLinus Torvalds }
25031da177e4SLinus Torvalds
25041da177e4SLinus Torvalds if (accum)
25051da177e4SLinus Torvalds return accum;
25061da177e4SLinus Torvalds
2507a4a8b99eSJan Kara map = &sbi->s_partmaps[part];
25086c79e987SMarcin Slusarz if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) {
250928de7948SCyrill Gorcunov accum += udf_count_free_bitmap(sb,
25106c79e987SMarcin Slusarz map->s_uspace.s_bitmap);
25111da177e4SLinus Torvalds }
25121da177e4SLinus Torvalds if (accum)
25131da177e4SLinus Torvalds return accum;
25141da177e4SLinus Torvalds
25156c79e987SMarcin Slusarz if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) {
251628de7948SCyrill Gorcunov accum += udf_count_free_table(sb,
25176c79e987SMarcin Slusarz map->s_uspace.s_table);
25181da177e4SLinus Torvalds }
25191da177e4SLinus Torvalds return accum;
25201da177e4SLinus Torvalds }
252154bb60d5SFabian Frederick
252254bb60d5SFabian Frederick MODULE_AUTHOR("Ben Fennema");
252354bb60d5SFabian Frederick MODULE_DESCRIPTION("Universal Disk Format Filesystem");
252454bb60d5SFabian Frederick MODULE_LICENSE("GPL");
252554bb60d5SFabian Frederick module_init(init_udf_fs)
252654bb60d5SFabian Frederick module_exit(exit_udf_fs)
2527