diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-09 15:51:21 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-09 15:51:21 -0500 |
commit | ac69e0928054ff29a5049902fb477f9c7605c773 (patch) | |
tree | 05be6b9285186823452e0adeffe40e1dfee6e354 /fs/udf | |
parent | 9e203936eac786f9268d6a13e6442d2accef1829 (diff) | |
parent | 302bf2f3259948c93361d501b04a5ed69c3bd4f8 (diff) |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
ext2/3/4: delete unneeded includes of module.h
ext{3,4}: Fix potential race when setversion ioctl updates inode
udf: Mark LVID buffer as uptodate before marking it dirty
ext3: Don't warn from writepage when readonly inode is spotted after error
jbd: Remove j_barrier mutex
reiserfs: Force inode evictions before umount to avoid crash
reiserfs: Fix quota mount option parsing
udf: Treat symlink component of type 2 as /
udf: Fix deadlock when converting file from in-ICB one to normal one
udf: Cleanup calling convention of inode_getblk()
ext2: Fix error handling on inode bitmap corruption
ext3: Fix error handling on inode bitmap corruption
ext3: replace ll_rw_block with other functions
ext3: NULL dereference in ext3_evict_inode()
jbd: clear revoked flag on buffers before a new transaction started
ext3: call ext3_mark_recovery_complete() when recovery is really needed
Diffstat (limited to 'fs/udf')
-rw-r--r-- | fs/udf/file.c | 6 | ||||
-rw-r--r-- | fs/udf/inode.c | 57 | ||||
-rw-r--r-- | fs/udf/super.c | 6 | ||||
-rw-r--r-- | fs/udf/symlink.c | 14 |
4 files changed, 52 insertions, 31 deletions
diff --git a/fs/udf/file.c b/fs/udf/file.c index d8ffa7cc661d..dca0c3881e82 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c | |||
@@ -125,7 +125,6 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
125 | err = udf_expand_file_adinicb(inode); | 125 | err = udf_expand_file_adinicb(inode); |
126 | if (err) { | 126 | if (err) { |
127 | udf_debug("udf_expand_adinicb: err=%d\n", err); | 127 | udf_debug("udf_expand_adinicb: err=%d\n", err); |
128 | up_write(&iinfo->i_data_sem); | ||
129 | return err; | 128 | return err; |
130 | } | 129 | } |
131 | } else { | 130 | } else { |
@@ -133,9 +132,10 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
133 | iinfo->i_lenAlloc = pos + count; | 132 | iinfo->i_lenAlloc = pos + count; |
134 | else | 133 | else |
135 | iinfo->i_lenAlloc = inode->i_size; | 134 | iinfo->i_lenAlloc = inode->i_size; |
135 | up_write(&iinfo->i_data_sem); | ||
136 | } | 136 | } |
137 | } | 137 | } else |
138 | up_write(&iinfo->i_data_sem); | 138 | up_write(&iinfo->i_data_sem); |
139 | 139 | ||
140 | retval = generic_file_aio_write(iocb, iov, nr_segs, ppos); | 140 | retval = generic_file_aio_write(iocb, iov, nr_segs, ppos); |
141 | if (retval > 0) | 141 | if (retval > 0) |
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 4598904be1bb..7699df7b3198 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c | |||
@@ -53,8 +53,7 @@ static int udf_update_inode(struct inode *, int); | |||
53 | static void udf_fill_inode(struct inode *, struct buffer_head *); | 53 | static void udf_fill_inode(struct inode *, struct buffer_head *); |
54 | static int udf_sync_inode(struct inode *inode); | 54 | static int udf_sync_inode(struct inode *inode); |
55 | static int udf_alloc_i_data(struct inode *inode, size_t size); | 55 | static int udf_alloc_i_data(struct inode *inode, size_t size); |
56 | static struct buffer_head *inode_getblk(struct inode *, sector_t, int *, | 56 | static sector_t inode_getblk(struct inode *, sector_t, int *, int *); |
57 | sector_t *, int *); | ||
58 | static int8_t udf_insert_aext(struct inode *, struct extent_position, | 57 | static int8_t udf_insert_aext(struct inode *, struct extent_position, |
59 | struct kernel_lb_addr, uint32_t); | 58 | struct kernel_lb_addr, uint32_t); |
60 | static void udf_split_extents(struct inode *, int *, int, int, | 59 | static void udf_split_extents(struct inode *, int *, int, int, |
@@ -151,6 +150,12 @@ const struct address_space_operations udf_aops = { | |||
151 | .bmap = udf_bmap, | 150 | .bmap = udf_bmap, |
152 | }; | 151 | }; |
153 | 152 | ||
153 | /* | ||
154 | * Expand file stored in ICB to a normal one-block-file | ||
155 | * | ||
156 | * This function requires i_data_sem for writing and releases it. | ||
157 | * This function requires i_mutex held | ||
158 | */ | ||
154 | int udf_expand_file_adinicb(struct inode *inode) | 159 | int udf_expand_file_adinicb(struct inode *inode) |
155 | { | 160 | { |
156 | struct page *page; | 161 | struct page *page; |
@@ -169,9 +174,15 @@ int udf_expand_file_adinicb(struct inode *inode) | |||
169 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; | 174 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; |
170 | /* from now on we have normal address_space methods */ | 175 | /* from now on we have normal address_space methods */ |
171 | inode->i_data.a_ops = &udf_aops; | 176 | inode->i_data.a_ops = &udf_aops; |
177 | up_write(&iinfo->i_data_sem); | ||
172 | mark_inode_dirty(inode); | 178 | mark_inode_dirty(inode); |
173 | return 0; | 179 | return 0; |
174 | } | 180 | } |
181 | /* | ||
182 | * Release i_data_sem so that we can lock a page - page lock ranks | ||
183 | * above i_data_sem. i_mutex still protects us against file changes. | ||
184 | */ | ||
185 | up_write(&iinfo->i_data_sem); | ||
175 | 186 | ||
176 | page = find_or_create_page(inode->i_mapping, 0, GFP_NOFS); | 187 | page = find_or_create_page(inode->i_mapping, 0, GFP_NOFS); |
177 | if (!page) | 188 | if (!page) |
@@ -187,6 +198,7 @@ int udf_expand_file_adinicb(struct inode *inode) | |||
187 | SetPageUptodate(page); | 198 | SetPageUptodate(page); |
188 | kunmap(page); | 199 | kunmap(page); |
189 | } | 200 | } |
201 | down_write(&iinfo->i_data_sem); | ||
190 | memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr, 0x00, | 202 | memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr, 0x00, |
191 | iinfo->i_lenAlloc); | 203 | iinfo->i_lenAlloc); |
192 | iinfo->i_lenAlloc = 0; | 204 | iinfo->i_lenAlloc = 0; |
@@ -196,17 +208,20 @@ int udf_expand_file_adinicb(struct inode *inode) | |||
196 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; | 208 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; |
197 | /* from now on we have normal address_space methods */ | 209 | /* from now on we have normal address_space methods */ |
198 | inode->i_data.a_ops = &udf_aops; | 210 | inode->i_data.a_ops = &udf_aops; |
211 | up_write(&iinfo->i_data_sem); | ||
199 | err = inode->i_data.a_ops->writepage(page, &udf_wbc); | 212 | err = inode->i_data.a_ops->writepage(page, &udf_wbc); |
200 | if (err) { | 213 | if (err) { |
201 | /* Restore everything back so that we don't lose data... */ | 214 | /* Restore everything back so that we don't lose data... */ |
202 | lock_page(page); | 215 | lock_page(page); |
203 | kaddr = kmap(page); | 216 | kaddr = kmap(page); |
217 | down_write(&iinfo->i_data_sem); | ||
204 | memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr, kaddr, | 218 | memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr, kaddr, |
205 | inode->i_size); | 219 | inode->i_size); |
206 | kunmap(page); | 220 | kunmap(page); |
207 | unlock_page(page); | 221 | unlock_page(page); |
208 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB; | 222 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB; |
209 | inode->i_data.a_ops = &udf_adinicb_aops; | 223 | inode->i_data.a_ops = &udf_adinicb_aops; |
224 | up_write(&iinfo->i_data_sem); | ||
210 | } | 225 | } |
211 | page_cache_release(page); | 226 | page_cache_release(page); |
212 | mark_inode_dirty(inode); | 227 | mark_inode_dirty(inode); |
@@ -310,7 +325,6 @@ static int udf_get_block(struct inode *inode, sector_t block, | |||
310 | struct buffer_head *bh_result, int create) | 325 | struct buffer_head *bh_result, int create) |
311 | { | 326 | { |
312 | int err, new; | 327 | int err, new; |
313 | struct buffer_head *bh; | ||
314 | sector_t phys = 0; | 328 | sector_t phys = 0; |
315 | struct udf_inode_info *iinfo; | 329 | struct udf_inode_info *iinfo; |
316 | 330 | ||
@@ -323,7 +337,6 @@ static int udf_get_block(struct inode *inode, sector_t block, | |||
323 | 337 | ||
324 | err = -EIO; | 338 | err = -EIO; |
325 | new = 0; | 339 | new = 0; |
326 | bh = NULL; | ||
327 | iinfo = UDF_I(inode); | 340 | iinfo = UDF_I(inode); |
328 | 341 | ||
329 | down_write(&iinfo->i_data_sem); | 342 | down_write(&iinfo->i_data_sem); |
@@ -332,13 +345,10 @@ static int udf_get_block(struct inode *inode, sector_t block, | |||
332 | iinfo->i_next_alloc_goal++; | 345 | iinfo->i_next_alloc_goal++; |
333 | } | 346 | } |
334 | 347 | ||
335 | err = 0; | ||
336 | 348 | ||
337 | bh = inode_getblk(inode, block, &err, &phys, &new); | 349 | phys = inode_getblk(inode, block, &err, &new); |
338 | BUG_ON(bh); | 350 | if (!phys) |
339 | if (err) | ||
340 | goto abort; | 351 | goto abort; |
341 | BUG_ON(!phys); | ||
342 | 352 | ||
343 | if (new) | 353 | if (new) |
344 | set_buffer_new(bh_result); | 354 | set_buffer_new(bh_result); |
@@ -547,11 +557,10 @@ out: | |||
547 | return err; | 557 | return err; |
548 | } | 558 | } |
549 | 559 | ||
550 | static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, | 560 | static sector_t inode_getblk(struct inode *inode, sector_t block, |
551 | int *err, sector_t *phys, int *new) | 561 | int *err, int *new) |
552 | { | 562 | { |
553 | static sector_t last_block; | 563 | static sector_t last_block; |
554 | struct buffer_head *result = NULL; | ||
555 | struct kernel_long_ad laarr[EXTENT_MERGE_SIZE]; | 564 | struct kernel_long_ad laarr[EXTENT_MERGE_SIZE]; |
556 | struct extent_position prev_epos, cur_epos, next_epos; | 565 | struct extent_position prev_epos, cur_epos, next_epos; |
557 | int count = 0, startnum = 0, endnum = 0; | 566 | int count = 0, startnum = 0, endnum = 0; |
@@ -566,6 +575,8 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, | |||
566 | int goal = 0, pgoal = iinfo->i_location.logicalBlockNum; | 575 | int goal = 0, pgoal = iinfo->i_location.logicalBlockNum; |
567 | int lastblock = 0; | 576 | int lastblock = 0; |
568 | 577 | ||
578 | *err = 0; | ||
579 | *new = 0; | ||
569 | prev_epos.offset = udf_file_entry_alloc_offset(inode); | 580 | prev_epos.offset = udf_file_entry_alloc_offset(inode); |
570 | prev_epos.block = iinfo->i_location; | 581 | prev_epos.block = iinfo->i_location; |
571 | prev_epos.bh = NULL; | 582 | prev_epos.bh = NULL; |
@@ -635,8 +646,7 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, | |||
635 | brelse(cur_epos.bh); | 646 | brelse(cur_epos.bh); |
636 | brelse(next_epos.bh); | 647 | brelse(next_epos.bh); |
637 | newblock = udf_get_lb_pblock(inode->i_sb, &eloc, offset); | 648 | newblock = udf_get_lb_pblock(inode->i_sb, &eloc, offset); |
638 | *phys = newblock; | 649 | return newblock; |
639 | return NULL; | ||
640 | } | 650 | } |
641 | 651 | ||
642 | last_block = block; | 652 | last_block = block; |
@@ -664,7 +674,7 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, | |||
664 | brelse(cur_epos.bh); | 674 | brelse(cur_epos.bh); |
665 | brelse(next_epos.bh); | 675 | brelse(next_epos.bh); |
666 | *err = ret; | 676 | *err = ret; |
667 | return NULL; | 677 | return 0; |
668 | } | 678 | } |
669 | c = 0; | 679 | c = 0; |
670 | offset = 0; | 680 | offset = 0; |
@@ -729,7 +739,7 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, | |||
729 | if (!newblocknum) { | 739 | if (!newblocknum) { |
730 | brelse(prev_epos.bh); | 740 | brelse(prev_epos.bh); |
731 | *err = -ENOSPC; | 741 | *err = -ENOSPC; |
732 | return NULL; | 742 | return 0; |
733 | } | 743 | } |
734 | iinfo->i_lenExtents += inode->i_sb->s_blocksize; | 744 | iinfo->i_lenExtents += inode->i_sb->s_blocksize; |
735 | } | 745 | } |
@@ -761,10 +771,10 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, | |||
761 | 771 | ||
762 | newblock = udf_get_pblock(inode->i_sb, newblocknum, | 772 | newblock = udf_get_pblock(inode->i_sb, newblocknum, |
763 | iinfo->i_location.partitionReferenceNum, 0); | 773 | iinfo->i_location.partitionReferenceNum, 0); |
764 | if (!newblock) | 774 | if (!newblock) { |
765 | return NULL; | 775 | *err = -EIO; |
766 | *phys = newblock; | 776 | return 0; |
767 | *err = 0; | 777 | } |
768 | *new = 1; | 778 | *new = 1; |
769 | iinfo->i_next_alloc_block = block; | 779 | iinfo->i_next_alloc_block = block; |
770 | iinfo->i_next_alloc_goal = newblocknum; | 780 | iinfo->i_next_alloc_goal = newblocknum; |
@@ -775,7 +785,7 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, | |||
775 | else | 785 | else |
776 | mark_inode_dirty(inode); | 786 | mark_inode_dirty(inode); |
777 | 787 | ||
778 | return result; | 788 | return newblock; |
779 | } | 789 | } |
780 | 790 | ||
781 | static void udf_split_extents(struct inode *inode, int *c, int offset, | 791 | static void udf_split_extents(struct inode *inode, int *c, int offset, |
@@ -1111,10 +1121,9 @@ int udf_setsize(struct inode *inode, loff_t newsize) | |||
1111 | if (bsize < | 1121 | if (bsize < |
1112 | (udf_file_entry_alloc_offset(inode) + newsize)) { | 1122 | (udf_file_entry_alloc_offset(inode) + newsize)) { |
1113 | err = udf_expand_file_adinicb(inode); | 1123 | err = udf_expand_file_adinicb(inode); |
1114 | if (err) { | 1124 | if (err) |
1115 | up_write(&iinfo->i_data_sem); | ||
1116 | return err; | 1125 | return err; |
1117 | } | 1126 | down_write(&iinfo->i_data_sem); |
1118 | } else | 1127 | } else |
1119 | iinfo->i_lenAlloc = newsize; | 1128 | iinfo->i_lenAlloc = newsize; |
1120 | } | 1129 | } |
diff --git a/fs/udf/super.c b/fs/udf/super.c index 0c33225647a0..c09a84daaf50 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
@@ -1798,6 +1798,12 @@ static void udf_close_lvid(struct super_block *sb) | |||
1798 | le16_to_cpu(lvid->descTag.descCRCLength))); | 1798 | le16_to_cpu(lvid->descTag.descCRCLength))); |
1799 | 1799 | ||
1800 | lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); | 1800 | lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); |
1801 | /* | ||
1802 | * We set buffer uptodate unconditionally here to avoid spurious | ||
1803 | * warnings from mark_buffer_dirty() when previous EIO has marked | ||
1804 | * the buffer as !uptodate | ||
1805 | */ | ||
1806 | set_buffer_uptodate(bh); | ||
1801 | mark_buffer_dirty(bh); | 1807 | mark_buffer_dirty(bh); |
1802 | sbi->s_lvid_dirty = 0; | 1808 | sbi->s_lvid_dirty = 0; |
1803 | mutex_unlock(&sbi->s_alloc_mutex); | 1809 | mutex_unlock(&sbi->s_alloc_mutex); |
diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c index b1d4488b0f14..d7c6dbe4194b 100644 --- a/fs/udf/symlink.c +++ b/fs/udf/symlink.c | |||
@@ -41,10 +41,16 @@ static void udf_pc_to_char(struct super_block *sb, unsigned char *from, | |||
41 | pc = (struct pathComponent *)(from + elen); | 41 | pc = (struct pathComponent *)(from + elen); |
42 | switch (pc->componentType) { | 42 | switch (pc->componentType) { |
43 | case 1: | 43 | case 1: |
44 | if (pc->lengthComponentIdent == 0) { | 44 | /* |
45 | p = to; | 45 | * Symlink points to some place which should be agreed |
46 | *p++ = '/'; | 46 | * upon between originator and receiver of the media. Ignore. |
47 | } | 47 | */ |
48 | if (pc->lengthComponentIdent > 0) | ||
49 | break; | ||
50 | /* Fall through */ | ||
51 | case 2: | ||
52 | p = to; | ||
53 | *p++ = '/'; | ||
48 | break; | 54 | break; |
49 | case 3: | 55 | case 3: |
50 | memcpy(p, "../", 3); | 56 | memcpy(p, "../", 3); |