diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/btrfs/qgroup.c | 8 | ||||
| -rw-r--r-- | fs/cifs/cifs_unicode.c | 2 | ||||
| -rw-r--r-- | fs/cifs/file.c | 2 | ||||
| -rw-r--r-- | fs/cifs/smb2pdu.h | 4 | ||||
| -rw-r--r-- | fs/dcache.c | 6 | ||||
| -rw-r--r-- | fs/debugfs/file.c | 74 | ||||
| -rw-r--r-- | fs/ecryptfs/file.c | 10 | ||||
| -rw-r--r-- | fs/ecryptfs/inode.c | 5 | ||||
| -rw-r--r-- | fs/ecryptfs/main.c | 1 | ||||
| -rw-r--r-- | fs/ext3/inode.c | 17 | ||||
| -rw-r--r-- | fs/fuse/control.c | 4 | ||||
| -rw-r--r-- | fs/fuse/cuse.c | 4 | ||||
| -rw-r--r-- | fs/fuse/dev.c | 1 | ||||
| -rw-r--r-- | fs/fuse/inode.c | 12 | ||||
| -rw-r--r-- | fs/gfs2/file.c | 31 | ||||
| -rw-r--r-- | fs/gfs2/inode.c | 8 | ||||
| -rw-r--r-- | fs/gfs2/rgrp.c | 62 | ||||
| -rw-r--r-- | fs/nfs/file.c | 4 | ||||
| -rw-r--r-- | fs/nfs/inode.c | 2 | ||||
| -rw-r--r-- | fs/nfs/nfs3proc.c | 2 | ||||
| -rw-r--r-- | fs/nfs/nfs4file.c | 4 | ||||
| -rw-r--r-- | fs/nfs/nfs4proc.c | 55 | ||||
| -rw-r--r-- | fs/nfs/nfs4xdr.c | 17 | ||||
| -rw-r--r-- | fs/nfs/super.c | 2 | ||||
| -rw-r--r-- | fs/proc/proc_sysctl.c | 5 | ||||
| -rw-r--r-- | fs/stat.c | 2 | ||||
| -rw-r--r-- | fs/udf/file.c | 35 | ||||
| -rw-r--r-- | fs/xfs/xfs_buf.c | 5 | ||||
| -rw-r--r-- | fs/xfs/xfs_buf.h | 41 | ||||
| -rw-r--r-- | fs/xfs/xfs_super.c | 1 | 
30 files changed, 236 insertions, 190 deletions
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 38b42e7bc91..b6501558174 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -1371,10 +1371,8 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,  	if (srcid) {  		srcgroup = find_qgroup_rb(fs_info, srcid); -		if (!srcgroup) { -			ret = -EINVAL; +		if (!srcgroup)  			goto unlock; -		}  		dstgroup->rfer = srcgroup->rfer - level_size;  		dstgroup->rfer_cmpr = srcgroup->rfer_cmpr - level_size;  		srcgroup->excl = level_size; @@ -1383,10 +1381,8 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,  		qgroup_dirty(fs_info, srcgroup);  	} -	if (!inherit) { -		ret = -EINVAL; +	if (!inherit)  		goto unlock; -	}  	i_qgroups = (u64 *)(inherit + 1);  	for (i = 0; i < inherit->num_qgroups; ++i) { diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index 7dab9c04ad5..53cf2aabce8 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c @@ -328,7 +328,7 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen,  	}  ctoUTF16_out: -	return i; +	return j;  }  #ifdef CONFIG_CIFS_SMB2 diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 9154192b068..71e9ad9f596 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -917,7 +917,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)  	if (!buf) {  		mutex_unlock(&cinode->lock_mutex);  		free_xid(xid); -		return rc; +		return -ENOMEM;  	}  	for (i = 0; i < 2; i++) { diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index c5fbfac5d57..15dc8eea827 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h @@ -96,7 +96,7 @@   *   */ -#define SMB2_HEADER_STRUCTURE_SIZE __constant_le16_to_cpu(64) +#define SMB2_HEADER_STRUCTURE_SIZE __constant_cpu_to_le16(64)  struct smb2_hdr {  	__be32 smb2_buf_length;	/* big endian on wire */ @@ -140,7 +140,7 @@ struct smb2_pdu {   *   */ -#define SMB2_ERROR_STRUCTURE_SIZE2 __constant_le16_to_cpu(9) +#define SMB2_ERROR_STRUCTURE_SIZE2 __constant_cpu_to_le16(9)  struct smb2_err_rsp {  	struct smb2_hdr hdr; diff --git a/fs/dcache.c b/fs/dcache.c index 8086636bf79..0364af2311f 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -389,7 +389,7 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)  	 * Inform try_to_ascend() that we are no longer attached to the  	 * dentry tree  	 */ -	dentry->d_flags |= DCACHE_DISCONNECTED; +	dentry->d_flags |= DCACHE_DENTRY_KILLED;  	if (parent)  		spin_unlock(&parent->d_lock);  	dentry_iput(dentry); @@ -1048,7 +1048,7 @@ static struct dentry *try_to_ascend(struct dentry *old, int locked, unsigned seq  	 * or deletion  	 */  	if (new != old->d_parent || -		 (old->d_flags & DCACHE_DISCONNECTED) || +		 (old->d_flags & DCACHE_DENTRY_KILLED) ||  		 (!locked && read_seqretry(&rename_lock, seq))) {  		spin_unlock(&new->d_lock);  		new = NULL; @@ -1141,7 +1141,7 @@ rename_retry:  EXPORT_SYMBOL(have_submounts);  /* - * Search the dentry child list for the specified parent, + * Search the dentry child list of the specified parent,   * and move any unused dentries to the end of the unused   * list for prune_dcache(). We descend to the next level   * whenever the d_subdirs list is non-empty and continue diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 2340f6978d6..c5ca6ae5a30 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -526,73 +526,51 @@ struct array_data {  	u32 elements;  }; -static int u32_array_open(struct inode *inode, struct file *file) -{ -	file->private_data = NULL; -	return nonseekable_open(inode, file); -} - -static size_t format_array(char *buf, size_t bufsize, const char *fmt, -			   u32 *array, u32 array_size) +static size_t u32_format_array(char *buf, size_t bufsize, +			       u32 *array, int array_size)  {  	size_t ret = 0; -	u32 i; -	for (i = 0; i < array_size; i++) { +	while (--array_size >= 0) {  		size_t len; +		char term = array_size ? ' ' : '\n'; -		len = snprintf(buf, bufsize, fmt, array[i]); -		len++;	/* ' ' or '\n' */ +		len = snprintf(buf, bufsize, "%u%c", *array++, term);  		ret += len; -		if (buf) { -			buf += len; -			bufsize -= len; -			buf[-1] = (i == array_size-1) ? '\n' : ' '; -		} +		buf += len; +		bufsize -= len;  	} - -	ret++;		/* \0 */ -	if (buf) -		*buf = '\0'; -  	return ret;  } -static char *format_array_alloc(const char *fmt, u32 *array, -						u32 array_size) +static int u32_array_open(struct inode *inode, struct file *file)  { -	size_t len = format_array(NULL, 0, fmt, array, array_size); -	char *ret; +	struct array_data *data = inode->i_private; +	int size, elements = data->elements; +	char *buf; -	ret = kmalloc(len, GFP_KERNEL); -	if (ret == NULL) -		return NULL; +	/* +	 * Max size: +	 *  - 10 digits + ' '/'\n' = 11 bytes per number +	 *  - terminating NUL character +	 */ +	size = elements*11; +	buf = kmalloc(size+1, GFP_KERNEL); +	if (!buf) +		return -ENOMEM; +	buf[size] = 0; -	format_array(ret, len, fmt, array, array_size); -	return ret; +	file->private_data = buf; +	u32_format_array(buf, size, data->array, data->elements); + +	return nonseekable_open(inode, file);  }  static ssize_t u32_array_read(struct file *file, char __user *buf, size_t len,  			      loff_t *ppos)  { -	struct inode *inode = file->f_path.dentry->d_inode; -	struct array_data *data = inode->i_private; -	size_t size; - -	if (*ppos == 0) { -		if (file->private_data) { -			kfree(file->private_data); -			file->private_data = NULL; -		} - -		file->private_data = format_array_alloc("%u", data->array, -							      data->elements); -	} - -	size = 0; -	if (file->private_data) -		size = strlen(file->private_data); +	size_t size = strlen(file->private_data);  	return simple_read_from_buffer(buf, len, ppos,  					file->private_data, size); diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 44ce5c6a541..d45ba456812 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -275,8 +275,14 @@ out:  static int ecryptfs_flush(struct file *file, fl_owner_t td)  { -	return file->f_mode & FMODE_WRITE -	       ? filemap_write_and_wait(file->f_mapping) : 0; +	struct file *lower_file = ecryptfs_file_to_lower(file); + +	if (lower_file->f_op && lower_file->f_op->flush) { +		filemap_write_and_wait(file->f_mapping); +		return lower_file->f_op->flush(lower_file, td); +	} + +	return 0;  }  static int ecryptfs_release(struct inode *inode, struct file *file) diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 534b129ea67..cc7709e7c50 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -619,6 +619,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,  	struct dentry *lower_old_dir_dentry;  	struct dentry *lower_new_dir_dentry;  	struct dentry *trap = NULL; +	struct inode *target_inode;  	lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);  	lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry); @@ -626,6 +627,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,  	dget(lower_new_dentry);  	lower_old_dir_dentry = dget_parent(lower_old_dentry);  	lower_new_dir_dentry = dget_parent(lower_new_dentry); +	target_inode = new_dentry->d_inode;  	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);  	/* source should not be ancestor of target */  	if (trap == lower_old_dentry) { @@ -641,6 +643,9 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,  			lower_new_dir_dentry->d_inode, lower_new_dentry);  	if (rc)  		goto out_lock; +	if (target_inode) +		fsstack_copy_attr_all(target_inode, +				      ecryptfs_inode_to_lower(target_inode));  	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);  	if (new_dir != old_dir)  		fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode); diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 2768138eefe..9b627c15010 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -162,6 +162,7 @@ void ecryptfs_put_lower_file(struct inode *inode)  	inode_info = ecryptfs_inode_to_private(inode);  	if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count,  				      &inode_info->lower_file_mutex)) { +		filemap_write_and_wait(inode->i_mapping);  		fput(inode_info->lower_file);  		inode_info->lower_file = NULL;  		mutex_unlock(&inode_info->lower_file_mutex); diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index a07597307fd..ff574b4e345 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -3072,6 +3072,8 @@ static int ext3_do_update_inode(handle_t *handle,  	struct ext3_inode_info *ei = EXT3_I(inode);  	struct buffer_head *bh = iloc->bh;  	int err = 0, rc, block; +	int need_datasync = 0; +	__le32 disksize;  	uid_t i_uid;  	gid_t i_gid; @@ -3113,7 +3115,11 @@ again:  		raw_inode->i_gid_high = 0;  	}  	raw_inode->i_links_count = cpu_to_le16(inode->i_nlink); -	raw_inode->i_size = cpu_to_le32(ei->i_disksize); +	disksize = cpu_to_le32(ei->i_disksize); +	if (disksize != raw_inode->i_size) { +		need_datasync = 1; +		raw_inode->i_size = disksize; +	}  	raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec);  	raw_inode->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec);  	raw_inode->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec); @@ -3129,8 +3135,11 @@ again:  	if (!S_ISREG(inode->i_mode)) {  		raw_inode->i_dir_acl = cpu_to_le32(ei->i_dir_acl);  	} else { -		raw_inode->i_size_high = -			cpu_to_le32(ei->i_disksize >> 32); +		disksize = cpu_to_le32(ei->i_disksize >> 32); +		if (disksize != raw_inode->i_size_high) { +			raw_inode->i_size_high = disksize; +			need_datasync = 1; +		}  		if (ei->i_disksize > 0x7fffffffULL) {  			struct super_block *sb = inode->i_sb;  			if (!EXT3_HAS_RO_COMPAT_FEATURE(sb, @@ -3183,6 +3192,8 @@ again:  	ext3_clear_inode_state(inode, EXT3_STATE_NEW);  	atomic_set(&ei->i_sync_tid, handle->h_transaction->t_tid); +	if (need_datasync) +		atomic_set(&ei->i_datasync_tid, handle->h_transaction->t_tid);  out_brelse:  	brelse (bh);  	ext3_std_error(inode->i_sb, err); diff --git a/fs/fuse/control.c b/fs/fuse/control.c index 03ff5b1eba9..75a20c092dd 100644 --- a/fs/fuse/control.c +++ b/fs/fuse/control.c @@ -117,7 +117,7 @@ static ssize_t fuse_conn_max_background_write(struct file *file,  					      const char __user *buf,  					      size_t count, loff_t *ppos)  { -	unsigned val; +	unsigned uninitialized_var(val);  	ssize_t ret;  	ret = fuse_conn_limit_write(file, buf, count, ppos, &val, @@ -154,7 +154,7 @@ static ssize_t fuse_conn_congestion_threshold_write(struct file *file,  						    const char __user *buf,  						    size_t count, loff_t *ppos)  { -	unsigned val; +	unsigned uninitialized_var(val);  	ssize_t ret;  	ret = fuse_conn_limit_write(file, buf, count, ppos, &val, diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index 3426521f320..ee8d5504229 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c @@ -396,7 +396,7 @@ err_device:  err_region:  	unregister_chrdev_region(devt, 1);  err: -	fc->conn_error = 1; +	fuse_conn_kill(fc);  	goto out;  } @@ -532,8 +532,6 @@ static int cuse_channel_release(struct inode *inode, struct file *file)  		cdev_del(cc->cdev);  	} -	/* kill connection and shutdown channel */ -	fuse_conn_kill(&cc->fc);  	rc = fuse_dev_release(inode, file);	/* puts the base reference */  	return rc; diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 7df2b5e8fbe..f4246cfc8d8 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1576,6 +1576,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,  		req->pages[req->num_pages] = page;  		req->num_pages++; +		offset = 0;  		num -= this_num;  		total_len += this_num;  		index++; diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index ce0a2838ccd..fca222dabe3 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -367,11 +367,6 @@ void fuse_conn_kill(struct fuse_conn *fc)  	wake_up_all(&fc->waitq);  	wake_up_all(&fc->blocked_waitq);  	wake_up_all(&fc->reserved_req_waitq); -	mutex_lock(&fuse_mutex); -	list_del(&fc->entry); -	fuse_ctl_remove_conn(fc); -	mutex_unlock(&fuse_mutex); -	fuse_bdi_destroy(fc);  }  EXPORT_SYMBOL_GPL(fuse_conn_kill); @@ -380,7 +375,14 @@ static void fuse_put_super(struct super_block *sb)  	struct fuse_conn *fc = get_fuse_conn_super(sb);  	fuse_send_destroy(fc); +  	fuse_conn_kill(fc); +	mutex_lock(&fuse_mutex); +	list_del(&fc->entry); +	fuse_ctl_remove_conn(fc); +	mutex_unlock(&fuse_mutex); +	fuse_bdi_destroy(fc); +  	fuse_conn_put(fc);  } diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index d1d791ef38d..382000ffac1 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -323,6 +323,29 @@ static long gfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  }  /** + * gfs2_size_hint - Give a hint to the size of a write request + * @file: The struct file + * @offset: The file offset of the write + * @size: The length of the write + * + * When we are about to do a write, this function records the total + * write size in order to provide a suitable hint to the lower layers + * about how many blocks will be required. + * + */ + +static void gfs2_size_hint(struct file *filep, loff_t offset, size_t size) +{ +	struct inode *inode = filep->f_dentry->d_inode; +	struct gfs2_sbd *sdp = GFS2_SB(inode); +	struct gfs2_inode *ip = GFS2_I(inode); +	size_t blks = (size + sdp->sd_sb.sb_bsize - 1) >> sdp->sd_sb.sb_bsize_shift; +	int hint = min_t(size_t, INT_MAX, blks); + +	atomic_set(&ip->i_res->rs_sizehint, hint); +} + +/**   * gfs2_allocate_page_backing - Use bmap to allocate blocks   * @page: The (locked) page to allocate backing for   * @@ -382,8 +405,7 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)  	if (ret)  		return ret; -	atomic_set(&ip->i_res->rs_sizehint, -		   PAGE_CACHE_SIZE >> sdp->sd_sb.sb_bsize_shift); +	gfs2_size_hint(vma->vm_file, pos, PAGE_CACHE_SIZE);  	gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);  	ret = gfs2_glock_nq(&gh); @@ -663,7 +685,8 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov,  	if (ret)  		return ret; -	atomic_set(&ip->i_res->rs_sizehint, writesize >> sdp->sd_sb.sb_bsize_shift); +	gfs2_size_hint(file, pos, writesize); +  	if (file->f_flags & O_APPEND) {  		struct gfs2_holder gh; @@ -789,7 +812,7 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,  	if (unlikely(error))  		goto out_uninit; -	atomic_set(&ip->i_res->rs_sizehint, len >> sdp->sd_sb.sb_bsize_shift); +	gfs2_size_hint(file, offset, len);  	while (len > 0) {  		if (len < bytes) diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 4ce22e54730..753af3d86bb 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -1722,7 +1722,9 @@ static int gfs2_setxattr(struct dentry *dentry, const char *name,  	gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);  	ret = gfs2_glock_nq(&gh);  	if (ret == 0) { -		ret = generic_setxattr(dentry, name, data, size, flags); +		ret = gfs2_rs_alloc(ip); +		if (ret == 0) +			ret = generic_setxattr(dentry, name, data, size, flags);  		gfs2_glock_dq(&gh);  	}  	gfs2_holder_uninit(&gh); @@ -1757,7 +1759,9 @@ static int gfs2_removexattr(struct dentry *dentry, const char *name)  	gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);  	ret = gfs2_glock_nq(&gh);  	if (ret == 0) { -		ret = generic_removexattr(dentry, name); +		ret = gfs2_rs_alloc(ip); +		if (ret == 0) +			ret = generic_removexattr(dentry, name);  		gfs2_glock_dq(&gh);  	}  	gfs2_holder_uninit(&gh); diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 4d34887a601..c9ed814eeb6 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -1961,7 +1961,7 @@ static void gfs2_rgrp_error(struct gfs2_rgrpd *rgd)   * @dinode: 1 if this block is a dinode block, otherwise data block   * @nblocks: desired extent length   * - * Lay claim to previously allocated block reservation blocks. + * Lay claim to previously reserved blocks.   * Returns: Starting block number of the blocks claimed.   * Sets *nblocks to the actual extent length allocated.   */ @@ -1970,19 +1970,17 @@ static u64 claim_reserved_blks(struct gfs2_inode *ip, bool dinode,  {  	struct gfs2_blkreserv *rs = ip->i_res;  	struct gfs2_rgrpd *rgd = rs->rs_rgd; -	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);  	struct gfs2_bitmap *bi;  	u64 start_block = gfs2_rs_startblk(rs);  	const unsigned int elen = *nblocks; -	/*BUG_ON(!gfs2_glock_is_locked_by_me(ip->i_gl));*/ -	gfs2_assert_withdraw(sdp, rgd); -	/*BUG_ON(!gfs2_glock_is_locked_by_me(rgd->rd_gl));*/  	bi = rs->rs_bi;  	gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);  	for (*nblocks = 0; *nblocks < elen && rs->rs_free; (*nblocks)++) { -		/* Make sure the bitmap hasn't changed */ +		if (gfs2_testbit(rgd, bi->bi_bh->b_data + bi->bi_offset, +				 bi->bi_len, rs->rs_biblk) != GFS2_BLKST_FREE) +			break;  		gfs2_setbit(rgd, bi->bi_clone, bi, rs->rs_biblk,  			    dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED);  		rs->rs_biblk++; @@ -1991,20 +1989,12 @@ static u64 claim_reserved_blks(struct gfs2_inode *ip, bool dinode,  		BUG_ON(!rgd->rd_reserved);  		rgd->rd_reserved--;  		dinode = false; -		trace_gfs2_rs(ip, rs, TRACE_RS_CLAIM);  	} -	if (!rs->rs_free) { -		struct gfs2_rgrpd *rgd = ip->i_res->rs_rgd; - +	trace_gfs2_rs(ip, rs, TRACE_RS_CLAIM); +	if (!rs->rs_free || *nblocks != elen)  		gfs2_rs_deltree(rs); -		/* -nblocks because we haven't returned to do the math yet. -		   I'm doing the math backwards to prevent negative numbers, -		   but think of it as: -		   if (unclaimed_blocks(rgd) - *nblocks >= RGRP_RSRV_MINBLKS */ -		if (unclaimed_blocks(rgd) >= RGRP_RSRV_MINBLKS + *nblocks) -			rg_mblk_search(rgd, ip); -	} +  	return start_block;  } @@ -2037,34 +2027,34 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,  	if (ip->i_res->rs_requested == 0)  		return -ECANCELED; -	/* Check if we have a multi-block reservation, and if so, claim the -	   next free block from it. */ +	/* If we have a reservation, claim blocks from it. */  	if (gfs2_rs_active(ip->i_res)) {  		BUG_ON(!ip->i_res->rs_free);  		rgd = ip->i_res->rs_rgd;  		block = claim_reserved_blks(ip, dinode, nblocks); -	} else { -		rgd = ip->i_rgd; +		if (*nblocks) +			goto found_blocks; +	} -		if (!dinode && rgrp_contains_block(rgd, ip->i_goal)) -			goal = ip->i_goal - rgd->rd_data0; -		else -			goal = rgd->rd_last_alloc; +	rgd = ip->i_rgd; -		blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, &bi); +	if (!dinode && rgrp_contains_block(rgd, ip->i_goal)) +		goal = ip->i_goal - rgd->rd_data0; +	else +		goal = rgd->rd_last_alloc; -		/* Since all blocks are reserved in advance, this shouldn't -		   happen */ -		if (blk == BFITNOENT) { -			printk(KERN_WARNING "BFITNOENT, nblocks=%u\n", -			       *nblocks); -			printk(KERN_WARNING "FULL=%d\n", -			       test_bit(GBF_FULL, &rgd->rd_bits->bi_flags)); -			goto rgrp_error; -		} +	blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, &bi); -		block = gfs2_alloc_extent(rgd, bi, blk, dinode, nblocks); +	/* Since all blocks are reserved in advance, this shouldn't happen */ +	if (blk == BFITNOENT) { +		printk(KERN_WARNING "BFITNOENT, nblocks=%u\n", *nblocks); +		printk(KERN_WARNING "FULL=%d\n", +		       test_bit(GBF_FULL, &rgd->rd_bits->bi_flags)); +		goto rgrp_error;  	} + +	block = gfs2_alloc_extent(rgd, bi, blk, dinode, nblocks); +found_blocks:  	ndata = *nblocks;  	if (dinode)  		ndata--; diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 75d6d0a3d32..6a7fcab7ecb 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -287,10 +287,12 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)  	struct inode *inode = file->f_path.dentry->d_inode;  	ret = filemap_write_and_wait_range(inode->i_mapping, start, end); +	if (ret != 0) +		goto out;  	mutex_lock(&inode->i_mutex);  	ret = nfs_file_fsync_commit(file, start, end, datasync);  	mutex_unlock(&inode->i_mutex); - +out:  	return ret;  } diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index c6e895f0fbf..9b47610338f 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -154,7 +154,7 @@ static void nfs_zap_caches_locked(struct inode *inode)  	nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);  	nfsi->attrtimeo_timestamp = jiffies; -	memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); +	memset(NFS_I(inode)->cookieverf, 0, sizeof(NFS_I(inode)->cookieverf));  	if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))  		nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;  	else diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index d6b3b5f2d77..69322096c32 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -643,7 +643,7 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,  		  u64 cookie, struct page **pages, unsigned int count, int plus)  {  	struct inode		*dir = dentry->d_inode; -	__be32			*verf = NFS_COOKIEVERF(dir); +	__be32			*verf = NFS_I(dir)->cookieverf;  	struct nfs3_readdirargs	arg = {  		.fh		= NFS_FH(dir),  		.cookie		= cookie, diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index acb65e7887f..eb5eb8eef4d 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c @@ -96,13 +96,15 @@ nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)  	struct inode *inode = file->f_path.dentry->d_inode;  	ret = filemap_write_and_wait_range(inode->i_mapping, start, end); +	if (ret != 0) +		goto out;  	mutex_lock(&inode->i_mutex);  	ret = nfs_file_fsync_commit(file, start, end, datasync);  	if (!ret && !datasync)  		/* application has asked for meta-data sync */  		ret = pnfs_layoutcommit_inode(inode, true);  	mutex_unlock(&inode->i_mutex); - +out:  	return ret;  } diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 635274140b1..1e50326d00d 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3215,11 +3215,11 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,  			dentry->d_parent->d_name.name,  			dentry->d_name.name,  			(unsigned long long)cookie); -	nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); +	nfs4_setup_readdir(cookie, NFS_I(dir)->cookieverf, dentry, &args);  	res.pgbase = args.pgbase;  	status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0);  	if (status >= 0) { -		memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); +		memcpy(NFS_I(dir)->cookieverf, res.verifier.data, NFS4_VERIFIER_SIZE);  		status += args.pgbase;  	} @@ -3653,11 +3653,11 @@ static inline int nfs4_server_supports_acls(struct nfs_server *server)  		&& (server->acl_bitmask & ACL4_SUPPORT_DENY_ACL);  } -/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_CACHE_SIZE, and that - * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_CACHE_SIZE) bytes on +/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_SIZE, and that + * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_SIZE) bytes on   * the stack.   */ -#define NFS4ACL_MAXPAGES (XATTR_SIZE_MAX >> PAGE_CACHE_SHIFT) +#define NFS4ACL_MAXPAGES DIV_ROUND_UP(XATTR_SIZE_MAX, PAGE_SIZE)  static int buf_to_pages_noslab(const void *buf, size_t buflen,  		struct page **pages, unsigned int *pgbase) @@ -3668,7 +3668,7 @@ static int buf_to_pages_noslab(const void *buf, size_t buflen,  	spages = pages;  	do { -		len = min_t(size_t, PAGE_CACHE_SIZE, buflen); +		len = min_t(size_t, PAGE_SIZE, buflen);  		newpage = alloc_page(GFP_KERNEL);  		if (newpage == NULL) @@ -3739,7 +3739,7 @@ static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size  	struct nfs4_cached_acl *acl;  	size_t buflen = sizeof(*acl) + acl_len; -	if (pages && buflen <= PAGE_SIZE) { +	if (buflen <= PAGE_SIZE) {  		acl = kmalloc(buflen, GFP_KERNEL);  		if (acl == NULL)  			goto out; @@ -3782,17 +3782,15 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu  		.rpc_argp = &args,  		.rpc_resp = &res,  	}; -	int ret = -ENOMEM, npages, i; -	size_t acl_len = 0; +	unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE); +	int ret = -ENOMEM, i; -	npages = (buflen + PAGE_SIZE - 1) >> PAGE_SHIFT;  	/* As long as we're doing a round trip to the server anyway,  	 * let's be prepared for a page of acl data. */  	if (npages == 0)  		npages = 1; - -	/* Add an extra page to handle the bitmap returned */ -	npages++; +	if (npages > ARRAY_SIZE(pages)) +		return -ERANGE;  	for (i = 0; i < npages; i++) {  		pages[i] = alloc_page(GFP_KERNEL); @@ -3808,11 +3806,6 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu  	args.acl_len = npages * PAGE_SIZE;  	args.acl_pgbase = 0; -	/* Let decode_getfacl know not to fail if the ACL data is larger than -	 * the page we send as a guess */ -	if (buf == NULL) -		res.acl_flags |= NFS4_ACL_LEN_REQUEST; -  	dprintk("%s  buf %p buflen %zu npages %d args.acl_len %zu\n",  		__func__, buf, buflen, npages, args.acl_len);  	ret = nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode), @@ -3820,20 +3813,19 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu  	if (ret)  		goto out_free; -	acl_len = res.acl_len; -	if (acl_len > args.acl_len) -		nfs4_write_cached_acl(inode, NULL, 0, acl_len); -	else -		nfs4_write_cached_acl(inode, pages, res.acl_data_offset, -				      acl_len); -	if (buf) { +	/* Handle the case where the passed-in buffer is too short */ +	if (res.acl_flags & NFS4_ACL_TRUNC) { +		/* Did the user only issue a request for the acl length? */ +		if (buf == NULL) +			goto out_ok;  		ret = -ERANGE; -		if (acl_len > buflen) -			goto out_free; -		_copy_from_pages(buf, pages, res.acl_data_offset, -				acl_len); +		goto out_free;  	} -	ret = acl_len; +	nfs4_write_cached_acl(inode, pages, res.acl_data_offset, res.acl_len); +	if (buf) +		_copy_from_pages(buf, pages, res.acl_data_offset, res.acl_len); +out_ok: +	ret = res.acl_len;  out_free:  	for (i = 0; i < npages; i++)  		if (pages[i]) @@ -3891,10 +3883,13 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl  		.rpc_argp	= &arg,  		.rpc_resp	= &res,  	}; +	unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE);  	int ret, i;  	if (!nfs4_server_supports_acls(server))  		return -EOPNOTSUPP; +	if (npages > ARRAY_SIZE(pages)) +		return -ERANGE;  	i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase);  	if (i < 0)  		return i; diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 1bfbd67c556..8dba6bd4855 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -5072,18 +5072,14 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,  		 * are stored with the acl data to handle the problem of  		 * variable length bitmaps.*/  		res->acl_data_offset = xdr_stream_pos(xdr) - pg_offset; - -		/* We ignore &savep and don't do consistency checks on -		 * the attr length.  Let userspace figure it out.... */  		res->acl_len = attrlen; -		if (attrlen > (xdr->nwords << 2)) { -			if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { -				/* getxattr interface called with a NULL buf */ -				goto out; -			} + +		/* Check for receive buffer overflow */ +		if (res->acl_len > (xdr->nwords << 2) || +		    res->acl_len + res->acl_data_offset > xdr->buf->page_len) { +			res->acl_flags |= NFS4_ACL_TRUNC;  			dprintk("NFS: acl reply: attrlen %u > page_len %u\n",  					attrlen, xdr->nwords << 2); -			return -EINVAL;  		}  	} else  		status = -EOPNOTSUPP; @@ -6229,7 +6225,8 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr,  	status = decode_open(xdr, res);  	if (status)  		goto out; -	if (decode_getfh(xdr, &res->fh) != 0) +	status = decode_getfh(xdr, &res->fh); +	if (status)  		goto out;  	decode_getfattr(xdr, res->f_attr, res->server);  out: diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 239aff7338e..b8eda700584 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -1867,6 +1867,7 @@ static int nfs23_validate_mount_data(void *options,  		memcpy(sap, &data->addr, sizeof(data->addr));  		args->nfs_server.addrlen = sizeof(data->addr); +		args->nfs_server.port = ntohs(data->addr.sin_port);  		if (!nfs_verify_server_address(sap))  			goto out_no_address; @@ -2564,6 +2565,7 @@ static int nfs4_validate_mount_data(void *options,  			return -EFAULT;  		if (!nfs_verify_server_address(sap))  			goto out_no_address; +		args->nfs_server.port = ntohs(((struct sockaddr_in *)sap)->sin_port);  		if (data->auth_flavourlen) {  			if (data->auth_flavourlen > 1) diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index dfafeb2b05a..eb7cc91b725 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -462,9 +462,6 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,  	err = ERR_PTR(-ENOMEM);  	inode = proc_sys_make_inode(dir->i_sb, h ? h : head, p); -	if (h) -		sysctl_head_finish(h); -  	if (!inode)  		goto out; @@ -473,6 +470,8 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,  	d_add(dentry, inode);  out: +	if (h) +		sysctl_head_finish(h);  	sysctl_head_finish(head);  	return err;  } diff --git a/fs/stat.c b/fs/stat.c index b6ff11825fc..40780229a03 100644 --- a/fs/stat.c +++ b/fs/stat.c @@ -58,7 +58,7 @@ EXPORT_SYMBOL(vfs_getattr);  int vfs_fstat(unsigned int fd, struct kstat *stat)  {  	int fput_needed; -	struct file *f = fget_light(fd, &fput_needed); +	struct file *f = fget_raw_light(fd, &fput_needed);  	int error = -EBADF;  	if (f) { diff --git a/fs/udf/file.c b/fs/udf/file.c index 7f3f7ba3df6..d1c6093fd3d 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -39,20 +39,24 @@  #include "udf_i.h"  #include "udf_sb.h" -static int udf_adinicb_readpage(struct file *file, struct page *page) +static void __udf_adinicb_readpage(struct page *page)  {  	struct inode *inode = page->mapping->host;  	char *kaddr;  	struct udf_inode_info *iinfo = UDF_I(inode); -	BUG_ON(!PageLocked(page)); -  	kaddr = kmap(page); -	memset(kaddr, 0, PAGE_CACHE_SIZE);  	memcpy(kaddr, iinfo->i_ext.i_data + iinfo->i_lenEAttr, inode->i_size); +	memset(kaddr + inode->i_size, 0, PAGE_CACHE_SIZE - inode->i_size);  	flush_dcache_page(page);  	SetPageUptodate(page);  	kunmap(page); +} + +static int udf_adinicb_readpage(struct file *file, struct page *page) +{ +	BUG_ON(!PageLocked(page)); +	__udf_adinicb_readpage(page);  	unlock_page(page);  	return 0; @@ -77,6 +81,25 @@ static int udf_adinicb_writepage(struct page *page,  	return 0;  } +static int udf_adinicb_write_begin(struct file *file, +			struct address_space *mapping, loff_t pos, +			unsigned len, unsigned flags, struct page **pagep, +			void **fsdata) +{ +	struct page *page; + +	if (WARN_ON_ONCE(pos >= PAGE_CACHE_SIZE)) +		return -EIO; +	page = grab_cache_page_write_begin(mapping, 0, flags); +	if (!page) +		return -ENOMEM; +	*pagep = page; + +	if (!PageUptodate(page) && len != PAGE_CACHE_SIZE) +		__udf_adinicb_readpage(page); +	return 0; +} +  static int udf_adinicb_write_end(struct file *file,  			struct address_space *mapping,  			loff_t pos, unsigned len, unsigned copied, @@ -98,8 +121,8 @@ static int udf_adinicb_write_end(struct file *file,  const struct address_space_operations udf_adinicb_aops = {  	.readpage	= udf_adinicb_readpage,  	.writepage	= udf_adinicb_writepage, -	.write_begin = simple_write_begin, -	.write_end = udf_adinicb_write_end, +	.write_begin	= udf_adinicb_write_begin, +	.write_end	= udf_adinicb_write_end,  };  static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index d7a9dd735e1..933b7930b86 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -96,6 +96,7 @@ xfs_buf_lru_add(  		atomic_inc(&bp->b_hold);  		list_add_tail(&bp->b_lru, &btp->bt_lru);  		btp->bt_lru_nr++; +		bp->b_lru_flags &= ~_XBF_LRU_DISPOSE;  	}  	spin_unlock(&btp->bt_lru_lock);  } @@ -154,7 +155,8 @@ xfs_buf_stale(  		struct xfs_buftarg *btp = bp->b_target;  		spin_lock(&btp->bt_lru_lock); -		if (!list_empty(&bp->b_lru)) { +		if (!list_empty(&bp->b_lru) && +		    !(bp->b_lru_flags & _XBF_LRU_DISPOSE)) {  			list_del_init(&bp->b_lru);  			btp->bt_lru_nr--;  			atomic_dec(&bp->b_hold); @@ -1501,6 +1503,7 @@ xfs_buftarg_shrink(  		 */  		list_move(&bp->b_lru, &dispose);  		btp->bt_lru_nr--; +		bp->b_lru_flags |= _XBF_LRU_DISPOSE;  	}  	spin_unlock(&btp->bt_lru_lock); diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h index d03b73b9604..7c0b6a0a155 100644 --- a/fs/xfs/xfs_buf.h +++ b/fs/xfs/xfs_buf.h @@ -38,27 +38,28 @@ typedef enum {  	XBRW_ZERO = 3,			/* Zero target memory */  } xfs_buf_rw_t; -#define XBF_READ	(1 << 0) /* buffer intended for reading from device */ -#define XBF_WRITE	(1 << 1) /* buffer intended for writing to device */ -#define XBF_READ_AHEAD	(1 << 2) /* asynchronous read-ahead */ -#define XBF_ASYNC	(1 << 4) /* initiator will not wait for completion */ -#define XBF_DONE	(1 << 5) /* all pages in the buffer uptodate */ -#define XBF_STALE	(1 << 6) /* buffer has been staled, do not find it */ +#define XBF_READ	 (1 << 0) /* buffer intended for reading from device */ +#define XBF_WRITE	 (1 << 1) /* buffer intended for writing to device */ +#define XBF_READ_AHEAD	 (1 << 2) /* asynchronous read-ahead */ +#define XBF_ASYNC	 (1 << 4) /* initiator will not wait for completion */ +#define XBF_DONE	 (1 << 5) /* all pages in the buffer uptodate */ +#define XBF_STALE	 (1 << 6) /* buffer has been staled, do not find it */  /* I/O hints for the BIO layer */ -#define XBF_SYNCIO	(1 << 10)/* treat this buffer as synchronous I/O */ -#define XBF_FUA		(1 << 11)/* force cache write through mode */ -#define XBF_FLUSH	(1 << 12)/* flush the disk cache before a write */ +#define XBF_SYNCIO	 (1 << 10)/* treat this buffer as synchronous I/O */ +#define XBF_FUA		 (1 << 11)/* force cache write through mode */ +#define XBF_FLUSH	 (1 << 12)/* flush the disk cache before a write */  /* flags used only as arguments to access routines */ -#define XBF_TRYLOCK	(1 << 16)/* lock requested, but do not wait */ -#define XBF_UNMAPPED	(1 << 17)/* do not map the buffer */ +#define XBF_TRYLOCK	 (1 << 16)/* lock requested, but do not wait */ +#define XBF_UNMAPPED	 (1 << 17)/* do not map the buffer */  /* flags used only internally */ -#define _XBF_PAGES	(1 << 20)/* backed by refcounted pages */ -#define _XBF_KMEM	(1 << 21)/* backed by heap memory */ -#define _XBF_DELWRI_Q	(1 << 22)/* buffer on a delwri queue */ -#define _XBF_COMPOUND	(1 << 23)/* compound buffer */ +#define _XBF_PAGES	 (1 << 20)/* backed by refcounted pages */ +#define _XBF_KMEM	 (1 << 21)/* backed by heap memory */ +#define _XBF_DELWRI_Q	 (1 << 22)/* buffer on a delwri queue */ +#define _XBF_COMPOUND	 (1 << 23)/* compound buffer */ +#define _XBF_LRU_DISPOSE (1 << 24)/* buffer being discarded */  typedef unsigned int xfs_buf_flags_t; @@ -72,12 +73,13 @@ typedef unsigned int xfs_buf_flags_t;  	{ XBF_SYNCIO,		"SYNCIO" }, \  	{ XBF_FUA,		"FUA" }, \  	{ XBF_FLUSH,		"FLUSH" }, \ -	{ XBF_TRYLOCK,		"TRYLOCK" }, 	/* should never be set */\ +	{ XBF_TRYLOCK,		"TRYLOCK" },	/* should never be set */\  	{ XBF_UNMAPPED,		"UNMAPPED" },	/* ditto */\  	{ _XBF_PAGES,		"PAGES" }, \  	{ _XBF_KMEM,		"KMEM" }, \  	{ _XBF_DELWRI_Q,	"DELWRI_Q" }, \ -	{ _XBF_COMPOUND,	"COMPOUND" } +	{ _XBF_COMPOUND,	"COMPOUND" }, \ +	{ _XBF_LRU_DISPOSE,	"LRU_DISPOSE" }  typedef struct xfs_buftarg {  	dev_t			bt_dev; @@ -124,7 +126,12 @@ typedef struct xfs_buf {  	xfs_buf_flags_t		b_flags;	/* status flags */  	struct semaphore	b_sema;		/* semaphore for lockables */ +	/* +	 * concurrent access to b_lru and b_lru_flags are protected by +	 * bt_lru_lock and not by b_sema +	 */  	struct list_head	b_lru;		/* lru list */ +	xfs_buf_flags_t		b_lru_flags;	/* internal lru status flags */  	wait_queue_head_t	b_waiters;	/* unpin waiters */  	struct list_head	b_list;  	struct xfs_perag	*b_pag;		/* contains rbtree root */ diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index bdaf4cb9f4a..19e2380fb86 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -919,6 +919,7 @@ xfs_fs_put_super(  	struct xfs_mount	*mp = XFS_M(sb);  	xfs_filestream_unmount(mp); +	cancel_delayed_work_sync(&mp->m_sync_work);  	xfs_unmountfs(mp);  	xfs_syncd_stop(mp);  	xfs_freesb(mp);  |