diff options
Diffstat (limited to 'fs/ext3')
| -rw-r--r-- | fs/ext3/acl.c | 223 | ||||
| -rw-r--r-- | fs/ext3/acl.h | 9 | ||||
| -rw-r--r-- | fs/ext3/balloc.c | 5 | ||||
| -rw-r--r-- | fs/ext3/dir.c | 46 | ||||
| -rw-r--r-- | fs/ext3/file.c | 11 | ||||
| -rw-r--r-- | fs/ext3/ialloc.c | 2 | ||||
| -rw-r--r-- | fs/ext3/inode.c | 138 | ||||
| -rw-r--r-- | fs/ext3/namei.c | 7 | ||||
| -rw-r--r-- | fs/ext3/super.c | 8 | ||||
| -rw-r--r-- | fs/ext3/xattr.c | 8 | ||||
| -rw-r--r-- | fs/ext3/xattr.h | 2 | ||||
| -rw-r--r-- | fs/ext3/xattr_security.c | 5 | 
12 files changed, 117 insertions, 347 deletions
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c index dbb5ad59a7f..8bbaf5bcf98 100644 --- a/fs/ext3/acl.c +++ b/fs/ext3/acl.c @@ -145,13 +145,6 @@ ext3_get_acl(struct inode *inode, int type)  	struct posix_acl *acl;  	int retval; -	if (!test_opt(inode->i_sb, POSIX_ACL)) -		return NULL; - -	acl = get_cached_acl(inode, type); -	if (acl != ACL_NOT_CACHED) -		return acl; -  	switch (type) {  	case ACL_TYPE_ACCESS:  		name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS; @@ -190,7 +183,7 @@ ext3_get_acl(struct inode *inode, int type)   * inode->i_mutex: down unless called from ext3_new_inode   */  static int -ext3_set_acl(handle_t *handle, struct inode *inode, int type, +__ext3_set_acl(handle_t *handle, struct inode *inode, int type,  	     struct posix_acl *acl)  {  	int name_index; @@ -198,9 +191,6 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,  	size_t size = 0;  	int error; -	if (S_ISLNK(inode->i_mode)) -		return -EOPNOTSUPP; -  	switch(type) {  		case ACL_TYPE_ACCESS:  			name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS; @@ -243,204 +233,49 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,  	return error;  } -/* - * Initialize the ACLs of a new inode. Called from ext3_new_inode. - * - * dir->i_mutex: down - * inode->i_mutex: up (access to inode is still exclusive) - */  int -ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir) +ext3_set_acl(struct inode *inode, struct posix_acl *acl, int type)  { -	struct posix_acl *acl = NULL; -	int error = 0; - -	if (!S_ISLNK(inode->i_mode)) { -		if (test_opt(dir->i_sb, POSIX_ACL)) { -			acl = ext3_get_acl(dir, ACL_TYPE_DEFAULT); -			if (IS_ERR(acl)) -				return PTR_ERR(acl); -		} -		if (!acl) -			inode->i_mode &= ~current_umask(); -	} -	if (test_opt(inode->i_sb, POSIX_ACL) && acl) { -		if (S_ISDIR(inode->i_mode)) { -			error = ext3_set_acl(handle, inode, -					     ACL_TYPE_DEFAULT, acl); -			if (error) -				goto cleanup; -		} -		error = posix_acl_create(&acl, GFP_NOFS, &inode->i_mode); -		if (error < 0) -			return error; - -		if (error > 0) { -			/* This is an extended ACL */ -			error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, acl); -		} -	} -cleanup: -	posix_acl_release(acl); -	return error; -} - -/* - * Does chmod for an inode that may have an Access Control List. The - * inode->i_mode field must be updated to the desired value by the caller - * before calling this function. - * Returns 0 on success, or a negative error number. - * - * We change the ACL rather than storing some ACL entries in the file - * mode permission bits (which would be more efficient), because that - * would break once additional permissions (like  ACL_APPEND, ACL_DELETE - * for directories) are added. There are no more bits available in the - * file mode. - * - * inode->i_mutex: down - */ -int -ext3_acl_chmod(struct inode *inode) -{ -	struct posix_acl *acl;  	handle_t *handle; -	int retries = 0; -        int error; +	int error, retries = 0; -	if (S_ISLNK(inode->i_mode)) -		return -EOPNOTSUPP; -	if (!test_opt(inode->i_sb, POSIX_ACL)) -		return 0; -	acl = ext3_get_acl(inode, ACL_TYPE_ACCESS); -	if (IS_ERR(acl) || !acl) -		return PTR_ERR(acl); -	error = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode); -	if (error) -		return error;  retry: -	handle = ext3_journal_start(inode, -			EXT3_DATA_TRANS_BLOCKS(inode->i_sb)); -	if (IS_ERR(handle)) { -		error = PTR_ERR(handle); -		ext3_std_error(inode->i_sb, error); -		goto out; -	} -	error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, acl); +	handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS(inode->i_sb)); +	if (IS_ERR(handle)) +		return PTR_ERR(handle); +	error = __ext3_set_acl(handle, inode, type, acl);  	ext3_journal_stop(handle); -	if (error == -ENOSPC && -	    ext3_should_retry_alloc(inode->i_sb, &retries)) +	if (error == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))  		goto retry; -out: -	posix_acl_release(acl);  	return error;  }  /* - * Extended attribute handlers + * Initialize the ACLs of a new inode. Called from ext3_new_inode. + * + * dir->i_mutex: down + * inode->i_mutex: up (access to inode is still exclusive)   */ -static size_t -ext3_xattr_list_acl_access(struct dentry *dentry, char *list, size_t list_len, -			   const char *name, size_t name_len, int type) -{ -	const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS); - -	if (!test_opt(dentry->d_sb, POSIX_ACL)) -		return 0; -	if (list && size <= list_len) -		memcpy(list, POSIX_ACL_XATTR_ACCESS, size); -	return size; -} - -static size_t -ext3_xattr_list_acl_default(struct dentry *dentry, char *list, size_t list_len, -			    const char *name, size_t name_len, int type) -{ -	const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT); - -	if (!test_opt(dentry->d_sb, POSIX_ACL)) -		return 0; -	if (list && size <= list_len) -		memcpy(list, POSIX_ACL_XATTR_DEFAULT, size); -	return size; -} - -static int -ext3_xattr_get_acl(struct dentry *dentry, const char *name, void *buffer, -		   size_t size, int type) +int +ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)  { -	struct posix_acl *acl; +	struct posix_acl *default_acl, *acl;  	int error; -	if (strcmp(name, "") != 0) -		return -EINVAL; -	if (!test_opt(dentry->d_sb, POSIX_ACL)) -		return -EOPNOTSUPP; - -	acl = ext3_get_acl(dentry->d_inode, type); -	if (IS_ERR(acl)) -		return PTR_ERR(acl); -	if (acl == NULL) -		return -ENODATA; -	error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size); -	posix_acl_release(acl); - -	return error; -} - -static int -ext3_xattr_set_acl(struct dentry *dentry, const char *name, const void *value, -		   size_t size, int flags, int type) -{ -	struct inode *inode = dentry->d_inode; -	handle_t *handle; -	struct posix_acl *acl; -	int error, retries = 0; - -	if (strcmp(name, "") != 0) -		return -EINVAL; -	if (!test_opt(inode->i_sb, POSIX_ACL)) -		return -EOPNOTSUPP; -	if (!inode_owner_or_capable(inode)) -		return -EPERM; - -	if (value) { -		acl = posix_acl_from_xattr(&init_user_ns, value, size); -		if (IS_ERR(acl)) -			return PTR_ERR(acl); -		else if (acl) { -			error = posix_acl_valid(acl); -			if (error) -				goto release_and_out; -		} -	} else -		acl = NULL; - -retry: -	handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS(inode->i_sb)); -	if (IS_ERR(handle)) -		return PTR_ERR(handle); -	error = ext3_set_acl(handle, inode, type, acl); -	ext3_journal_stop(handle); -	if (error == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries)) -		goto retry; +	error = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl); +	if (error) +		return error; -release_and_out: -	posix_acl_release(acl); +	if (default_acl) { +		error = __ext3_set_acl(handle, inode, ACL_TYPE_DEFAULT, +				       default_acl); +		posix_acl_release(default_acl); +	} +	if (acl) { +		if (!error) +			error = __ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, +					       acl); +		posix_acl_release(acl); +	}  	return error;  } - -const struct xattr_handler ext3_xattr_acl_access_handler = { -	.prefix	= POSIX_ACL_XATTR_ACCESS, -	.flags	= ACL_TYPE_ACCESS, -	.list	= ext3_xattr_list_acl_access, -	.get	= ext3_xattr_get_acl, -	.set	= ext3_xattr_set_acl, -}; - -const struct xattr_handler ext3_xattr_acl_default_handler = { -	.prefix	= POSIX_ACL_XATTR_DEFAULT, -	.flags	= ACL_TYPE_DEFAULT, -	.list	= ext3_xattr_list_acl_default, -	.get	= ext3_xattr_get_acl, -	.set	= ext3_xattr_set_acl, -}; diff --git a/fs/ext3/acl.h b/fs/ext3/acl.h index dbc921e458c..ea1c69edab9 100644 --- a/fs/ext3/acl.h +++ b/fs/ext3/acl.h @@ -55,18 +55,13 @@ static inline int ext3_acl_count(size_t size)  /* acl.c */  extern struct posix_acl *ext3_get_acl(struct inode *inode, int type); -extern int ext3_acl_chmod (struct inode *); +extern int ext3_set_acl(struct inode *inode, struct posix_acl *acl, int type);  extern int ext3_init_acl (handle_t *, struct inode *, struct inode *);  #else  /* CONFIG_EXT3_FS_POSIX_ACL */  #include <linux/sched.h>  #define ext3_get_acl NULL - -static inline int -ext3_acl_chmod(struct inode *inode) -{ -	return 0; -} +#define ext3_set_acl NULL  static inline int  ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir) diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 22548f56197..158b5d4ce06 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -1727,10 +1727,7 @@ allocated:  	percpu_counter_sub(&sbi->s_freeblocks_counter, num);  	BUFFER_TRACE(gdp_bh, "journal_dirty_metadata for group descriptor"); -	err = ext3_journal_dirty_metadata(handle, gdp_bh); -	if (!fatal) -		fatal = err; - +	fatal = ext3_journal_dirty_metadata(handle, gdp_bh);  	if (fatal)  		goto out; diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index bafdd48eefd..17742eed2c1 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c @@ -275,7 +275,7 @@ static inline loff_t ext3_get_htree_eof(struct file *filp)   * NOTE: offsets obtained *before* ext3_set_inode_flag(dir, EXT3_INODE_INDEX)   *       will be invalid once the directory was converted into a dx directory   */ -loff_t ext3_dir_llseek(struct file *file, loff_t offset, int whence) +static loff_t ext3_dir_llseek(struct file *file, loff_t offset, int whence)  {  	struct inode *inode = file->f_mapping->host;  	int dx_dir = is_dx_dir(inode); @@ -309,43 +309,17 @@ struct fname {   */  static void free_rb_tree_fname(struct rb_root *root)  { -	struct rb_node	*n = root->rb_node; -	struct rb_node	*parent; -	struct fname	*fname; - -	while (n) { -		/* Do the node's children first */ -		if (n->rb_left) { -			n = n->rb_left; -			continue; -		} -		if (n->rb_right) { -			n = n->rb_right; -			continue; -		} -		/* -		 * The node has no children; free it, and then zero -		 * out parent's link to it.  Finally go to the -		 * beginning of the loop and try to free the parent -		 * node. -		 */ -		parent = rb_parent(n); -		fname = rb_entry(n, struct fname, rb_hash); -		while (fname) { -			struct fname * old = fname; +	struct fname *fname, *next; + +	rbtree_postorder_for_each_entry_safe(fname, next, root, rb_hash) +		do { +			struct fname *old = fname;  			fname = fname->next; -			kfree (old); -		} -		if (!parent) -			*root = RB_ROOT; -		else if (parent->rb_left == n) -			parent->rb_left = NULL; -		else if (parent->rb_right == n) -			parent->rb_right = NULL; -		n = parent; -	} -} +			kfree(old); +		} while (fname); +	*root = RB_ROOT; +}  static struct dir_private_info *ext3_htree_create_dir_info(struct file *filp,  							   loff_t pos) diff --git a/fs/ext3/file.c b/fs/ext3/file.c index 25cb413277e..a062fa1e1b1 100644 --- a/fs/ext3/file.c +++ b/fs/ext3/file.c @@ -50,10 +50,10 @@ static int ext3_release_file (struct inode * inode, struct file * filp)  const struct file_operations ext3_file_operations = {  	.llseek		= generic_file_llseek, -	.read		= do_sync_read, -	.write		= do_sync_write, -	.aio_read	= generic_file_aio_read, -	.aio_write	= generic_file_aio_write, +	.read		= new_sync_read, +	.write		= new_sync_write, +	.read_iter	= generic_file_read_iter, +	.write_iter	= generic_file_write_iter,  	.unlocked_ioctl	= ext3_ioctl,  #ifdef CONFIG_COMPAT  	.compat_ioctl	= ext3_compat_ioctl, @@ -63,7 +63,7 @@ const struct file_operations ext3_file_operations = {  	.release	= ext3_release_file,  	.fsync		= ext3_sync_file,  	.splice_read	= generic_file_splice_read, -	.splice_write	= generic_file_splice_write, +	.splice_write	= iter_file_splice_write,  };  const struct inode_operations ext3_file_inode_operations = { @@ -75,6 +75,7 @@ const struct inode_operations ext3_file_inode_operations = {  	.removexattr	= generic_removexattr,  #endif  	.get_acl	= ext3_get_acl, +	.set_acl	= ext3_set_acl,  	.fiemap		= ext3_fiemap,  }; diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index 082afd78b10..a1b810230cc 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c @@ -215,7 +215,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)  		int best_ndir = inodes_per_group;  		int best_group = -1; -		get_random_bytes(&group, sizeof(group)); +		group = prandom_u32();  		parent_group = (unsigned)group % ngroups;  		for (i = 0; i < ngroups; i++) {  			group = (parent_group + i) % ngroups; diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 2bd85486b87..2c6ccc49ba2 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -228,7 +228,7 @@ void ext3_evict_inode (struct inode *inode)  		log_wait_commit(journal, commit_tid);  		filemap_write_and_wait(&inode->i_data);  	} -	truncate_inode_pages(&inode->i_data, 0); +	truncate_inode_pages_final(&inode->i_data);  	ext3_discard_reservation(inode);  	rsv = ei->i_block_alloc_info; @@ -1559,56 +1559,17 @@ static int buffer_unmapped(handle_t *handle, struct buffer_head *bh)  }  /* - * Note that we always start a transaction even if we're not journalling - * data.  This is to preserve ordering: any hole instantiation within - * __block_write_full_page -> ext3_get_block() should be journalled - * along with the data so we don't crash and then get metadata which + * Note that whenever we need to map blocks we start a transaction even if + * we're not journalling data.  This is to preserve ordering: any hole + * instantiation within __block_write_full_page -> ext3_get_block() should be + * journalled along with the data so we don't crash and then get metadata which   * refers to old data.   *   * In all journalling modes block_write_full_page() will start the I/O.   * - * Problem: - * - *	ext3_writepage() -> kmalloc() -> __alloc_pages() -> page_launder() -> - *		ext3_writepage() - * - * Similar for: - * - *	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_mutex. - * - * Setting PF_MEMALLOC here doesn't work - too many internal memory - * allocations fail. - * - * 16May01: If we're reentered then journal_current_handle() will be - *	    non-zero. We simply *return*. - * - * 1 July 2001: @@@ FIXME: - *   In journalled data mode, a data buffer may be metadata against the - *   current transaction.  But the same file is part of a shared mapping - *   and someone does a writepage() on it. - * - *   We will move the buffer onto the async_data list, but *after* it has - *   been dirtied. So there's a small window where we have dirty data on - *   BJ_Metadata. - * - *   Note that this only applies to the last partial page in the file.  The - *   bit which block_write_full_page() uses prepare/commit for.  (That's - *   broken code anyway: it's wrong for msync()). - * - *   It's a rare case: affects the final partial page, for journalled data - *   where the file is subject to bith write() and writepage() in the same - *   transction.  To fix it we'll need a custom block_write_full_page(). - *   We'll probably need that anyway for journalling writepage() output. - *   * We don't honour synchronous mounts for writepage().  That would be   * disastrous.  Any write() or metadata operation will sync the fs for   * us. - * - * AKPM2: if all the page's buffers are mapped to disk and !data=journal, - * we don't need to open a transaction here.   */  static int ext3_ordered_writepage(struct page *page,  				struct writeback_control *wbc) @@ -1673,12 +1634,9 @@ static int ext3_ordered_writepage(struct page *page,  	 * block_write_full_page() succeeded.  Otherwise they are unmapped,  	 * and generally junk.  	 */ -	if (ret == 0) { -		err = walk_page_buffers(handle, page_bufs, 0, PAGE_CACHE_SIZE, +	if (ret == 0) +		ret = walk_page_buffers(handle, page_bufs, 0, PAGE_CACHE_SIZE,  					NULL, journal_dirty_data_fn); -		if (!ret) -			ret = err; -	}  	walk_page_buffers(handle, page_bufs, 0,  			PAGE_CACHE_SIZE, NULL, bput_one);  	err = ext3_journal_stop(handle); @@ -1758,17 +1716,17 @@ static int ext3_journalled_writepage(struct page *page,  	WARN_ON_ONCE(IS_RDONLY(inode) &&  		     !(EXT3_SB(inode->i_sb)->s_mount_state & EXT3_ERROR_FS)); -	if (ext3_journal_current_handle()) -		goto no_write; -  	trace_ext3_journalled_writepage(page); -	handle = ext3_journal_start(inode, ext3_writepage_trans_blocks(inode)); -	if (IS_ERR(handle)) { -		ret = PTR_ERR(handle); -		goto no_write; -	} -  	if (!page_has_buffers(page) || PageChecked(page)) { +		if (ext3_journal_current_handle()) +			goto no_write; + +		handle = ext3_journal_start(inode, +					    ext3_writepage_trans_blocks(inode)); +		if (IS_ERR(handle)) { +			ret = PTR_ERR(handle); +			goto no_write; +		}  		/*  		 * It's mmapped pagecache.  Add buffers and journal it.  There  		 * doesn't seem much point in redirtying the page here. @@ -1791,17 +1749,18 @@ static int ext3_journalled_writepage(struct page *page,  		atomic_set(&EXT3_I(inode)->i_datasync_tid,  			   handle->h_transaction->t_tid);  		unlock_page(page); +		err = ext3_journal_stop(handle); +		if (!ret) +			ret = err;  	} else {  		/* -		 * It may be a page full of checkpoint-mode buffers.  We don't -		 * really know unless we go poke around in the buffer_heads. -		 * But block_write_full_page will do the right thing. +		 * It is a page full of checkpoint-mode buffers. Go and write +		 * them. They should have been already mapped when they went +		 * to the journal so provide NULL get_block function to catch +		 * errors.  		 */ -		ret = block_write_full_page(page, ext3_get_block, wbc); +		ret = block_write_full_page(page, NULL, wbc);  	} -	err = ext3_journal_stop(handle); -	if (!ret) -		ret = err;  out:  	return ret; @@ -1862,8 +1821,7 @@ static int ext3_releasepage(struct page *page, gfp_t wait)   * VFS code falls back into buffered path in that case so we are safe.   */  static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb, -			const struct iovec *iov, loff_t offset, -			unsigned long nr_segs) +			struct iov_iter *iter, loff_t offset)  {  	struct file *file = iocb->ki_filp;  	struct inode *inode = file->f_mapping->host; @@ -1871,10 +1829,10 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,  	handle_t *handle;  	ssize_t ret;  	int orphan = 0; -	size_t count = iov_length(iov, nr_segs); +	size_t count = iov_iter_count(iter);  	int retries = 0; -	trace_ext3_direct_IO_enter(inode, offset, iov_length(iov, nr_segs), rw); +	trace_ext3_direct_IO_enter(inode, offset, count, rw);  	if (rw == WRITE) {  		loff_t final_size = offset + count; @@ -1898,15 +1856,14 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,  	}  retry: -	ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs, -				 ext3_get_block); +	ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, ext3_get_block);  	/*  	 * In case of error extending write may have instantiated a few  	 * blocks outside i_size. Trim these off again.  	 */  	if (unlikely((rw & WRITE) && ret < 0)) {  		loff_t isize = i_size_read(inode); -		loff_t end = offset + iov_length(iov, nr_segs); +		loff_t end = offset + count;  		if (end > isize)  			ext3_truncate_failed_direct_write(inode); @@ -1925,6 +1882,8 @@ retry:  			 * and pretend the write failed... */  			ext3_truncate_failed_direct_write(inode);  			ret = PTR_ERR(handle); +			if (inode->i_nlink) +				ext3_orphan_del(NULL, inode);  			goto out;  		}  		if (inode->i_nlink) @@ -1949,8 +1908,7 @@ retry:  			ret = err;  	}  out: -	trace_ext3_direct_IO_exit(inode, offset, -				iov_length(iov, nr_segs), rw, ret); +	trace_ext3_direct_IO_exit(inode, offset, count, rw, ret);  	return ret;  } @@ -3212,21 +3170,20 @@ out_brelse:   *   * We are called from a few places:   * - * - Within generic_file_write() for O_SYNC files. + * - Within generic_file_aio_write() -> generic_write_sync() for O_SYNC files.   *   Here, there will be no transaction running. We wait for any running   *   transaction to commit.   * - * - Within sys_sync(), kupdate and such. - *   We wait on commit, if tol to. + * - Within flush work (for sys_sync(), kupdate and such). + *   We wait on commit, if told to.   * - * - Within prune_icache() (PF_MEMALLOC == true) - *   Here we simply return.  We can't afford to block kswapd on the - *   journal commit. + * - Within iput_final() -> write_inode_now() + *   We wait on commit, if told to.   *   * In all cases it is actually safe for us to return without doing anything,   * because the inode has been copied into a raw inode buffer in - * ext3_mark_inode_dirty().  This is a correctness thing for O_SYNC and for - * knfsd. + * ext3_mark_inode_dirty().  This is a correctness thing for WB_SYNC_ALL + * writeback.   *   * Note that we are absolutely dependent upon all inode dirtiers doing the   * right thing: they *must* call mark_inode_dirty() after dirtying info in @@ -3238,13 +3195,13 @@ out_brelse:   *	stuff();   *	inode->i_size = expr;   * - * is in error because a kswapd-driven write_inode() could occur while - * `stuff()' is running, and the new i_size will be lost.  Plus the inode - * will no longer be on the superblock's dirty inode list. + * is in error because write_inode() could occur while `stuff()' is running, + * and the new i_size will be lost.  Plus the inode will no longer be on the + * superblock's dirty inode list.   */  int ext3_write_inode(struct inode *inode, struct writeback_control *wbc)  { -	if (current->flags & PF_MEMALLOC) +	if (WARN_ON_ONCE(current->flags & PF_MEMALLOC))  		return 0;  	if (ext3_journal_current_handle()) { @@ -3253,7 +3210,12 @@ int ext3_write_inode(struct inode *inode, struct writeback_control *wbc)  		return -EIO;  	} -	if (wbc->sync_mode != WB_SYNC_ALL) +	/* +	 * No need to force transaction in WB_SYNC_NONE mode. Also +	 * ext3_sync_fs() will force the commit after everything is +	 * written. +	 */ +	if (wbc->sync_mode != WB_SYNC_ALL || wbc->for_sync)  		return 0;  	return ext3_force_commit(inode->i_sb); @@ -3365,7 +3327,7 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)  	mark_inode_dirty(inode);  	if (ia_valid & ATTR_MODE) -		rc = ext3_acl_chmod(inode); +		rc = posix_acl_chmod(inode, inode->i_mode);  err_out:  	ext3_std_error(inode->i_sb, error); diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 1194b1f0f83..f197736dccf 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -1783,7 +1783,7 @@ retry:  		d_tmpfile(dentry, inode);  		err = ext3_orphan_add(handle, inode);  		if (err) -			goto err_drop_inode; +			goto err_unlock_inode;  		mark_inode_dirty(inode);  		unlock_new_inode(inode);  	} @@ -1791,10 +1791,9 @@ retry:  	if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))  		goto retry;  	return err; -err_drop_inode: +err_unlock_inode:  	ext3_journal_stop(handle);  	unlock_new_inode(inode); -	iput(inode);  	return err;  } @@ -2570,6 +2569,7 @@ const struct inode_operations ext3_dir_inode_operations = {  	.removexattr	= generic_removexattr,  #endif  	.get_acl	= ext3_get_acl, +	.set_acl	= ext3_set_acl,  };  const struct inode_operations ext3_special_inode_operations = { @@ -2581,4 +2581,5 @@ const struct inode_operations ext3_special_inode_operations = {  	.removexattr	= generic_removexattr,  #endif  	.get_acl	= ext3_get_acl, +	.set_acl	= ext3_set_acl,  }; diff --git a/fs/ext3/super.c b/fs/ext3/super.c index c50c7619037..08cdfe5461e 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -527,7 +527,7 @@ static void init_once(void *foo)  	inode_init_once(&ei->vfs_inode);  } -static int init_inodecache(void) +static int __init init_inodecache(void)  {  	ext3_inode_cachep = kmem_cache_create("ext3_inode_cache",  					     sizeof(struct ext3_inode_info), @@ -2649,6 +2649,8 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)  	int i;  #endif +	sync_filesystem(sb); +  	/* Store the original options */  	old_sb_flags = sb->s_flags;  	old_opts.s_mount_opt = sbi->s_mount_opt; @@ -2825,6 +2827,10 @@ static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf)  		 * bitmap, and an inode table.  		 */  		overhead += ngroups * (2 + sbi->s_itb_per_group); + +		/* Add the journal blocks as well */ +                overhead += sbi->s_journal->j_maxlen; +  		sbi->s_overhead_last = overhead;  		smp_wmb();  		sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count); diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index b1fc96383e0..c6874be6d58 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c @@ -102,8 +102,8 @@ static struct mb_cache *ext3_xattr_cache;  static const struct xattr_handler *ext3_xattr_handler_map[] = {  	[EXT3_XATTR_INDEX_USER]		     = &ext3_xattr_user_handler,  #ifdef CONFIG_EXT3_FS_POSIX_ACL -	[EXT3_XATTR_INDEX_POSIX_ACL_ACCESS]  = &ext3_xattr_acl_access_handler, -	[EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT] = &ext3_xattr_acl_default_handler, +	[EXT3_XATTR_INDEX_POSIX_ACL_ACCESS]  = &posix_acl_access_xattr_handler, +	[EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT] = &posix_acl_default_xattr_handler,  #endif  	[EXT3_XATTR_INDEX_TRUSTED]	     = &ext3_xattr_trusted_handler,  #ifdef CONFIG_EXT3_FS_SECURITY @@ -115,8 +115,8 @@ const struct xattr_handler *ext3_xattr_handlers[] = {  	&ext3_xattr_user_handler,  	&ext3_xattr_trusted_handler,  #ifdef CONFIG_EXT3_FS_POSIX_ACL -	&ext3_xattr_acl_access_handler, -	&ext3_xattr_acl_default_handler, +	&posix_acl_access_xattr_handler, +	&posix_acl_default_xattr_handler,  #endif  #ifdef CONFIG_EXT3_FS_SECURITY  	&ext3_xattr_security_handler, diff --git a/fs/ext3/xattr.h b/fs/ext3/xattr.h index 2be4f69bfa6..32e93ebf803 100644 --- a/fs/ext3/xattr.h +++ b/fs/ext3/xattr.h @@ -60,8 +60,6 @@ struct ext3_xattr_entry {  extern const struct xattr_handler ext3_xattr_user_handler;  extern const struct xattr_handler ext3_xattr_trusted_handler; -extern const struct xattr_handler ext3_xattr_acl_access_handler; -extern const struct xattr_handler ext3_xattr_acl_default_handler;  extern const struct xattr_handler ext3_xattr_security_handler;  extern ssize_t ext3_listxattr(struct dentry *, char *, size_t); diff --git a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c index 3387664ad70..722c2bf9645 100644 --- a/fs/ext3/xattr_security.c +++ b/fs/ext3/xattr_security.c @@ -43,8 +43,9 @@ ext3_xattr_security_set(struct dentry *dentry, const char *name,  			      name, value, size, flags);  } -int ext3_initxattrs(struct inode *inode, const struct xattr *xattr_array, -		    void *fs_info) +static int ext3_initxattrs(struct inode *inode, +			   const struct xattr *xattr_array, +			   void *fs_info)  {  	const struct xattr *xattr;  	handle_t *handle = fs_info;  | 
