From a0e589b485cd5e6a74d40d195b3d7de212b4227d Mon Sep 17 00:00:00 2001 From: Ashish Sangwan Date: Tue, 26 Jun 2012 19:33:11 +0530 Subject: UDF: Remove unnecessary variable "offset" from udf_fill_inode The variable "offset" is not needed. Remove it. Signed-off-by: Ashish Sangwan Signed-off-by: Namjae Jeon Signed-off-by: Jan Kara --- fs/udf/inode.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'fs/udf/inode.c') diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 873e1bab9c4..fafaad795cd 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -1247,7 +1247,6 @@ 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; @@ -1359,7 +1358,6 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) iinfo->i_lenEAttr = le32_to_cpu(fe->lengthExtendedAttr); iinfo->i_lenAlloc = le32_to_cpu(fe->lengthAllocDescs); iinfo->i_checkpoint = le32_to_cpu(fe->checkpoint); - offset = sizeof(struct fileEntry) + iinfo->i_lenEAttr; } else { inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) << (inode->i_sb->s_blocksize_bits - 9); @@ -1381,8 +1379,6 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) iinfo->i_lenEAttr = le32_to_cpu(efe->lengthExtendedAttr); iinfo->i_lenAlloc = le32_to_cpu(efe->lengthAllocDescs); iinfo->i_checkpoint = le32_to_cpu(efe->checkpoint); - offset = sizeof(struct extendedFileEntry) + - iinfo->i_lenEAttr; } switch (fe->icbTag.fileType) { -- cgit v1.2.3 From bb2b6d19ec8b593b66402e2895c4314955b19833 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 23 Jul 2012 16:39:29 +0000 Subject: udf: fix udf_setsize() for file data in ICB If the new size is larger than the old size and the old file data was stored in the ICB (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) and the new size still fits in the ICB, skip the call to udf_extend_file() as it does not handle this i_alloc_type value (it calls BUG()). Signed-off-by: Ian Abbott Signed-off-by: Jan Kara --- fs/udf/inode.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'fs/udf/inode.c') diff --git a/fs/udf/inode.c b/fs/udf/inode.c index fafaad795cd..aa233469b3c 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -1124,14 +1124,17 @@ int udf_setsize(struct inode *inode, loff_t newsize) if (err) return err; down_write(&iinfo->i_data_sem); - } else + } 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 { -- cgit v1.2.3 From 378b8e1ad18e7c97832aa3771e295153c4cd2a55 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Fri, 31 Aug 2012 12:49:07 -0400 Subject: udf: add writepages support for udf Use mpage_writepages() instead of multiple calls to udf_writepage() to make performance higher. *Write Speed with writepage() = RecSize ReadSpeed WriteSpeed RanReadSpeed RanWriteSpeed 10485760 0.00MB/sec 8.56MB/sec 0.00MB/sec 8.20MB/sec 1048576 0.00MB/sec 8.57MB/sec 0.00MB/sec 6.42MB/sec 524288 0.00MB/sec 8.59MB/sec 0.00MB/sec 5.24MB/sec 262144 0.00MB/sec 8.59MB/sec 0.00MB/sec 4.17MB/sec 131072 0.00MB/sec 8.53MB/sec 0.00MB/sec 3.32MB/sec 65536 0.00MB/sec 8.49MB/sec 0.00MB/sec 2.31MB/sec *Write Speed with writepages() RecSize ReadSpeed WriteSpeed RanReadSpeed RanWriteSpeed 10485760 0.00MB/sec 9.88MB/sec 0.00MB/sec 9.60MB/sec 1048576 0.00MB/sec 9.95MB/sec 0.00MB/sec 7.52MB/sec 524288 0.00MB/sec 9.98MB/sec 0.00MB/sec 6.16MB/sec 262144 0.00MB/sec 9.90MB/sec 0.00MB/sec 4.98MB/sec 131072 0.00MB/sec 9.89MB/sec 0.00MB/sec 3.78MB/sec 65536 0.00MB/sec 9.81MB/sec 0.00MB/sec 2.50MB/sec There is about 1.4MB/sec speed improvement over 8.5MB/sec, which comes out around 16% improvement. Signed-off-by: Namjae Jeon Signed-off-by: Ashish Sangwan Signed-off-by: Jan Kara --- fs/udf/inode.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'fs/udf/inode.c') diff --git a/fs/udf/inode.c b/fs/udf/inode.c index aa233469b3c..1a0588e77a2 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -100,6 +100,12 @@ 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 mpage_readpage(page, udf_get_block); @@ -145,6 +151,7 @@ const struct address_space_operations udf_aops = { .readpage = udf_readpage, .readpages = udf_readpages, .writepage = udf_writepage, + .writepages = udf_writepages, .write_begin = udf_write_begin, .write_end = generic_write_end, .bmap = udf_bmap, -- cgit v1.2.3 From 5eec54fcde7e065eb3d8a6e70e61d90673ca706b Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 5 Sep 2012 17:44:31 +0100 Subject: UDF: Add support for O_DIRECT Add support for the O_DIRECT flag. There are two cases to deal with: 1. Small files stored in the ICB (inode control block?): just return 0 from the new udf_adinicb_direct_IO() handler to fall back to buffered I/O. 2. Larger files, not stored in the ICB: nothing special here. Just call blockdev_direct_IO() from our new udf_direct_IO() handler and tidy up any blocks instantiated outside i_size on error. This is pretty standard. Factor error handling code out of udf_write_begin() into new function udf_write_failed() so it can also be called by udf_direct_IO(). Also change the whitespace in udf_aops to make it a bit neater. Signed-off-by: Ian Abbott Signed-off-by: Jan Kara --- fs/udf/inode.c | 52 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 16 deletions(-) (limited to 'fs/udf/inode.c') diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 1a0588e77a2..41d58309d6a 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -95,6 +95,22 @@ void udf_evict_inode(struct inode *inode) } } +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, to, 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); + } + } +} + static int udf_writepage(struct page *page, struct writeback_control *wbc) { return block_write_full_page(page, udf_get_block, wbc); @@ -124,21 +140,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)) { - 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); - } - } - } + if (unlikely(ret)) + udf_write_failed(mapping, pos + len); + return ret; +} +static ssize_t udf_direct_IO(int rw, struct kiocb *iocb, + const struct iovec *iov, + loff_t offset, unsigned long nr_segs) +{ + struct file *file = iocb->ki_filp; + struct address_space *mapping = file->f_mapping; + struct inode *inode = mapping->host; + ssize_t ret; + + ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs, + udf_get_block); + if (unlikely(ret < 0 && (rw & WRITE))) + udf_write_failed(mapping, offset + iov_length(iov, nr_segs)); return ret; } @@ -152,8 +171,9 @@ const struct address_space_operations udf_aops = { .readpages = udf_readpages, .writepage = udf_writepage, .writepages = udf_writepages, - .write_begin = udf_write_begin, - .write_end = generic_write_end, + .write_begin = udf_write_begin, + .write_end = generic_write_end, + .direct_IO = udf_direct_IO, .bmap = udf_bmap, }; -- cgit v1.2.3 From c2ba138a27ddac4abbc931599dbce907c868910a Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 10 Feb 2012 12:20:35 -0800 Subject: userns: Convert the udf filesystem to use kuid/kgid where appropriate Cc: Jan Kara Signed-off-by: Eric W. Biederman --- fs/udf/inode.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'fs/udf/inode.c') diff --git a/fs/udf/inode.c b/fs/udf/inode.c index fafaad795cd..1825dc0af72 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -1309,14 +1309,14 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) } read_lock(&sbi->s_cred_lock); - inode->i_uid = le32_to_cpu(fe->uid); - if (inode->i_uid == -1 || + 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; @@ -1539,12 +1539,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) | -- cgit v1.2.3 From 2fb7d99d0de3fd8ae869f35ab682581d8455887a Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Wed, 10 Oct 2012 00:08:56 +0900 Subject: udf: fix memory leak while allocating blocks during write Need to brelse the buffer_head stored in cur_epos and next_epos. Signed-off-by: Namjae Jeon Signed-off-by: Ashish Sangwan Signed-off-by: Jan Kara --- fs/udf/inode.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'fs/udf/inode.c') diff --git a/fs/udf/inode.c b/fs/udf/inode.c index df88b957ccf..2b7759371ff 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -765,6 +765,8 @@ static sector_t 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 0; } @@ -795,6 +797,8 @@ static sector_t 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); -- cgit v1.2.3 From fb719c59bdb4fca86ee1fd1f42ab3735ca12b6b2 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Wed, 10 Oct 2012 00:09:12 +0900 Subject: udf: don't increment lenExtents while writing to a hole Incrementing lenExtents even while writing to a hole is bad for performance as calls to udf_discard_prealloc and udf_truncate_tail_extent would not return from start if isize != lenExtents Signed-off-by: Namjae Jeon Signed-off-by: Ashish Sangwan Signed-off-by: Jan Kara --- fs/udf/inode.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'fs/udf/inode.c') diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 2b7759371ff..8266f2ed7fc 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -601,6 +601,7 @@ static sector_t 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; @@ -680,7 +681,7 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, /* Are we beyond EOF? */ if (etype == -1) { int ret; - + isBeyondEOF = 1; if (count) { if (c) laarr[0] = laarr[1]; @@ -723,6 +724,7 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, endnum = c + 1; lastblock = 1; } else { + isBeyondEOF = 0; endnum = startnum = ((count > 2) ? 2 : count); /* if the current extent is in position 0, @@ -770,7 +772,8 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, *err = -ENOSPC; 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 -- cgit v1.2.3 From 6d31d15f21b376ac0d8a2323fd6673683bc82bd6 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Wed, 10 Oct 2012 00:09:44 +0900 Subject: udf: remove un-needed variable from inode_getblk The variable last_block is not needed. Signed-off-by: Namjae Jeon Signed-off-by: Ashish Sangwan Signed-off-by: Jan Kara --- fs/udf/inode.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'fs/udf/inode.c') diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 8266f2ed7fc..cbae1ed0b7c 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -587,7 +587,6 @@ out: static sector_t inode_getblk(struct inode *inode, sector_t block, int *err, int *new) { - static sector_t last_block; struct kernel_long_ad laarr[EXTENT_MERGE_SIZE]; struct extent_position prev_epos, cur_epos, next_epos; int count = 0, startnum = 0, endnum = 0; @@ -677,7 +676,6 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, return newblock; } - last_block = block; /* Are we beyond EOF? */ if (etype == -1) { int ret; @@ -719,7 +717,6 @@ static sector_t 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; -- cgit v1.2.3