aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext3
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext3')
-rw-r--r--fs/ext3/dir.c157
-rw-r--r--fs/ext3/fsync.c8
-rw-r--r--fs/ext3/inode.c10
-rw-r--r--fs/ext3/namei.c54
-rw-r--r--fs/ext3/super.c13
5 files changed, 136 insertions, 106 deletions
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c
index 87eccbbca255..f522425aaa24 100644
--- a/fs/ext3/dir.c
+++ b/fs/ext3/dir.c
@@ -28,8 +28,7 @@ static unsigned char ext3_filetype_table[] = {
28 DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK 28 DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
29}; 29};
30 30
31static int ext3_dx_readdir(struct file * filp, 31static int ext3_dx_readdir(struct file *, struct dir_context *);
32 void * dirent, filldir_t filldir);
33 32
34static unsigned char get_dtype(struct super_block *sb, int filetype) 33static unsigned char get_dtype(struct super_block *sb, int filetype)
35{ 34{
@@ -91,36 +90,30 @@ int ext3_check_dir_entry (const char * function, struct inode * dir,
91 return error_msg == NULL ? 1 : 0; 90 return error_msg == NULL ? 1 : 0;
92} 91}
93 92
94static int ext3_readdir(struct file * filp, 93static int ext3_readdir(struct file *file, struct dir_context *ctx)
95 void * dirent, filldir_t filldir)
96{ 94{
97 int error = 0;
98 unsigned long offset; 95 unsigned long offset;
99 int i, stored; 96 int i;
100 struct ext3_dir_entry_2 *de; 97 struct ext3_dir_entry_2 *de;
101 int err; 98 int err;
102 struct inode *inode = file_inode(filp); 99 struct inode *inode = file_inode(file);
103 struct super_block *sb = inode->i_sb; 100 struct super_block *sb = inode->i_sb;
104 int ret = 0;
105 int dir_has_error = 0; 101 int dir_has_error = 0;
106 102
107 if (is_dx_dir(inode)) { 103 if (is_dx_dir(inode)) {
108 err = ext3_dx_readdir(filp, dirent, filldir); 104 err = ext3_dx_readdir(file, ctx);
109 if (err != ERR_BAD_DX_DIR) { 105 if (err != ERR_BAD_DX_DIR)
110 ret = err; 106 return err;
111 goto out;
112 }
113 /* 107 /*
114 * We don't set the inode dirty flag since it's not 108 * We don't set the inode dirty flag since it's not
115 * critical that it get flushed back to the disk. 109 * critical that it get flushed back to the disk.
116 */ 110 */
117 EXT3_I(file_inode(filp))->i_flags &= ~EXT3_INDEX_FL; 111 EXT3_I(inode)->i_flags &= ~EXT3_INDEX_FL;
118 } 112 }
119 stored = 0; 113 offset = ctx->pos & (sb->s_blocksize - 1);
120 offset = filp->f_pos & (sb->s_blocksize - 1);
121 114
122 while (!error && !stored && filp->f_pos < inode->i_size) { 115 while (ctx->pos < inode->i_size) {
123 unsigned long blk = filp->f_pos >> EXT3_BLOCK_SIZE_BITS(sb); 116 unsigned long blk = ctx->pos >> EXT3_BLOCK_SIZE_BITS(sb);
124 struct buffer_head map_bh; 117 struct buffer_head map_bh;
125 struct buffer_head *bh = NULL; 118 struct buffer_head *bh = NULL;
126 119
@@ -129,12 +122,12 @@ static int ext3_readdir(struct file * filp,
129 if (err > 0) { 122 if (err > 0) {
130 pgoff_t index = map_bh.b_blocknr >> 123 pgoff_t index = map_bh.b_blocknr >>
131 (PAGE_CACHE_SHIFT - inode->i_blkbits); 124 (PAGE_CACHE_SHIFT - inode->i_blkbits);
132 if (!ra_has_index(&filp->f_ra, index)) 125 if (!ra_has_index(&file->f_ra, index))
133 page_cache_sync_readahead( 126 page_cache_sync_readahead(
134 sb->s_bdev->bd_inode->i_mapping, 127 sb->s_bdev->bd_inode->i_mapping,
135 &filp->f_ra, filp, 128 &file->f_ra, file,
136 index, 1); 129 index, 1);
137 filp->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT; 130 file->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT;
138 bh = ext3_bread(NULL, inode, blk, 0, &err); 131 bh = ext3_bread(NULL, inode, blk, 0, &err);
139 } 132 }
140 133
@@ -146,22 +139,21 @@ static int ext3_readdir(struct file * filp,
146 if (!dir_has_error) { 139 if (!dir_has_error) {
147 ext3_error(sb, __func__, "directory #%lu " 140 ext3_error(sb, __func__, "directory #%lu "
148 "contains a hole at offset %lld", 141 "contains a hole at offset %lld",
149 inode->i_ino, filp->f_pos); 142 inode->i_ino, ctx->pos);
150 dir_has_error = 1; 143 dir_has_error = 1;
151 } 144 }
152 /* corrupt size? Maybe no more blocks to read */ 145 /* corrupt size? Maybe no more blocks to read */
153 if (filp->f_pos > inode->i_blocks << 9) 146 if (ctx->pos > inode->i_blocks << 9)
154 break; 147 break;
155 filp->f_pos += sb->s_blocksize - offset; 148 ctx->pos += sb->s_blocksize - offset;
156 continue; 149 continue;
157 } 150 }
158 151
159revalidate:
160 /* If the dir block has changed since the last call to 152 /* If the dir block has changed since the last call to
161 * readdir(2), then we might be pointing to an invalid 153 * readdir(2), then we might be pointing to an invalid
162 * dirent right now. Scan from the start of the block 154 * dirent right now. Scan from the start of the block
163 * to make sure. */ 155 * to make sure. */
164 if (filp->f_version != inode->i_version) { 156 if (offset && file->f_version != inode->i_version) {
165 for (i = 0; i < sb->s_blocksize && i < offset; ) { 157 for (i = 0; i < sb->s_blocksize && i < offset; ) {
166 de = (struct ext3_dir_entry_2 *) 158 de = (struct ext3_dir_entry_2 *)
167 (bh->b_data + i); 159 (bh->b_data + i);
@@ -177,53 +169,40 @@ revalidate:
177 i += ext3_rec_len_from_disk(de->rec_len); 169 i += ext3_rec_len_from_disk(de->rec_len);
178 } 170 }
179 offset = i; 171 offset = i;
180 filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) 172 ctx->pos = (ctx->pos & ~(sb->s_blocksize - 1))
181 | offset; 173 | offset;
182 filp->f_version = inode->i_version; 174 file->f_version = inode->i_version;
183 } 175 }
184 176
185 while (!error && filp->f_pos < inode->i_size 177 while (ctx->pos < inode->i_size
186 && offset < sb->s_blocksize) { 178 && offset < sb->s_blocksize) {
187 de = (struct ext3_dir_entry_2 *) (bh->b_data + offset); 179 de = (struct ext3_dir_entry_2 *) (bh->b_data + offset);
188 if (!ext3_check_dir_entry ("ext3_readdir", inode, de, 180 if (!ext3_check_dir_entry ("ext3_readdir", inode, de,
189 bh, offset)) { 181 bh, offset)) {
190 /* On error, skip the f_pos to the 182 /* On error, skip the to the
191 next block. */ 183 next block. */
192 filp->f_pos = (filp->f_pos | 184 ctx->pos = (ctx->pos |
193 (sb->s_blocksize - 1)) + 1; 185 (sb->s_blocksize - 1)) + 1;
194 brelse (bh); 186 break;
195 ret = stored;
196 goto out;
197 } 187 }
198 offset += ext3_rec_len_from_disk(de->rec_len); 188 offset += ext3_rec_len_from_disk(de->rec_len);
199 if (le32_to_cpu(de->inode)) { 189 if (le32_to_cpu(de->inode)) {
200 /* We might block in the next section 190 if (!dir_emit(ctx, de->name, de->name_len,
201 * if the data destination is 191 le32_to_cpu(de->inode),
202 * currently swapped out. So, use a 192 get_dtype(sb, de->file_type))) {
203 * version stamp to detect whether or 193 brelse(bh);
204 * not the directory has been modified 194 return 0;
205 * during the copy operation. 195 }
206 */
207 u64 version = filp->f_version;
208
209 error = filldir(dirent, de->name,
210 de->name_len,
211 filp->f_pos,
212 le32_to_cpu(de->inode),
213 get_dtype(sb, de->file_type));
214 if (error)
215 break;
216 if (version != filp->f_version)
217 goto revalidate;
218 stored ++;
219 } 196 }
220 filp->f_pos += ext3_rec_len_from_disk(de->rec_len); 197 ctx->pos += ext3_rec_len_from_disk(de->rec_len);
221 } 198 }
222 offset = 0; 199 offset = 0;
223 brelse (bh); 200 brelse (bh);
201 if (ctx->pos < inode->i_size)
202 if (!dir_relax(inode))
203 return 0;
224 } 204 }
225out: 205 return 0;
226 return ret;
227} 206}
228 207
229static inline int is_32bit_api(void) 208static inline int is_32bit_api(void)
@@ -452,62 +431,54 @@ int ext3_htree_store_dirent(struct file *dir_file, __u32 hash,
452 * for all entres on the fname linked list. (Normally there is only 431 * for all entres on the fname linked list. (Normally there is only
453 * one entry on the linked list, unless there are 62 bit hash collisions.) 432 * one entry on the linked list, unless there are 62 bit hash collisions.)
454 */ 433 */
455static int call_filldir(struct file * filp, void * dirent, 434static bool call_filldir(struct file *file, struct dir_context *ctx,
456 filldir_t filldir, struct fname *fname) 435 struct fname *fname)
457{ 436{
458 struct dir_private_info *info = filp->private_data; 437 struct dir_private_info *info = file->private_data;
459 loff_t curr_pos; 438 struct inode *inode = file_inode(file);
460 struct inode *inode = file_inode(filp); 439 struct super_block *sb = inode->i_sb;
461 struct super_block * sb;
462 int error;
463
464 sb = inode->i_sb;
465 440
466 if (!fname) { 441 if (!fname) {
467 printk("call_filldir: called with null fname?!?\n"); 442 printk("call_filldir: called with null fname?!?\n");
468 return 0; 443 return true;
469 } 444 }
470 curr_pos = hash2pos(filp, fname->hash, fname->minor_hash); 445 ctx->pos = hash2pos(file, fname->hash, fname->minor_hash);
471 while (fname) { 446 while (fname) {
472 error = filldir(dirent, fname->name, 447 if (!dir_emit(ctx, fname->name, fname->name_len,
473 fname->name_len, curr_pos,
474 fname->inode, 448 fname->inode,
475 get_dtype(sb, fname->file_type)); 449 get_dtype(sb, fname->file_type))) {
476 if (error) {
477 filp->f_pos = curr_pos;
478 info->extra_fname = fname; 450 info->extra_fname = fname;
479 return error; 451 return false;
480 } 452 }
481 fname = fname->next; 453 fname = fname->next;
482 } 454 }
483 return 0; 455 return true;
484} 456}
485 457
486static int ext3_dx_readdir(struct file * filp, 458static int ext3_dx_readdir(struct file *file, struct dir_context *ctx)
487 void * dirent, filldir_t filldir)
488{ 459{
489 struct dir_private_info *info = filp->private_data; 460 struct dir_private_info *info = file->private_data;
490 struct inode *inode = file_inode(filp); 461 struct inode *inode = file_inode(file);
491 struct fname *fname; 462 struct fname *fname;
492 int ret; 463 int ret;
493 464
494 if (!info) { 465 if (!info) {
495 info = ext3_htree_create_dir_info(filp, filp->f_pos); 466 info = ext3_htree_create_dir_info(file, ctx->pos);
496 if (!info) 467 if (!info)
497 return -ENOMEM; 468 return -ENOMEM;
498 filp->private_data = info; 469 file->private_data = info;
499 } 470 }
500 471
501 if (filp->f_pos == ext3_get_htree_eof(filp)) 472 if (ctx->pos == ext3_get_htree_eof(file))
502 return 0; /* EOF */ 473 return 0; /* EOF */
503 474
504 /* Some one has messed with f_pos; reset the world */ 475 /* Some one has messed with f_pos; reset the world */
505 if (info->last_pos != filp->f_pos) { 476 if (info->last_pos != ctx->pos) {
506 free_rb_tree_fname(&info->root); 477 free_rb_tree_fname(&info->root);
507 info->curr_node = NULL; 478 info->curr_node = NULL;
508 info->extra_fname = NULL; 479 info->extra_fname = NULL;
509 info->curr_hash = pos2maj_hash(filp, filp->f_pos); 480 info->curr_hash = pos2maj_hash(file, ctx->pos);
510 info->curr_minor_hash = pos2min_hash(filp, filp->f_pos); 481 info->curr_minor_hash = pos2min_hash(file, ctx->pos);
511 } 482 }
512 483
513 /* 484 /*
@@ -515,7 +486,7 @@ static int ext3_dx_readdir(struct file * filp,
515 * chain, return them first. 486 * chain, return them first.
516 */ 487 */
517 if (info->extra_fname) { 488 if (info->extra_fname) {
518 if (call_filldir(filp, dirent, filldir, info->extra_fname)) 489 if (!call_filldir(file, ctx, info->extra_fname))
519 goto finished; 490 goto finished;
520 info->extra_fname = NULL; 491 info->extra_fname = NULL;
521 goto next_node; 492 goto next_node;
@@ -529,17 +500,17 @@ static int ext3_dx_readdir(struct file * filp,
529 * cached entries. 500 * cached entries.
530 */ 501 */
531 if ((!info->curr_node) || 502 if ((!info->curr_node) ||
532 (filp->f_version != inode->i_version)) { 503 (file->f_version != inode->i_version)) {
533 info->curr_node = NULL; 504 info->curr_node = NULL;
534 free_rb_tree_fname(&info->root); 505 free_rb_tree_fname(&info->root);
535 filp->f_version = inode->i_version; 506 file->f_version = inode->i_version;
536 ret = ext3_htree_fill_tree(filp, info->curr_hash, 507 ret = ext3_htree_fill_tree(file, info->curr_hash,
537 info->curr_minor_hash, 508 info->curr_minor_hash,
538 &info->next_hash); 509 &info->next_hash);
539 if (ret < 0) 510 if (ret < 0)
540 return ret; 511 return ret;
541 if (ret == 0) { 512 if (ret == 0) {
542 filp->f_pos = ext3_get_htree_eof(filp); 513 ctx->pos = ext3_get_htree_eof(file);
543 break; 514 break;
544 } 515 }
545 info->curr_node = rb_first(&info->root); 516 info->curr_node = rb_first(&info->root);
@@ -548,7 +519,7 @@ static int ext3_dx_readdir(struct file * filp,
548 fname = rb_entry(info->curr_node, struct fname, rb_hash); 519 fname = rb_entry(info->curr_node, struct fname, rb_hash);
549 info->curr_hash = fname->hash; 520 info->curr_hash = fname->hash;
550 info->curr_minor_hash = fname->minor_hash; 521 info->curr_minor_hash = fname->minor_hash;
551 if (call_filldir(filp, dirent, filldir, fname)) 522 if (!call_filldir(file, ctx, fname))
552 break; 523 break;
553 next_node: 524 next_node:
554 info->curr_node = rb_next(info->curr_node); 525 info->curr_node = rb_next(info->curr_node);
@@ -559,7 +530,7 @@ static int ext3_dx_readdir(struct file * filp,
559 info->curr_minor_hash = fname->minor_hash; 530 info->curr_minor_hash = fname->minor_hash;
560 } else { 531 } else {
561 if (info->next_hash == ~0) { 532 if (info->next_hash == ~0) {
562 filp->f_pos = ext3_get_htree_eof(filp); 533 ctx->pos = ext3_get_htree_eof(file);
563 break; 534 break;
564 } 535 }
565 info->curr_hash = info->next_hash; 536 info->curr_hash = info->next_hash;
@@ -567,7 +538,7 @@ static int ext3_dx_readdir(struct file * filp,
567 } 538 }
568 } 539 }
569finished: 540finished:
570 info->last_pos = filp->f_pos; 541 info->last_pos = ctx->pos;
571 return 0; 542 return 0;
572} 543}
573 544
@@ -582,7 +553,7 @@ static int ext3_release_dir (struct inode * inode, struct file * filp)
582const struct file_operations ext3_dir_operations = { 553const struct file_operations ext3_dir_operations = {
583 .llseek = ext3_dir_llseek, 554 .llseek = ext3_dir_llseek,
584 .read = generic_read_dir, 555 .read = generic_read_dir,
585 .readdir = ext3_readdir, 556 .iterate = ext3_readdir,
586 .unlocked_ioctl = ext3_ioctl, 557 .unlocked_ioctl = ext3_ioctl,
587#ifdef CONFIG_COMPAT 558#ifdef CONFIG_COMPAT
588 .compat_ioctl = ext3_compat_ioctl, 559 .compat_ioctl = ext3_compat_ioctl,
diff --git a/fs/ext3/fsync.c b/fs/ext3/fsync.c
index b31dbd4c46ad..1cb9c7e10c6f 100644
--- a/fs/ext3/fsync.c
+++ b/fs/ext3/fsync.c
@@ -48,9 +48,13 @@ int ext3_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
48 48
49 trace_ext3_sync_file_enter(file, datasync); 49 trace_ext3_sync_file_enter(file, datasync);
50 50
51 if (inode->i_sb->s_flags & MS_RDONLY) 51 if (inode->i_sb->s_flags & MS_RDONLY) {
52 /* Make sure that we read updated state */
53 smp_rmb();
54 if (EXT3_SB(inode->i_sb)->s_mount_state & EXT3_ERROR_FS)
55 return -EROFS;
52 return 0; 56 return 0;
53 57 }
54 ret = filemap_write_and_wait_range(inode->i_mapping, start, end); 58 ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
55 if (ret) 59 if (ret)
56 goto out; 60 goto out;
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 23c712825640..2bd85486b879 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -1825,19 +1825,20 @@ ext3_readpages(struct file *file, struct address_space *mapping,
1825 return mpage_readpages(mapping, pages, nr_pages, ext3_get_block); 1825 return mpage_readpages(mapping, pages, nr_pages, ext3_get_block);
1826} 1826}
1827 1827
1828static void ext3_invalidatepage(struct page *page, unsigned long offset) 1828static void ext3_invalidatepage(struct page *page, unsigned int offset,
1829 unsigned int length)
1829{ 1830{
1830 journal_t *journal = EXT3_JOURNAL(page->mapping->host); 1831 journal_t *journal = EXT3_JOURNAL(page->mapping->host);
1831 1832
1832 trace_ext3_invalidatepage(page, offset); 1833 trace_ext3_invalidatepage(page, offset, length);
1833 1834
1834 /* 1835 /*
1835 * If it's a full truncate we just forget about the pending dirtying 1836 * If it's a full truncate we just forget about the pending dirtying
1836 */ 1837 */
1837 if (offset == 0) 1838 if (offset == 0 && length == PAGE_CACHE_SIZE)
1838 ClearPageChecked(page); 1839 ClearPageChecked(page);
1839 1840
1840 journal_invalidatepage(journal, page, offset); 1841 journal_invalidatepage(journal, page, offset, length);
1841} 1842}
1842 1843
1843static int ext3_releasepage(struct page *page, gfp_t wait) 1844static int ext3_releasepage(struct page *page, gfp_t wait)
@@ -1984,6 +1985,7 @@ static const struct address_space_operations ext3_ordered_aops = {
1984 .direct_IO = ext3_direct_IO, 1985 .direct_IO = ext3_direct_IO,
1985 .migratepage = buffer_migrate_page, 1986 .migratepage = buffer_migrate_page,
1986 .is_partially_uptodate = block_is_partially_uptodate, 1987 .is_partially_uptodate = block_is_partially_uptodate,
1988 .is_dirty_writeback = buffer_check_dirty_writeback,
1987 .error_remove_page = generic_error_remove_page, 1989 .error_remove_page = generic_error_remove_page,
1988}; 1990};
1989 1991
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 692de13e3596..1194b1f0f839 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -576,11 +576,8 @@ static int htree_dirblock_to_tree(struct file *dir_file,
576 if (!ext3_check_dir_entry("htree_dirblock_to_tree", dir, de, bh, 576 if (!ext3_check_dir_entry("htree_dirblock_to_tree", dir, de, bh,
577 (block<<EXT3_BLOCK_SIZE_BITS(dir->i_sb)) 577 (block<<EXT3_BLOCK_SIZE_BITS(dir->i_sb))
578 +((char *)de - bh->b_data))) { 578 +((char *)de - bh->b_data))) {
579 /* On error, skip the f_pos to the next block. */ 579 /* silently ignore the rest of the block */
580 dir_file->f_pos = (dir_file->f_pos | 580 break;
581 (dir->i_sb->s_blocksize - 1)) + 1;
582 brelse (bh);
583 return count;
584 } 581 }
585 ext3fs_dirhash(de->name, de->name_len, hinfo); 582 ext3fs_dirhash(de->name, de->name_len, hinfo);
586 if ((hinfo->hash < start_hash) || 583 if ((hinfo->hash < start_hash) ||
@@ -1762,6 +1759,45 @@ retry:
1762 return err; 1759 return err;
1763} 1760}
1764 1761
1762static int ext3_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
1763{
1764 handle_t *handle;
1765 struct inode *inode;
1766 int err, retries = 0;
1767
1768 dquot_initialize(dir);
1769
1770retry:
1771 handle = ext3_journal_start(dir, EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb) +
1772 4 + EXT3_XATTR_TRANS_BLOCKS);
1773
1774 if (IS_ERR(handle))
1775 return PTR_ERR(handle);
1776
1777 inode = ext3_new_inode (handle, dir, NULL, mode);
1778 err = PTR_ERR(inode);
1779 if (!IS_ERR(inode)) {
1780 inode->i_op = &ext3_file_inode_operations;
1781 inode->i_fop = &ext3_file_operations;
1782 ext3_set_aops(inode);
1783 d_tmpfile(dentry, inode);
1784 err = ext3_orphan_add(handle, inode);
1785 if (err)
1786 goto err_drop_inode;
1787 mark_inode_dirty(inode);
1788 unlock_new_inode(inode);
1789 }
1790 ext3_journal_stop(handle);
1791 if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
1792 goto retry;
1793 return err;
1794err_drop_inode:
1795 ext3_journal_stop(handle);
1796 unlock_new_inode(inode);
1797 iput(inode);
1798 return err;
1799}
1800
1765static int ext3_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode) 1801static int ext3_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode)
1766{ 1802{
1767 handle_t *handle; 1803 handle_t *handle;
@@ -2303,7 +2339,7 @@ static int ext3_link (struct dentry * old_dentry,
2303 2339
2304retry: 2340retry:
2305 handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) + 2341 handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
2306 EXT3_INDEX_EXTRA_TRANS_BLOCKS); 2342 EXT3_INDEX_EXTRA_TRANS_BLOCKS + 1);
2307 if (IS_ERR(handle)) 2343 if (IS_ERR(handle))
2308 return PTR_ERR(handle); 2344 return PTR_ERR(handle);
2309 2345
@@ -2317,6 +2353,11 @@ retry:
2317 err = ext3_add_entry(handle, dentry, inode); 2353 err = ext3_add_entry(handle, dentry, inode);
2318 if (!err) { 2354 if (!err) {
2319 ext3_mark_inode_dirty(handle, inode); 2355 ext3_mark_inode_dirty(handle, inode);
2356 /* this can happen only for tmpfile being
2357 * linked the first time
2358 */
2359 if (inode->i_nlink == 1)
2360 ext3_orphan_del(handle, inode);
2320 d_instantiate(dentry, inode); 2361 d_instantiate(dentry, inode);
2321 } else { 2362 } else {
2322 drop_nlink(inode); 2363 drop_nlink(inode);
@@ -2519,6 +2560,7 @@ const struct inode_operations ext3_dir_inode_operations = {
2519 .mkdir = ext3_mkdir, 2560 .mkdir = ext3_mkdir,
2520 .rmdir = ext3_rmdir, 2561 .rmdir = ext3_rmdir,
2521 .mknod = ext3_mknod, 2562 .mknod = ext3_mknod,
2563 .tmpfile = ext3_tmpfile,
2522 .rename = ext3_rename, 2564 .rename = ext3_rename,
2523 .setattr = ext3_setattr, 2565 .setattr = ext3_setattr,
2524#ifdef CONFIG_EXT3_FS_XATTR 2566#ifdef CONFIG_EXT3_FS_XATTR
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 6356665a74bb..c47f14750722 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -174,6 +174,11 @@ static void ext3_handle_error(struct super_block *sb)
174 if (test_opt (sb, ERRORS_RO)) { 174 if (test_opt (sb, ERRORS_RO)) {
175 ext3_msg(sb, KERN_CRIT, 175 ext3_msg(sb, KERN_CRIT,
176 "error: remounting filesystem read-only"); 176 "error: remounting filesystem read-only");
177 /*
178 * Make sure updated value of ->s_mount_state will be visible
179 * before ->s_flags update.
180 */
181 smp_wmb();
177 sb->s_flags |= MS_RDONLY; 182 sb->s_flags |= MS_RDONLY;
178 } 183 }
179 ext3_commit_super(sb, es, 1); 184 ext3_commit_super(sb, es, 1);
@@ -291,8 +296,14 @@ void ext3_abort(struct super_block *sb, const char *function,
291 ext3_msg(sb, KERN_CRIT, 296 ext3_msg(sb, KERN_CRIT,
292 "error: remounting filesystem read-only"); 297 "error: remounting filesystem read-only");
293 EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS; 298 EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
294 sb->s_flags |= MS_RDONLY;
295 set_opt(EXT3_SB(sb)->s_mount_opt, ABORT); 299 set_opt(EXT3_SB(sb)->s_mount_opt, ABORT);
300 /*
301 * Make sure updated value of ->s_mount_state will be visible
302 * before ->s_flags update.
303 */
304 smp_wmb();
305 sb->s_flags |= MS_RDONLY;
306
296 if (EXT3_SB(sb)->s_journal) 307 if (EXT3_SB(sb)->s_journal)
297 journal_abort(EXT3_SB(sb)->s_journal, -EIO); 308 journal_abort(EXT3_SB(sb)->s_journal, -EIO);
298} 309}