Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 374e5525 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-udf-2.6:
  UDF: Fix compiler warning
  udf: Convert UDF to new truncate calling sequence
parents 978ca164 6f644e5f
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@
#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)
		ext2_find_next_bit((unsigned long *)(addr), size, offset)

static int read_block_bitmap(struct super_block *sb,
			     struct udf_bitmap *bitmap, unsigned int block,
@@ -297,7 +297,7 @@ static int udf_bitmap_new_block(struct super_block *sb,
				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)
+3 −4
Original line number Diff line number Diff line
@@ -123,8 +123,8 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
		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) {
				udf_debug("udf_expand_adinicb: err=%d\n", err);
				up_write(&iinfo->i_data_sem);
				return err;
@@ -237,7 +237,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;
	}
@@ -249,5 +249,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,
};
+166 −73
Original line number Diff line number Diff line
@@ -73,14 +73,12 @@ 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);
		udf_setsize(inode, 0);
		udf_update_inode(inode, IS_SYNC(inode));
	}
	} else
		truncate_inode_pages(&inode->i_data, 0);
	invalidate_inode_buffers(inode);
	end_writeback(inode);
	if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB &&
@@ -117,9 +115,18 @@ static int udf_write_begin(struct file *file, struct address_space *mapping,

	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);
		struct inode *inode = mapping->host;
		struct udf_inode_info *iinfo = UDF_I(inode);
		loff_t isize = inode->i_size;

		if (pos + len > isize) {
			truncate_pagecache(inode, pos + len, isize);
			if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
				down_write(&iinfo->i_data_sem);
				udf_truncate_extents(inode);
				up_write(&iinfo->i_data_sem);
			}
		}
	}

	return ret;
@@ -139,30 +146,31 @@ const struct address_space_operations udf_aops = {
	.bmap		= udf_bmap,
};

void udf_expand_file_adinicb(struct inode *inode, int newsize, int *err)
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;

	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;
		mark_inode_dirty(inode);
		return;
		return 0;
	}

	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);
@@ -181,11 +189,24 @@ 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;
	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);
		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;
	}
	page_cache_release(page);

	mark_inode_dirty(inode);

	return err;
}

struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block,
@@ -348,8 +369,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);
@@ -357,6 +380,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... */
@@ -422,26 +446,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++;
@@ -453,11 +480,68 @@ int udf_extend_file(struct inode *inode, struct extent_position *last_pos,
	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 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 struct buffer_head *inode_getblk(struct inode *inode, sector_t block,
					int *err, sector_t *phys, int *new)
{
@@ -540,7 +624,7 @@ 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);
@@ -564,19 +648,17 @@ 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;
			*err = ret;
			return NULL;
		}
		c = 0;
@@ -1005,52 +1087,66 @@ 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;

	iinfo = UDF_I(inode);
	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
	if (newsize > inode->i_size) {
		down_write(&iinfo->i_data_sem);
		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;
			if (bsize <
			    (udf_file_entry_alloc_offset(inode) + newsize)) {
				err = udf_expand_file_adinicb(inode);
				if (err) {
					up_write(&iinfo->i_data_sem);
				return;
					return err;
				}
			} 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;
				iinfo->i_lenAlloc = newsize;
		}
		err = udf_extend_file(inode, newsize);
		if (err) {
			up_write(&iinfo->i_data_sem);
			return err;
		}
		truncate_setsize(inode, newsize);
		up_write(&iinfo->i_data_sem);
	} else {
		block_truncate_page(inode->i_mapping, inode->i_size,
		if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
			down_write(&iinfo->i_data_sem);
			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);
		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);
	return 0;
}

static void __udf_read_inode(struct inode *inode)
@@ -1637,14 +1733,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,
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);

@@ -1660,7 +1755,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;
@@ -1672,12 +1767,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);
@@ -1746,7 +1841,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;
@@ -1764,10 +1859,10 @@ 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,
void udf_write_aext(struct inode *inode, struct extent_position *epos,
		    struct kernel_lb_addr *eloc, uint32_t elen, int inc)
{
	int adsize;
@@ -1798,7 +1893,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) {
@@ -1817,8 +1912,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,
+60 −86
Original line number Diff line number Diff line
@@ -197,6 +197,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,7 +224,11 @@ 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) {
	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;
@@ -261,54 +270,19 @@ void udf_truncate_extents(struct inode *inode)
			else
				indirect_ext_len = 1;
		} else {
				extent_trunc(inode, &epos, &eloc, etype,
					     elen, 0);
			extent_trunc(inode, &epos, &eloc, etype, elen, 0);
			epos.offset += adsize;
		}
	}

	if (indirect_ext_len) {
		BUG_ON(!epos.bh);
			udf_free_blocks(sb, inode, &epos.block, 0,
					indirect_ext_len);
		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;

			/*
			 *  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));
		}
	}
	iinfo->i_lenExtents = inode->i_size;

	brelse(epos.bh);
+5 −7
Original line number Diff line number Diff line
@@ -136,21 +136,19 @@ 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 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 int8_t udf_write_aext(struct inode *, struct extent_position *,
extern void 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);