diff options
Diffstat (limited to 'fs/ext3')
| -rw-r--r-- | fs/ext3/dir.c | 52 | ||||
| -rw-r--r-- | fs/ext3/file.c | 4 | ||||
| -rw-r--r-- | fs/ext3/inode.c | 16 | ||||
| -rw-r--r-- | fs/ext3/ioctl.c | 4 | ||||
| -rw-r--r-- | fs/ext3/super.c | 6 | 
5 files changed, 39 insertions, 43 deletions
| diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index 832867aef3d..773459164bb 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c @@ -95,11 +95,10 @@ static int ext3_readdir(struct file * filp,  			 void * dirent, filldir_t filldir)  {  	int error = 0; -	unsigned long offset, blk; -	int i, num, stored; -	struct buffer_head * bh, * tmp, * bha[16]; -	struct ext3_dir_entry_2 * de; -	struct super_block * sb; +	unsigned long offset; +	int i, stored; +	struct ext3_dir_entry_2 *de; +	struct super_block *sb;  	int err;  	struct inode *inode = filp->f_dentry->d_inode;  	int ret = 0; @@ -124,12 +123,29 @@ static int ext3_readdir(struct file * filp,  	}  #endif  	stored = 0; -	bh = NULL;  	offset = filp->f_pos & (sb->s_blocksize - 1);  	while (!error && !stored && filp->f_pos < inode->i_size) { -		blk = (filp->f_pos) >> EXT3_BLOCK_SIZE_BITS(sb); -		bh = ext3_bread(NULL, inode, blk, 0, &err); +		unsigned long blk = filp->f_pos >> EXT3_BLOCK_SIZE_BITS(sb); +		struct buffer_head map_bh; +		struct buffer_head *bh = NULL; + +		map_bh.b_state = 0; +		err = ext3_get_block_handle(NULL, inode, blk, &map_bh, 0, 0); +		if (!err) { +			page_cache_readahead(sb->s_bdev->bd_inode->i_mapping, +				&filp->f_ra, +				filp, +				map_bh.b_blocknr >> +					(PAGE_CACHE_SHIFT - inode->i_blkbits), +				1); +			bh = ext3_bread(NULL, inode, blk, 0, &err); +		} + +		/* +		 * We ignore I/O errors on directories so users have a chance +		 * of recovering data when there's a bad sector +		 */  		if (!bh) {  			ext3_error (sb, "ext3_readdir",  				"directory #%lu contains a hole at offset %lu", @@ -138,26 +154,6 @@ static int ext3_readdir(struct file * filp,  			continue;  		} -		/* -		 * Do the readahead -		 */ -		if (!offset) { -			for (i = 16 >> (EXT3_BLOCK_SIZE_BITS(sb) - 9), num = 0; -			     i > 0; i--) { -				tmp = ext3_getblk (NULL, inode, ++blk, 0, &err); -				if (tmp && !buffer_uptodate(tmp) && -						!buffer_locked(tmp)) -					bha[num++] = tmp; -				else -					brelse (tmp); -			} -			if (num) { -				ll_rw_block (READA, num, bha); -				for (i = 0; i < num; i++) -					brelse (bha[i]); -			} -		} -  revalidate:  		/* If the dir block has changed since the last call to  		 * readdir(2), then we might be pointing to an invalid diff --git a/fs/ext3/file.c b/fs/ext3/file.c index 98e78345ead..59098ea5671 100644 --- a/fs/ext3/file.c +++ b/fs/ext3/file.c @@ -37,9 +37,9 @@ static int ext3_release_file (struct inode * inode, struct file * filp)  	if ((filp->f_mode & FMODE_WRITE) &&  			(atomic_read(&inode->i_writecount) == 1))  	{ -		down(&EXT3_I(inode)->truncate_sem); +		mutex_lock(&EXT3_I(inode)->truncate_mutex);  		ext3_discard_reservation(inode); -		up(&EXT3_I(inode)->truncate_sem); +		mutex_unlock(&EXT3_I(inode)->truncate_mutex);  	}  	if (is_dx(inode) && filp->private_data)  		ext3_htree_free_dir_info(filp->private_data); diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 0384e539b88..2c361377e0a 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -671,7 +671,7 @@ err_out:   * The BKL may not be held on entry here.  Be sure to take it early.   */ -static int +int  ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,  		struct buffer_head *bh_result, int create, int extend_disksize)  { @@ -702,7 +702,7 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,  	if (!create || err == -EIO)  		goto cleanup; -	down(&ei->truncate_sem); +	mutex_lock(&ei->truncate_mutex);  	/*  	 * If the indirect block is missing while we are reading @@ -723,7 +723,7 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,  		}  		partial = ext3_get_branch(inode, depth, offsets, chain, &err);  		if (!partial) { -			up(&ei->truncate_sem); +			mutex_unlock(&ei->truncate_mutex);  			if (err)  				goto cleanup;  			clear_buffer_new(bh_result); @@ -759,13 +759,13 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,  		err = ext3_splice_branch(handle, inode, iblock, chain,  					 partial, left);  	/* -	 * i_disksize growing is protected by truncate_sem.  Don't forget to +	 * i_disksize growing is protected by truncate_mutex.  Don't forget to  	 * protect it if you're about to implement concurrent  	 * ext3_get_block() -bzzz  	*/  	if (!err && extend_disksize && inode->i_size > ei->i_disksize)  		ei->i_disksize = inode->i_size; -	up(&ei->truncate_sem); +	mutex_unlock(&ei->truncate_mutex);  	if (err)  		goto cleanup; @@ -1227,7 +1227,7 @@ static int journal_dirty_data_fn(handle_t *handle, struct buffer_head *bh)   *	ext3_file_write() -> generic_file_write() -> __alloc_pages() -> ...   *   * Same applies to ext3_get_block().  We will deadlock on various things like - * lock_journal and i_truncate_sem. + * lock_journal and i_truncate_mutex.   *   * Setting PF_MEMALLOC here doesn't work - too many internal memory   * allocations fail. @@ -2161,7 +2161,7 @@ void ext3_truncate(struct inode * inode)  	 * From here we block out all ext3_get_block() callers who want to  	 * modify the block allocation tree.  	 */ -	down(&ei->truncate_sem); +	mutex_lock(&ei->truncate_mutex);  	if (n == 1) {		/* direct blocks */  		ext3_free_data(handle, inode, NULL, i_data+offsets[0], @@ -2228,7 +2228,7 @@ do_indirects:  	ext3_discard_reservation(inode); -	up(&ei->truncate_sem); +	mutex_unlock(&ei->truncate_mutex);  	inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;  	ext3_mark_inode_dirty(handle, inode); diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c index 556cd551007..aaf1da17b6d 100644 --- a/fs/ext3/ioctl.c +++ b/fs/ext3/ioctl.c @@ -182,7 +182,7 @@ flags_err:  		 * need to allocate reservation structure for this inode  		 * before set the window size  		 */ -		down(&ei->truncate_sem); +		mutex_lock(&ei->truncate_mutex);  		if (!ei->i_block_alloc_info)  			ext3_init_block_alloc_info(inode); @@ -190,7 +190,7 @@ flags_err:  			struct ext3_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node;  			rsv->rsv_goal_size = rsv_window_size;  		} -		up(&ei->truncate_sem); +		mutex_unlock(&ei->truncate_mutex);  		return 0;  	}  	case EXT3_IOC_GROUP_EXTEND: { diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 56bf7658601..efe5b20d7a5 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -472,7 +472,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)  #ifdef CONFIG_EXT3_FS_XATTR  		init_rwsem(&ei->xattr_sem);  #endif -		init_MUTEX(&ei->truncate_sem); +		mutex_init(&ei->truncate_mutex);  		inode_init_once(&ei->vfs_inode);  	}  } @@ -2382,8 +2382,8 @@ static int ext3_statfs (struct super_block * sb, struct kstatfs * buf)   * Process 1                         Process 2   * ext3_create()                     quota_sync()   *   journal_start()                   write_dquot() - *   DQUOT_INIT()                        down(dqio_sem) - *     down(dqio_sem)                    journal_start() + *   DQUOT_INIT()                        down(dqio_mutex) + *     down(dqio_mutex)                    journal_start()   *   */ | 
