diff options
Diffstat (limited to 'fs/udf')
| -rw-r--r-- | fs/udf/Kconfig | 1 | ||||
| -rw-r--r-- | fs/udf/balloc.c | 112 | ||||
| -rw-r--r-- | fs/udf/dir.c | 68 | ||||
| -rw-r--r-- | fs/udf/directory.c | 8 | ||||
| -rw-r--r-- | fs/udf/file.c | 108 | ||||
| -rw-r--r-- | fs/udf/ialloc.c | 34 | ||||
| -rw-r--r-- | fs/udf/inode.c | 574 | ||||
| -rw-r--r-- | fs/udf/lowlevel.c | 2 | ||||
| -rw-r--r-- | fs/udf/misc.c | 19 | ||||
| -rw-r--r-- | fs/udf/namei.c | 199 | ||||
| -rw-r--r-- | fs/udf/partition.c | 46 | ||||
| -rw-r--r-- | fs/udf/super.c | 1061 | ||||
| -rw-r--r-- | fs/udf/symlink.c | 26 | ||||
| -rw-r--r-- | fs/udf/truncate.c | 168 | ||||
| -rw-r--r-- | fs/udf/udf_i.h | 30 | ||||
| -rw-r--r-- | fs/udf/udf_sb.h | 46 | ||||
| -rw-r--r-- | fs/udf/udfdecl.h | 57 | ||||
| -rw-r--r-- | fs/udf/udftime.c | 3 | ||||
| -rw-r--r-- | fs/udf/unicode.c | 6 | 
19 files changed, 1483 insertions, 1085 deletions
diff --git a/fs/udf/Kconfig b/fs/udf/Kconfig index f8def3c8ea4..0e0e99bd6bc 100644 --- a/fs/udf/Kconfig +++ b/fs/udf/Kconfig @@ -1,6 +1,5 @@  config UDF_FS  	tristate "UDF file system support" -	depends on BKL # needs serious work to remove  	select CRC_ITU_T  	help  	  This is the new file system used on some CD-ROMs and DVDs. Say Y if diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c index b608efaa4ce..1ba2baaf436 100644 --- a/fs/udf/balloc.c +++ b/fs/udf/balloc.c @@ -27,11 +27,10 @@  #include "udf_i.h"  #include "udf_sb.h" -#define udf_clear_bit(nr, addr) ext2_clear_bit(nr, addr) -#define udf_set_bit(nr, addr) ext2_set_bit(nr, addr) -#define udf_test_bit(nr, addr) ext2_test_bit(nr, addr) -#define udf_find_next_one_bit(addr, size, offset) \ -		ext2_find_next_bit(addr, size, offset) +#define udf_clear_bit	__test_and_clear_bit_le +#define udf_set_bit	__test_and_set_bit_le +#define udf_test_bit	test_bit_le +#define udf_find_next_one_bit	find_next_bit_le  static int read_block_bitmap(struct super_block *sb,  			     struct udf_bitmap *bitmap, unsigned int block, @@ -60,8 +59,8 @@ static int __load_block_bitmap(struct super_block *sb,  	int nr_groups = bitmap->s_nr_groups;  	if (block_group >= nr_groups) { -		udf_debug("block_group (%d) > nr_groups (%d)\n", block_group, -			  nr_groups); +		udf_debug("block_group (%d) > nr_groups (%d)\n", +			  block_group, nr_groups);  	}  	if (bitmap->s_block_bitmap[block_group]) { @@ -106,7 +105,6 @@ static void udf_add_free_space(struct super_block *sb, u16 partition, u32 cnt)  }  static void udf_bitmap_free_blocks(struct super_block *sb, -				   struct inode *inode,  				   struct udf_bitmap *bitmap,  				   struct kernel_lb_addr *bloc,  				   uint32_t offset, @@ -127,8 +125,9 @@ static void udf_bitmap_free_blocks(struct super_block *sb,  	if (bloc->logicalBlockNum + count < count ||  	    (bloc->logicalBlockNum + count) > partmap->s_partition_len) {  		udf_debug("%d < %d || %d + %d > %d\n", -			  bloc->logicalBlockNum, 0, bloc->logicalBlockNum, -			  count, partmap->s_partition_len); +			  bloc->logicalBlockNum, 0, +			  bloc->logicalBlockNum, count, +			  partmap->s_partition_len);  		goto error_return;  	} @@ -156,11 +155,10 @@ static void udf_bitmap_free_blocks(struct super_block *sb,  			if (udf_set_bit(bit + i, bh->b_data)) {  				udf_debug("bit %ld already set\n", bit + i);  				udf_debug("byte=%2x\n", -					((char *)bh->b_data)[(bit + i) >> 3]); -			} else { -				udf_add_free_space(sb, sbi->s_partition, 1); +					  ((char *)bh->b_data)[(bit + i) >> 3]);  			}  		} +		udf_add_free_space(sb, sbi->s_partition, count);  		mark_buffer_dirty(bh);  		if (overflow) {  			block += count; @@ -173,7 +171,6 @@ error_return:  }  static int udf_bitmap_prealloc_blocks(struct super_block *sb, -				      struct inode *inode,  				      struct udf_bitmap *bitmap,  				      uint16_t partition, uint32_t first_block,  				      uint32_t block_count) @@ -224,7 +221,6 @@ out:  }  static int udf_bitmap_new_block(struct super_block *sb, -				struct inode *inode,  				struct udf_bitmap *bitmap, uint16_t partition,  				uint32_t goal, int *err)  { @@ -298,7 +294,7 @@ repeat:  				break;  			}  		} else { -			bit = udf_find_next_one_bit((char *)bh->b_data, +			bit = udf_find_next_one_bit(bh->b_data,  						    sb->s_blocksize << 3,  						    group_start << 3);  			if (bit < sb->s_blocksize << 3) @@ -350,7 +346,6 @@ error_return:  }  static void udf_table_free_blocks(struct super_block *sb, -				  struct inode *inode,  				  struct inode *table,  				  struct kernel_lb_addr *bloc,  				  uint32_t offset, @@ -371,7 +366,8 @@ static void udf_table_free_blocks(struct super_block *sb,  	if (bloc->logicalBlockNum + count < count ||  	    (bloc->logicalBlockNum + count) > partmap->s_partition_len) {  		udf_debug("%d < %d || %d + %d > %d\n", -			  bloc->logicalBlockNum, 0, bloc->logicalBlockNum, count, +			  bloc->logicalBlockNum, 0, +			  bloc->logicalBlockNum, count,  			  partmap->s_partition_len);  		goto error_return;  	} @@ -581,7 +577,6 @@ error_return:  }  static int udf_table_prealloc_blocks(struct super_block *sb, -				     struct inode *inode,  				     struct inode *table, uint16_t partition,  				     uint32_t first_block, uint32_t block_count)  { @@ -643,7 +638,6 @@ static int udf_table_prealloc_blocks(struct super_block *sb,  }  static int udf_table_new_block(struct super_block *sb, -			       struct inode *inode,  			       struct inode *table, uint16_t partition,  			       uint32_t goal, int *err)  { @@ -743,18 +737,23 @@ void udf_free_blocks(struct super_block *sb, struct inode *inode,  	struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition];  	if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) { -		udf_bitmap_free_blocks(sb, inode, map->s_uspace.s_bitmap, +		udf_bitmap_free_blocks(sb, map->s_uspace.s_bitmap,  				       bloc, offset, count);  	} else if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) { -		udf_table_free_blocks(sb, inode, map->s_uspace.s_table, +		udf_table_free_blocks(sb, map->s_uspace.s_table,  				      bloc, offset, count);  	} else if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) { -		udf_bitmap_free_blocks(sb, inode, map->s_fspace.s_bitmap, +		udf_bitmap_free_blocks(sb, map->s_fspace.s_bitmap,  				       bloc, offset, count);  	} else if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) { -		udf_table_free_blocks(sb, inode, map->s_fspace.s_table, +		udf_table_free_blocks(sb, map->s_fspace.s_table,  				      bloc, offset, count);  	} + +	if (inode) { +		inode_sub_bytes(inode, +				((sector_t)count) << sb->s_blocksize_bits); +	}  }  inline int udf_prealloc_blocks(struct super_block *sb, @@ -763,29 +762,34 @@ inline int udf_prealloc_blocks(struct super_block *sb,  			       uint32_t block_count)  {  	struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition]; +	sector_t allocated;  	if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) -		return udf_bitmap_prealloc_blocks(sb, inode, -						  map->s_uspace.s_bitmap, -						  partition, first_block, -						  block_count); +		allocated = udf_bitmap_prealloc_blocks(sb, +						       map->s_uspace.s_bitmap, +						       partition, first_block, +						       block_count);  	else if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) -		return udf_table_prealloc_blocks(sb, inode, -						 map->s_uspace.s_table, -						 partition, first_block, -						 block_count); +		allocated = udf_table_prealloc_blocks(sb, +						      map->s_uspace.s_table, +						      partition, first_block, +						      block_count);  	else if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) -		return udf_bitmap_prealloc_blocks(sb, inode, -						  map->s_fspace.s_bitmap, -						  partition, first_block, -						  block_count); +		allocated = udf_bitmap_prealloc_blocks(sb, +						       map->s_fspace.s_bitmap, +						       partition, first_block, +						       block_count);  	else if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) -		return udf_table_prealloc_blocks(sb, inode, -						 map->s_fspace.s_table, -						 partition, first_block, -						 block_count); +		allocated = udf_table_prealloc_blocks(sb, +						      map->s_fspace.s_table, +						      partition, first_block, +						      block_count);  	else  		return 0; + +	if (inode && allocated > 0) +		inode_add_bytes(inode, allocated << sb->s_blocksize_bits); +	return allocated;  }  inline int udf_new_block(struct super_block *sb, @@ -793,25 +797,29 @@ inline int udf_new_block(struct super_block *sb,  			 uint16_t partition, uint32_t goal, int *err)  {  	struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition]; +	int block;  	if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) -		return udf_bitmap_new_block(sb, inode, -					   map->s_uspace.s_bitmap, -					   partition, goal, err); +		block = udf_bitmap_new_block(sb, +					     map->s_uspace.s_bitmap, +					     partition, goal, err);  	else if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) -		return udf_table_new_block(sb, inode, -					   map->s_uspace.s_table, -					   partition, goal, err); -	else if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) -		return udf_bitmap_new_block(sb, inode, -					    map->s_fspace.s_bitmap, +		block = udf_table_new_block(sb, +					    map->s_uspace.s_table,  					    partition, goal, err); +	else if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) +		block = udf_bitmap_new_block(sb, +					     map->s_fspace.s_bitmap, +					     partition, goal, err);  	else if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) -		return udf_table_new_block(sb, inode, -					   map->s_fspace.s_table, -					   partition, goal, err); +		block = udf_table_new_block(sb, +					    map->s_fspace.s_table, +					    partition, goal, err);  	else {  		*err = -EIO;  		return 0;  	} +	if (inode && block) +		inode_add_bytes(inode, sb->s_blocksize); +	return block;  } diff --git a/fs/udf/dir.c b/fs/udf/dir.c index 51552bf5022..a012c51caff 100644 --- a/fs/udf/dir.c +++ b/fs/udf/dir.c @@ -30,20 +30,21 @@  #include <linux/errno.h>  #include <linux/mm.h>  #include <linux/slab.h> -#include <linux/smp_lock.h>  #include <linux/buffer_head.h>  #include "udf_i.h"  #include "udf_sb.h" -static int do_udf_readdir(struct inode *dir, struct file *filp, -			  filldir_t filldir, void *dirent) + +static int udf_readdir(struct file *file, struct dir_context *ctx)  { +	struct inode *dir = file_inode(file); +	struct udf_inode_info *iinfo = UDF_I(dir);  	struct udf_fileident_bh fibh = { .sbh = NULL, .ebh = NULL};  	struct fileIdentDesc *fi = NULL;  	struct fileIdentDesc cfi;  	int block, iblock; -	loff_t nf_pos = (filp->f_pos - 1) << 2; +	loff_t nf_pos;  	int flen;  	unsigned char *fname = NULL;  	unsigned char *nameptr; @@ -55,10 +56,14 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,  	uint32_t elen;  	sector_t offset;  	int i, num, ret = 0; -	unsigned int dt_type;  	struct extent_position epos = { NULL, 0, {0, 0} }; -	struct udf_inode_info *iinfo; +	if (ctx->pos == 0) { +		if (!dir_emit_dot(file, ctx)) +			return 0; +		ctx->pos = 1; +	} +	nf_pos = (ctx->pos - 1) << 2;  	if (nf_pos >= size)  		goto out; @@ -72,7 +77,6 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,  		nf_pos = udf_ext0_offset(dir);  	fibh.soffset = fibh.eoffset = nf_pos & (dir->i_sb->s_blocksize - 1); -	iinfo = UDF_I(dir);  	if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {  		if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits,  		    &epos, &eloc, &elen, &offset) @@ -117,7 +121,9 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,  	}  	while (nf_pos < size) { -		filp->f_pos = (nf_pos >> 2) + 1; +		struct kernel_lb_addr tloc; + +		ctx->pos = (nf_pos >> 2) + 1;  		fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc,  					&elen, &offset); @@ -156,24 +162,22 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,  		}  		if (cfi.fileCharacteristics & FID_FILE_CHAR_PARENT) { -			iblock = parent_ino(filp->f_path.dentry); -			flen = 2; -			memcpy(fname, "..", flen); -			dt_type = DT_DIR; -		} else { -			struct kernel_lb_addr tloc = lelb_to_cpu(cfi.icb.extLocation); - -			iblock = udf_get_lb_pblock(dir->i_sb, &tloc, 0); -			flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); -			dt_type = DT_UNKNOWN; +			if (!dir_emit_dotdot(file, ctx)) +				goto out; +			continue;  		} -		if (flen && filldir(dirent, fname, flen, filp->f_pos, -				    iblock, dt_type) < 0) +		flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); +		if (!flen) +			continue; + +		tloc = lelb_to_cpu(cfi.icb.extLocation); +		iblock = udf_get_lb_pblock(dir->i_sb, &tloc, 0); +		if (!dir_emit(ctx, fname, flen, iblock, DT_UNKNOWN))  			goto out;  	} /* end while */ -	filp->f_pos = (nf_pos >> 2) + 1; +	ctx->pos = (nf_pos >> 2) + 1;  out:  	if (fibh.sbh != fibh.ebh) @@ -185,31 +189,11 @@ out:  	return ret;  } -static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir) -{ -	struct inode *dir = filp->f_path.dentry->d_inode; -	int result; - -	lock_kernel(); - -	if (filp->f_pos == 0) { -		if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR) < 0) { -			unlock_kernel(); -			return 0; -		} -		filp->f_pos++; -	} - -	result = do_udf_readdir(dir, filp, filldir, dirent); -	unlock_kernel(); - 	return result; -} -  /* readdir and lookup functions */  const struct file_operations udf_dir_operations = {  	.llseek			= generic_file_llseek,  	.read			= generic_read_dir, -	.readdir		= udf_readdir, +	.iterate		= udf_readdir,  	.unlocked_ioctl		= udf_ioctl,  	.fsync			= generic_file_fsync,  }; diff --git a/fs/udf/directory.c b/fs/udf/directory.c index 2ffdb6733af..3e44f575fb9 100644 --- a/fs/udf/directory.c +++ b/fs/udf/directory.c @@ -162,8 +162,8 @@ struct fileIdentDesc *udf_get_fileident(void *buffer, int bufsize, int *offset)  	int padlen;  	if ((!buffer) || (!offset)) { -		udf_debug("invalidparms\n, buffer=%p, offset=%p\n", buffer, -			  offset); +		udf_debug("invalidparms, buffer=%p, offset=%p\n", +			  buffer, offset);  		return NULL;  	} @@ -201,7 +201,7 @@ struct short_ad *udf_get_fileshortad(uint8_t *ptr, int maxoffset, uint32_t *offs  	struct short_ad *sa;  	if ((!ptr) || (!offset)) { -		printk(KERN_ERR "udf: udf_get_fileshortad() invalidparms\n"); +		pr_err("%s: invalidparms\n", __func__);  		return NULL;  	} @@ -223,7 +223,7 @@ struct long_ad *udf_get_filelongad(uint8_t *ptr, int maxoffset, uint32_t *offset  	struct long_ad *la;  	if ((!ptr) || (!offset)) { -		printk(KERN_ERR "udf: udf_get_filelongad() invalidparms\n"); +		pr_err("%s: invalidparms\n", __func__);  		return NULL;  	} diff --git a/fs/udf/file.c b/fs/udf/file.c index 66b9e7e7e4c..d80738fdf42 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -32,7 +32,6 @@  #include <linux/string.h> /* memset */  #include <linux/capability.h>  #include <linux/errno.h> -#include <linux/smp_lock.h>  #include <linux/pagemap.h>  #include <linux/buffer_head.h>  #include <linux/aio.h> @@ -40,20 +39,24 @@  #include "udf_i.h"  #include "udf_sb.h" -static int udf_adinicb_readpage(struct file *file, struct page *page) +static void __udf_adinicb_readpage(struct page *page)  {  	struct inode *inode = page->mapping->host;  	char *kaddr;  	struct udf_inode_info *iinfo = UDF_I(inode); -	BUG_ON(!PageLocked(page)); -  	kaddr = kmap(page); -	memset(kaddr, 0, PAGE_CACHE_SIZE);  	memcpy(kaddr, iinfo->i_ext.i_data + iinfo->i_lenEAttr, inode->i_size); +	memset(kaddr + inode->i_size, 0, PAGE_CACHE_SIZE - inode->i_size);  	flush_dcache_page(page);  	SetPageUptodate(page);  	kunmap(page); +} + +static int udf_adinicb_readpage(struct file *file, struct page *page) +{ +	BUG_ON(!PageLocked(page)); +	__udf_adinicb_readpage(page);  	unlock_page(page);  	return 0; @@ -78,6 +81,25 @@ static int udf_adinicb_writepage(struct page *page,  	return 0;  } +static int udf_adinicb_write_begin(struct file *file, +			struct address_space *mapping, loff_t pos, +			unsigned len, unsigned flags, struct page **pagep, +			void **fsdata) +{ +	struct page *page; + +	if (WARN_ON_ONCE(pos >= PAGE_CACHE_SIZE)) +		return -EIO; +	page = grab_cache_page_write_begin(mapping, 0, flags); +	if (!page) +		return -ENOMEM; +	*pagep = page; + +	if (!PageUptodate(page) && len != PAGE_CACHE_SIZE) +		__udf_adinicb_readpage(page); +	return 0; +} +  static int udf_adinicb_write_end(struct file *file,  			struct address_space *mapping,  			loff_t pos, unsigned len, unsigned copied, @@ -88,43 +110,53 @@ static int udf_adinicb_write_end(struct file *file,  	char *kaddr;  	struct udf_inode_info *iinfo = UDF_I(inode); -	kaddr = kmap_atomic(page, KM_USER0); +	kaddr = kmap_atomic(page);  	memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr + offset,  		kaddr + offset, copied); -	kunmap_atomic(kaddr, KM_USER0); +	kunmap_atomic(kaddr);  	return simple_write_end(file, mapping, pos, len, copied, page, fsdata);  } +static ssize_t udf_adinicb_direct_IO(int rw, struct kiocb *iocb, +				     struct iov_iter *iter, +				     loff_t offset) +{ +	/* Fallback to buffered I/O. */ +	return 0; +} +  const struct address_space_operations udf_adinicb_aops = {  	.readpage	= udf_adinicb_readpage,  	.writepage	= udf_adinicb_writepage, -	.sync_page	= block_sync_page, -	.write_begin = simple_write_begin, -	.write_end = udf_adinicb_write_end, +	.write_begin	= udf_adinicb_write_begin, +	.write_end	= udf_adinicb_write_end, +	.direct_IO	= udf_adinicb_direct_IO,  }; -static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, -				  unsigned long nr_segs, loff_t ppos) +static ssize_t udf_file_write_iter(struct kiocb *iocb, struct iov_iter *from)  {  	ssize_t retval;  	struct file *file = iocb->ki_filp; -	struct inode *inode = file->f_path.dentry->d_inode; +	struct inode *inode = file_inode(file);  	int err, pos; -	size_t count = iocb->ki_left; +	size_t count = iocb->ki_nbytes;  	struct udf_inode_info *iinfo = UDF_I(inode); +	mutex_lock(&inode->i_mutex); +	down_write(&iinfo->i_data_sem);  	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {  		if (file->f_flags & O_APPEND)  			pos = inode->i_size;  		else -			pos = ppos; +			pos = iocb->ki_pos;  		if (inode->i_sb->s_blocksize <  				(udf_file_entry_alloc_offset(inode) +  						pos + count)) { -			udf_expand_file_adinicb(inode, pos + count, &err); -			if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { +			err = udf_expand_file_adinicb(inode); +			if (err) { +				mutex_unlock(&inode->i_mutex);  				udf_debug("udf_expand_adinicb: err=%d\n", err);  				return err;  			} @@ -133,25 +165,33 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,  				iinfo->i_lenAlloc = pos + count;  			else  				iinfo->i_lenAlloc = inode->i_size; +			up_write(&iinfo->i_data_sem);  		} -	} +	} else +		up_write(&iinfo->i_data_sem); + +	retval = __generic_file_write_iter(iocb, from); +	mutex_unlock(&inode->i_mutex); + +	if (retval > 0) { +		ssize_t err; -	retval = generic_file_aio_write(iocb, iov, nr_segs, ppos); -	if (retval > 0)  		mark_inode_dirty(inode); +		err = generic_write_sync(file, iocb->ki_pos - retval, retval); +		if (err < 0) +			retval = err; +	}  	return retval;  }  long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  { -	struct inode *inode = filp->f_dentry->d_inode; +	struct inode *inode = file_inode(filp);  	long old_block, new_block;  	int result = -EINVAL; -	lock_kernel(); - -	if (file_permission(filp, MAY_READ) != 0) { +	if (inode_permission(inode, MAY_READ) != 0) {  		udf_debug("no permission to access inode %lu\n", inode->i_ino);  		result = -EPERM;  		goto out; @@ -173,7 +213,7 @@ long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  		goto out;  	case UDF_RELOCATE_BLOCKS:  		if (!capable(CAP_SYS_ADMIN)) { -			result = -EACCES; +			result = -EPERM;  			goto out;  		}  		if (get_user(old_block, (long __user *)arg)) { @@ -196,31 +236,28 @@ long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  	}  out: -	unlock_kernel();  	return result;  }  static int udf_release_file(struct inode *inode, struct file *filp)  {  	if (filp->f_mode & FMODE_WRITE) { -		mutex_lock(&inode->i_mutex); -		lock_kernel(); +		down_write(&UDF_I(inode)->i_data_sem);  		udf_discard_prealloc(inode);  		udf_truncate_tail_extent(inode); -		unlock_kernel(); -		mutex_unlock(&inode->i_mutex); +		up_write(&UDF_I(inode)->i_data_sem);  	}  	return 0;  }  const struct file_operations udf_file_operations = { -	.read			= do_sync_read, -	.aio_read		= generic_file_aio_read, +	.read			= new_sync_read, +	.read_iter		= generic_file_read_iter,  	.unlocked_ioctl		= udf_ioctl,  	.open			= generic_file_open,  	.mmap			= generic_file_mmap, -	.write			= do_sync_write, -	.aio_write		= udf_file_aio_write, +	.write			= new_sync_write, +	.write_iter		= udf_file_write_iter,  	.release		= udf_release_file,  	.fsync			= generic_file_fsync,  	.splice_read		= generic_file_splice_read, @@ -238,7 +275,7 @@ static int udf_setattr(struct dentry *dentry, struct iattr *attr)  	if ((attr->ia_valid & ATTR_SIZE) &&  	    attr->ia_size != i_size_read(inode)) { -		error = vmtruncate(inode, attr->ia_size); +		error = udf_setsize(inode, attr->ia_size);  		if (error)  			return error;  	} @@ -250,5 +287,4 @@ static int udf_setattr(struct dentry *dentry, struct iattr *attr)  const struct inode_operations udf_file_inode_operations = {  	.setattr		= udf_setattr, -	.truncate		= udf_truncate,  }; diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c index 75d9304d0dc..6eaf5edf1ea 100644 --- a/fs/udf/ialloc.c +++ b/fs/udf/ialloc.c @@ -30,23 +30,22 @@ void udf_free_inode(struct inode *inode)  {  	struct super_block *sb = inode->i_sb;  	struct udf_sb_info *sbi = UDF_SB(sb); +	struct logicalVolIntegrityDescImpUse *lvidiu = udf_sb_lvidiu(sb); -	mutex_lock(&sbi->s_alloc_mutex); -	if (sbi->s_lvid_bh) { -		struct logicalVolIntegrityDescImpUse *lvidiu = -							udf_sb_lvidiu(sbi); +	if (lvidiu) { +		mutex_lock(&sbi->s_alloc_mutex);  		if (S_ISDIR(inode->i_mode))  			le32_add_cpu(&lvidiu->numDirs, -1);  		else  			le32_add_cpu(&lvidiu->numFiles, -1);  		udf_updated_lvid(sb); +		mutex_unlock(&sbi->s_alloc_mutex);  	} -	mutex_unlock(&sbi->s_alloc_mutex);  	udf_free_blocks(sb, NULL, &UDF_I(inode)->i_location, 0, 1);  } -struct inode *udf_new_inode(struct inode *dir, int mode, int *err) +struct inode *udf_new_inode(struct inode *dir, umode_t mode, int *err)  {  	struct super_block *sb = dir->i_sb;  	struct udf_sb_info *sbi = UDF_SB(sb); @@ -55,6 +54,7 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err)  	uint32_t start = UDF_I(dir)->i_location.logicalBlockNum;  	struct udf_inode_info *iinfo;  	struct udf_inode_info *dinfo = UDF_I(dir); +	struct logicalVolIntegrityDescImpUse *lvidiu;  	inode = new_inode(sb); @@ -92,28 +92,17 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err)  		return NULL;  	} -	mutex_lock(&sbi->s_alloc_mutex); -	if (sbi->s_lvid_bh) { -		struct logicalVolIntegrityDesc *lvid = -			(struct logicalVolIntegrityDesc *) -			sbi->s_lvid_bh->b_data; -		struct logicalVolIntegrityDescImpUse *lvidiu = -							udf_sb_lvidiu(sbi); -		struct logicalVolHeaderDesc *lvhd; -		uint64_t uniqueID; -		lvhd = (struct logicalVolHeaderDesc *) -				(lvid->logicalVolContentsUse); +	lvidiu = udf_sb_lvidiu(sb); +	if (lvidiu) { +		iinfo->i_unique = lvid_get_unique_id(sb); +		mutex_lock(&sbi->s_alloc_mutex);  		if (S_ISDIR(mode))  			le32_add_cpu(&lvidiu->numDirs, 1);  		else  			le32_add_cpu(&lvidiu->numFiles, 1); -		iinfo->i_unique = uniqueID = le64_to_cpu(lvhd->uniqueID); -		if (!(++uniqueID & 0x00000000FFFFFFFFUL)) -			uniqueID += 16; -		lvhd->uniqueID = cpu_to_le64(uniqueID);  		udf_updated_lvid(sb); +		mutex_unlock(&sbi->s_alloc_mutex);  	} -	mutex_unlock(&sbi->s_alloc_mutex);  	inode_init_owner(inode, dir, mode); @@ -125,6 +114,7 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err)  	iinfo->i_lenEAttr = 0;  	iinfo->i_lenAlloc = 0;  	iinfo->i_use = 0; +	iinfo->i_checkpoint = 1;  	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB))  		iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;  	else if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD)) diff --git a/fs/udf/inode.c b/fs/udf/inode.c index fc48f37aa2d..236cd48184c 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -31,13 +31,14 @@  #include "udfdecl.h"  #include <linux/mm.h> -#include <linux/smp_lock.h>  #include <linux/module.h>  #include <linux/pagemap.h>  #include <linux/buffer_head.h>  #include <linux/writeback.h>  #include <linux/slab.h>  #include <linux/crc-itu-t.h> +#include <linux/mpage.h> +#include <linux/aio.h>  #include "udf_i.h"  #include "udf_sb.h" @@ -48,12 +49,12 @@ MODULE_LICENSE("GPL");  #define EXTENT_MERGE_SIZE 5 -static mode_t udf_convert_permissions(struct fileEntry *); +static umode_t udf_convert_permissions(struct fileEntry *);  static int udf_update_inode(struct inode *, int);  static void udf_fill_inode(struct inode *, struct buffer_head *); +static int udf_sync_inode(struct inode *inode);  static int udf_alloc_i_data(struct inode *inode, size_t size); -static struct buffer_head *inode_getblk(struct inode *, sector_t, int *, -					sector_t *, int *); +static sector_t inode_getblk(struct inode *, sector_t, int *, int *);  static int8_t udf_insert_aext(struct inode *, struct extent_position,  			      struct kernel_lb_addr, uint32_t);  static void udf_split_extents(struct inode *, int *, int, int, @@ -67,39 +68,117 @@ static void udf_update_extents(struct inode *,  			       struct extent_position *);  static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int); +static void __udf_clear_extent_cache(struct inode *inode) +{ +	struct udf_inode_info *iinfo = UDF_I(inode); + +	if (iinfo->cached_extent.lstart != -1) { +		brelse(iinfo->cached_extent.epos.bh); +		iinfo->cached_extent.lstart = -1; +	} +} + +/* Invalidate extent cache */ +static void udf_clear_extent_cache(struct inode *inode) +{ +	struct udf_inode_info *iinfo = UDF_I(inode); + +	spin_lock(&iinfo->i_extent_cache_lock); +	__udf_clear_extent_cache(inode); +	spin_unlock(&iinfo->i_extent_cache_lock); +} + +/* Return contents of extent cache */ +static int udf_read_extent_cache(struct inode *inode, loff_t bcount, +				 loff_t *lbcount, struct extent_position *pos) +{ +	struct udf_inode_info *iinfo = UDF_I(inode); +	int ret = 0; + +	spin_lock(&iinfo->i_extent_cache_lock); +	if ((iinfo->cached_extent.lstart <= bcount) && +	    (iinfo->cached_extent.lstart != -1)) { +		/* Cache hit */ +		*lbcount = iinfo->cached_extent.lstart; +		memcpy(pos, &iinfo->cached_extent.epos, +		       sizeof(struct extent_position)); +		if (pos->bh) +			get_bh(pos->bh); +		ret = 1; +	} +	spin_unlock(&iinfo->i_extent_cache_lock); +	return ret; +} + +/* Add extent to extent cache */ +static void udf_update_extent_cache(struct inode *inode, loff_t estart, +				    struct extent_position *pos, int next_epos) +{ +	struct udf_inode_info *iinfo = UDF_I(inode); + +	spin_lock(&iinfo->i_extent_cache_lock); +	/* Invalidate previously cached extent */ +	__udf_clear_extent_cache(inode); +	if (pos->bh) +		get_bh(pos->bh); +	memcpy(&iinfo->cached_extent.epos, pos, +	       sizeof(struct extent_position)); +	iinfo->cached_extent.lstart = estart; +	if (next_epos) +		switch (iinfo->i_alloc_type) { +		case ICBTAG_FLAG_AD_SHORT: +			iinfo->cached_extent.epos.offset -= +			sizeof(struct short_ad); +			break; +		case ICBTAG_FLAG_AD_LONG: +			iinfo->cached_extent.epos.offset -= +			sizeof(struct long_ad); +		} +	spin_unlock(&iinfo->i_extent_cache_lock); +}  void udf_evict_inode(struct inode *inode)  {  	struct udf_inode_info *iinfo = UDF_I(inode);  	int want_delete = 0; -	truncate_inode_pages(&inode->i_data, 0); -  	if (!inode->i_nlink && !is_bad_inode(inode)) {  		want_delete = 1; -		inode->i_size = 0; -		udf_truncate(inode); -		lock_kernel(); +		udf_setsize(inode, 0);  		udf_update_inode(inode, IS_SYNC(inode)); -		unlock_kernel();  	} +	truncate_inode_pages_final(&inode->i_data);  	invalidate_inode_buffers(inode); -	end_writeback(inode); +	clear_inode(inode);  	if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB &&  	    inode->i_size != iinfo->i_lenExtents) { -		printk(KERN_WARNING "UDF-fs (%s): Inode %lu (mode %o) has " -			"inode size %llu different from extent length %llu. " -			"Filesystem need not be standards compliant.\n", -			inode->i_sb->s_id, inode->i_ino, inode->i_mode, -			(unsigned long long)inode->i_size, -			(unsigned long long)iinfo->i_lenExtents); +		udf_warn(inode->i_sb, "Inode %lu (mode %o) has inode size %llu different from extent length %llu. Filesystem need not be standards compliant.\n", +			 inode->i_ino, inode->i_mode, +			 (unsigned long long)inode->i_size, +			 (unsigned long long)iinfo->i_lenExtents);  	}  	kfree(iinfo->i_ext.i_data);  	iinfo->i_ext.i_data = NULL; +	udf_clear_extent_cache(inode);  	if (want_delete) { -		lock_kernel();  		udf_free_inode(inode); -		unlock_kernel(); +	} +} + +static void udf_write_failed(struct address_space *mapping, loff_t to) +{ +	struct inode *inode = mapping->host; +	struct udf_inode_info *iinfo = UDF_I(inode); +	loff_t isize = inode->i_size; + +	if (to > isize) { +		truncate_pagecache(inode, isize); +		if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { +			down_write(&iinfo->i_data_sem); +			udf_clear_extent_cache(inode); +			udf_truncate_extents(inode); +			up_write(&iinfo->i_data_sem); +		}  	}  } @@ -108,9 +187,21 @@ static int udf_writepage(struct page *page, struct writeback_control *wbc)  	return block_write_full_page(page, udf_get_block, wbc);  } +static int udf_writepages(struct address_space *mapping, +			struct writeback_control *wbc) +{ +	return mpage_writepages(mapping, wbc, udf_get_block); +} +  static int udf_readpage(struct file *file, struct page *page)  { -	return block_read_full_page(page, udf_get_block); +	return mpage_readpage(page, udf_get_block); +} + +static int udf_readpages(struct file *file, struct address_space *mapping, +			struct list_head *pages, unsigned nr_pages) +{ +	return mpage_readpages(mapping, pages, nr_pages, udf_get_block);  }  static int udf_write_begin(struct file *file, struct address_space *mapping, @@ -120,12 +211,24 @@ static int udf_write_begin(struct file *file, struct address_space *mapping,  	int ret;  	ret = block_write_begin(mapping, pos, len, flags, pagep, udf_get_block); -	if (unlikely(ret)) { -		loff_t isize = mapping->host->i_size; -		if (pos + len > isize) -			vmtruncate(mapping->host, isize); -	} +	if (unlikely(ret)) +		udf_write_failed(mapping, pos + len); +	return ret; +} +static ssize_t udf_direct_IO(int rw, struct kiocb *iocb, +			     struct iov_iter *iter, +			     loff_t offset) +{ +	struct file *file = iocb->ki_filp; +	struct address_space *mapping = file->f_mapping; +	struct inode *inode = mapping->host; +	size_t count = iov_iter_count(iter); +	ssize_t ret; + +	ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, udf_get_block); +	if (unlikely(ret < 0 && (rw & WRITE))) +		udf_write_failed(mapping, offset + count);  	return ret;  } @@ -136,37 +239,53 @@ static sector_t udf_bmap(struct address_space *mapping, sector_t block)  const struct address_space_operations udf_aops = {  	.readpage	= udf_readpage, +	.readpages	= udf_readpages,  	.writepage	= udf_writepage, -	.sync_page	= block_sync_page, -	.write_begin		= udf_write_begin, -	.write_end		= generic_write_end, +	.writepages	= udf_writepages, +	.write_begin	= udf_write_begin, +	.write_end	= generic_write_end, +	.direct_IO	= udf_direct_IO,  	.bmap		= udf_bmap,  }; -void udf_expand_file_adinicb(struct inode *inode, int newsize, int *err) +/* + * Expand file stored in ICB to a normal one-block-file + * + * This function requires i_data_sem for writing and releases it. + * This function requires i_mutex held + */ +int udf_expand_file_adinicb(struct inode *inode)  {  	struct page *page;  	char *kaddr;  	struct udf_inode_info *iinfo = UDF_I(inode); +	int err;  	struct writeback_control udf_wbc = {  		.sync_mode = WB_SYNC_NONE,  		.nr_to_write = 1,  	}; -	/* from now on we have normal address_space methods */ -	inode->i_data.a_ops = &udf_aops; - +	WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex));  	if (!iinfo->i_lenAlloc) {  		if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))  			iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;  		else  			iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; +		/* from now on we have normal address_space methods */ +		inode->i_data.a_ops = &udf_aops; +		up_write(&iinfo->i_data_sem);  		mark_inode_dirty(inode); -		return; +		return 0;  	} +	/* +	 * Release i_data_sem so that we can lock a page - page lock ranks +	 * above i_data_sem. i_mutex still protects us against file changes. +	 */ +	up_write(&iinfo->i_data_sem); -	page = grab_cache_page(inode->i_mapping, 0); -	BUG_ON(!PageLocked(page)); +	page = find_or_create_page(inode->i_mapping, 0, GFP_NOFS); +	if (!page) +		return -ENOMEM;  	if (!PageUptodate(page)) {  		kaddr = kmap(page); @@ -178,6 +297,7 @@ void udf_expand_file_adinicb(struct inode *inode, int newsize, int *err)  		SetPageUptodate(page);  		kunmap(page);  	} +	down_write(&iinfo->i_data_sem);  	memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr, 0x00,  	       iinfo->i_lenAlloc);  	iinfo->i_lenAlloc = 0; @@ -185,11 +305,27 @@ void udf_expand_file_adinicb(struct inode *inode, int newsize, int *err)  		iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;  	else  		iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; - -	inode->i_data.a_ops->writepage(page, &udf_wbc); +	/* from now on we have normal address_space methods */ +	inode->i_data.a_ops = &udf_aops; +	up_write(&iinfo->i_data_sem); +	err = inode->i_data.a_ops->writepage(page, &udf_wbc); +	if (err) { +		/* Restore everything back so that we don't lose data... */ +		lock_page(page); +		kaddr = kmap(page); +		down_write(&iinfo->i_data_sem); +		memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr, kaddr, +		       inode->i_size); +		kunmap(page); +		unlock_page(page); +		iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB; +		inode->i_data.a_ops = &udf_adinicb_aops; +		up_write(&iinfo->i_data_sem); +	}  	page_cache_release(page); -  	mark_inode_dirty(inode); + +	return err;  }  struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block, @@ -288,7 +424,6 @@ static int udf_get_block(struct inode *inode, sector_t block,  			 struct buffer_head *bh_result, int create)  {  	int err, new; -	struct buffer_head *bh;  	sector_t phys = 0;  	struct udf_inode_info *iinfo; @@ -301,30 +436,25 @@ static int udf_get_block(struct inode *inode, sector_t block,  	err = -EIO;  	new = 0; -	bh = NULL; - -	lock_kernel(); -  	iinfo = UDF_I(inode); + +	down_write(&iinfo->i_data_sem);  	if (block == iinfo->i_next_alloc_block + 1) {  		iinfo->i_next_alloc_block++;  		iinfo->i_next_alloc_goal++;  	} -	err = 0; - -	bh = inode_getblk(inode, block, &err, &phys, &new); -	BUG_ON(bh); -	if (err) +	udf_clear_extent_cache(inode); +	phys = inode_getblk(inode, block, &err, &new); +	if (!phys)  		goto abort; -	BUG_ON(!phys);  	if (new)  		set_buffer_new(bh_result);  	map_bh(bh_result, inode->i_sb, phys);  abort: -	unlock_kernel(); +	up_write(&iinfo->i_data_sem);  	return err;  } @@ -353,8 +483,10 @@ static struct buffer_head *udf_getblk(struct inode *inode, long block,  }  /* Extend the file by 'blocks' blocks, return the number of extents added */ -int udf_extend_file(struct inode *inode, struct extent_position *last_pos, -		    struct kernel_long_ad *last_ext, sector_t blocks) +static int udf_do_extend_file(struct inode *inode, +			      struct extent_position *last_pos, +			      struct kernel_long_ad *last_ext, +			      sector_t blocks)  {  	sector_t add;  	int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK); @@ -362,6 +494,7 @@ int udf_extend_file(struct inode *inode, struct extent_position *last_pos,  	struct kernel_lb_addr prealloc_loc = {};  	int prealloc_len = 0;  	struct udf_inode_info *iinfo; +	int err;  	/* The previous extent is fake and we should not extend by anything  	 * - there's nothing to do... */ @@ -427,26 +560,29 @@ int udf_extend_file(struct inode *inode, struct extent_position *last_pos,  	/* Create enough extents to cover the whole hole */  	while (blocks > add) {  		blocks -= add; -		if (udf_add_aext(inode, last_pos, &last_ext->extLocation, -				 last_ext->extLength, 1) == -1) -			return -1; +		err = udf_add_aext(inode, last_pos, &last_ext->extLocation, +				   last_ext->extLength, 1); +		if (err) +			return err;  		count++;  	}  	if (blocks) {  		last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |  			(blocks << sb->s_blocksize_bits); -		if (udf_add_aext(inode, last_pos, &last_ext->extLocation, -				 last_ext->extLength, 1) == -1) -			return -1; +		err = udf_add_aext(inode, last_pos, &last_ext->extLocation, +				   last_ext->extLength, 1); +		if (err) +			return err;  		count++;  	}  out:  	/* Do we have some preallocated blocks saved? */  	if (prealloc_len) { -		if (udf_add_aext(inode, last_pos, &prealloc_loc, -				 prealloc_len, 1) == -1) -			return -1; +		err = udf_add_aext(inode, last_pos, &prealloc_loc, +				   prealloc_len, 1); +		if (err) +			return err;  		last_ext->extLocation = prealloc_loc;  		last_ext->extLength = prealloc_len;  		count++; @@ -458,16 +594,71 @@ out:  	else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)  		last_pos->offset -= sizeof(struct long_ad);  	else -		return -1; +		return -EIO;  	return count;  } -static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, -					int *err, sector_t *phys, int *new) +static int udf_extend_file(struct inode *inode, loff_t newsize) +{ + +	struct extent_position epos; +	struct kernel_lb_addr eloc; +	uint32_t elen; +	int8_t etype; +	struct super_block *sb = inode->i_sb; +	sector_t first_block = newsize >> sb->s_blocksize_bits, offset; +	int adsize; +	struct udf_inode_info *iinfo = UDF_I(inode); +	struct kernel_long_ad extent; +	int err; + +	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) +		adsize = sizeof(struct short_ad); +	else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) +		adsize = sizeof(struct long_ad); +	else +		BUG(); + +	etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset); + +	/* File has extent covering the new size (could happen when extending +	 * inside a block)? */ +	if (etype != -1) +		return 0; +	if (newsize & (sb->s_blocksize - 1)) +		offset++; +	/* Extended file just to the boundary of the last file block? */ +	if (offset == 0) +		return 0; + +	/* Truncate is extending the file by 'offset' blocks */ +	if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) || +	    (epos.bh && epos.offset == sizeof(struct allocExtDesc))) { +		/* File has no extents at all or has empty last +		 * indirect extent! Create a fake extent... */ +		extent.extLocation.logicalBlockNum = 0; +		extent.extLocation.partitionReferenceNum = 0; +		extent.extLength = EXT_NOT_RECORDED_NOT_ALLOCATED; +	} else { +		epos.offset -= adsize; +		etype = udf_next_aext(inode, &epos, &extent.extLocation, +				      &extent.extLength, 0); +		extent.extLength |= etype << 30; +	} +	err = udf_do_extend_file(inode, &epos, &extent, offset); +	if (err < 0) +		goto out; +	err = 0; +	iinfo->i_lenExtents = newsize; +out: +	brelse(epos.bh); +	return err; +} + +static sector_t inode_getblk(struct inode *inode, sector_t block, +			     int *err, int *new)  { -	static sector_t last_block; -	struct buffer_head *result = NULL;  	struct kernel_long_ad laarr[EXTENT_MERGE_SIZE];  	struct extent_position prev_epos, cur_epos, next_epos;  	int count = 0, startnum = 0, endnum = 0; @@ -481,7 +672,10 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block,  	struct udf_inode_info *iinfo = UDF_I(inode);  	int goal = 0, pgoal = iinfo->i_location.logicalBlockNum;  	int lastblock = 0; +	bool isBeyondEOF; +	*err = 0; +	*new = 0;  	prev_epos.offset = udf_file_entry_alloc_offset(inode);  	prev_epos.block = iinfo->i_location;  	prev_epos.bh = NULL; @@ -545,21 +739,19 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block,  			elen = EXT_RECORDED_ALLOCATED |  				((elen + inode->i_sb->s_blocksize - 1) &  				 ~(inode->i_sb->s_blocksize - 1)); -			etype = udf_write_aext(inode, &cur_epos, &eloc, elen, 1); +			udf_write_aext(inode, &cur_epos, &eloc, elen, 1);  		}  		brelse(prev_epos.bh);  		brelse(cur_epos.bh);  		brelse(next_epos.bh);  		newblock = udf_get_lb_pblock(inode->i_sb, &eloc, offset); -		*phys = newblock; -		return NULL; +		return newblock;  	} -	last_block = block;  	/* Are we beyond EOF? */  	if (etype == -1) {  		int ret; - +		isBeyondEOF = 1;  		if (count) {  			if (c)  				laarr[0] = laarr[1]; @@ -569,20 +761,18 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block,  			memset(&laarr[0].extLocation, 0x00,  				sizeof(struct kernel_lb_addr));  			laarr[0].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED; -			/* Will udf_extend_file() create real extent from +			/* Will udf_do_extend_file() create real extent from  			   a fake one? */  			startnum = (offset > 0);  		}  		/* Create extents for the hole between EOF and offset */ -		ret = udf_extend_file(inode, &prev_epos, laarr, offset); -		if (ret == -1) { +		ret = udf_do_extend_file(inode, &prev_epos, laarr, offset); +		if (ret < 0) {  			brelse(prev_epos.bh);  			brelse(cur_epos.bh);  			brelse(next_epos.bh); -			/* We don't really know the error here so we just make -			 * something up */ -			*err = -ENOSPC; -			return NULL; +			*err = ret; +			return 0;  		}  		c = 0;  		offset = 0; @@ -599,11 +789,11 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block,  			memset(&laarr[c].extLocation, 0x00,  				sizeof(struct kernel_lb_addr));  			count++; -			endnum++;  		}  		endnum = c + 1;  		lastblock = 1;  	} else { +		isBeyondEOF = 0;  		endnum = startnum = ((count > 2) ? 2 : count);  		/* if the current extent is in position 0, @@ -646,10 +836,13 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block,  				goal, err);  		if (!newblocknum) {  			brelse(prev_epos.bh); +			brelse(cur_epos.bh); +			brelse(next_epos.bh);  			*err = -ENOSPC; -			return NULL; +			return 0;  		} -		iinfo->i_lenExtents += inode->i_sb->s_blocksize; +		if (isBeyondEOF) +			iinfo->i_lenExtents += inode->i_sb->s_blocksize;  	}  	/* if the extent the requsted block is located in contains multiple @@ -676,13 +869,15 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block,  	udf_update_extents(inode, laarr, startnum, endnum, &prev_epos);  	brelse(prev_epos.bh); +	brelse(cur_epos.bh); +	brelse(next_epos.bh);  	newblock = udf_get_pblock(inode->i_sb, newblocknum,  				iinfo->i_location.partitionReferenceNum, 0); -	if (!newblock) -		return NULL; -	*phys = newblock; -	*err = 0; +	if (!newblock) { +		*err = -EIO; +		return 0; +	}  	*new = 1;  	iinfo->i_next_alloc_block = block;  	iinfo->i_next_alloc_goal = newblocknum; @@ -693,7 +888,7 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block,  	else  		mark_inode_dirty(inode); -	return result; +	return newblock;  }  static void udf_split_extents(struct inode *inode, int *c, int offset, @@ -1010,50 +1205,70 @@ struct buffer_head *udf_bread(struct inode *inode, int block,  	return NULL;  } -void udf_truncate(struct inode *inode) +int udf_setsize(struct inode *inode, loff_t newsize)  { -	int offset;  	int err;  	struct udf_inode_info *iinfo; +	int bsize = 1 << inode->i_blkbits;  	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||  	      S_ISLNK(inode->i_mode))) -		return; +		return -EINVAL;  	if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) -		return; +		return -EPERM; -	lock_kernel();  	iinfo = UDF_I(inode); -	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { -		if (inode->i_sb->s_blocksize < -				(udf_file_entry_alloc_offset(inode) + -				 inode->i_size)) { -			udf_expand_file_adinicb(inode, inode->i_size, &err); -			if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { -				inode->i_size = iinfo->i_lenAlloc; -				unlock_kernel(); -				return; -			} else -				udf_truncate_extents(inode); -		} else { -			offset = inode->i_size & (inode->i_sb->s_blocksize - 1); -			memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr + offset, -				0x00, inode->i_sb->s_blocksize - -				offset - udf_file_entry_alloc_offset(inode)); -			iinfo->i_lenAlloc = inode->i_size; +	if (newsize > inode->i_size) { +		down_write(&iinfo->i_data_sem); +		if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { +			if (bsize < +			    (udf_file_entry_alloc_offset(inode) + newsize)) { +				err = udf_expand_file_adinicb(inode); +				if (err) +					return err; +				down_write(&iinfo->i_data_sem); +			} else { +				iinfo->i_lenAlloc = newsize; +				goto set_size; +			} +		} +		err = udf_extend_file(inode, newsize); +		if (err) { +			up_write(&iinfo->i_data_sem); +			return err;  		} +set_size: +		truncate_setsize(inode, newsize); +		up_write(&iinfo->i_data_sem);  	} else { -		block_truncate_page(inode->i_mapping, inode->i_size, -				    udf_get_block); +		if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { +			down_write(&iinfo->i_data_sem); +			udf_clear_extent_cache(inode); +			memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr + newsize, +			       0x00, bsize - newsize - +			       udf_file_entry_alloc_offset(inode)); +			iinfo->i_lenAlloc = newsize; +			truncate_setsize(inode, newsize); +			up_write(&iinfo->i_data_sem); +			goto update_time; +		} +		err = block_truncate_page(inode->i_mapping, newsize, +					  udf_get_block); +		if (err) +			return err; +		down_write(&iinfo->i_data_sem); +		udf_clear_extent_cache(inode); +		truncate_setsize(inode, newsize);  		udf_truncate_extents(inode); +		up_write(&iinfo->i_data_sem);  	} - +update_time:  	inode->i_mtime = inode->i_ctime = current_fs_time(inode->i_sb);  	if (IS_SYNC(inode))  		udf_sync_inode(inode);  	else  		mark_inode_dirty(inode); -	unlock_kernel(); +	return 0;  }  static void __udf_read_inode(struct inode *inode) @@ -1077,16 +1292,15 @@ static void __udf_read_inode(struct inode *inode)  	 */  	bh = udf_read_ptagged(inode->i_sb, &iinfo->i_location, 0, &ident);  	if (!bh) { -		printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed !bh\n", -		       inode->i_ino); +		udf_err(inode->i_sb, "(ino %ld) failed !bh\n", inode->i_ino);  		make_bad_inode(inode);  		return;  	}  	if (ident != TAG_IDENT_FE && ident != TAG_IDENT_EFE &&  	    ident != TAG_IDENT_USE) { -		printk(KERN_ERR "udf: udf_read_inode(ino %ld) " -				"failed ident=%d\n", inode->i_ino, ident); +		udf_err(inode->i_sb, "(ino %ld) failed ident=%d\n", +			inode->i_ino, ident);  		brelse(bh);  		make_bad_inode(inode);  		return; @@ -1126,8 +1340,8 @@ static void __udf_read_inode(struct inode *inode)  		}  		brelse(ibh);  	} else if (fe->icbTag.strategyType != cpu_to_le16(4)) { -		printk(KERN_ERR "udf: unsupported strategy type: %d\n", -		       le16_to_cpu(fe->icbTag.strategyType)); +		udf_err(inode->i_sb, "unsupported strategy type: %d\n", +			le16_to_cpu(fe->icbTag.strategyType));  		brelse(bh);  		make_bad_inode(inode);  		return; @@ -1141,9 +1355,9 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)  {  	struct fileEntry *fe;  	struct extendedFileEntry *efe; -	int offset;  	struct udf_sb_info *sbi = UDF_SB(inode->i_sb);  	struct udf_inode_info *iinfo = UDF_I(inode); +	unsigned int link_count;  	fe = (struct fileEntry *)bh->b_data;  	efe = (struct extendedFileEntry *)bh->b_data; @@ -1202,25 +1416,19 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)  		return;  	} -	inode->i_uid = le32_to_cpu(fe->uid); -	if (inode->i_uid == -1 || +	read_lock(&sbi->s_cred_lock); +	i_uid_write(inode, le32_to_cpu(fe->uid)); +	if (!uid_valid(inode->i_uid) ||  	    UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_IGNORE) ||  	    UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_SET))  		inode->i_uid = UDF_SB(inode->i_sb)->s_uid; -	inode->i_gid = le32_to_cpu(fe->gid); -	if (inode->i_gid == -1 || +	i_gid_write(inode, le32_to_cpu(fe->gid)); +	if (!gid_valid(inode->i_gid) ||  	    UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_IGNORE) ||  	    UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_SET))  		inode->i_gid = UDF_SB(inode->i_sb)->s_gid; -	inode->i_nlink = le16_to_cpu(fe->fileLinkCount); -	if (!inode->i_nlink) -		inode->i_nlink = 1; - -	inode->i_size = le64_to_cpu(fe->informationLength); -	iinfo->i_lenExtents = inode->i_size; -  	if (fe->icbTag.fileType != ICBTAG_FILE_TYPE_DIRECTORY &&  			sbi->s_fmode != UDF_INVALID_MODE)  		inode->i_mode = sbi->s_fmode; @@ -1230,6 +1438,15 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)  	else  		inode->i_mode = udf_convert_permissions(fe);  	inode->i_mode &= ~sbi->s_umask; +	read_unlock(&sbi->s_cred_lock); + +	link_count = le16_to_cpu(fe->fileLinkCount); +	if (!link_count) +		link_count = 1; +	set_nlink(inode, link_count); + +	inode->i_size = le64_to_cpu(fe->informationLength); +	iinfo->i_lenExtents = inode->i_size;  	if (iinfo->i_efe == 0) {  		inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) << @@ -1248,7 +1465,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)  		iinfo->i_unique = le64_to_cpu(fe->uniqueID);  		iinfo->i_lenEAttr = le32_to_cpu(fe->lengthExtendedAttr);  		iinfo->i_lenAlloc = le32_to_cpu(fe->lengthAllocDescs); -		offset = sizeof(struct fileEntry) + iinfo->i_lenEAttr; +		iinfo->i_checkpoint = le32_to_cpu(fe->checkpoint);  	} else {  		inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<  		    (inode->i_sb->s_blocksize_bits - 9); @@ -1269,8 +1486,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)  		iinfo->i_unique = le64_to_cpu(efe->uniqueID);  		iinfo->i_lenEAttr = le32_to_cpu(efe->lengthExtendedAttr);  		iinfo->i_lenAlloc = le32_to_cpu(efe->lengthAllocDescs); -		offset = sizeof(struct extendedFileEntry) + -							iinfo->i_lenEAttr; +		iinfo->i_checkpoint = le32_to_cpu(efe->checkpoint);  	}  	switch (fe->icbTag.fileType) { @@ -1319,9 +1535,8 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)  		udf_debug("METADATA BITMAP FILE-----\n");  		break;  	default: -		printk(KERN_ERR "udf: udf_fill_inode(ino %ld) failed unknown " -				"file type=%d\n", inode->i_ino, -				fe->icbTag.fileType); +		udf_err(inode->i_sb, "(ino %ld) failed unknown file type=%d\n", +			inode->i_ino, fe->icbTag.fileType);  		make_bad_inode(inode);  		return;  	} @@ -1344,17 +1559,17 @@ static int udf_alloc_i_data(struct inode *inode, size_t size)  	iinfo->i_ext.i_data = kmalloc(size, GFP_KERNEL);  	if (!iinfo->i_ext.i_data) { -		printk(KERN_ERR "udf:udf_alloc_i_data (ino %ld) " -				"no free memory\n", inode->i_ino); +		udf_err(inode->i_sb, "(ino %ld) no free memory\n", +			inode->i_ino);  		return -ENOMEM;  	}  	return 0;  } -static mode_t udf_convert_permissions(struct fileEntry *fe) +static umode_t udf_convert_permissions(struct fileEntry *fe)  { -	mode_t mode; +	umode_t mode;  	uint32_t permissions;  	uint32_t flags; @@ -1373,16 +1588,10 @@ static mode_t udf_convert_permissions(struct fileEntry *fe)  int udf_write_inode(struct inode *inode, struct writeback_control *wbc)  { -	int ret; - -	lock_kernel(); -	ret = udf_update_inode(inode, wbc->sync_mode == WB_SYNC_ALL); -	unlock_kernel(); - -	return ret; +	return udf_update_inode(inode, wbc->sync_mode == WB_SYNC_ALL);  } -int udf_sync_inode(struct inode *inode) +static int udf_sync_inode(struct inode *inode)  {  	return udf_update_inode(inode, 1);  } @@ -1392,6 +1601,7 @@ static int udf_update_inode(struct inode *inode, int do_sync)  	struct buffer_head *bh = NULL;  	struct fileEntry *fe;  	struct extendedFileEntry *efe; +	uint64_t lb_recorded;  	uint32_t udfperms;  	uint16_t icbflags;  	uint16_t crclen; @@ -1437,12 +1647,12 @@ static int udf_update_inode(struct inode *inode, int do_sync)  	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_FORGET))  		fe->uid = cpu_to_le32(-1);  	else -		fe->uid = cpu_to_le32(inode->i_uid); +		fe->uid = cpu_to_le32(i_uid_read(inode));  	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_FORGET))  		fe->gid = cpu_to_le32(-1);  	else -		fe->gid = cpu_to_le32(inode->i_gid); +		fe->gid = cpu_to_le32(i_gid_read(inode));  	udfperms = ((inode->i_mode & S_IRWXO)) |  		   ((inode->i_mode & S_IRWXG) << 2) | @@ -1486,13 +1696,18 @@ static int udf_update_inode(struct inode *inode, int do_sync)  		dsea->minorDeviceIdent = cpu_to_le32(iminor(inode));  	} +	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) +		lb_recorded = 0; /* No extents => no blocks! */ +	else +		lb_recorded = +			(inode->i_blocks + (1 << (blocksize_bits - 9)) - 1) >> +			(blocksize_bits - 9); +  	if (iinfo->i_efe == 0) {  		memcpy(bh->b_data + sizeof(struct fileEntry),  		       iinfo->i_ext.i_data,  		       inode->i_sb->s_blocksize - sizeof(struct fileEntry)); -		fe->logicalBlocksRecorded = cpu_to_le64( -			(inode->i_blocks + (1 << (blocksize_bits - 9)) - 1) >> -			(blocksize_bits - 9)); +		fe->logicalBlocksRecorded = cpu_to_le64(lb_recorded);  		udf_time_to_disk_stamp(&fe->accessTime, inode->i_atime);  		udf_time_to_disk_stamp(&fe->modificationTime, inode->i_mtime); @@ -1504,6 +1719,7 @@ static int udf_update_inode(struct inode *inode, int do_sync)  		fe->uniqueID = cpu_to_le64(iinfo->i_unique);  		fe->lengthExtendedAttr = cpu_to_le32(iinfo->i_lenEAttr);  		fe->lengthAllocDescs = cpu_to_le32(iinfo->i_lenAlloc); +		fe->checkpoint = cpu_to_le32(iinfo->i_checkpoint);  		fe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_FE);  		crclen = sizeof(struct fileEntry);  	} else { @@ -1512,9 +1728,7 @@ static int udf_update_inode(struct inode *inode, int do_sync)  		       inode->i_sb->s_blocksize -  					sizeof(struct extendedFileEntry));  		efe->objectSize = cpu_to_le64(inode->i_size); -		efe->logicalBlocksRecorded = cpu_to_le64( -			(inode->i_blocks + (1 << (blocksize_bits - 9)) - 1) >> -			(blocksize_bits - 9)); +		efe->logicalBlocksRecorded = cpu_to_le64(lb_recorded);  		if (iinfo->i_crtime.tv_sec > inode->i_atime.tv_sec ||  		    (iinfo->i_crtime.tv_sec == inode->i_atime.tv_sec && @@ -1543,6 +1757,7 @@ static int udf_update_inode(struct inode *inode, int do_sync)  		efe->uniqueID = cpu_to_le64(iinfo->i_unique);  		efe->lengthExtendedAttr = cpu_to_le32(iinfo->i_lenEAttr);  		efe->lengthAllocDescs = cpu_to_le32(iinfo->i_lenAlloc); +		efe->checkpoint = cpu_to_le32(iinfo->i_checkpoint);  		efe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EFE);  		crclen = sizeof(struct extendedFileEntry);  	} @@ -1601,9 +1816,8 @@ out:  	if (do_sync) {  		sync_dirty_buffer(bh);  		if (buffer_write_io_error(bh)) { -			printk(KERN_WARNING "IO error syncing udf inode " -				"[%s:%08lx]\n", inode->i_sb->s_id, -				inode->i_ino); +			udf_warn(inode->i_sb, "IO error syncing udf inode [%08lx]\n", +				 inode->i_ino);  			err = -EIO;  		}  	} @@ -1644,14 +1858,13 @@ struct inode *udf_iget(struct super_block *sb, struct kernel_lb_addr *ino)  	return NULL;  } -int8_t udf_add_aext(struct inode *inode, struct extent_position *epos, -		    struct kernel_lb_addr *eloc, uint32_t elen, int inc) +int udf_add_aext(struct inode *inode, struct extent_position *epos, +		 struct kernel_lb_addr *eloc, uint32_t elen, int inc)  {  	int adsize;  	struct short_ad *sad = NULL;  	struct long_ad *lad = NULL;  	struct allocExtDesc *aed; -	int8_t etype;  	uint8_t *ptr;  	struct udf_inode_info *iinfo = UDF_I(inode); @@ -1667,7 +1880,7 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,  	else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)  		adsize = sizeof(struct long_ad);  	else -		return -1; +		return -EIO;  	if (epos->offset + (2 * adsize) > inode->i_sb->s_blocksize) {  		unsigned char *sptr, *dptr; @@ -1679,12 +1892,12 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,  						obloc.partitionReferenceNum,  						obloc.logicalBlockNum, &err);  		if (!epos->block.logicalBlockNum) -			return -1; +			return -ENOSPC;  		nbh = udf_tgetblk(inode->i_sb, udf_get_lb_pblock(inode->i_sb,  								 &epos->block,  								 0));  		if (!nbh) -			return -1; +			return -EIO;  		lock_buffer(nbh);  		memset(nbh->b_data, 0x00, inode->i_sb->s_blocksize);  		set_buffer_uptodate(nbh); @@ -1753,7 +1966,7 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,  		epos->bh = nbh;  	} -	etype = udf_write_aext(inode, epos, eloc, elen, inc); +	udf_write_aext(inode, epos, eloc, elen, inc);  	if (!epos->bh) {  		iinfo->i_lenAlloc += adsize; @@ -1771,11 +1984,11 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,  		mark_buffer_dirty_inode(epos->bh, inode);  	} -	return etype; +	return 0;  } -int8_t udf_write_aext(struct inode *inode, struct extent_position *epos, -		      struct kernel_lb_addr *eloc, uint32_t elen, int inc) +void udf_write_aext(struct inode *inode, struct extent_position *epos, +		    struct kernel_lb_addr *eloc, uint32_t elen, int inc)  {  	int adsize;  	uint8_t *ptr; @@ -1805,7 +2018,7 @@ int8_t udf_write_aext(struct inode *inode, struct extent_position *epos,  		adsize = sizeof(struct long_ad);  		break;  	default: -		return -1; +		return;  	}  	if (epos->bh) { @@ -1824,8 +2037,6 @@ int8_t udf_write_aext(struct inode *inode, struct extent_position *epos,  	if (inc)  		epos->offset += adsize; - -	return (elen >> 30);  }  int8_t udf_next_aext(struct inode *inode, struct extent_position *epos, @@ -1897,8 +2108,7 @@ int8_t udf_current_aext(struct inode *inode, struct extent_position *epos,  		*elen = le32_to_cpu(lad->extLength) & UDF_EXTENT_LENGTH_MASK;  		break;  	default: -		udf_debug("alloc_type = %d unsupported\n", -				iinfo->i_alloc_type); +		udf_debug("alloc_type = %d unsupported\n", iinfo->i_alloc_type);  		return -1;  	} @@ -2020,11 +2230,12 @@ int8_t inode_bmap(struct inode *inode, sector_t block,  	struct udf_inode_info *iinfo;  	iinfo = UDF_I(inode); -	pos->offset = 0; -	pos->block = iinfo->i_location; -	pos->bh = NULL; +	if (!udf_read_extent_cache(inode, bcount, &lbcount, pos)) { +		pos->offset = 0; +		pos->block = iinfo->i_location; +		pos->bh = NULL; +	}  	*elen = 0; -  	do {  		etype = udf_next_aext(inode, pos, eloc, elen, 1);  		if (etype == -1) { @@ -2034,7 +2245,8 @@ int8_t inode_bmap(struct inode *inode, sector_t block,  		}  		lbcount += *elen;  	} while (lbcount <= bcount); - +	/* update extent cache */ +	udf_update_extent_cache(inode, lbcount - *elen, pos, 1);  	*offset = (bcount + *elen - lbcount) >> blocksize_bits;  	return etype; @@ -2048,7 +2260,7 @@ long udf_block_map(struct inode *inode, sector_t block)  	struct extent_position epos = {};  	int ret; -	lock_kernel(); +	down_read(&UDF_I(inode)->i_data_sem);  	if (inode_bmap(inode, block, &epos, &eloc, &elen, &offset) ==  						(EXT_RECORDED_ALLOCATED >> 30)) @@ -2056,7 +2268,7 @@ long udf_block_map(struct inode *inode, sector_t block)  	else  		ret = 0; -	unlock_kernel(); +	up_read(&UDF_I(inode)->i_data_sem);  	brelse(epos.bh);  	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV)) diff --git a/fs/udf/lowlevel.c b/fs/udf/lowlevel.c index 43e24a3b8e1..6583fe9b064 100644 --- a/fs/udf/lowlevel.c +++ b/fs/udf/lowlevel.c @@ -38,7 +38,7 @@ unsigned int udf_get_last_session(struct super_block *sb)  	if (i == 0) {  		udf_debug("XA disk: %s, vol_desc_start=%d\n", -			  (ms_info.xa_flag ? "yes" : "no"), ms_info.addr.lba); +			  ms_info.xa_flag ? "yes" : "no", ms_info.addr.lba);  		if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */  			vol_desc_start = ms_info.addr.lba;  	} else { diff --git a/fs/udf/misc.c b/fs/udf/misc.c index 9215700c00a..c175b4dabc1 100644 --- a/fs/udf/misc.c +++ b/fs/udf/misc.c @@ -204,6 +204,7 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,  {  	struct tag *tag_p;  	struct buffer_head *bh = NULL; +	u8 checksum;  	/* Read the block */  	if (block == 0xFFFFFFFF) @@ -211,8 +212,8 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,  	bh = udf_tread(sb, block);  	if (!bh) { -		udf_debug("block=%d, location=%d: read failed\n", -			  block, location); +		udf_err(sb, "read failed, block=%u, location=%d\n", +			block, location);  		return NULL;  	} @@ -227,16 +228,18 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,  	}  	/* Verify the tag checksum */ -	if (udf_tag_checksum(tag_p) != tag_p->tagChecksum) { -		printk(KERN_ERR "udf: tag checksum failed block %d\n", block); +	checksum = udf_tag_checksum(tag_p); +	if (checksum != tag_p->tagChecksum) { +		udf_err(sb, "tag checksum failed, block %u: 0x%02x != 0x%02x\n", +			block, checksum, tag_p->tagChecksum);  		goto error_out;  	}  	/* Verify the tag version */  	if (tag_p->descVersion != cpu_to_le16(0x0002U) &&  	    tag_p->descVersion != cpu_to_le16(0x0003U)) { -		udf_debug("tag version 0x%04x != 0x0002 || 0x0003 block %d\n", -			  le16_to_cpu(tag_p->descVersion), block); +		udf_err(sb, "tag version 0x%04x != 0x0002 || 0x0003, block %u\n", +			le16_to_cpu(tag_p->descVersion), block);  		goto error_out;  	} @@ -248,8 +251,8 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,  		return bh;  	udf_debug("Crc failure block %d: crc = %d, crclen = %d\n", block, -	    le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength)); - +		  le16_to_cpu(tag_p->descCRC), +		  le16_to_cpu(tag_p->descCRCLength));  error_out:  	brelse(bh);  	return NULL; diff --git a/fs/udf/namei.c b/fs/udf/namei.c index 6d8dc02baeb..9737cba1357 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -27,7 +27,6 @@  #include <linux/errno.h>  #include <linux/mm.h>  #include <linux/slab.h> -#include <linux/smp_lock.h>  #include <linux/buffer_head.h>  #include <linux/sched.h>  #include <linux/crc-itu-t.h> @@ -228,10 +227,8 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,  		}  		if ((cfi->fileCharacteristics & FID_FILE_CHAR_PARENT) && -		    isdotdot) { -			brelse(epos.bh); -			return fi; -		} +		    isdotdot) +			goto out_ok;  		if (!lfi)  			continue; @@ -254,7 +251,7 @@ out_ok:  }  static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry, -				 struct nameidata *nd) +				 unsigned int flags)  {  	struct inode *inode = NULL;  	struct fileIdentDesc cfi; @@ -263,7 +260,6 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,  	if (dentry->d_name.len > UDF_NAME_LEN - 2)  		return ERR_PTR(-ENAMETOOLONG); -	lock_kernel();  #ifdef UDF_RECOVERY  	/* temporary shorthand for specifying files by inode number */  	if (!strncmp(dentry->d_name.name, ".B=", 3)) { @@ -275,7 +271,6 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,  		};  		inode = udf_iget(dir->i_sb, lb);  		if (!inode) { -			unlock_kernel();  			return ERR_PTR(-EACCES);  		}  	} else @@ -291,11 +286,9 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,  		loc = lelb_to_cpu(cfi.icb.extLocation);  		inode = udf_iget(dir->i_sb, &loc);  		if (!inode) { -			unlock_kernel();  			return ERR_PTR(-EACCES);  		}  	} -	unlock_kernel();  	return d_splice_alias(inode, dentry);  } @@ -476,15 +469,19 @@ add:  				f_pos >> dir->i_sb->s_blocksize_bits, 1, err);  		if (!fibh->ebh)  			goto out_err; +		/* Extents could have been merged, invalidate our position */ +		brelse(epos.bh); +		epos.bh = NULL; +		epos.block = dinfo->i_location; +		epos.offset = udf_file_entry_alloc_offset(dir);  		if (!fibh->soffset) { -			if (udf_next_aext(dir, &epos, &eloc, &elen, 1) == -			    (EXT_RECORDED_ALLOCATED >> 30)) { -				block = eloc.logicalBlockNum + ((elen - 1) >> +			/* Find the freshly allocated block */ +			while (udf_next_aext(dir, &epos, &eloc, &elen, 1) == +				(EXT_RECORDED_ALLOCATED >> 30)) +				; +			block = eloc.logicalBlockNum + ((elen - 1) >>  					dir->i_sb->s_blocksize_bits); -			} else -				block++; -  			brelse(fibh->sbh);  			fibh->sbh = fibh->ebh;  			fi = (struct fileIdentDesc *)(fibh->sbh->b_data); @@ -553,8 +550,8 @@ static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi,  	return udf_write_fi(inode, cfi, fi, fibh, NULL, NULL);  } -static int udf_create(struct inode *dir, struct dentry *dentry, int mode, -		      struct nameidata *nd) +static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode, +		      bool excl)  {  	struct udf_fileident_bh fibh;  	struct inode *inode; @@ -562,10 +559,8 @@ static int udf_create(struct inode *dir, struct dentry *dentry, int mode,  	int err;  	struct udf_inode_info *iinfo; -	lock_kernel();  	inode = udf_new_inode(dir, mode, &err);  	if (!inode) { -		unlock_kernel();  		return err;  	} @@ -580,10 +575,8 @@ static int udf_create(struct inode *dir, struct dentry *dentry, int mode,  	fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);  	if (!fi) { -		inode->i_nlink--; -		mark_inode_dirty(inode); +		inode_dec_link_count(inode);  		iput(inode); -		unlock_kernel();  		return err;  	}  	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); @@ -596,13 +589,35 @@ static int udf_create(struct inode *dir, struct dentry *dentry, int mode,  	if (fibh.sbh != fibh.ebh)  		brelse(fibh.ebh);  	brelse(fibh.sbh); -	unlock_kernel();  	d_instantiate(dentry, inode);  	return 0;  } -static int udf_mknod(struct inode *dir, struct dentry *dentry, int mode, +static int udf_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) +{ +	struct inode *inode; +	struct udf_inode_info *iinfo; +	int err; + +	inode = udf_new_inode(dir, mode, &err); +	if (!inode) +		return err; + +	iinfo = UDF_I(inode); +	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) +		inode->i_data.a_ops = &udf_adinicb_aops; +	else +		inode->i_data.a_ops = &udf_aops; +	inode->i_op = &udf_file_inode_operations; +	inode->i_fop = &udf_file_operations; +	mark_inode_dirty(inode); + +	d_tmpfile(dentry, inode); +	return 0; +} + +static int udf_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,  		     dev_t rdev)  {  	struct inode *inode; @@ -614,7 +629,6 @@ static int udf_mknod(struct inode *dir, struct dentry *dentry, int mode,  	if (!old_valid_dev(rdev))  		return -EINVAL; -	lock_kernel();  	err = -EIO;  	inode = udf_new_inode(dir, mode, &err);  	if (!inode) @@ -624,10 +638,8 @@ static int udf_mknod(struct inode *dir, struct dentry *dentry, int mode,  	init_special_inode(inode, mode, rdev);  	fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);  	if (!fi) { -		inode->i_nlink--; -		mark_inode_dirty(inode); +		inode_dec_link_count(inode);  		iput(inode); -		unlock_kernel();  		return err;  	}  	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); @@ -646,11 +658,10 @@ static int udf_mknod(struct inode *dir, struct dentry *dentry, int mode,  	err = 0;  out: -	unlock_kernel();  	return err;  } -static int udf_mkdir(struct inode *dir, struct dentry *dentry, int mode) +static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)  {  	struct inode *inode;  	struct udf_fileident_bh fibh; @@ -659,11 +670,6 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, int mode)  	struct udf_inode_info *dinfo = UDF_I(dir);  	struct udf_inode_info *iinfo; -	lock_kernel(); -	err = -EMLINK; -	if (dir->i_nlink >= (256 << sizeof(dir->i_nlink)) - 1) -		goto out; -  	err = -EIO;  	inode = udf_new_inode(dir, S_IFDIR | mode, &err);  	if (!inode) @@ -674,12 +680,11 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, int mode)  	inode->i_fop = &udf_dir_operations;  	fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err);  	if (!fi) { -		inode->i_nlink--; -		mark_inode_dirty(inode); +		inode_dec_link_count(inode);  		iput(inode);  		goto out;  	} -	inode->i_nlink = 2; +	set_nlink(inode, 2);  	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);  	cfi.icb.extLocation = cpu_to_lelb(dinfo->i_location);  	*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse = @@ -692,7 +697,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, int mode)  	fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);  	if (!fi) { -		inode->i_nlink = 0; +		clear_nlink(inode);  		mark_inode_dirty(inode);  		iput(inode);  		goto out; @@ -712,7 +717,6 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, int mode)  	err = 0;  out: -	unlock_kernel();  	return err;  } @@ -794,7 +798,6 @@ static int udf_rmdir(struct inode *dir, struct dentry *dentry)  	struct kernel_lb_addr tloc;  	retval = -ENOENT; -	lock_kernel();  	fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi);  	if (!fi)  		goto out; @@ -810,9 +813,8 @@ static int udf_rmdir(struct inode *dir, struct dentry *dentry)  	if (retval)  		goto end_rmdir;  	if (inode->i_nlink != 2) -		udf_warning(inode->i_sb, "udf_rmdir", -			    "empty directory has nlink != 2 (%d)", -			    inode->i_nlink); +		udf_warn(inode->i_sb, "empty directory has nlink != 2 (%d)\n", +			 inode->i_nlink);  	clear_nlink(inode);  	inode->i_size = 0;  	inode_dec_link_count(dir); @@ -826,7 +828,6 @@ end_rmdir:  	brelse(fibh.sbh);  out: -	unlock_kernel();  	return retval;  } @@ -840,7 +841,6 @@ static int udf_unlink(struct inode *dir, struct dentry *dentry)  	struct kernel_lb_addr tloc;  	retval = -ENOENT; -	lock_kernel();  	fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi);  	if (!fi)  		goto out; @@ -853,7 +853,7 @@ static int udf_unlink(struct inode *dir, struct dentry *dentry)  	if (!inode->i_nlink) {  		udf_debug("Deleting nonexistent file (%lu), %d\n",  			  inode->i_ino, inode->i_nlink); -		inode->i_nlink = 1; +		set_nlink(inode, 1);  	}  	retval = udf_delete_entry(dir, fi, &fibh, &cfi);  	if (retval) @@ -870,7 +870,6 @@ end_unlink:  	brelse(fibh.sbh);  out: -	unlock_kernel();  	return retval;  } @@ -890,21 +889,21 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,  	int block;  	unsigned char *name = NULL;  	int namelen; -	struct buffer_head *bh;  	struct udf_inode_info *iinfo; +	struct super_block *sb = dir->i_sb; -	lock_kernel();  	inode = udf_new_inode(dir, S_IFLNK | S_IRWXUGO, &err);  	if (!inode)  		goto out; +	iinfo = UDF_I(inode); +	down_write(&iinfo->i_data_sem);  	name = kmalloc(UDF_NAME_LEN, GFP_NOFS);  	if (!name) {  		err = -ENOMEM;  		goto out_no_entry;  	} -	iinfo = UDF_I(inode);  	inode->i_data.a_ops = &udf_symlink_aops;  	inode->i_op = &udf_symlink_inode_operations; @@ -912,7 +911,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,  		struct kernel_lb_addr eloc;  		uint32_t bsize; -		block = udf_new_block(inode->i_sb, inode, +		block = udf_new_block(sb, inode,  				iinfo->i_location.partitionReferenceNum,  				iinfo->i_location.logicalBlockNum, &err);  		if (!block) @@ -923,17 +922,17 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,  		eloc.logicalBlockNum = block;  		eloc.partitionReferenceNum =  				iinfo->i_location.partitionReferenceNum; -		bsize = inode->i_sb->s_blocksize; +		bsize = sb->s_blocksize;  		iinfo->i_lenExtents = bsize;  		udf_add_aext(inode, &epos, &eloc, bsize, 0);  		brelse(epos.bh); -		block = udf_get_pblock(inode->i_sb, block, +		block = udf_get_pblock(sb, block,  				iinfo->i_location.partitionReferenceNum,  				0); -		epos.bh = udf_tgetblk(inode->i_sb, block); +		epos.bh = udf_tgetblk(sb, block);  		lock_buffer(epos.bh); -		memset(epos.bh->b_data, 0x00, inode->i_sb->s_blocksize); +		memset(epos.bh->b_data, 0x00, bsize);  		set_buffer_uptodate(epos.bh);  		unlock_buffer(epos.bh);  		mark_buffer_dirty_inode(epos.bh, inode); @@ -941,7 +940,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,  	} else  		ea = iinfo->i_ext.i_data + iinfo->i_lenEAttr; -	eoffset = inode->i_sb->s_blocksize - udf_ext0_offset(inode); +	eoffset = sb->s_blocksize - udf_ext0_offset(inode);  	pc = (struct pathComponent *)ea;  	if (*symname == '/') { @@ -981,7 +980,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,  		}  		if (pc->componentType == 5) { -			namelen = udf_put_filename(inode->i_sb, compstart, name, +			namelen = udf_put_filename(sb, compstart, name,  						   symname - compstart);  			if (!namelen)  				goto out_no_entry; @@ -1011,27 +1010,16 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,  	else  		udf_truncate_tail_extent(inode);  	mark_inode_dirty(inode); +	up_write(&iinfo->i_data_sem);  	fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);  	if (!fi)  		goto out_no_entry; -	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); +	cfi.icb.extLength = cpu_to_le32(sb->s_blocksize);  	cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location); -	bh = UDF_SB(inode->i_sb)->s_lvid_bh; -	if (bh) { -		struct logicalVolIntegrityDesc *lvid = -				(struct logicalVolIntegrityDesc *)bh->b_data; -		struct logicalVolHeaderDesc *lvhd; -		uint64_t uniqueID; -		lvhd = (struct logicalVolHeaderDesc *) -				lvid->logicalVolContentsUse; -		uniqueID = le64_to_cpu(lvhd->uniqueID); +	if (UDF_SB(inode->i_sb)->s_lvid_bh) {  		*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse = -			cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL); -		if (!(++uniqueID & 0x00000000FFFFFFFFUL)) -			uniqueID += 16; -		lvhd->uniqueID = cpu_to_le64(uniqueID); -		mark_buffer_dirty(bh); +			cpu_to_le32(lvid_get_unique_id(sb));  	}  	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);  	if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) @@ -1044,10 +1032,10 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,  out:  	kfree(name); -	unlock_kernel();  	return err;  out_no_entry: +	up_write(&iinfo->i_data_sem);  	inode_dec_link_count(inode);  	iput(inode);  	goto out; @@ -1060,36 +1048,16 @@ static int udf_link(struct dentry *old_dentry, struct inode *dir,  	struct udf_fileident_bh fibh;  	struct fileIdentDesc cfi, *fi;  	int err; -	struct buffer_head *bh; - -	lock_kernel(); -	if (inode->i_nlink >= (256 << sizeof(inode->i_nlink)) - 1) { -		unlock_kernel(); -		return -EMLINK; -	}  	fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);  	if (!fi) { -		unlock_kernel();  		return err;  	}  	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);  	cfi.icb.extLocation = cpu_to_lelb(UDF_I(inode)->i_location); -	bh = UDF_SB(inode->i_sb)->s_lvid_bh; -	if (bh) { -		struct logicalVolIntegrityDesc *lvid = -				(struct logicalVolIntegrityDesc *)bh->b_data; -		struct logicalVolHeaderDesc *lvhd; -		uint64_t uniqueID; -		lvhd = (struct logicalVolHeaderDesc *) -				(lvid->logicalVolContentsUse); -		uniqueID = le64_to_cpu(lvhd->uniqueID); +	if (UDF_SB(inode->i_sb)->s_lvid_bh) {  		*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse = -			cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL); -		if (!(++uniqueID & 0x00000000FFFFFFFFUL)) -			uniqueID += 16; -		lvhd->uniqueID = cpu_to_le64(uniqueID); -		mark_buffer_dirty(bh); +			cpu_to_le32(lvid_get_unique_id(inode->i_sb));  	}  	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);  	if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) @@ -1103,7 +1071,6 @@ static int udf_link(struct dentry *old_dentry, struct inode *dir,  	mark_inode_dirty(inode);  	ihold(inode);  	d_instantiate(dentry, inode); -	unlock_kernel();  	return 0;  } @@ -1124,7 +1091,6 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry,  	struct kernel_lb_addr tloc;  	struct udf_inode_info *old_iinfo = UDF_I(old_inode); -	lock_kernel();  	ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi);  	if (ofi) {  		if (ofibh.sbh != ofibh.ebh) @@ -1174,12 +1140,6 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry,  		if (udf_get_lb_pblock(old_inode->i_sb, &tloc, 0) !=  				old_dir->i_ino)  			goto end_rename; - -		retval = -EMLINK; -		if (!new_inode && -			new_dir->i_nlink >= -				(256 << sizeof(new_dir->i_nlink)) - 1) -			goto end_rename;  	}  	if (!nfi) {  		nfi = udf_add_entry(new_dir, new_dentry, &nfibh, &ncfi, @@ -1248,7 +1208,6 @@ end_rename:  			brelse(nfibh.ebh);  		brelse(nfibh.sbh);  	} -	unlock_kernel();  	return retval;  } @@ -1257,11 +1216,10 @@ static struct dentry *udf_get_parent(struct dentry *child)  {  	struct kernel_lb_addr tloc;  	struct inode *inode = NULL; -	struct qstr dotdot = {.name = "..", .len = 2}; +	struct qstr dotdot = QSTR_INIT("..", 2);  	struct fileIdentDesc cfi;  	struct udf_fileident_bh fibh; -	lock_kernel();  	if (!udf_find_entry(child->d_inode, &dotdot, &fibh, &cfi))  		goto out_unlock; @@ -1273,11 +1231,9 @@ static struct dentry *udf_get_parent(struct dentry *child)  	inode = udf_iget(child->d_inode->i_sb, &tloc);  	if (!inode)  		goto out_unlock; -	unlock_kernel();  	return d_obtain_alias(inode);  out_unlock: -	unlock_kernel();  	return ERR_PTR(-EACCES);  } @@ -1327,31 +1283,33 @@ static struct dentry *udf_fh_to_parent(struct super_block *sb,  				 fid->udf.parent_partref,  				 fid->udf.parent_generation);  } -static int udf_encode_fh(struct dentry *de, __u32 *fh, int *lenp, -			 int connectable) +static int udf_encode_fh(struct inode *inode, __u32 *fh, int *lenp, +			 struct inode *parent)  {  	int len = *lenp; -	struct inode *inode =  de->d_inode;  	struct kernel_lb_addr location = UDF_I(inode)->i_location;  	struct fid *fid = (struct fid *)fh;  	int type = FILEID_UDF_WITHOUT_PARENT; -	if (len < 3 || (connectable && len < 5)) -		return 255; +	if (parent && (len < 5)) { +		*lenp = 5; +		return FILEID_INVALID; +	} else if (len < 3) { +		*lenp = 3; +		return FILEID_INVALID; +	}  	*lenp = 3;  	fid->udf.block = location.logicalBlockNum;  	fid->udf.partref = location.partitionReferenceNum; +	fid->udf.parent_partref = 0;  	fid->udf.generation = inode->i_generation; -	if (connectable && !S_ISDIR(inode->i_mode)) { -		spin_lock(&de->d_lock); -		inode = de->d_parent->d_inode; -		location = UDF_I(inode)->i_location; +	if (parent) { +		location = UDF_I(parent)->i_location;  		fid->udf.parent_block = location.logicalBlockNum;  		fid->udf.parent_partref = location.partitionReferenceNum;  		fid->udf.parent_generation = inode->i_generation; -		spin_unlock(&de->d_lock);  		*lenp = 5;  		type = FILEID_UDF_WITH_PARENT;  	} @@ -1376,6 +1334,7 @@ const struct inode_operations udf_dir_inode_operations = {  	.rmdir				= udf_rmdir,  	.mknod				= udf_mknod,  	.rename				= udf_rename, +	.tmpfile			= udf_tmpfile,  };  const struct inode_operations udf_symlink_inode_operations = {  	.readlink	= generic_readlink, diff --git a/fs/udf/partition.c b/fs/udf/partition.c index 745eb209be0..d6caf01a209 100644 --- a/fs/udf/partition.c +++ b/fs/udf/partition.c @@ -25,6 +25,7 @@  #include <linux/fs.h>  #include <linux/string.h>  #include <linux/buffer_head.h> +#include <linux/mutex.h>  uint32_t udf_get_pblock(struct super_block *sb, uint32_t block,  			uint16_t partition, uint32_t offset) @@ -32,8 +33,8 @@ uint32_t udf_get_pblock(struct super_block *sb, uint32_t block,  	struct udf_sb_info *sbi = UDF_SB(sb);  	struct udf_part_map *map;  	if (partition >= sbi->s_partitions) { -		udf_debug("block=%d, partition=%d, offset=%d: " -			  "invalid partition\n", block, partition, offset); +		udf_debug("block=%d, partition=%d, offset=%d: invalid partition\n", +			  block, partition, offset);  		return 0xFFFFFFFF;  	}  	map = &sbi->s_partmaps[partition]; @@ -59,8 +60,8 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block,  	vdata = &map->s_type_specific.s_virtual;  	if (block > vdata->s_num_entries) { -		udf_debug("Trying to access block beyond end of VAT " -			  "(%d max %d)\n", block, vdata->s_num_entries); +		udf_debug("Trying to access block beyond end of VAT (%d max %d)\n", +			  block, vdata->s_num_entries);  		return 0xFFFFFFFF;  	} @@ -159,7 +160,9 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)  	struct udf_sb_info *sbi = UDF_SB(sb);  	u16 reallocationTableLen;  	struct buffer_head *bh; +	int ret = 0; +	mutex_lock(&sbi->s_alloc_mutex);  	for (i = 0; i < sbi->s_partitions; i++) {  		struct udf_part_map *map = &sbi->s_partmaps[i];  		if (old_block > map->s_partition_root && @@ -175,8 +178,10 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)  					break;  				} -			if (!st) -				return 1; +			if (!st) { +				ret = 1; +				goto out; +			}  			reallocationTableLen =  					le16_to_cpu(st->reallocationTableLen); @@ -207,14 +212,16 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)  						     ((old_block -  							map->s_partition_root) &  						     (sdata->s_packet_len - 1)); -					return 0; +					ret = 0; +					goto out;  				} else if (origLoc == packet) {  					*new_block = le32_to_cpu(  							entry->mappedLocation) +  						     ((old_block -  							map->s_partition_root) &  						     (sdata->s_packet_len - 1)); -					return 0; +					ret = 0; +					goto out;  				} else if (origLoc > packet)  					break;  			} @@ -251,20 +258,24 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)  					      st->mapEntry[k].mappedLocation) +  					((old_block - map->s_partition_root) &  					 (sdata->s_packet_len - 1)); -				return 0; +				ret = 0; +				goto out;  			} -			return 1; +			ret = 1; +			goto out;  		} /* if old_block */  	}  	if (i == sbi->s_partitions) {  		/* outside of partitions */  		/* for now, fail =) */ -		return 1; +		ret = 1;  	} -	return 0; +out: +	mutex_unlock(&sbi->s_alloc_mutex); +	return ret;  }  static uint32_t udf_try_read_meta(struct inode *inode, uint32_t block, @@ -310,9 +321,14 @@ uint32_t udf_get_pblock_meta25(struct super_block *sb, uint32_t block,  	/* We shouldn't mount such media... */  	BUG_ON(!inode);  	retblk = udf_try_read_meta(inode, block, partition, offset); -	if (retblk == 0xFFFFFFFF) { -		udf_warning(sb, __func__, "error reading from METADATA, " -			"trying to read from MIRROR"); +	if (retblk == 0xFFFFFFFF && mdata->s_metadata_fe) { +		udf_warn(sb, "error reading from METADATA, trying to read from MIRROR\n"); +		if (!(mdata->s_flags & MF_MIRROR_FE_LOADED)) { +			mdata->s_mirror_fe = udf_find_metadata_inode_efe(sb, +				mdata->s_mirror_file_loc, map->s_partition_num); +			mdata->s_flags |= MF_MIRROR_FE_LOADED; +		} +  		inode = mdata->s_mirror_fe;  		if (!inode)  			return 0xFFFFFFFF; diff --git a/fs/udf/super.c b/fs/udf/super.c index 4a5c7c61836..3286db047a4 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -48,7 +48,6 @@  #include <linux/stat.h>  #include <linux/cdrom.h>  #include <linux/nls.h> -#include <linux/smp_lock.h>  #include <linux/buffer_head.h>  #include <linux/vfs.h>  #include <linux/vmalloc.h> @@ -57,6 +56,7 @@  #include <linux/seq_file.h>  #include <linux/bitmap.h>  #include <linux/crc-itu-t.h> +#include <linux/log2.h>  #include <asm/byteorder.h>  #include "udf_sb.h" @@ -76,7 +76,10 @@  #define UDF_DEFAULT_BLOCKSIZE 2048 -static char error_buf[1024]; +#define VSD_FIRST_SECTOR_OFFSET		32768 +#define VSD_MAX_SECTOR_OFFSET		0x800000 + +enum { UDF_MAX_LINKS = 0xffff };  /* These are the "meat" - everything else is stuffing */  static int udf_fill_super(struct super_block *, void *, int); @@ -92,17 +95,27 @@ static void udf_open_lvid(struct super_block *);  static void udf_close_lvid(struct super_block *);  static unsigned int udf_count_free(struct super_block *);  static int udf_statfs(struct dentry *, struct kstatfs *); -static int udf_show_options(struct seq_file *, struct vfsmount *); -static void udf_error(struct super_block *sb, const char *function, -		      const char *fmt, ...); +static int udf_show_options(struct seq_file *, struct dentry *); -struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct udf_sb_info *sbi) +struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct super_block *sb)  { -	struct logicalVolIntegrityDesc *lvid = -		(struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data; -	__u32 number_of_partitions = le32_to_cpu(lvid->numOfPartitions); -	__u32 offset = number_of_partitions * 2 * -				sizeof(uint32_t)/sizeof(uint8_t); +	struct logicalVolIntegrityDesc *lvid; +	unsigned int partnum; +	unsigned int offset; + +	if (!UDF_SB(sb)->s_lvid_bh) +		return NULL; +	lvid = (struct logicalVolIntegrityDesc *)UDF_SB(sb)->s_lvid_bh->b_data; +	partnum = le32_to_cpu(lvid->numOfPartitions); +	if ((sb->s_blocksize - sizeof(struct logicalVolIntegrityDescImpUse) - +	     offsetof(struct logicalVolIntegrityDesc, impUse)) / +	     (2 * sizeof(uint32_t)) < partnum) { +		udf_err(sb, "Logical volume integrity descriptor corrupted " +			"(numOfPartitions = %u)!\n", partnum); +		return NULL; +	} +	/* The offset is to skip freeSpaceTable and sizeTable arrays */ +	offset = partnum * 2 * sizeof(uint32_t);  	return (struct logicalVolIntegrityDescImpUse *)&(lvid->impUse[offset]);  } @@ -120,6 +133,7 @@ static struct file_system_type udf_fstype = {  	.kill_sb	= kill_block_super,  	.fs_flags	= FS_REQUIRES_DEV,  }; +MODULE_ALIAS_FS("udf");  static struct kmem_cache *udf_inode_cachep; @@ -135,15 +149,24 @@ static struct inode *udf_alloc_inode(struct super_block *sb)  	ei->i_next_alloc_block = 0;  	ei->i_next_alloc_goal = 0;  	ei->i_strat4096 = 0; +	init_rwsem(&ei->i_data_sem); +	ei->cached_extent.lstart = -1; +	spin_lock_init(&ei->i_extent_cache_lock);  	return &ei->vfs_inode;  } -static void udf_destroy_inode(struct inode *inode) +static void udf_i_callback(struct rcu_head *head)  { +	struct inode *inode = container_of(head, struct inode, i_rcu);  	kmem_cache_free(udf_inode_cachep, UDF_I(inode));  } +static void udf_destroy_inode(struct inode *inode) +{ +	call_rcu(&inode->i_rcu, udf_i_callback); +} +  static void init_once(void *foo)  {  	struct udf_inode_info *ei = (struct udf_inode_info *)foo; @@ -152,7 +175,7 @@ static void init_once(void *foo)  	inode_init_once(&ei->vfs_inode);  } -static int init_inodecache(void) +static int __init init_inodecache(void)  {  	udf_inode_cachep = kmem_cache_create("udf_inode_cache",  					     sizeof(struct udf_inode_info), @@ -166,6 +189,11 @@ static int init_inodecache(void)  static void destroy_inodecache(void)  { +	/* +	 * Make sure all delayed rcu free inodes are flushed before we +	 * destroy cache. +	 */ +	rcu_barrier();  	kmem_cache_destroy(udf_inode_cachep);  } @@ -193,11 +221,11 @@ struct udf_options {  	unsigned int fileset;  	unsigned int rootdir;  	unsigned int flags; -	mode_t umask; -	gid_t gid; -	uid_t uid; -	mode_t fmode; -	mode_t dmode; +	umode_t umask; +	kgid_t gid; +	kuid_t uid; +	umode_t fmode; +	umode_t dmode;  	struct nls_table *nls_map;  }; @@ -237,9 +265,8 @@ static int udf_sb_alloc_partition_maps(struct super_block *sb, u32 count)  	sbi->s_partmaps = kcalloc(count, sizeof(struct udf_part_map),  				  GFP_KERNEL);  	if (!sbi->s_partmaps) { -		udf_error(sb, __func__, -			  "Unable to allocate space for %d partition maps", -			  count); +		udf_err(sb, "Unable to allocate space for %d partition maps\n", +			count);  		sbi->s_partitions = 0;  		return -ENOMEM;  	} @@ -248,9 +275,67 @@ static int udf_sb_alloc_partition_maps(struct super_block *sb, u32 count)  	return 0;  } -static int udf_show_options(struct seq_file *seq, struct vfsmount *mnt) +static void udf_sb_free_bitmap(struct udf_bitmap *bitmap) +{ +	int i; +	int nr_groups = bitmap->s_nr_groups; +	int size = sizeof(struct udf_bitmap) + (sizeof(struct buffer_head *) * +						nr_groups); + +	for (i = 0; i < nr_groups; i++) +		if (bitmap->s_block_bitmap[i]) +			brelse(bitmap->s_block_bitmap[i]); + +	if (size <= PAGE_SIZE) +		kfree(bitmap); +	else +		vfree(bitmap); +} + +static void udf_free_partition(struct udf_part_map *map) +{ +	int i; +	struct udf_meta_data *mdata; + +	if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) +		iput(map->s_uspace.s_table); +	if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) +		iput(map->s_fspace.s_table); +	if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) +		udf_sb_free_bitmap(map->s_uspace.s_bitmap); +	if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) +		udf_sb_free_bitmap(map->s_fspace.s_bitmap); +	if (map->s_partition_type == UDF_SPARABLE_MAP15) +		for (i = 0; i < 4; i++) +			brelse(map->s_type_specific.s_sparing.s_spar_map[i]); +	else if (map->s_partition_type == UDF_METADATA_MAP25) { +		mdata = &map->s_type_specific.s_metadata; +		iput(mdata->s_metadata_fe); +		mdata->s_metadata_fe = NULL; + +		iput(mdata->s_mirror_fe); +		mdata->s_mirror_fe = NULL; + +		iput(mdata->s_bitmap_fe); +		mdata->s_bitmap_fe = NULL; +	} +} + +static void udf_sb_free_partitions(struct super_block *sb)  { -	struct super_block *sb = mnt->mnt_sb; +	struct udf_sb_info *sbi = UDF_SB(sb); +	int i; +	if (sbi->s_partmaps == NULL) +		return; +	for (i = 0; i < sbi->s_partitions; i++) +		udf_free_partition(&sbi->s_partmaps[i]); +	kfree(sbi->s_partmaps); +	sbi->s_partmaps = NULL; +} + +static int udf_show_options(struct seq_file *seq, struct dentry *root) +{ +	struct super_block *sb = root->d_sb;  	struct udf_sb_info *sbi = UDF_SB(sb);  	if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT)) @@ -274,15 +359,15 @@ static int udf_show_options(struct seq_file *seq, struct vfsmount *mnt)  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_GID_IGNORE))  		seq_puts(seq, ",gid=ignore");  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_UID_SET)) -		seq_printf(seq, ",uid=%u", sbi->s_uid); +		seq_printf(seq, ",uid=%u", from_kuid(&init_user_ns, sbi->s_uid));  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_GID_SET)) -		seq_printf(seq, ",gid=%u", sbi->s_gid); +		seq_printf(seq, ",gid=%u", from_kgid(&init_user_ns, sbi->s_gid));  	if (sbi->s_umask != 0) -		seq_printf(seq, ",umask=%o", sbi->s_umask); +		seq_printf(seq, ",umask=%ho", sbi->s_umask);  	if (sbi->s_fmode != UDF_INVALID_MODE) -		seq_printf(seq, ",mode=%o", sbi->s_fmode); +		seq_printf(seq, ",mode=%ho", sbi->s_fmode);  	if (sbi->s_dmode != UDF_INVALID_MODE) -		seq_printf(seq, ",dmode=%o", sbi->s_dmode); +		seq_printf(seq, ",dmode=%ho", sbi->s_dmode);  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_SESSION_SET))  		seq_printf(seq, ",session=%u", sbi->s_session);  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_LASTBLOCK_SET)) @@ -420,6 +505,7 @@ static int udf_parse_options(char *options, struct udf_options *uopt,  	while ((p = strsep(&options, ",")) != NULL) {  		substring_t args[MAX_OPT_ARGS];  		int token; +		unsigned n;  		if (!*p)  			continue; @@ -431,7 +517,10 @@ static int udf_parse_options(char *options, struct udf_options *uopt,  		case Opt_bs:  			if (match_int(&args[0], &option))  				return 0; -			uopt->blocksize = option; +			n = option; +			if (n != 512 && n != 1024 && n != 2048 && n != 4096) +				return 0; +			uopt->blocksize = n;  			uopt->flags |= (1 << UDF_FLAG_BLOCKSIZE_SET);  			break;  		case Opt_unhide: @@ -455,13 +544,17 @@ static int udf_parse_options(char *options, struct udf_options *uopt,  		case Opt_gid:  			if (match_int(args, &option))  				return 0; -			uopt->gid = option; +			uopt->gid = make_kgid(current_user_ns(), option); +			if (!gid_valid(uopt->gid)) +				return 0;  			uopt->flags |= (1 << UDF_FLAG_GID_SET);  			break;  		case Opt_uid:  			if (match_int(args, &option))  				return 0; -			uopt->uid = option; +			uopt->uid = make_kuid(current_user_ns(), option); +			if (!uid_valid(uopt->uid)) +				return 0;  			uopt->flags |= (1 << UDF_FLAG_UID_SET);  			break;  		case Opt_umask: @@ -543,8 +636,7 @@ static int udf_parse_options(char *options, struct udf_options *uopt,  			uopt->dmode = option & 0777;  			break;  		default: -			printk(KERN_ERR "udf: bad mount option \"%s\" " -			       "or missing value\n", p); +			pr_err("bad mount option \"%s\" or missing value\n", p);  			return 0;  		}  	} @@ -556,6 +648,14 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options)  	struct udf_options uopt;  	struct udf_sb_info *sbi = UDF_SB(sb);  	int error = 0; +	struct logicalVolIntegrityDescImpUse *lvidiu = udf_sb_lvidiu(sb); + +	sync_filesystem(sb); +	if (lvidiu) { +		int write_rev = le16_to_cpu(lvidiu->minUDFWriteRev); +		if (write_rev > UDF_MAX_WRITE_VERSION && !(*flags & MS_RDONLY)) +			return -EACCES; +	}  	uopt.flags = sbi->s_flags;  	uopt.uid   = sbi->s_uid; @@ -567,19 +667,14 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options)  	if (!udf_parse_options(options, &uopt, true))  		return -EINVAL; -	lock_kernel(); +	write_lock(&sbi->s_cred_lock);  	sbi->s_flags = uopt.flags;  	sbi->s_uid   = uopt.uid;  	sbi->s_gid   = uopt.gid;  	sbi->s_umask = uopt.umask;  	sbi->s_fmode = uopt.fmode;  	sbi->s_dmode = uopt.dmode; - -	if (sbi->s_lvid_bh) { -		int write_rev = le16_to_cpu(udf_sb_lvidiu(sbi)->minUDFWriteRev); -		if (write_rev > UDF_MAX_WRITE_VERSION) -			*flags |= MS_RDONLY; -	} +	write_unlock(&sbi->s_cred_lock);  	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))  		goto out_unlock; @@ -590,7 +685,6 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options)  		udf_open_lvid(sb);  out_unlock: -	unlock_kernel();  	return error;  } @@ -599,7 +693,7 @@ out_unlock:  static loff_t udf_check_vsd(struct super_block *sb)  {  	struct volStructDesc *vsd = NULL; -	loff_t sector = 32768; +	loff_t sector = VSD_FIRST_SECTOR_OFFSET;  	int sectorsize;  	struct buffer_head *bh = NULL;  	int nsr02 = 0; @@ -617,8 +711,18 @@ static loff_t udf_check_vsd(struct super_block *sb)  	udf_debug("Starting at sector %u (%ld byte sectors)\n",  		  (unsigned int)(sector >> sb->s_blocksize_bits),  		  sb->s_blocksize); -	/* Process the sequence (if applicable) */ -	for (; !nsr02 && !nsr03; sector += sectorsize) { +	/* Process the sequence (if applicable). The hard limit on the sector +	 * offset is arbitrary, hopefully large enough so that all valid UDF +	 * filesystems will be recognised. There is no mention of an upper +	 * bound to the size of the volume recognition area in the standard. +	 *  The limit will prevent the code to read all the sectors of a +	 * specially crafted image (like a bluray disc full of CD001 sectors), +	 * potentially causing minutes or even hours of uninterruptible I/O +	 * activity. This actually happened with uninitialised SSD partitions +	 * (all 0xFF) before the check for the limit and all valid IDs were +	 * added */ +	for (; !nsr02 && !nsr03 && sector < VSD_MAX_SECTOR_OFFSET; +	     sector += sectorsize) {  		/* Read a block */  		bh = udf_tread(sb, sector >> sb->s_blocksize_bits);  		if (!bh) @@ -628,30 +732,23 @@ static loff_t udf_check_vsd(struct super_block *sb)  		vsd = (struct volStructDesc *)(bh->b_data +  					      (sector & (sb->s_blocksize - 1))); -		if (vsd->stdIdent[0] == 0) { -			brelse(bh); -			break; -		} else if (!strncmp(vsd->stdIdent, VSD_STD_ID_CD001, +		if (!strncmp(vsd->stdIdent, VSD_STD_ID_CD001,  				    VSD_STD_ID_LEN)) {  			switch (vsd->structType) {  			case 0:  				udf_debug("ISO9660 Boot Record found\n");  				break;  			case 1: -				udf_debug("ISO9660 Primary Volume Descriptor " -					  "found\n"); +				udf_debug("ISO9660 Primary Volume Descriptor found\n");  				break;  			case 2: -				udf_debug("ISO9660 Supplementary Volume " -					  "Descriptor found\n"); +				udf_debug("ISO9660 Supplementary Volume Descriptor found\n");  				break;  			case 3: -				udf_debug("ISO9660 Volume Partition Descriptor " -					  "found\n"); +				udf_debug("ISO9660 Volume Partition Descriptor found\n");  				break;  			case 255: -				udf_debug("ISO9660 Volume Descriptor Set " -					  "Terminator found\n"); +				udf_debug("ISO9660 Volume Descriptor Set Terminator found\n");  				break;  			default:  				udf_debug("ISO9660 VRS (%u) found\n", @@ -671,6 +768,17 @@ static loff_t udf_check_vsd(struct super_block *sb)  		else if (!strncmp(vsd->stdIdent, VSD_STD_ID_NSR03,  				    VSD_STD_ID_LEN))  			nsr03 = sector; +		else if (!strncmp(vsd->stdIdent, VSD_STD_ID_BOOT2, +				    VSD_STD_ID_LEN)) +			; /* nothing */ +		else if (!strncmp(vsd->stdIdent, VSD_STD_ID_CDW02, +				    VSD_STD_ID_LEN)) +			; /* nothing */ +		else { +			/* invalid id : end of volume recognition area */ +			brelse(bh); +			break; +		}  		brelse(bh);  	} @@ -678,7 +786,8 @@ static loff_t udf_check_vsd(struct super_block *sb)  		return nsr03;  	else if (nsr02)  		return nsr02; -	else if (sector - (sbi->s_session << sb->s_blocksize_bits) == 32768) +	else if (!bh && sector - (sbi->s_session << sb->s_blocksize_bits) == +			VSD_FIRST_SECTOR_OFFSET)  		return -1;  	else  		return 0; @@ -774,27 +883,38 @@ static int udf_find_fileset(struct super_block *sb,  	return 1;  } +/* + * Load primary Volume Descriptor Sequence + * + * Return <0 on error, 0 on success. -EAGAIN is special meaning next sequence + * should be tried. + */  static int udf_load_pvoldesc(struct super_block *sb, sector_t block)  {  	struct primaryVolDesc *pvoldesc;  	struct ustr *instr, *outstr;  	struct buffer_head *bh;  	uint16_t ident; -	int ret = 1; +	int ret = -ENOMEM;  	instr = kmalloc(sizeof(struct ustr), GFP_NOFS);  	if (!instr) -		return 1; +		return -ENOMEM;  	outstr = kmalloc(sizeof(struct ustr), GFP_NOFS);  	if (!outstr)  		goto out1;  	bh = udf_read_tagged(sb, block, block, &ident); -	if (!bh) +	if (!bh) { +		ret = -EAGAIN;  		goto out2; +	} -	BUG_ON(ident != TAG_IDENT_PVD); +	if (ident != TAG_IDENT_PVD) { +		ret = -EIO; +		goto out_bh; +	}  	pvoldesc = (struct primaryVolDesc *)bh->b_data; @@ -802,8 +922,7 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block)  			      pvoldesc->recordingDateAndTime)) {  #ifdef UDFFS_DEBUG  		struct timestamp *ts = &pvoldesc->recordingDateAndTime; -		udf_debug("recording time %04u/%02u/%02u" -			  " %02u:%02u (%x)\n", +		udf_debug("recording time %04u/%02u/%02u %02u:%02u (%x)\n",  			  le16_to_cpu(ts->year), ts->month, ts->day, ts->hour,  			  ts->minute, le16_to_cpu(ts->typeAndTimezone));  #endif @@ -814,15 +933,16 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block)  			strncpy(UDF_SB(sb)->s_volume_ident, outstr->u_name,  				outstr->u_len > 31 ? 31 : outstr->u_len);  			udf_debug("volIdent[] = '%s'\n", -					UDF_SB(sb)->s_volume_ident); +				  UDF_SB(sb)->s_volume_ident);  		}  	if (!udf_build_ustr(instr, pvoldesc->volSetIdent, 128))  		if (udf_CS0toUTF8(outstr, instr))  			udf_debug("volSetIdent[] = '%s'\n", outstr->u_name); -	brelse(bh);  	ret = 0; +out_bh: +	brelse(bh);  out2:  	kfree(outstr);  out1: @@ -830,64 +950,57 @@ out1:  	return ret;  } +struct inode *udf_find_metadata_inode_efe(struct super_block *sb, +					u32 meta_file_loc, u32 partition_num) +{ +	struct kernel_lb_addr addr; +	struct inode *metadata_fe; + +	addr.logicalBlockNum = meta_file_loc; +	addr.partitionReferenceNum = partition_num; + +	metadata_fe = udf_iget(sb, &addr); + +	if (metadata_fe == NULL) +		udf_warn(sb, "metadata inode efe not found\n"); +	else if (UDF_I(metadata_fe)->i_alloc_type != ICBTAG_FLAG_AD_SHORT) { +		udf_warn(sb, "metadata inode efe does not have short allocation descriptors!\n"); +		iput(metadata_fe); +		metadata_fe = NULL; +	} + +	return metadata_fe; +} +  static int udf_load_metadata_files(struct super_block *sb, int partition)  {  	struct udf_sb_info *sbi = UDF_SB(sb);  	struct udf_part_map *map;  	struct udf_meta_data *mdata;  	struct kernel_lb_addr addr; -	int fe_error = 0;  	map = &sbi->s_partmaps[partition];  	mdata = &map->s_type_specific.s_metadata;  	/* metadata address */ -	addr.logicalBlockNum =  mdata->s_meta_file_loc; -	addr.partitionReferenceNum = map->s_partition_num; -  	udf_debug("Metadata file location: block = %d part = %d\n", -			  addr.logicalBlockNum, addr.partitionReferenceNum); +		  mdata->s_meta_file_loc, map->s_partition_num); -	mdata->s_metadata_fe = udf_iget(sb, &addr); +	mdata->s_metadata_fe = udf_find_metadata_inode_efe(sb, +		mdata->s_meta_file_loc, map->s_partition_num);  	if (mdata->s_metadata_fe == NULL) { -		udf_warning(sb, __func__, "metadata inode efe not found, " -				"will try mirror inode."); -		fe_error = 1; -	} else if (UDF_I(mdata->s_metadata_fe)->i_alloc_type != -		 ICBTAG_FLAG_AD_SHORT) { -		udf_warning(sb, __func__, "metadata inode efe does not have " -			"short allocation descriptors!"); -		fe_error = 1; -		iput(mdata->s_metadata_fe); -		mdata->s_metadata_fe = NULL; -	} +		/* mirror file entry */ +		udf_debug("Mirror metadata file location: block = %d part = %d\n", +			  mdata->s_mirror_file_loc, map->s_partition_num); -	/* mirror file entry */ -	addr.logicalBlockNum = mdata->s_mirror_file_loc; -	addr.partitionReferenceNum = map->s_partition_num; +		mdata->s_mirror_fe = udf_find_metadata_inode_efe(sb, +			mdata->s_mirror_file_loc, map->s_partition_num); -	udf_debug("Mirror metadata file location: block = %d part = %d\n", -			  addr.logicalBlockNum, addr.partitionReferenceNum); - -	mdata->s_mirror_fe = udf_iget(sb, &addr); - -	if (mdata->s_mirror_fe == NULL) { -		if (fe_error) { -			udf_error(sb, __func__, "mirror inode efe not found " -			"and metadata inode is missing too, exiting..."); -			goto error_exit; -		} else -			udf_warning(sb, __func__, "mirror inode efe not found," -					" but metadata inode is OK"); -	} else if (UDF_I(mdata->s_mirror_fe)->i_alloc_type != -		 ICBTAG_FLAG_AD_SHORT) { -		udf_warning(sb, __func__, "mirror inode efe does not have " -			"short allocation descriptors!"); -		iput(mdata->s_mirror_fe); -		mdata->s_mirror_fe = NULL; -		if (fe_error) -			goto error_exit; +		if (mdata->s_mirror_fe == NULL) { +			udf_err(sb, "Both metadata and mirror metadata inode efe can not found\n"); +			return -EIO; +		}  	}  	/* @@ -900,29 +1013,21 @@ static int udf_load_metadata_files(struct super_block *sb, int partition)  		addr.partitionReferenceNum = map->s_partition_num;  		udf_debug("Bitmap file location: block = %d part = %d\n", -			addr.logicalBlockNum, addr.partitionReferenceNum); +			  addr.logicalBlockNum, addr.partitionReferenceNum);  		mdata->s_bitmap_fe = udf_iget(sb, &addr); -  		if (mdata->s_bitmap_fe == NULL) {  			if (sb->s_flags & MS_RDONLY) -				udf_warning(sb, __func__, "bitmap inode efe " -					"not found but it's ok since the disc" -					" is mounted read-only"); +				udf_warn(sb, "bitmap inode efe not found but it's ok since the disc is mounted read-only\n");  			else { -				udf_error(sb, __func__, "bitmap inode efe not " -					"found and attempted read-write mount"); -				goto error_exit; +				udf_err(sb, "bitmap inode efe not found and attempted read-write mount\n"); +				return -EIO;  			}  		}  	}  	udf_debug("udf_load_metadata_files Ok\n"); -  	return 0; - -error_exit: -	return 1;  }  static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh, @@ -959,19 +1064,13 @@ static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index)  		(sizeof(struct buffer_head *) * nr_groups);  	if (size <= PAGE_SIZE) -		bitmap = kmalloc(size, GFP_KERNEL); +		bitmap = kzalloc(size, GFP_KERNEL);  	else -		bitmap = vmalloc(size); /* TODO: get rid of vmalloc */ +		bitmap = vzalloc(size); /* TODO: get rid of vzalloc */ -	if (bitmap == NULL) { -		udf_error(sb, __func__, -			  "Unable to allocate space for bitmap " -			  "and %d buffer_head pointers", nr_groups); +	if (bitmap == NULL)  		return NULL; -	} -	memset(bitmap, 0x00, size); -	bitmap->s_block_bitmap = (struct buffer_head **)(bitmap + 1);  	bitmap->s_nr_groups = nr_groups;  	return bitmap;  } @@ -997,10 +1096,9 @@ static int udf_fill_partdesc_info(struct super_block *sb,  	if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_OVERWRITABLE))  		map->s_partition_flags |= UDF_PART_FLAG_OVERWRITABLE; -	udf_debug("Partition (%d type %x) starts at physical %d, " -		  "block length %d\n", p_index, -		  map->s_partition_type, map->s_partition_root, -		  map->s_partition_len); +	udf_debug("Partition (%d type %x) starts at physical %d, block length %d\n", +		  p_index, map->s_partition_type, +		  map->s_partition_root, map->s_partition_len);  	if (strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR02) &&  	    strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR03)) @@ -1017,26 +1115,24 @@ static int udf_fill_partdesc_info(struct super_block *sb,  		map->s_uspace.s_table = udf_iget(sb, &loc);  		if (!map->s_uspace.s_table) {  			udf_debug("cannot load unallocSpaceTable (part %d)\n", -					p_index); -			return 1; +				  p_index); +			return -EIO;  		}  		map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_TABLE;  		udf_debug("unallocSpaceTable (part %d) @ %ld\n", -				p_index, map->s_uspace.s_table->i_ino); +			  p_index, map->s_uspace.s_table->i_ino);  	}  	if (phd->unallocSpaceBitmap.extLength) {  		struct udf_bitmap *bitmap = udf_sb_alloc_bitmap(sb, p_index);  		if (!bitmap) -			return 1; +			return -ENOMEM;  		map->s_uspace.s_bitmap = bitmap; -		bitmap->s_extLength = le32_to_cpu( -				phd->unallocSpaceBitmap.extLength);  		bitmap->s_extPosition = le32_to_cpu(  				phd->unallocSpaceBitmap.extPosition);  		map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_BITMAP; -		udf_debug("unallocSpaceBitmap (part %d) @ %d\n", p_index, -						bitmap->s_extPosition); +		udf_debug("unallocSpaceBitmap (part %d) @ %d\n", +			  p_index, bitmap->s_extPosition);  	}  	if (phd->partitionIntegrityTable.extLength) @@ -1052,27 +1148,25 @@ static int udf_fill_partdesc_info(struct super_block *sb,  		map->s_fspace.s_table = udf_iget(sb, &loc);  		if (!map->s_fspace.s_table) {  			udf_debug("cannot load freedSpaceTable (part %d)\n", -				p_index); -			return 1; +				  p_index); +			return -EIO;  		}  		map->s_partition_flags |= UDF_PART_FLAG_FREED_TABLE;  		udf_debug("freedSpaceTable (part %d) @ %ld\n", -				p_index, map->s_fspace.s_table->i_ino); +			  p_index, map->s_fspace.s_table->i_ino);  	}  	if (phd->freedSpaceBitmap.extLength) {  		struct udf_bitmap *bitmap = udf_sb_alloc_bitmap(sb, p_index);  		if (!bitmap) -			return 1; +			return -ENOMEM;  		map->s_fspace.s_bitmap = bitmap; -		bitmap->s_extLength = le32_to_cpu( -				phd->freedSpaceBitmap.extLength);  		bitmap->s_extPosition = le32_to_cpu(  				phd->freedSpaceBitmap.extPosition);  		map->s_partition_flags |= UDF_PART_FLAG_FREED_BITMAP; -		udf_debug("freedSpaceBitmap (part %d) @ %d\n", p_index, -					bitmap->s_extPosition); +		udf_debug("freedSpaceBitmap (part %d) @ %d\n", +			  p_index, bitmap->s_extPosition);  	}  	return 0;  } @@ -1112,15 +1206,13 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)  	udf_find_vat_block(sb, p_index, type1_index, sbi->s_last_block);  	if (!sbi->s_vat_inode &&  	    sbi->s_last_block != blocks - 1) { -		printk(KERN_NOTICE "UDF-fs: Failed to read VAT inode from the" -		       " last recorded block (%lu), retrying with the last " -		       "block of the device (%lu).\n", -		       (unsigned long)sbi->s_last_block, -		       (unsigned long)blocks - 1); +		pr_notice("Failed to read VAT inode from the last recorded block (%lu), retrying with the last block of the device (%lu).\n", +			  (unsigned long)sbi->s_last_block, +			  (unsigned long)blocks - 1);  		udf_find_vat_block(sb, p_index, type1_index, blocks - 1);  	}  	if (!sbi->s_vat_inode) -		return 1; +		return -EIO;  	if (map->s_partition_type == UDF_VIRTUAL_MAP15) {  		map->s_type_specific.s_virtual.s_start_offset = 0; @@ -1132,7 +1224,7 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)  			pos = udf_block_map(sbi->s_vat_inode, 0);  			bh = sb_bread(sb, pos);  			if (!bh) -				return 1; +				return -EIO;  			vat20 = (struct virtualAllocationTable20 *)bh->b_data;  		} else {  			vat20 = (struct virtualAllocationTable20 *) @@ -1150,6 +1242,12 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)  	return 0;  } +/* + * Load partition descriptor block + * + * Returns <0 on error, 0 on success, -EAGAIN is special - try next descriptor + * sequence. + */  static int udf_load_partdesc(struct super_block *sb, sector_t block)  {  	struct buffer_head *bh; @@ -1159,13 +1257,15 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block)  	int i, type1_idx;  	uint16_t partitionNumber;  	uint16_t ident; -	int ret = 0; +	int ret;  	bh = udf_read_tagged(sb, block, block, &ident);  	if (!bh) -		return 1; -	if (ident != TAG_IDENT_PD) +		return -EAGAIN; +	if (ident != TAG_IDENT_PD) { +		ret = 0;  		goto out_bh; +	}  	p = (struct partitionDesc *)bh->b_data;  	partitionNumber = le16_to_cpu(p->partitionNumber); @@ -1184,16 +1284,22 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block)  	if (i >= sbi->s_partitions) {  		udf_debug("Partition (%d) not found in partition map\n",  			  partitionNumber); +		ret = 0;  		goto out_bh;  	}  	ret = udf_fill_partdesc_info(sb, p, i); +	if (ret < 0) +		goto out_bh;  	/*  	 * Now rescan for VIRTUAL or METADATA partitions when SPARABLE and  	 * PHYSICAL partitions are already set up  	 */  	type1_idx = i; +#ifdef UDFFS_DEBUG +	map = NULL; /* supress 'maybe used uninitialized' warning */ +#endif  	for (i = 0; i < sbi->s_partitions; i++) {  		map = &sbi->s_partmaps[i]; @@ -1204,66 +1310,124 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block)  			break;  	} -	if (i >= sbi->s_partitions) +	if (i >= sbi->s_partitions) { +		ret = 0;  		goto out_bh; +	}  	ret = udf_fill_partdesc_info(sb, p, i); -	if (ret) +	if (ret < 0)  		goto out_bh;  	if (map->s_partition_type == UDF_METADATA_MAP25) {  		ret = udf_load_metadata_files(sb, i); -		if (ret) { -			printk(KERN_ERR "UDF-fs: error loading MetaData " -			"partition map %d\n", i); +		if (ret < 0) { +			udf_err(sb, "error loading MetaData partition map %d\n", +				i);  			goto out_bh;  		}  	} else { -		ret = udf_load_vat(sb, i, type1_idx); -		if (ret) -			goto out_bh;  		/* -		 * Mark filesystem read-only if we have a partition with -		 * virtual map since we don't handle writing to it (we -		 * overwrite blocks instead of relocating them). +		 * If we have a partition with virtual map, we don't handle +		 * writing to it (we overwrite blocks instead of relocating +		 * them).  		 */ -		sb->s_flags |= MS_RDONLY; -		printk(KERN_NOTICE "UDF-fs: Filesystem marked read-only " -			"because writing to pseudooverwrite partition is " -			"not implemented.\n"); +		if (!(sb->s_flags & MS_RDONLY)) { +			ret = -EACCES; +			goto out_bh; +		} +		ret = udf_load_vat(sb, i, type1_idx); +		if (ret < 0) +			goto out_bh;  	} +	ret = 0;  out_bh:  	/* In case loading failed, we handle cleanup in udf_fill_super */  	brelse(bh);  	return ret;  } +static int udf_load_sparable_map(struct super_block *sb, +				 struct udf_part_map *map, +				 struct sparablePartitionMap *spm) +{ +	uint32_t loc; +	uint16_t ident; +	struct sparingTable *st; +	struct udf_sparing_data *sdata = &map->s_type_specific.s_sparing; +	int i; +	struct buffer_head *bh; + +	map->s_partition_type = UDF_SPARABLE_MAP15; +	sdata->s_packet_len = le16_to_cpu(spm->packetLength); +	if (!is_power_of_2(sdata->s_packet_len)) { +		udf_err(sb, "error loading logical volume descriptor: " +			"Invalid packet length %u\n", +			(unsigned)sdata->s_packet_len); +		return -EIO; +	} +	if (spm->numSparingTables > 4) { +		udf_err(sb, "error loading logical volume descriptor: " +			"Too many sparing tables (%d)\n", +			(int)spm->numSparingTables); +		return -EIO; +	} + +	for (i = 0; i < spm->numSparingTables; i++) { +		loc = le32_to_cpu(spm->locSparingTable[i]); +		bh = udf_read_tagged(sb, loc, loc, &ident); +		if (!bh) +			continue; + +		st = (struct sparingTable *)bh->b_data; +		if (ident != 0 || +		    strncmp(st->sparingIdent.ident, UDF_ID_SPARING, +			    strlen(UDF_ID_SPARING)) || +		    sizeof(*st) + le16_to_cpu(st->reallocationTableLen) > +							sb->s_blocksize) { +			brelse(bh); +			continue; +		} + +		sdata->s_spar_map[i] = bh; +	} +	map->s_partition_func = udf_get_pblock_spar15; +	return 0; +} +  static int udf_load_logicalvol(struct super_block *sb, sector_t block,  			       struct kernel_lb_addr *fileset)  {  	struct logicalVolDesc *lvd; -	int i, j, offset; +	int i, offset;  	uint8_t type;  	struct udf_sb_info *sbi = UDF_SB(sb);  	struct genericPartitionMap *gpm;  	uint16_t ident;  	struct buffer_head *bh; -	int ret = 0; +	unsigned int table_len; +	int ret;  	bh = udf_read_tagged(sb, block, block, &ident);  	if (!bh) -		return 1; +		return -EAGAIN;  	BUG_ON(ident != TAG_IDENT_LVD);  	lvd = (struct logicalVolDesc *)bh->b_data; - -	i = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps)); -	if (i != 0) { -		ret = i; +	table_len = le32_to_cpu(lvd->mapTableLength); +	if (table_len > sb->s_blocksize - sizeof(*lvd)) { +		udf_err(sb, "error loading logical volume descriptor: " +			"Partition table too long (%u > %lu)\n", table_len, +			sb->s_blocksize - sizeof(*lvd)); +		ret = -EIO;  		goto out_bh;  	} +	ret = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps)); +	if (ret) +		goto out_bh; +  	for (i = 0, offset = 0; -	     i < sbi->s_partitions && offset < le32_to_cpu(lvd->mapTableLength); +	     i < sbi->s_partitions && offset < table_len;  	     i++, offset += gpm->partitionMapLength) {  		struct udf_part_map *map = &sbi->s_partmaps[i];  		gpm = (struct genericPartitionMap *) @@ -1298,38 +1462,10 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,  			} else if (!strncmp(upm2->partIdent.ident,  						UDF_ID_SPARABLE,  						strlen(UDF_ID_SPARABLE))) { -				uint32_t loc; -				struct sparingTable *st; -				struct sparablePartitionMap *spm = -					(struct sparablePartitionMap *)gpm; - -				map->s_partition_type = UDF_SPARABLE_MAP15; -				map->s_type_specific.s_sparing.s_packet_len = -						le16_to_cpu(spm->packetLength); -				for (j = 0; j < spm->numSparingTables; j++) { -					struct buffer_head *bh2; - -					loc = le32_to_cpu( -						spm->locSparingTable[j]); -					bh2 = udf_read_tagged(sb, loc, loc, -							     &ident); -					map->s_type_specific.s_sparing. -							s_spar_map[j] = bh2; - -					if (bh2 == NULL) -						continue; - -					st = (struct sparingTable *)bh2->b_data; -					if (ident != 0 || strncmp( -						st->sparingIdent.ident, -						UDF_ID_SPARING, -						strlen(UDF_ID_SPARING))) { -						brelse(bh2); -						map->s_type_specific.s_sparing. -							s_spar_map[j] = NULL; -					} -				} -				map->s_partition_func = udf_get_pblock_spar15; +				ret = udf_load_sparable_map(sb, map, +					(struct sparablePartitionMap *)gpm); +				if (ret < 0) +					goto out_bh;  			} else if (!strncmp(upm2->partIdent.ident,  						UDF_ID_METADATA,  						strlen(UDF_ID_METADATA))) { @@ -1338,9 +1474,8 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,  				struct metadataPartitionMap *mdm =  						(struct metadataPartitionMap *)  						&(lvd->partitionMaps[offset]); -				udf_debug("Parsing Logical vol part %d " -					"type %d  id=%s\n", i, type, -					UDF_ID_METADATA); +				udf_debug("Parsing Logical vol part %d type %d  id=%s\n", +					  i, type, UDF_ID_METADATA);  				map->s_partition_type = UDF_METADATA_MAP25;  				map->s_partition_func = udf_get_pblock_meta25; @@ -1355,25 +1490,24 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,  					le32_to_cpu(mdm->allocUnitSize);  				mdata->s_align_unit_size =  					le16_to_cpu(mdm->alignUnitSize); -				mdata->s_dup_md_flag 	 = -					mdm->flags & 0x01; +				if (mdm->flags & 0x01) +					mdata->s_flags |= MF_DUPLICATE_MD;  				udf_debug("Metadata Ident suffix=0x%x\n", -					(le16_to_cpu( -					 ((__le16 *) -					      mdm->partIdent.identSuffix)[0]))); +					  le16_to_cpu(*(__le16 *) +						      mdm->partIdent.identSuffix));  				udf_debug("Metadata part num=%d\n", -					le16_to_cpu(mdm->partitionNum)); +					  le16_to_cpu(mdm->partitionNum));  				udf_debug("Metadata part alloc unit size=%d\n", -					le32_to_cpu(mdm->allocUnitSize)); +					  le32_to_cpu(mdm->allocUnitSize));  				udf_debug("Metadata file loc=%d\n", -					le32_to_cpu(mdm->metadataFileLoc)); +					  le32_to_cpu(mdm->metadataFileLoc));  				udf_debug("Mirror file loc=%d\n", -				       le32_to_cpu(mdm->metadataMirrorFileLoc)); +					  le32_to_cpu(mdm->metadataMirrorFileLoc));  				udf_debug("Bitmap file loc=%d\n", -				       le32_to_cpu(mdm->metadataBitmapFileLoc)); -				udf_debug("Duplicate Flag: %d %d\n", -					mdata->s_dup_md_flag, mdm->flags); +					  le32_to_cpu(mdm->metadataBitmapFileLoc)); +				udf_debug("Flags: %d %d\n", +					  mdata->s_flags, mdm->flags);  			} else {  				udf_debug("Unknown ident: %s\n",  					  upm2->partIdent.ident); @@ -1383,21 +1517,20 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,  			map->s_partition_num = le16_to_cpu(upm2->partitionNum);  		}  		udf_debug("Partition (%d:%d) type %d on volume %d\n", -			  i, map->s_partition_num, type, -			  map->s_volumeseqnum); +			  i, map->s_partition_num, type, map->s_volumeseqnum);  	}  	if (fileset) {  		struct long_ad *la = (struct long_ad *)&(lvd->logicalVolContentsUse[0]);  		*fileset = lelb_to_cpu(la->extLocation); -		udf_debug("FileSet found in LogicalVolDesc at block=%d, " -			  "partition=%d\n", fileset->logicalBlockNum, +		udf_debug("FileSet found in LogicalVolDesc at block=%d, partition=%d\n", +			  fileset->logicalBlockNum,  			  fileset->partitionReferenceNum);  	}  	if (lvd->integritySeqExt.extLength)  		udf_load_logicalvolint(sb, leea_to_cpu(lvd->integritySeqExt)); - +	ret = 0;  out_bh:  	brelse(bh);  	return ret; @@ -1435,22 +1568,18 @@ static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_  }  /* - * udf_process_sequence + * Process a main/reserve volume descriptor sequence. + *   @block		First block of first extent of the sequence. + *   @lastblock		Lastblock of first extent of the sequence. + *   @fileset		There we store extent containing root fileset   * - * PURPOSE - *	Process a main/reserve volume descriptor sequence. - * - * PRE-CONDITIONS - *	sb			Pointer to _locked_ superblock. - *	block			First block of first extent of the sequence. - *	lastblock		Lastblock of first extent of the sequence. - * - * HISTORY - *	July 1, 1997 - Andrew E. Mileski - *	Written, tested, and released. + * Returns <0 on error, 0 on success. -EAGAIN is special - try next descriptor + * sequence   */ -static noinline int udf_process_sequence(struct super_block *sb, long block, -				long lastblock, struct kernel_lb_addr *fileset) +static noinline int udf_process_sequence( +		struct super_block *sb, +		sector_t block, sector_t lastblock, +		struct kernel_lb_addr *fileset)  {  	struct buffer_head *bh = NULL;  	struct udf_vds_record vds[VDS_POS_LENGTH]; @@ -1461,6 +1590,7 @@ static noinline int udf_process_sequence(struct super_block *sb, long block,  	uint32_t vdsn;  	uint16_t ident;  	long next_s = 0, next_e = 0; +	int ret;  	memset(vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH); @@ -1472,10 +1602,10 @@ static noinline int udf_process_sequence(struct super_block *sb, long block,  		bh = udf_read_tagged(sb, block, block, &ident);  		if (!bh) { -			printk(KERN_ERR "udf: Block %Lu of volume descriptor " -			       "sequence is corrupted or we could not read " -			       "it.\n", (unsigned long long)block); -			return 1; +			udf_err(sb, +				"Block %llu of volume descriptor sequence is corrupted or we could not read it\n", +				(unsigned long long)block); +			return -EAGAIN;  		}  		/* Process each descriptor (ISO 13346 3/8.3-8.4) */ @@ -1547,15 +1677,20 @@ static noinline int udf_process_sequence(struct super_block *sb, long block,  	 * in a suitable order  	 */  	if (!vds[VDS_POS_PRIMARY_VOL_DESC].block) { -		printk(KERN_ERR "udf: Primary Volume Descriptor not found!\n"); -		return 1; +		udf_err(sb, "Primary Volume Descriptor not found!\n"); +		return -EAGAIN; +	} +	ret = udf_load_pvoldesc(sb, vds[VDS_POS_PRIMARY_VOL_DESC].block); +	if (ret < 0) +		return ret; + +	if (vds[VDS_POS_LOGICAL_VOL_DESC].block) { +		ret = udf_load_logicalvol(sb, +					  vds[VDS_POS_LOGICAL_VOL_DESC].block, +					  fileset); +		if (ret < 0) +			return ret;  	} -	if (udf_load_pvoldesc(sb, vds[VDS_POS_PRIMARY_VOL_DESC].block)) -		return 1; - -	if (vds[VDS_POS_LOGICAL_VOL_DESC].block && udf_load_logicalvol(sb, -	    vds[VDS_POS_LOGICAL_VOL_DESC].block, fileset)) -		return 1;  	if (vds[VDS_POS_PARTITION_DESC].block) {  		/* @@ -1564,19 +1699,27 @@ static noinline int udf_process_sequence(struct super_block *sb, long block,  		 */  		for (block = vds[VDS_POS_PARTITION_DESC].block;  		     block < vds[VDS_POS_TERMINATING_DESC].block; -		     block++) -			if (udf_load_partdesc(sb, block)) -				return 1; +		     block++) { +			ret = udf_load_partdesc(sb, block); +			if (ret < 0) +				return ret; +		}  	}  	return 0;  } +/* + * Load Volume Descriptor Sequence described by anchor in bh + * + * Returns <0 on error, 0 on success + */  static int udf_load_sequence(struct super_block *sb, struct buffer_head *bh,  			     struct kernel_lb_addr *fileset)  {  	struct anchorVolDescPtr *anchor; -	long main_s, main_e, reserve_s, reserve_e; +	sector_t main_s, main_e, reserve_s, reserve_e; +	int ret;  	anchor = (struct anchorVolDescPtr *)bh->b_data; @@ -1594,14 +1737,26 @@ static int udf_load_sequence(struct super_block *sb, struct buffer_head *bh,  	/* Process the main & reserve sequences */  	/* responsible for finding the PartitionDesc(s) */ -	if (!udf_process_sequence(sb, main_s, main_e, fileset)) -		return 1; -	return !udf_process_sequence(sb, reserve_s, reserve_e, fileset); +	ret = udf_process_sequence(sb, main_s, main_e, fileset); +	if (ret != -EAGAIN) +		return ret; +	udf_sb_free_partitions(sb); +	ret = udf_process_sequence(sb, reserve_s, reserve_e, fileset); +	if (ret < 0) { +		udf_sb_free_partitions(sb); +		/* No sequence was OK, return -EIO */ +		if (ret == -EAGAIN) +			ret = -EIO; +	} +	return ret;  }  /*   * Check whether there is an anchor block in the given block and   * load Volume Descriptor Sequence if so. + * + * Returns <0 on error, 0 on success, -EAGAIN is special - try next anchor + * block   */  static int udf_check_anchor_block(struct super_block *sb, sector_t block,  				  struct kernel_lb_addr *fileset) @@ -1613,33 +1768,40 @@ static int udf_check_anchor_block(struct super_block *sb, sector_t block,  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV) &&  	    udf_fixed_to_variable(block) >=  	    sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits) -		return 0; +		return -EAGAIN;  	bh = udf_read_tagged(sb, block, block, &ident);  	if (!bh) -		return 0; +		return -EAGAIN;  	if (ident != TAG_IDENT_AVDP) {  		brelse(bh); -		return 0; +		return -EAGAIN;  	}  	ret = udf_load_sequence(sb, bh, fileset);  	brelse(bh);  	return ret;  } -/* Search for an anchor volume descriptor pointer */ -static sector_t udf_scan_anchors(struct super_block *sb, sector_t lastblock, -				 struct kernel_lb_addr *fileset) +/* + * Search for an anchor volume descriptor pointer. + * + * Returns < 0 on error, 0 on success. -EAGAIN is special - try next set + * of anchors. + */ +static int udf_scan_anchors(struct super_block *sb, sector_t *lastblock, +			    struct kernel_lb_addr *fileset)  {  	sector_t last[6];  	int i;  	struct udf_sb_info *sbi = UDF_SB(sb);  	int last_count = 0; +	int ret;  	/* First try user provided anchor */  	if (sbi->s_anchor) { -		if (udf_check_anchor_block(sb, sbi->s_anchor, fileset)) -			return lastblock; +		ret = udf_check_anchor_block(sb, sbi->s_anchor, fileset); +		if (ret != -EAGAIN) +			return ret;  	}  	/*  	 * according to spec, anchor is in either: @@ -1648,39 +1810,46 @@ static sector_t udf_scan_anchors(struct super_block *sb, sector_t lastblock,  	 *     lastblock  	 *  however, if the disc isn't closed, it could be 512.  	 */ -	if (udf_check_anchor_block(sb, sbi->s_session + 256, fileset)) -		return lastblock; +	ret = udf_check_anchor_block(sb, sbi->s_session + 256, fileset); +	if (ret != -EAGAIN) +		return ret;  	/*  	 * The trouble is which block is the last one. Drives often misreport  	 * this so we try various possibilities.  	 */ -	last[last_count++] = lastblock; -	if (lastblock >= 1) -		last[last_count++] = lastblock - 1; -	last[last_count++] = lastblock + 1; -	if (lastblock >= 2) -		last[last_count++] = lastblock - 2; -	if (lastblock >= 150) -		last[last_count++] = lastblock - 150; -	if (lastblock >= 152) -		last[last_count++] = lastblock - 152; +	last[last_count++] = *lastblock; +	if (*lastblock >= 1) +		last[last_count++] = *lastblock - 1; +	last[last_count++] = *lastblock + 1; +	if (*lastblock >= 2) +		last[last_count++] = *lastblock - 2; +	if (*lastblock >= 150) +		last[last_count++] = *lastblock - 150; +	if (*lastblock >= 152) +		last[last_count++] = *lastblock - 152;  	for (i = 0; i < last_count; i++) {  		if (last[i] >= sb->s_bdev->bd_inode->i_size >>  				sb->s_blocksize_bits)  			continue; -		if (udf_check_anchor_block(sb, last[i], fileset)) -			return last[i]; +		ret = udf_check_anchor_block(sb, last[i], fileset); +		if (ret != -EAGAIN) { +			if (!ret) +				*lastblock = last[i]; +			return ret; +		}  		if (last[i] < 256)  			continue; -		if (udf_check_anchor_block(sb, last[i] - 256, fileset)) -			return last[i]; +		ret = udf_check_anchor_block(sb, last[i] - 256, fileset); +		if (ret != -EAGAIN) { +			if (!ret) +				*lastblock = last[i]; +			return ret; +		}  	}  	/* Finally try block 512 in case media is open */ -	if (udf_check_anchor_block(sb, sbi->s_session + 512, fileset)) -		return last[0]; -	return 0; +	return udf_check_anchor_block(sb, sbi->s_session + 512, fileset);  }  /* @@ -1688,54 +1857,59 @@ static sector_t udf_scan_anchors(struct super_block *sb, sector_t lastblock,   * area specified by it. The function expects sbi->s_lastblock to be the last   * block on the media.   * - * Return 1 if ok, 0 if not found. - * + * Return <0 on error, 0 if anchor found. -EAGAIN is special meaning anchor + * was not found.   */  static int udf_find_anchor(struct super_block *sb,  			   struct kernel_lb_addr *fileset)  { -	sector_t lastblock;  	struct udf_sb_info *sbi = UDF_SB(sb); +	sector_t lastblock = sbi->s_last_block; +	int ret; -	lastblock = udf_scan_anchors(sb, sbi->s_last_block, fileset); -	if (lastblock) +	ret = udf_scan_anchors(sb, &lastblock, fileset); +	if (ret != -EAGAIN)  		goto out;  	/* No anchor found? Try VARCONV conversion of block numbers */  	UDF_SET_FLAG(sb, UDF_FLAG_VARCONV); +	lastblock = udf_variable_to_fixed(sbi->s_last_block);  	/* Firstly, we try to not convert number of the last block */ -	lastblock = udf_scan_anchors(sb, -				udf_variable_to_fixed(sbi->s_last_block), -				fileset); -	if (lastblock) +	ret = udf_scan_anchors(sb, &lastblock, fileset); +	if (ret != -EAGAIN)  		goto out; +	lastblock = sbi->s_last_block;  	/* Secondly, we try with converted number of the last block */ -	lastblock = udf_scan_anchors(sb, sbi->s_last_block, fileset); -	if (!lastblock) { +	ret = udf_scan_anchors(sb, &lastblock, fileset); +	if (ret < 0) {  		/* VARCONV didn't help. Clear it. */  		UDF_CLEAR_FLAG(sb, UDF_FLAG_VARCONV); -		return 0;  	}  out: -	sbi->s_last_block = lastblock; -	return 1; +	if (ret == 0) +		sbi->s_last_block = lastblock; +	return ret;  }  /*   * Check Volume Structure Descriptor, find Anchor block and load Volume - * Descriptor Sequence + * Descriptor Sequence. + * + * Returns < 0 on error, 0 on success. -EAGAIN is special meaning anchor + * block was not found.   */  static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt,  			int silent, struct kernel_lb_addr *fileset)  {  	struct udf_sb_info *sbi = UDF_SB(sb);  	loff_t nsr_off; +	int ret;  	if (!sb_set_blocksize(sb, uopt->blocksize)) {  		if (!silent) -			printk(KERN_WARNING "UDF-fs: Bad block size\n"); -		return 0; +			udf_warn(sb, "Bad block size\n"); +		return -EINVAL;  	}  	sbi->s_last_block = uopt->lastblock;  	if (!uopt->novrs) { @@ -1743,12 +1917,13 @@ static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt,  		nsr_off = udf_check_vsd(sb);  		if (!nsr_off) {  			if (!silent) -				printk(KERN_WARNING "UDF-fs: No VRS found\n"); +				udf_warn(sb, "No VRS found\n");  			return 0;  		}  		if (nsr_off == -1) -			udf_debug("Failed to read byte 32768. Assuming open " -				  "disc. Skipping validity check\n"); +			udf_debug("Failed to read sector at offset %d. " +				  "Assuming open disc. Skipping validity " +				  "check\n", VSD_FIRST_SECTOR_OFFSET);  		if (!sbi->s_last_block)  			sbi->s_last_block = udf_get_last_block(sb);  	} else { @@ -1757,12 +1932,13 @@ static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt,  	/* Look for anchor block and load Volume Descriptor Sequence */  	sbi->s_anchor = uopt->anchor; -	if (!udf_find_anchor(sb, fileset)) { -		if (!silent) -			printk(KERN_WARNING "UDF-fs: No anchor found\n"); -		return 0; +	ret = udf_find_anchor(sb, fileset); +	if (ret < 0) { +		if (!silent && ret == -EAGAIN) +			udf_warn(sb, "No anchor found\n"); +		return ret;  	} -	return 1; +	return 0;  }  static void udf_open_lvid(struct super_block *sb) @@ -1775,8 +1951,11 @@ static void udf_open_lvid(struct super_block *sb)  	if (!bh)  		return;  	lvid = (struct logicalVolIntegrityDesc *)bh->b_data; -	lvidiu = udf_sb_lvidiu(sbi); +	lvidiu = udf_sb_lvidiu(sb); +	if (!lvidiu) +		return; +	mutex_lock(&sbi->s_alloc_mutex);  	lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;  	lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;  	udf_time_to_disk_stamp(&lvid->recordingDateAndTime, @@ -1790,6 +1969,9 @@ static void udf_open_lvid(struct super_block *sb)  	lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);  	mark_buffer_dirty(bh);  	sbi->s_lvid_dirty = 0; +	mutex_unlock(&sbi->s_alloc_mutex); +	/* Make opening of filesystem visible on the media immediately */ +	sync_dirty_buffer(bh);  }  static void udf_close_lvid(struct super_block *sb) @@ -1801,9 +1983,12 @@ static void udf_close_lvid(struct super_block *sb)  	if (!bh)  		return; -  	lvid = (struct logicalVolIntegrityDesc *)bh->b_data; -	lvidiu = udf_sb_lvidiu(sbi); +	lvidiu = udf_sb_lvidiu(sb); +	if (!lvidiu) +		return; + +	mutex_lock(&sbi->s_alloc_mutex);  	lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;  	lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;  	udf_time_to_disk_stamp(&lvid->recordingDateAndTime, CURRENT_TIME); @@ -1820,79 +2005,64 @@ static void udf_close_lvid(struct super_block *sb)  				le16_to_cpu(lvid->descTag.descCRCLength)));  	lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); +	/* +	 * We set buffer uptodate unconditionally here to avoid spurious +	 * warnings from mark_buffer_dirty() when previous EIO has marked +	 * the buffer as !uptodate +	 */ +	set_buffer_uptodate(bh);  	mark_buffer_dirty(bh);  	sbi->s_lvid_dirty = 0; +	mutex_unlock(&sbi->s_alloc_mutex); +	/* Make closing of filesystem visible on the media immediately */ +	sync_dirty_buffer(bh);  } -static void udf_sb_free_bitmap(struct udf_bitmap *bitmap) +u64 lvid_get_unique_id(struct super_block *sb)  { -	int i; -	int nr_groups = bitmap->s_nr_groups; -	int size = sizeof(struct udf_bitmap) + (sizeof(struct buffer_head *) * -						nr_groups); - -	for (i = 0; i < nr_groups; i++) -		if (bitmap->s_block_bitmap[i]) -			brelse(bitmap->s_block_bitmap[i]); - -	if (size <= PAGE_SIZE) -		kfree(bitmap); -	else -		vfree(bitmap); -} +	struct buffer_head *bh; +	struct udf_sb_info *sbi = UDF_SB(sb); +	struct logicalVolIntegrityDesc *lvid; +	struct logicalVolHeaderDesc *lvhd; +	u64 uniqueID; +	u64 ret; -static void udf_free_partition(struct udf_part_map *map) -{ -	int i; -	struct udf_meta_data *mdata; +	bh = sbi->s_lvid_bh; +	if (!bh) +		return 0; -	if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) -		iput(map->s_uspace.s_table); -	if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) -		iput(map->s_fspace.s_table); -	if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) -		udf_sb_free_bitmap(map->s_uspace.s_bitmap); -	if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) -		udf_sb_free_bitmap(map->s_fspace.s_bitmap); -	if (map->s_partition_type == UDF_SPARABLE_MAP15) -		for (i = 0; i < 4; i++) -			brelse(map->s_type_specific.s_sparing.s_spar_map[i]); -	else if (map->s_partition_type == UDF_METADATA_MAP25) { -		mdata = &map->s_type_specific.s_metadata; -		iput(mdata->s_metadata_fe); -		mdata->s_metadata_fe = NULL; +	lvid = (struct logicalVolIntegrityDesc *)bh->b_data; +	lvhd = (struct logicalVolHeaderDesc *)lvid->logicalVolContentsUse; -		iput(mdata->s_mirror_fe); -		mdata->s_mirror_fe = NULL; +	mutex_lock(&sbi->s_alloc_mutex); +	ret = uniqueID = le64_to_cpu(lvhd->uniqueID); +	if (!(++uniqueID & 0xFFFFFFFF)) +		uniqueID += 16; +	lvhd->uniqueID = cpu_to_le64(uniqueID); +	mutex_unlock(&sbi->s_alloc_mutex); +	mark_buffer_dirty(bh); -		iput(mdata->s_bitmap_fe); -		mdata->s_bitmap_fe = NULL; -	} +	return ret;  }  static int udf_fill_super(struct super_block *sb, void *options, int silent)  { -	int i; -	int ret; +	int ret = -EINVAL;  	struct inode *inode = NULL;  	struct udf_options uopt;  	struct kernel_lb_addr rootdir, fileset;  	struct udf_sb_info *sbi; -	lock_kernel(); -  	uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT); -	uopt.uid = -1; -	uopt.gid = -1; +	uopt.uid = INVALID_UID; +	uopt.gid = INVALID_GID;  	uopt.umask = 0;  	uopt.fmode = UDF_INVALID_MODE;  	uopt.dmode = UDF_INVALID_MODE;  	sbi = kzalloc(sizeof(struct udf_sb_info), GFP_KERNEL); -	if (!sbi) { -		unlock_kernel(); +	if (!sbi)  		return -ENOMEM; -	}  	sb->s_fs_info = sbi; @@ -1903,8 +2073,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)  	if (uopt.flags & (1 << UDF_FLAG_UTF8) &&  	    uopt.flags & (1 << UDF_FLAG_NLS_MAP)) { -		udf_error(sb, "udf_read_super", -			  "utf8 cannot be combined with iocharset\n"); +		udf_err(sb, "utf8 cannot be combined with iocharset\n");  		goto error_out;  	}  #ifdef CONFIG_UDF_NLS @@ -1929,6 +2098,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)  	sbi->s_fmode = uopt.fmode;  	sbi->s_dmode = uopt.dmode;  	sbi->s_nls_map = uopt.nls_map; +	rwlock_init(&sbi->s_cred_lock);  	if (uopt.session == 0xFFFFFFFF)  		sbi->s_session = udf_get_last_session(sb); @@ -1941,7 +2111,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)  	sb->s_op = &udf_sb_ops;  	sb->s_export_op = &udf_export_ops; -	sb->s_dirt = 0;  	sb->s_magic = UDF_SUPER_MAGIC;  	sb->s_time_gran = 1000; @@ -1950,17 +2119,21 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)  	} else {  		uopt.blocksize = bdev_logical_block_size(sb->s_bdev);  		ret = udf_load_vrs(sb, &uopt, silent, &fileset); -		if (!ret && uopt.blocksize != UDF_DEFAULT_BLOCKSIZE) { +		if (ret == -EAGAIN && uopt.blocksize != UDF_DEFAULT_BLOCKSIZE) {  			if (!silent) -				printk(KERN_NOTICE -				       "UDF-fs: Rescanning with blocksize " -				       "%d\n", UDF_DEFAULT_BLOCKSIZE); +				pr_notice("Rescanning with blocksize %d\n", +					  UDF_DEFAULT_BLOCKSIZE); +			brelse(sbi->s_lvid_bh); +			sbi->s_lvid_bh = NULL;  			uopt.blocksize = UDF_DEFAULT_BLOCKSIZE;  			ret = udf_load_vrs(sb, &uopt, silent, &fileset);  		}  	} -	if (!ret) { -		printk(KERN_WARNING "UDF-fs: No partition found (1)\n"); +	if (ret < 0) { +		if (ret == -EAGAIN) { +			udf_warn(sb, "No partition found (1)\n"); +			ret = -EINVAL; +		}  		goto error_out;  	} @@ -1968,20 +2141,27 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)  	if (sbi->s_lvid_bh) {  		struct logicalVolIntegrityDescImpUse *lvidiu = -							udf_sb_lvidiu(sbi); -		uint16_t minUDFReadRev = le16_to_cpu(lvidiu->minUDFReadRev); -		uint16_t minUDFWriteRev = le16_to_cpu(lvidiu->minUDFWriteRev); -		/* uint16_t maxUDFWriteRev = -				le16_to_cpu(lvidiu->maxUDFWriteRev); */ +							udf_sb_lvidiu(sb); +		uint16_t minUDFReadRev; +		uint16_t minUDFWriteRev; +		if (!lvidiu) { +			ret = -EINVAL; +			goto error_out; +		} +		minUDFReadRev = le16_to_cpu(lvidiu->minUDFReadRev); +		minUDFWriteRev = le16_to_cpu(lvidiu->minUDFWriteRev);  		if (minUDFReadRev > UDF_MAX_READ_VERSION) { -			printk(KERN_ERR "UDF-fs: minUDFReadRev=%x " -					"(max is %x)\n", -			       le16_to_cpu(lvidiu->minUDFReadRev), -			       UDF_MAX_READ_VERSION); +			udf_err(sb, "minUDFReadRev=%x (max is %x)\n", +				minUDFReadRev, +				UDF_MAX_READ_VERSION); +			ret = -EINVAL; +			goto error_out; +		} else if (minUDFWriteRev > UDF_MAX_WRITE_VERSION && +			   !(sb->s_flags & MS_RDONLY)) { +			ret = -EACCES;  			goto error_out; -		} else if (minUDFWriteRev > UDF_MAX_WRITE_VERSION) -			sb->s_flags |= MS_RDONLY; +		}  		sbi->s_udfrev = minUDFWriteRev; @@ -1992,28 +2172,30 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)  	}  	if (!sbi->s_partitions) { -		printk(KERN_WARNING "UDF-fs: No partition found (2)\n"); +		udf_warn(sb, "No partition found (2)\n"); +		ret = -EINVAL;  		goto error_out;  	}  	if (sbi->s_partmaps[sbi->s_partition].s_partition_flags & -			UDF_PART_FLAG_READ_ONLY) { -		printk(KERN_NOTICE "UDF-fs: Partition marked readonly; " -				   "forcing readonly mount\n"); -		sb->s_flags |= MS_RDONLY; +			UDF_PART_FLAG_READ_ONLY && +	    !(sb->s_flags & MS_RDONLY)) { +		ret = -EACCES; +		goto error_out;  	}  	if (udf_find_fileset(sb, &fileset, &rootdir)) { -		printk(KERN_WARNING "UDF-fs: No fileset found\n"); +		udf_warn(sb, "No fileset found\n"); +		ret = -EINVAL;  		goto error_out;  	}  	if (!silent) {  		struct timestamp ts;  		udf_time_to_disk_stamp(&ts, sbi->s_record_time); -		udf_info("UDF: Mounting volume '%s', " -			 "timestamp %04u/%02u/%02u %02u:%02u (%x)\n", -			 sbi->s_volume_ident, le16_to_cpu(ts.year), ts.month, ts.day, +		udf_info("Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n", +			 sbi->s_volume_ident, +			 le16_to_cpu(ts.year), ts.month, ts.day,  			 ts.hour, ts.minute, le16_to_cpu(ts.typeAndTimezone));  	}  	if (!(sb->s_flags & MS_RDONLY)) @@ -2024,29 +2206,26 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)  	/* perhaps it's not extensible enough, but for now ... */  	inode = udf_iget(sb, &rootdir);  	if (!inode) { -		printk(KERN_ERR "UDF-fs: Error in udf_iget, block=%d, " -				"partition=%d\n", +		udf_err(sb, "Error in udf_iget, block=%d, partition=%d\n",  		       rootdir.logicalBlockNum, rootdir.partitionReferenceNum); +		ret = -EIO;  		goto error_out;  	}  	/* Allocate a dentry for the root inode */ -	sb->s_root = d_alloc_root(inode); +	sb->s_root = d_make_root(inode);  	if (!sb->s_root) { -		printk(KERN_ERR "UDF-fs: Couldn't allocate root dentry\n"); -		iput(inode); +		udf_err(sb, "Couldn't allocate root dentry\n"); +		ret = -ENOMEM;  		goto error_out;  	}  	sb->s_maxbytes = MAX_LFS_FILESIZE; -	unlock_kernel(); +	sb->s_max_links = UDF_MAX_LINKS;  	return 0;  error_out:  	if (sbi->s_vat_inode)  		iput(sbi->s_vat_inode); -	if (sbi->s_partitions) -		for (i = 0; i < sbi->s_partitions; i++) -			udf_free_partition(&sbi->s_partmaps[i]);  #ifdef CONFIG_UDF_NLS  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))  		unload_nls(sbi->s_nls_map); @@ -2054,57 +2233,53 @@ error_out:  	if (!(sb->s_flags & MS_RDONLY))  		udf_close_lvid(sb);  	brelse(sbi->s_lvid_bh); - -	kfree(sbi->s_partmaps); +	udf_sb_free_partitions(sb);  	kfree(sbi);  	sb->s_fs_info = NULL; -	unlock_kernel(); -	return -EINVAL; +	return ret;  } -static void udf_error(struct super_block *sb, const char *function, -		      const char *fmt, ...) +void _udf_err(struct super_block *sb, const char *function, +	      const char *fmt, ...)  { +	struct va_format vaf;  	va_list args; -	if (!(sb->s_flags & MS_RDONLY)) { -		/* mark sb error */ -		sb->s_dirt = 1; -	}  	va_start(args, fmt); -	vsnprintf(error_buf, sizeof(error_buf), fmt, args); + +	vaf.fmt = fmt; +	vaf.va = &args; + +	pr_err("error (device %s): %s: %pV", sb->s_id, function, &vaf); +  	va_end(args); -	printk(KERN_CRIT "UDF-fs error (device %s): %s: %s\n", -		sb->s_id, function, error_buf);  } -void udf_warning(struct super_block *sb, const char *function, -		 const char *fmt, ...) +void _udf_warn(struct super_block *sb, const char *function, +	       const char *fmt, ...)  { +	struct va_format vaf;  	va_list args;  	va_start(args, fmt); -	vsnprintf(error_buf, sizeof(error_buf), fmt, args); + +	vaf.fmt = fmt; +	vaf.va = &args; + +	pr_warn("warning (device %s): %s: %pV", sb->s_id, function, &vaf); +  	va_end(args); -	printk(KERN_WARNING "UDF-fs warning (device %s): %s: %s\n", -	       sb->s_id, function, error_buf);  }  static void udf_put_super(struct super_block *sb)  { -	int i;  	struct udf_sb_info *sbi;  	sbi = UDF_SB(sb); -	lock_kernel(); -  	if (sbi->s_vat_inode)  		iput(sbi->s_vat_inode); -	if (sbi->s_partitions) -		for (i = 0; i < sbi->s_partitions; i++) -			udf_free_partition(&sbi->s_partmaps[i]);  #ifdef CONFIG_UDF_NLS  	if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))  		unload_nls(sbi->s_nls_map); @@ -2112,11 +2287,9 @@ static void udf_put_super(struct super_block *sb)  	if (!(sb->s_flags & MS_RDONLY))  		udf_close_lvid(sb);  	brelse(sbi->s_lvid_bh); -	kfree(sbi->s_partmaps); +	udf_sb_free_partitions(sb);  	kfree(sb->s_fs_info);  	sb->s_fs_info = NULL; - -	unlock_kernel();  }  static int udf_sync_fs(struct super_block *sb, int wait) @@ -2130,7 +2303,6 @@ static int udf_sync_fs(struct super_block *sb, int wait)  		 * the buffer for IO  		 */  		mark_buffer_dirty(sbi->s_lvid_bh); -		sb->s_dirt = 0;  		sbi->s_lvid_dirty = 0;  	}  	mutex_unlock(&sbi->s_alloc_mutex); @@ -2145,11 +2317,7 @@ static int udf_statfs(struct dentry *dentry, struct kstatfs *buf)  	struct logicalVolIntegrityDescImpUse *lvidiu;  	u64 id = huge_encode_dev(sb->s_bdev->bd_dev); -	if (sbi->s_lvid_bh != NULL) -		lvidiu = udf_sb_lvidiu(sbi); -	else -		lvidiu = NULL; - +	lvidiu = udf_sb_lvidiu(sb);  	buf->f_type = UDF_SUPER_MAGIC;  	buf->f_bsize = sb->s_blocksize;  	buf->f_blocks = sbi->s_partmaps[sbi->s_partition].s_partition_len; @@ -2179,18 +2347,16 @@ static unsigned int udf_count_free_bitmap(struct super_block *sb,  	uint16_t ident;  	struct spaceBitmapDesc *bm; -	lock_kernel(); -  	loc.logicalBlockNum = bitmap->s_extPosition;  	loc.partitionReferenceNum = UDF_SB(sb)->s_partition;  	bh = udf_read_ptagged(sb, &loc, 0, &ident);  	if (!bh) { -		printk(KERN_ERR "udf: udf_count_free failed\n"); +		udf_err(sb, "udf_count_free failed\n");  		goto out;  	} else if (ident != TAG_IDENT_SBD) {  		brelse(bh); -		printk(KERN_ERR "udf: udf_count_free failed\n"); +		udf_err(sb, "udf_count_free failed\n");  		goto out;  	} @@ -2217,10 +2383,7 @@ static unsigned int udf_count_free_bitmap(struct super_block *sb,  		}  	}  	brelse(bh); -  out: -	unlock_kernel(); -  	return accum;  } @@ -2233,8 +2396,7 @@ static unsigned int udf_count_free_table(struct super_block *sb,  	int8_t etype;  	struct extent_position epos; -	lock_kernel(); - +	mutex_lock(&UDF_SB(sb)->s_alloc_mutex);  	epos.block = UDF_I(table)->i_location;  	epos.offset = sizeof(struct unallocSpaceEntry);  	epos.bh = NULL; @@ -2243,8 +2405,7 @@ static unsigned int udf_count_free_table(struct super_block *sb,  		accum += (elen >> table->i_sb->s_blocksize_bits);  	brelse(epos.bh); - -	unlock_kernel(); +	mutex_unlock(&UDF_SB(sb)->s_alloc_mutex);  	return accum;  } diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c index 16064787d2b..d7c6dbe4194 100644 --- a/fs/udf/symlink.c +++ b/fs/udf/symlink.c @@ -27,7 +27,6 @@  #include <linux/mm.h>  #include <linux/stat.h>  #include <linux/pagemap.h> -#include <linux/smp_lock.h>  #include <linux/buffer_head.h>  #include "udf_i.h" @@ -42,10 +41,16 @@ static void udf_pc_to_char(struct super_block *sb, unsigned char *from,  		pc = (struct pathComponent *)(from + elen);  		switch (pc->componentType) {  		case 1: -			if (pc->lengthComponentIdent == 0) { -				p = to; -				*p++ = '/'; -			} +			/* +			 * Symlink points to some place which should be agreed + 			 * upon between originator and receiver of the media. Ignore. +			 */ +			if (pc->lengthComponentIdent > 0) +				break; +			/* Fall through */ +		case 2: +			p = to; +			*p++ = '/';  			break;  		case 3:  			memcpy(p, "../", 3); @@ -78,13 +83,16 @@ static int udf_symlink_filler(struct file *file, struct page *page)  	int err = -EIO;  	unsigned char *p = kmap(page);  	struct udf_inode_info *iinfo; +	uint32_t pos; -	lock_kernel();  	iinfo = UDF_I(inode); +	pos = udf_block_map(inode, 0); + +	down_read(&iinfo->i_data_sem);  	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {  		symlink = iinfo->i_ext.i_data + iinfo->i_lenEAttr;  	} else { -		bh = sb_bread(inode->i_sb, udf_block_map(inode, 0)); +		bh = sb_bread(inode->i_sb, pos);  		if (!bh)  			goto out; @@ -95,14 +103,14 @@ static int udf_symlink_filler(struct file *file, struct page *page)  	udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p);  	brelse(bh); -	unlock_kernel(); +	up_read(&iinfo->i_data_sem);  	SetPageUptodate(page);  	kunmap(page);  	unlock_page(page);  	return 0;  out: -	unlock_kernel(); +	up_read(&iinfo->i_data_sem);  	SetPageError(page);  	kunmap(page);  	unlock_page(page); diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c index 225527cdc88..8a9657d7f7c 100644 --- a/fs/udf/truncate.c +++ b/fs/udf/truncate.c @@ -95,23 +95,21 @@ void udf_truncate_tail_extent(struct inode *inode)  		lbcount += elen;  		if (lbcount > inode->i_size) {  			if (lbcount - inode->i_size >= inode->i_sb->s_blocksize) -				printk(KERN_WARNING -				       "udf_truncate_tail_extent(): Too long " -				       "extent after EOF in inode %u: i_size: " -				       "%Ld lbcount: %Ld extent %u+%u\n", -				       (unsigned)inode->i_ino, -				       (long long)inode->i_size, -				       (long long)lbcount, -				       (unsigned)eloc.logicalBlockNum, -				       (unsigned)elen); +				udf_warn(inode->i_sb, +					 "Too long extent after EOF in inode %u: i_size: %lld lbcount: %lld extent %u+%u\n", +					 (unsigned)inode->i_ino, +					 (long long)inode->i_size, +					 (long long)lbcount, +					 (unsigned)eloc.logicalBlockNum, +					 (unsigned)elen);  			nelen = elen - (lbcount - inode->i_size);  			epos.offset -= adsize;  			extent_trunc(inode, &epos, &eloc, etype, elen, nelen);  			epos.offset += adsize;  			if (udf_next_aext(inode, &epos, &eloc, &elen, 1) != -1) -				printk(KERN_ERR "udf_truncate_tail_extent(): " -				       "Extent after EOF in inode %u.\n", -				       (unsigned)inode->i_ino); +				udf_err(inode->i_sb, +					"Extent after EOF in inode %u\n", +					(unsigned)inode->i_ino);  			break;  		}  	} @@ -197,6 +195,11 @@ static void udf_update_alloc_ext_desc(struct inode *inode,  	mark_buffer_dirty_inode(epos->bh, inode);  } +/* + * Truncate extents of inode to inode->i_size. This function can be used only + * for making file shorter. For making file longer, udf_extend_file() has to + * be used. + */  void udf_truncate_extents(struct inode *inode)  {  	struct extent_position epos; @@ -219,96 +222,65 @@ void udf_truncate_extents(struct inode *inode)  	etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset);  	byte_offset = (offset << sb->s_blocksize_bits) +  		(inode->i_size & (sb->s_blocksize - 1)); -	if (etype != -1) { -		epos.offset -= adsize; -		extent_trunc(inode, &epos, &eloc, etype, elen, byte_offset); -		epos.offset += adsize; -		if (byte_offset) -			lenalloc = epos.offset; -		else -			lenalloc = epos.offset - adsize; - -		if (!epos.bh) -			lenalloc -= udf_file_entry_alloc_offset(inode); -		else -			lenalloc -= sizeof(struct allocExtDesc); - -		while ((etype = udf_current_aext(inode, &epos, &eloc, -						 &elen, 0)) != -1) { -			if (etype == (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) { -				udf_write_aext(inode, &epos, &neloc, nelen, 0); -				if (indirect_ext_len) { -					/* We managed to free all extents in the -					 * indirect extent - free it too */ -					BUG_ON(!epos.bh); -					udf_free_blocks(sb, inode, &epos.block, -							0, indirect_ext_len); -				} else if (!epos.bh) { -					iinfo->i_lenAlloc = lenalloc; -					mark_inode_dirty(inode); -				} else -					udf_update_alloc_ext_desc(inode, -							&epos, lenalloc); -				brelse(epos.bh); -				epos.offset = sizeof(struct allocExtDesc); -				epos.block = eloc; -				epos.bh = udf_tread(sb, -						udf_get_lb_pblock(sb, &eloc, 0)); -				if (elen) -					indirect_ext_len = -						(elen + sb->s_blocksize - 1) >> -						sb->s_blocksize_bits; -				else -					indirect_ext_len = 1; -			} else { -				extent_trunc(inode, &epos, &eloc, etype, -					     elen, 0); -				epos.offset += adsize; -			} -		} +	if (etype == -1) { +		/* We should extend the file? */ +		WARN_ON(byte_offset); +		return; +	} +	epos.offset -= adsize; +	extent_trunc(inode, &epos, &eloc, etype, elen, byte_offset); +	epos.offset += adsize; +	if (byte_offset) +		lenalloc = epos.offset; +	else +		lenalloc = epos.offset - adsize; -		if (indirect_ext_len) { -			BUG_ON(!epos.bh); -			udf_free_blocks(sb, inode, &epos.block, 0, -					indirect_ext_len); -		} else if (!epos.bh) { -			iinfo->i_lenAlloc = lenalloc; -			mark_inode_dirty(inode); -		} else -			udf_update_alloc_ext_desc(inode, &epos, lenalloc); -	} else if (inode->i_size) { -		if (byte_offset) { -			struct kernel_long_ad extent; +	if (!epos.bh) +		lenalloc -= udf_file_entry_alloc_offset(inode); +	else +		lenalloc -= sizeof(struct allocExtDesc); -			/* -			 *  OK, there is not extent covering inode->i_size and -			 *  no extent above inode->i_size => truncate is -			 *  extending the file by 'offset' blocks. -			 */ -			if ((!epos.bh && -			     epos.offset == -					udf_file_entry_alloc_offset(inode)) || -			    (epos.bh && epos.offset == -						sizeof(struct allocExtDesc))) { -				/* File has no extents at all or has empty last -				 * indirect extent! Create a fake extent... */ -				extent.extLocation.logicalBlockNum = 0; -				extent.extLocation.partitionReferenceNum = 0; -				extent.extLength = -					EXT_NOT_RECORDED_NOT_ALLOCATED; -			} else { -				epos.offset -= adsize; -				etype = udf_next_aext(inode, &epos, -						      &extent.extLocation, -						      &extent.extLength, 0); -				extent.extLength |= etype << 30; -			} -			udf_extend_file(inode, &epos, &extent, -					offset + -					((inode->i_size & -						(sb->s_blocksize - 1)) != 0)); +	while ((etype = udf_current_aext(inode, &epos, &eloc, +					 &elen, 0)) != -1) { +		if (etype == (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) { +			udf_write_aext(inode, &epos, &neloc, nelen, 0); +			if (indirect_ext_len) { +				/* We managed to free all extents in the +				 * indirect extent - free it too */ +				BUG_ON(!epos.bh); +				udf_free_blocks(sb, NULL, &epos.block, +						0, indirect_ext_len); +			} else if (!epos.bh) { +				iinfo->i_lenAlloc = lenalloc; +				mark_inode_dirty(inode); +			} else +				udf_update_alloc_ext_desc(inode, +						&epos, lenalloc); +			brelse(epos.bh); +			epos.offset = sizeof(struct allocExtDesc); +			epos.block = eloc; +			epos.bh = udf_tread(sb, +					udf_get_lb_pblock(sb, &eloc, 0)); +			if (elen) +				indirect_ext_len = +					(elen + sb->s_blocksize - 1) >> +					sb->s_blocksize_bits; +			else +				indirect_ext_len = 1; +		} else { +			extent_trunc(inode, &epos, &eloc, etype, elen, 0); +			epos.offset += adsize;  		}  	} + +	if (indirect_ext_len) { +		BUG_ON(!epos.bh); +		udf_free_blocks(sb, NULL, &epos.block, 0, indirect_ext_len); +	} else if (!epos.bh) { +		iinfo->i_lenAlloc = lenalloc; +		mark_inode_dirty(inode); +	} else +		udf_update_alloc_ext_desc(inode, &epos, lenalloc);  	iinfo->i_lenExtents = inode->i_size;  	brelse(epos.bh); diff --git a/fs/udf/udf_i.h b/fs/udf/udf_i.h index e58d1de4107..b5cd8ed2aa1 100644 --- a/fs/udf/udf_i.h +++ b/fs/udf/udf_i.h @@ -1,6 +1,31 @@  #ifndef _UDF_I_H  #define _UDF_I_H +struct extent_position { +	struct buffer_head *bh; +	uint32_t offset; +	struct kernel_lb_addr block; +}; + +struct udf_ext_cache { +	/* Extent position */ +	struct extent_position epos; +	/* Start logical offset in bytes */ +	loff_t lstart; +}; + +/* + * The i_data_sem and i_mutex serve for protection of allocation information + * of a regular files and symlinks. This includes all extents belonging to + * the file/symlink, a fact whether data are in-inode or in external data + * blocks, preallocation, goal block information... When extents are read, + * i_mutex or i_data_sem must be held (for reading is enough in case of + * i_data_sem). When extents are changed, i_data_sem must be held for writing + * and also i_mutex must be held. + * + * For directories i_mutex is used for all the necessary protection. + */ +  struct udf_inode_info {  	struct timespec		i_crtime;  	/* Physical address of inode */ @@ -11,6 +36,7 @@ struct udf_inode_info {  	__u64			i_lenExtents;  	__u32			i_next_alloc_block;  	__u32			i_next_alloc_goal; +	__u32			i_checkpoint;  	unsigned		i_alloc_type : 3;  	unsigned		i_efe : 1;	/* extendedFileEntry */  	unsigned		i_use : 1;	/* unallocSpaceEntry */ @@ -21,6 +47,10 @@ struct udf_inode_info {  		struct long_ad		*i_lad;  		__u8		*i_data;  	} i_ext; +	struct rw_semaphore	i_data_sem; +	struct udf_ext_cache cached_extent; +	/* Spinlock for protecting extent cache */ +	spinlock_t i_extent_cache_lock;  	struct inode vfs_inode;  }; diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h index d113b72c276..1f32c7bd9f5 100644 --- a/fs/udf/udf_sb.h +++ b/fs/udf/udf_sb.h @@ -2,6 +2,7 @@  #define __LINUX_UDF_SB_H  #include <linux/mutex.h> +#include <linux/bitops.h>  /* Since UDF 2.01 is ISO 13346 based... */  #define UDF_SUPER_MAGIC			0x15013346 @@ -49,17 +50,20 @@  #define UDF_SPARABLE_MAP15		0x1522U  #define UDF_METADATA_MAP25		0x2511U -#define UDF_INVALID_MODE		((mode_t)-1) +#define UDF_INVALID_MODE		((umode_t)-1)  #pragma pack(1) /* XXX(hch): Why?  This file just defines in-core structures */ +#define MF_DUPLICATE_MD		0x01 +#define MF_MIRROR_FE_LOADED	0x02 +  struct udf_meta_data {  	__u32	s_meta_file_loc;  	__u32	s_mirror_file_loc;  	__u32	s_bitmap_file_loc;  	__u32	s_alloc_unit_size;  	__u16	s_align_unit_size; -	__u8 	s_dup_md_flag; +	int	s_flags;  	struct inode *s_metadata_fe;  	struct inode *s_mirror_fe;  	struct inode *s_bitmap_fe; @@ -76,10 +80,9 @@ struct udf_virtual_data {  };  struct udf_bitmap { -	__u32			s_extLength;  	__u32			s_extPosition; -	__u16			s_nr_groups; -	struct buffer_head 	**s_block_bitmap; +	int			s_nr_groups; +	struct buffer_head 	*s_block_bitmap[0];  };  struct udf_part_map { @@ -123,11 +126,13 @@ struct udf_sb_info {  	struct buffer_head	*s_lvid_bh;  	/* Default permissions */ -	mode_t			s_umask; -	gid_t			s_gid; -	uid_t			s_uid; -	mode_t			s_fmode; -	mode_t			s_dmode; +	umode_t			s_umask; +	kgid_t			s_gid; +	kuid_t			s_uid; +	umode_t			s_fmode; +	umode_t			s_dmode; +	/* Lock protecting consistency of above permission settings */ +	rwlock_t		s_cred_lock;  	/* Root Info */  	struct timespec		s_record_time; @@ -139,7 +144,7 @@ struct udf_sb_info {  	__u16			s_udfrev;  	/* Miscellaneous flags */ -	__u32			s_flags; +	unsigned long		s_flags;  	/* Encoding info */  	struct nls_table	*s_nls_map; @@ -157,12 +162,23 @@ static inline struct udf_sb_info *UDF_SB(struct super_block *sb)  	return sb->s_fs_info;  } -struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct udf_sb_info *sbi); +struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct super_block *sb);  int udf_compute_nr_groups(struct super_block *sb, u32 partition); -#define UDF_QUERY_FLAG(X,Y)			( UDF_SB(X)->s_flags & ( 1 << (Y) ) ) -#define UDF_SET_FLAG(X,Y)			( UDF_SB(X)->s_flags |= ( 1 << (Y) ) ) -#define UDF_CLEAR_FLAG(X,Y)			( UDF_SB(X)->s_flags &= ~( 1 << (Y) ) ) +static inline int UDF_QUERY_FLAG(struct super_block *sb, int flag) +{ +	return test_bit(flag, &UDF_SB(sb)->s_flags); +} + +static inline void UDF_SET_FLAG(struct super_block *sb, int flag) +{ +	set_bit(flag, &UDF_SB(sb)->s_flags); +} + +static inline void UDF_CLEAR_FLAG(struct super_block *sb, int flag) +{ +	clear_bit(flag, &UDF_SB(sb)->s_flags); +}  #endif /* __LINUX_UDF_SB_H */ diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index 6995ab1f430..be7dabbbcb4 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h @@ -1,6 +1,8 @@  #ifndef __UDF_DECL_H  #define __UDF_DECL_H +#define pr_fmt(fmt) "UDF-fs: " fmt +  #include "ecma_167.h"  #include "osta_udf.h" @@ -16,23 +18,30 @@  #define UDF_PREALLOCATE  #define UDF_DEFAULT_PREALLOC_BLOCKS	8 +extern __printf(3, 4) void _udf_err(struct super_block *sb, +		const char *function, const char *fmt, ...); +#define udf_err(sb, fmt, ...)					\ +	_udf_err(sb, __func__, fmt, ##__VA_ARGS__) + +extern __printf(3, 4) void _udf_warn(struct super_block *sb, +		const char *function, const char *fmt, ...); +#define udf_warn(sb, fmt, ...)					\ +	_udf_warn(sb, __func__, fmt, ##__VA_ARGS__) + +#define udf_info(fmt, ...)					\ +	pr_info("INFO " fmt, ##__VA_ARGS__) +  #undef UDFFS_DEBUG  #ifdef UDFFS_DEBUG -#define udf_debug(f, a...) \ -do { \ -	printk(KERN_DEBUG "UDF-fs DEBUG %s:%d:%s: ", \ -		__FILE__, __LINE__, __func__); \ -	printk(f, ##a); \ -} while (0) +#define udf_debug(fmt, ...)					\ +	printk(KERN_DEBUG pr_fmt("%s:%d:%s: " fmt),		\ +	       __FILE__, __LINE__, __func__, ##__VA_ARGS__)  #else -#define udf_debug(f, a...) /**/ +#define udf_debug(fmt, ...)					\ +	no_printk(fmt, ##__VA_ARGS__)  #endif -#define udf_info(f, a...) \ -	printk(KERN_INFO "UDF-fs INFO " f, ##a); - -  #define udf_fixed_to_variable(x) ( ( ( (x) >> 5 ) * 39 ) + ( (x) & 0x0000001F ) )  #define udf_variable_to_fixed(x) ( ( ( (x) / 39 ) << 5 ) + ( (x) % 39 ) ) @@ -104,14 +113,9 @@ struct ustr {  	uint8_t u_len;  }; -struct extent_position { -	struct buffer_head *bh; -	uint32_t offset; -	struct kernel_lb_addr block; -};  /* super.c */ -extern void udf_warning(struct super_block *, const char *, const char *, ...); +  static inline void udf_updated_lvid(struct super_block *sb)  {  	struct buffer_head *bh = UDF_SB(sb)->s_lvid_bh; @@ -120,9 +124,11 @@ static inline void udf_updated_lvid(struct super_block *sb)  	WARN_ON_ONCE(((struct logicalVolIntegrityDesc *)  		     bh->b_data)->integrityType !=  		     cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN)); -	sb->s_dirt = 1;  	UDF_SB(sb)->s_lvid_dirty = 1;  } +extern u64 lvid_get_unique_id(struct super_block *sb); +struct inode *udf_find_metadata_inode_efe(struct super_block *sb, +					u32 meta_file_loc, u32 partition_num);  /* namei.c */  extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *, @@ -133,23 +139,20 @@ extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *,  extern long udf_ioctl(struct file *, unsigned int, unsigned long);  /* inode.c */  extern struct inode *udf_iget(struct super_block *, struct kernel_lb_addr *); -extern int udf_sync_inode(struct inode *); -extern void udf_expand_file_adinicb(struct inode *, int, int *); +extern int udf_expand_file_adinicb(struct inode *);  extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *);  extern struct buffer_head *udf_bread(struct inode *, int, int, int *); -extern void udf_truncate(struct inode *); +extern int udf_setsize(struct inode *, loff_t);  extern void udf_read_inode(struct inode *);  extern void udf_evict_inode(struct inode *);  extern int udf_write_inode(struct inode *, struct writeback_control *wbc);  extern long udf_block_map(struct inode *, sector_t); -extern int udf_extend_file(struct inode *, struct extent_position *, -			   struct kernel_long_ad *, sector_t);  extern int8_t inode_bmap(struct inode *, sector_t, struct extent_position *,  			 struct kernel_lb_addr *, uint32_t *, sector_t *); -extern int8_t udf_add_aext(struct inode *, struct extent_position *, +extern int udf_add_aext(struct inode *, struct extent_position *, +			struct kernel_lb_addr *, uint32_t, int); +extern void udf_write_aext(struct inode *, struct extent_position *,  			   struct kernel_lb_addr *, uint32_t, int); -extern int8_t udf_write_aext(struct inode *, struct extent_position *, -			     struct kernel_lb_addr *, uint32_t, int);  extern int8_t udf_delete_aext(struct inode *, struct extent_position,  			      struct kernel_lb_addr, uint32_t);  extern int8_t udf_next_aext(struct inode *, struct extent_position *, @@ -206,7 +209,7 @@ extern int udf_CS0toUTF8(struct ustr *, const struct ustr *);  /* ialloc.c */  extern void udf_free_inode(struct inode *); -extern struct inode *udf_new_inode(struct inode *, int, int *); +extern struct inode *udf_new_inode(struct inode *, umode_t, int *);  /* truncate.c */  extern void udf_truncate_tail_extent(struct inode *); diff --git a/fs/udf/udftime.c b/fs/udf/udftime.c index b8c828c4d20..1f11483eba6 100644 --- a/fs/udf/udftime.c +++ b/fs/udf/udftime.c @@ -34,9 +34,10 @@   * http://www.boulder.nist.gov/timefreq/pubs/bulletin/leapsecond.htm   */ +#include "udfdecl.h" +  #include <linux/types.h>  #include <linux/kernel.h> -#include "udfdecl.h"  #define EPOCH_YEAR 1970 diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c index d03a90b6ad6..44b815e57f9 100644 --- a/fs/udf/unicode.c +++ b/fs/udf/unicode.c @@ -114,7 +114,7 @@ int udf_CS0toUTF8(struct ustr *utf_o, const struct ustr *ocu_i)  	cmp_id = ocu_i->u_cmpID;  	if (cmp_id != 8 && cmp_id != 16) {  		memset(utf_o, 0, sizeof(struct ustr)); -		printk(KERN_ERR "udf: unknown compression code (%d) stri=%s\n", +		pr_err("unknown compression code (%d) stri=%s\n",  		       cmp_id, ocu_i->u_name);  		return 0;  	} @@ -242,7 +242,7 @@ try_again:  	if (utf_cnt) {  error_out:  		ocu[++u_len] = '?'; -		printk(KERN_DEBUG "udf: bad UTF-8 character\n"); +		printk(KERN_DEBUG pr_fmt("bad UTF-8 character\n"));  	}  	ocu[length - 1] = (uint8_t)u_len + 1; @@ -267,7 +267,7 @@ static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o,  	cmp_id = ocu_i->u_cmpID;  	if (cmp_id != 8 && cmp_id != 16) {  		memset(utf_o, 0, sizeof(struct ustr)); -		printk(KERN_ERR "udf: unknown compression code (%d) stri=%s\n", +		pr_err("unknown compression code (%d) stri=%s\n",  		       cmp_id, ocu_i->u_name);  		return 0;  	}  | 
