diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/9p/v9fs_vfs.h | 6 | ||||
| -rw-r--r-- | fs/9p/vfs_file.c | 36 | ||||
| -rw-r--r-- | fs/9p/vfs_inode.c | 139 | ||||
| -rw-r--r-- | fs/9p/vfs_inode_dotl.c | 86 | ||||
| -rw-r--r-- | fs/9p/vfs_super.c | 2 | ||||
| -rw-r--r-- | fs/attr.c | 5 | ||||
| -rw-r--r-- | fs/block_dev.c | 7 | ||||
| -rw-r--r-- | fs/btrfs/btrfs_inode.h | 6 | ||||
| -rw-r--r-- | fs/btrfs/file-item.c | 4 | ||||
| -rw-r--r-- | fs/btrfs/file.c | 49 | ||||
| -rw-r--r-- | fs/btrfs/free-space-cache.c | 4 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 40 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.c | 51 | ||||
| -rw-r--r-- | fs/btrfs/transaction.c | 4 | ||||
| -rw-r--r-- | fs/btrfs/xattr.c | 59 | ||||
| -rw-r--r-- | fs/ceph/mds_client.c | 2 | ||||
| -rw-r--r-- | fs/ceph/super.c | 4 | ||||
| -rw-r--r-- | fs/cifs/cifsencrypt.c | 54 | ||||
| -rw-r--r-- | fs/cifs/cifsfs.c | 10 | ||||
| -rw-r--r-- | fs/cifs/cifssmb.c | 3 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 8 | ||||
| -rw-r--r-- | fs/cifs/xattr.c | 40 | ||||
| -rw-r--r-- | fs/coda/coda_linux.h | 5 | ||||
| -rw-r--r-- | fs/compat.c | 5 | ||||
| -rw-r--r-- | fs/configfs/inode.c | 3 | ||||
| -rw-r--r-- | fs/configfs/item.c | 2 | ||||
| -rw-r--r-- | fs/eventpoll.c | 2 | ||||
| -rw-r--r-- | fs/ext2/xattr_security.c | 34 | ||||
| -rw-r--r-- | fs/ext3/inode.c | 4 | ||||
| -rw-r--r-- | fs/ext3/namei.c | 3 | ||||
| -rw-r--r-- | fs/ext3/xattr_security.c | 36 | ||||
| -rw-r--r-- | fs/ext4/ext4.h | 1 | ||||
| -rw-r--r-- | fs/ext4/inode.c | 7 | ||||
| -rw-r--r-- | fs/ext4/namei.c | 3 | ||||
| -rw-r--r-- | fs/ext4/page-io.c | 18 | ||||
| -rw-r--r-- | fs/ext4/xattr_security.c | 36 | ||||
| -rw-r--r-- | fs/fuse/dev.c | 16 | ||||
| -rw-r--r-- | fs/fuse/file.c | 84 | ||||
| -rw-r--r-- | fs/fuse/fuse_i.h | 8 | ||||
| -rw-r--r-- | fs/fuse/inode.c | 13 | ||||
| -rw-r--r-- | fs/gfs2/inode.c | 36 | ||||
| -rw-r--r-- | fs/gfs2/log.c | 4 | ||||
| -rw-r--r-- | fs/gfs2/meta_io.c | 6 | ||||
| -rw-r--r-- | fs/gfs2/ops_fstype.c | 2 | ||||
| -rw-r--r-- | fs/gfs2/quota.c | 2 | ||||
| -rw-r--r-- | fs/hfsplus/super.c | 15 | ||||
| -rw-r--r-- | fs/hfsplus/wrapper.c | 4 | ||||
| -rw-r--r-- | fs/hugetlbfs/inode.c | 1 | ||||
| -rw-r--r-- | fs/inode.c | 24 | ||||
| -rw-r--r-- | fs/jffs2/security.c | 35 | ||||
| -rw-r--r-- | fs/jfs/xattr.c | 55 | ||||
| -rw-r--r-- | fs/locks.c | 2 | ||||
| -rw-r--r-- | fs/namei.c | 41 | ||||
| -rw-r--r-- | fs/namespace.c | 2 | ||||
| -rw-r--r-- | fs/nfs/nfs4_fs.h | 8 | ||||
| -rw-r--r-- | fs/nfs/nfs4proc.c | 20 | ||||
| -rw-r--r-- | fs/nfs/nfs4renewd.c | 12 | ||||
| -rw-r--r-- | fs/nfs/nfs4state.c | 6 | ||||
| -rw-r--r-- | fs/nfs/super.c | 25 | ||||
| -rw-r--r-- | fs/nfs/write.c | 2 | ||||
| -rw-r--r-- | fs/ocfs2/xattr.c | 38 | ||||
| -rw-r--r-- | fs/proc/task_mmu.c | 80 | ||||
| -rw-r--r-- | fs/quota/quota.c | 2 | ||||
| -rw-r--r-- | fs/reiserfs/journal.c | 9 | ||||
| -rw-r--r-- | fs/reiserfs/resize.c | 4 | ||||
| -rw-r--r-- | fs/reiserfs/xattr_security.c | 4 | ||||
| -rw-r--r-- | fs/squashfs/Kconfig | 6 | ||||
| -rw-r--r-- | fs/stat.c | 2 | ||||
| -rw-r--r-- | fs/ubifs/debug.h | 6 | ||||
| -rw-r--r-- | fs/xattr.c | 63 | ||||
| -rw-r--r-- | fs/xfs/Makefile | 119 | ||||
| -rw-r--r-- | fs/xfs/kmem.c (renamed from fs/xfs/linux-2.6/kmem.c) | 0 | ||||
| -rw-r--r-- | fs/xfs/kmem.h (renamed from fs/xfs/linux-2.6/kmem.h) | 7 | ||||
| -rw-r--r-- | fs/xfs/mrlock.h (renamed from fs/xfs/linux-2.6/mrlock.h) | 0 | ||||
| -rw-r--r-- | fs/xfs/time.h (renamed from fs/xfs/linux-2.6/time.h) | 0 | ||||
| -rw-r--r-- | fs/xfs/uuid.c (renamed from fs/xfs/support/uuid.c) | 0 | ||||
| -rw-r--r-- | fs/xfs/uuid.h (renamed from fs/xfs/support/uuid.h) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs.h | 3 | ||||
| -rw-r--r-- | fs/xfs/xfs_acl.c (renamed from fs/xfs/linux-2.6/xfs_acl.c) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_aops.c (renamed from fs/xfs/linux-2.6/xfs_aops.c) | 3 | ||||
| -rw-r--r-- | fs/xfs/xfs_aops.h (renamed from fs/xfs/linux-2.6/xfs_aops.h) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_buf.c (renamed from fs/xfs/linux-2.6/xfs_buf.c) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_buf.h (renamed from fs/xfs/linux-2.6/xfs_buf.h) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_buf_item.c | 3 | ||||
| -rw-r--r-- | fs/xfs/xfs_discard.c (renamed from fs/xfs/linux-2.6/xfs_discard.c) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_discard.h (renamed from fs/xfs/linux-2.6/xfs_discard.h) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_dquot.c (renamed from fs/xfs/quota/xfs_dquot.c) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_dquot.h (renamed from fs/xfs/quota/xfs_dquot.h) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_dquot_item.c (renamed from fs/xfs/quota/xfs_dquot_item.c) | 10 | ||||
| -rw-r--r-- | fs/xfs/xfs_dquot_item.h (renamed from fs/xfs/quota/xfs_dquot_item.h) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_export.c (renamed from fs/xfs/linux-2.6/xfs_export.c) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_export.h (renamed from fs/xfs/linux-2.6/xfs_export.h) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_file.c (renamed from fs/xfs/linux-2.6/xfs_file.c) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_fs_subr.c (renamed from fs/xfs/linux-2.6/xfs_fs_subr.c) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_globals.c (renamed from fs/xfs/linux-2.6/xfs_globals.c) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_inode_item.c | 10 | ||||
| -rw-r--r-- | fs/xfs/xfs_ioctl.c (renamed from fs/xfs/linux-2.6/xfs_ioctl.c) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_ioctl.h (renamed from fs/xfs/linux-2.6/xfs_ioctl.h) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_ioctl32.c (renamed from fs/xfs/linux-2.6/xfs_ioctl32.c) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_ioctl32.h (renamed from fs/xfs/linux-2.6/xfs_ioctl32.h) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_iops.c (renamed from fs/xfs/linux-2.6/xfs_iops.c) | 53 | ||||
| -rw-r--r-- | fs/xfs/xfs_iops.h (renamed from fs/xfs/linux-2.6/xfs_iops.h) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_linux.h (renamed from fs/xfs/linux-2.6/xfs_linux.h) | 29 | ||||
| -rw-r--r-- | fs/xfs/xfs_message.c (renamed from fs/xfs/linux-2.6/xfs_message.c) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_message.h (renamed from fs/xfs/linux-2.6/xfs_message.h) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_qm.c (renamed from fs/xfs/quota/xfs_qm.c) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_qm.h (renamed from fs/xfs/quota/xfs_qm.h) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_qm_bhv.c (renamed from fs/xfs/quota/xfs_qm_bhv.c) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_qm_stats.c (renamed from fs/xfs/quota/xfs_qm_stats.c) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_qm_stats.h (renamed from fs/xfs/quota/xfs_qm_stats.h) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_qm_syscalls.c (renamed from fs/xfs/quota/xfs_qm_syscalls.c) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_quota_priv.h (renamed from fs/xfs/quota/xfs_quota_priv.h) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_quotaops.c (renamed from fs/xfs/linux-2.6/xfs_quotaops.c) | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_stats.c (renamed from fs/xfs/linux-2.6/xfs_stats.c) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_stats.h (renamed from fs/xfs/linux-2.6/xfs_stats.h) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_super.c (renamed from fs/xfs/linux-2.6/xfs_super.c) | 49 | ||||
| -rw-r--r-- | fs/xfs/xfs_super.h (renamed from fs/xfs/linux-2.6/xfs_super.h) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_sync.c (renamed from fs/xfs/linux-2.6/xfs_sync.c) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_sync.h (renamed from fs/xfs/linux-2.6/xfs_sync.h) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_sysctl.c (renamed from fs/xfs/linux-2.6/xfs_sysctl.c) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_sysctl.h (renamed from fs/xfs/linux-2.6/xfs_sysctl.h) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_trace.c (renamed from fs/xfs/linux-2.6/xfs_trace.c) | 4 | ||||
| -rw-r--r-- | fs/xfs/xfs_trace.h (renamed from fs/xfs/linux-2.6/xfs_trace.h) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_trans.h | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_trans_ail.c | 83 | ||||
| -rw-r--r-- | fs/xfs/xfs_trans_dquot.c (renamed from fs/xfs/quota/xfs_trans_dquot.c) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_trans_priv.h | 8 | ||||
| -rw-r--r-- | fs/xfs/xfs_vnode.h (renamed from fs/xfs/linux-2.6/xfs_vnode.h) | 0 | ||||
| -rw-r--r-- | fs/xfs/xfs_xattr.c (renamed from fs/xfs/linux-2.6/xfs_xattr.c) | 0 | 
129 files changed, 1046 insertions, 754 deletions
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index 46ce357ca1a..410ffd6ceb5 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h @@ -54,9 +54,9 @@ extern struct kmem_cache *v9fs_inode_cache;  struct inode *v9fs_alloc_inode(struct super_block *sb);  void v9fs_destroy_inode(struct inode *inode); -struct inode *v9fs_get_inode(struct super_block *sb, int mode); +struct inode *v9fs_get_inode(struct super_block *sb, int mode, dev_t);  int v9fs_init_inode(struct v9fs_session_info *v9ses, -		    struct inode *inode, int mode); +		    struct inode *inode, int mode, dev_t);  void v9fs_evict_inode(struct inode *inode);  ino_t v9fs_qid2ino(struct p9_qid *qid);  void v9fs_stat2inode(struct p9_wstat *, struct inode *, struct super_block *); @@ -83,4 +83,6 @@ static inline void v9fs_invalidate_inode_attr(struct inode *inode)  	v9inode->cache_validity |= V9FS_INO_INVALID_ATTR;  	return;  } + +int v9fs_open_to_dotl_flags(int flags);  #endif diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 3c173fcc2c5..62857a810a7 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -65,7 +65,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)  	v9inode = V9FS_I(inode);  	v9ses = v9fs_inode2v9ses(inode);  	if (v9fs_proto_dotl(v9ses)) -		omode = file->f_flags; +		omode = v9fs_open_to_dotl_flags(file->f_flags);  	else  		omode = v9fs_uflags2omode(file->f_flags,  					v9fs_proto_dotu(v9ses)); @@ -169,7 +169,18 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl)  	/* convert posix lock to p9 tlock args */  	memset(&flock, 0, sizeof(flock)); -	flock.type = fl->fl_type; +	/* map the lock type */ +	switch (fl->fl_type) { +	case F_RDLCK: +		flock.type = P9_LOCK_TYPE_RDLCK; +		break; +	case F_WRLCK: +		flock.type = P9_LOCK_TYPE_WRLCK; +		break; +	case F_UNLCK: +		flock.type = P9_LOCK_TYPE_UNLCK; +		break; +	}  	flock.start = fl->fl_start;  	if (fl->fl_end == OFFSET_MAX)  		flock.length = 0; @@ -245,7 +256,7 @@ static int v9fs_file_getlock(struct file *filp, struct file_lock *fl)  	/* convert posix lock to p9 tgetlock args */  	memset(&glock, 0, sizeof(glock)); -	glock.type = fl->fl_type; +	glock.type  = P9_LOCK_TYPE_UNLCK;  	glock.start = fl->fl_start;  	if (fl->fl_end == OFFSET_MAX)  		glock.length = 0; @@ -257,17 +268,26 @@ static int v9fs_file_getlock(struct file *filp, struct file_lock *fl)  	res = p9_client_getlock_dotl(fid, &glock);  	if (res < 0)  		return res; -	if (glock.type != F_UNLCK) { -		fl->fl_type = glock.type; +	/* map 9p lock type to os lock type */ +	switch (glock.type) { +	case P9_LOCK_TYPE_RDLCK: +		fl->fl_type = F_RDLCK; +		break; +	case P9_LOCK_TYPE_WRLCK: +		fl->fl_type = F_WRLCK; +		break; +	case P9_LOCK_TYPE_UNLCK: +		fl->fl_type = F_UNLCK; +		break; +	} +	if (glock.type != P9_LOCK_TYPE_UNLCK) {  		fl->fl_start = glock.start;  		if (glock.length == 0)  			fl->fl_end = OFFSET_MAX;  		else  			fl->fl_end = glock.start + glock.length - 1;  		fl->fl_pid = glock.proc_id; -	} else -		fl->fl_type = F_UNLCK; - +	}  	return res;  } diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 8bb5507e822..e3c03db3c78 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -95,15 +95,18 @@ static int unixmode2p9mode(struct v9fs_session_info *v9ses, int mode)  /**   * p9mode2unixmode- convert plan9 mode bits to unix mode bits   * @v9ses: v9fs session information - * @mode: mode to convert + * @stat: p9_wstat from which mode need to be derived + * @rdev: major number, minor number in case of device files.   *   */ - -static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode) +static int p9mode2unixmode(struct v9fs_session_info *v9ses, +			   struct p9_wstat *stat, dev_t *rdev)  {  	int res; +	int mode = stat->mode; -	res = mode & 0777; +	res = mode & S_IALLUGO; +	*rdev = 0;  	if ((mode & P9_DMDIR) == P9_DMDIR)  		res |= S_IFDIR; @@ -116,9 +119,26 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)  		 && (v9ses->nodev == 0))  		res |= S_IFIFO;  	else if ((mode & P9_DMDEVICE) && (v9fs_proto_dotu(v9ses)) -		 && (v9ses->nodev == 0)) -		res |= S_IFBLK; -	else +		 && (v9ses->nodev == 0)) { +		char type = 0, ext[32]; +		int major = -1, minor = -1; + +		strncpy(ext, stat->extension, sizeof(ext)); +		sscanf(ext, "%c %u %u", &type, &major, &minor); +		switch (type) { +		case 'c': +			res |= S_IFCHR; +			break; +		case 'b': +			res |= S_IFBLK; +			break; +		default: +			P9_DPRINTK(P9_DEBUG_ERROR, +				"Unknown special type %c %s\n", type, +				stat->extension); +		}; +		*rdev = MKDEV(major, minor); +	} else  		res |= S_IFREG;  	if (v9fs_proto_dotu(v9ses)) { @@ -131,7 +151,6 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)  		if ((mode & P9_DMSETVTX) == P9_DMSETVTX)  			res |= S_ISVTX;  	} -  	return res;  } @@ -242,13 +261,13 @@ void v9fs_destroy_inode(struct inode *inode)  }  int v9fs_init_inode(struct v9fs_session_info *v9ses, -		    struct inode *inode, int mode) +		    struct inode *inode, int mode, dev_t rdev)  {  	int err = 0;  	inode_init_owner(inode, NULL, mode);  	inode->i_blocks = 0; -	inode->i_rdev = 0; +	inode->i_rdev = rdev;  	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;  	inode->i_mapping->a_ops = &v9fs_addr_operations; @@ -335,7 +354,7 @@ error:   *   */ -struct inode *v9fs_get_inode(struct super_block *sb, int mode) +struct inode *v9fs_get_inode(struct super_block *sb, int mode, dev_t rdev)  {  	int err;  	struct inode *inode; @@ -348,7 +367,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)  		P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");  		return ERR_PTR(-ENOMEM);  	} -	err = v9fs_init_inode(v9ses, inode, mode); +	err = v9fs_init_inode(v9ses, inode, mode, rdev);  	if (err) {  		iput(inode);  		return ERR_PTR(err); @@ -435,11 +454,12 @@ void v9fs_evict_inode(struct inode *inode)  static int v9fs_test_inode(struct inode *inode, void *data)  {  	int umode; +	dev_t rdev;  	struct v9fs_inode *v9inode = V9FS_I(inode);  	struct p9_wstat *st = (struct p9_wstat *)data;  	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); -	umode = p9mode2unixmode(v9ses, st->mode); +	umode = p9mode2unixmode(v9ses, st, &rdev);  	/* don't match inode of different type */  	if ((inode->i_mode & S_IFMT) != (umode & S_IFMT))  		return 0; @@ -473,6 +493,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb,  				   struct p9_wstat *st,  				   int new)  { +	dev_t rdev;  	int retval, umode;  	unsigned long i_ino;  	struct inode *inode; @@ -496,8 +517,8 @@ static struct inode *v9fs_qid_iget(struct super_block *sb,  	 * later.  	 */  	inode->i_ino = i_ino; -	umode = p9mode2unixmode(v9ses, st->mode); -	retval = v9fs_init_inode(v9ses, inode, umode); +	umode = p9mode2unixmode(v9ses, st, &rdev); +	retval = v9fs_init_inode(v9ses, inode, umode, rdev);  	if (retval)  		goto error; @@ -532,6 +553,19 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,  }  /** + * v9fs_at_to_dotl_flags- convert Linux specific AT flags to + * plan 9 AT flag. + * @flags: flags to convert + */ +static int v9fs_at_to_dotl_flags(int flags) +{ +	int rflags = 0; +	if (flags & AT_REMOVEDIR) +		rflags |= P9_DOTL_AT_REMOVEDIR; +	return rflags; +} + +/**   * v9fs_remove - helper function to remove files and directories   * @dir: directory inode that is being deleted   * @dentry:  dentry that is being deleted @@ -558,7 +592,8 @@ static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)  		return retval;  	}  	if (v9fs_proto_dotl(v9ses)) -		retval = p9_client_unlinkat(dfid, dentry->d_name.name, flags); +		retval = p9_client_unlinkat(dfid, dentry->d_name.name, +					    v9fs_at_to_dotl_flags(flags));  	if (retval == -EOPNOTSUPP) {  		/* Try the one based on path */  		v9fid = v9fs_fid_clone(dentry); @@ -645,13 +680,11 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,  		P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);  		goto error;  	} -	d_instantiate(dentry, inode);  	err = v9fs_fid_add(dentry, fid);  	if (err < 0)  		goto error; - +	d_instantiate(dentry, inode);  	return ofid; -  error:  	if (ofid)  		p9_client_clunk(ofid); @@ -792,6 +825,7 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)  struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,  				      struct nameidata *nameidata)  { +	struct dentry *res;  	struct super_block *sb;  	struct v9fs_session_info *v9ses;  	struct p9_fid *dfid, *fid; @@ -823,22 +857,35 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,  		return ERR_PTR(result);  	} - -	inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb); +	/* +	 * Make sure we don't use a wrong inode due to parallel +	 * unlink. For cached mode create calls request for new +	 * inode. But with cache disabled, lookup should do this. +	 */ +	if (v9ses->cache) +		inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb); +	else +		inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);  	if (IS_ERR(inode)) {  		result = PTR_ERR(inode);  		inode = NULL;  		goto error;  	} -  	result = v9fs_fid_add(dentry, fid);  	if (result < 0)  		goto error_iput; -  inst_out: -	d_add(dentry, inode); -	return NULL; - +	/* +	 * If we had a rename on the server and a parallel lookup +	 * for the new name, then make sure we instantiate with +	 * the new name. ie look up for a/b, while on server somebody +	 * moved b under k and client parallely did a lookup for +	 * k/b. +	 */ +	res = d_materialise_unique(dentry, inode); +	if (!IS_ERR(res)) +		return res; +	result = PTR_ERR(res);  error_iput:  	iput(inode);  error: @@ -1002,7 +1049,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,  		return PTR_ERR(st);  	v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb); -		generic_fillattr(dentry->d_inode, stat); +	generic_fillattr(dentry->d_inode, stat);  	p9stat_free(st);  	kfree(st); @@ -1086,6 +1133,7 @@ void  v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,  	struct super_block *sb)  { +	mode_t mode;  	char ext[32];  	char tag_name[14];  	unsigned int i_nlink; @@ -1121,31 +1169,9 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,  				inode->i_nlink = i_nlink;  		}  	} -	inode->i_mode = p9mode2unixmode(v9ses, stat->mode); -	if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) { -		char type = 0; -		int major = -1; -		int minor = -1; - -		strncpy(ext, stat->extension, sizeof(ext)); -		sscanf(ext, "%c %u %u", &type, &major, &minor); -		switch (type) { -		case 'c': -			inode->i_mode &= ~S_IFBLK; -			inode->i_mode |= S_IFCHR; -			break; -		case 'b': -			break; -		default: -			P9_DPRINTK(P9_DEBUG_ERROR, -				"Unknown special type %c %s\n", type, -				stat->extension); -		}; -		inode->i_rdev = MKDEV(major, minor); -		init_special_inode(inode, inode->i_mode, inode->i_rdev); -	} else -		inode->i_rdev = 0; - +	mode = stat->mode & S_IALLUGO; +	mode |= inode->i_mode & ~S_IALLUGO; +	inode->i_mode = mode;  	i_size_write(inode, stat->length);  	/* not real number of blocks, but 512 byte ones ... */ @@ -1411,6 +1437,8 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)  int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)  { +	int umode; +	dev_t rdev;  	loff_t i_size;  	struct p9_wstat *st;  	struct v9fs_session_info *v9ses; @@ -1419,6 +1447,12 @@ int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)  	st = p9_client_stat(fid);  	if (IS_ERR(st))  		return PTR_ERR(st); +	/* +	 * Don't update inode if the file type is different +	 */ +	umode = p9mode2unixmode(v9ses, st, &rdev); +	if ((inode->i_mode & S_IFMT) != (umode & S_IFMT)) +		goto out;  	spin_lock(&inode->i_lock);  	/* @@ -1430,6 +1464,7 @@ int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)  	if (v9ses->cache)  		inode->i_size = i_size;  	spin_unlock(&inode->i_lock); +out:  	p9stat_free(st);  	kfree(st);  	return 0; diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index b6c8ed20519..aded79fcd5c 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -153,7 +153,8 @@ static struct inode *v9fs_qid_iget_dotl(struct super_block *sb,  	 * later.  	 */  	inode->i_ino = i_ino; -	retval = v9fs_init_inode(v9ses, inode, st->st_mode); +	retval = v9fs_init_inode(v9ses, inode, +				 st->st_mode, new_decode_dev(st->st_rdev));  	if (retval)  		goto error; @@ -190,6 +191,58 @@ v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid,  	return inode;  } +struct dotl_openflag_map { +	int open_flag; +	int dotl_flag; +}; + +static int v9fs_mapped_dotl_flags(int flags) +{ +	int i; +	int rflags = 0; +	struct dotl_openflag_map dotl_oflag_map[] = { +		{ O_CREAT,	P9_DOTL_CREATE }, +		{ O_EXCL,	P9_DOTL_EXCL }, +		{ O_NOCTTY,	P9_DOTL_NOCTTY }, +		{ O_TRUNC,	P9_DOTL_TRUNC }, +		{ O_APPEND,	P9_DOTL_APPEND }, +		{ O_NONBLOCK,	P9_DOTL_NONBLOCK }, +		{ O_DSYNC,	P9_DOTL_DSYNC }, +		{ FASYNC,	P9_DOTL_FASYNC }, +		{ O_DIRECT,	P9_DOTL_DIRECT }, +		{ O_LARGEFILE,	P9_DOTL_LARGEFILE }, +		{ O_DIRECTORY,	P9_DOTL_DIRECTORY }, +		{ O_NOFOLLOW,	P9_DOTL_NOFOLLOW }, +		{ O_NOATIME,	P9_DOTL_NOATIME }, +		{ O_CLOEXEC,	P9_DOTL_CLOEXEC }, +		{ O_SYNC,	P9_DOTL_SYNC}, +	}; +	for (i = 0; i < ARRAY_SIZE(dotl_oflag_map); i++) { +		if (flags & dotl_oflag_map[i].open_flag) +			rflags |= dotl_oflag_map[i].dotl_flag; +	} +	return rflags; +} + +/** + * v9fs_open_to_dotl_flags- convert Linux specific open flags to + * plan 9 open flag. + * @flags: flags to convert + */ +int v9fs_open_to_dotl_flags(int flags) +{ +	int rflags = 0; + +	/* +	 * We have same bits for P9_DOTL_READONLY, P9_DOTL_WRONLY +	 * and P9_DOTL_NOACCESS +	 */ +	rflags |= flags & O_ACCMODE; +	rflags |= v9fs_mapped_dotl_flags(flags); + +	return rflags; +} +  /**   * v9fs_vfs_create_dotl - VFS hook to create files for 9P2000.L protocol.   * @dir: directory inode that is being created @@ -258,7 +311,8 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,  			   "Failed to get acl values in creat %d\n", err);  		goto error;  	} -	err = p9_client_create_dotl(ofid, name, flags, mode, gid, &qid); +	err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags), +				    mode, gid, &qid);  	if (err < 0) {  		P9_DPRINTK(P9_DEBUG_VFS,  				"p9_client_open_dotl failed in creat %d\n", @@ -281,10 +335,10 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,  		P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);  		goto error;  	} -	d_instantiate(dentry, inode);  	err = v9fs_fid_add(dentry, fid);  	if (err < 0)  		goto error; +	d_instantiate(dentry, inode);  	/* Now set the ACL based on the default value */  	v9fs_set_create_acl(dentry, &dacl, &pacl); @@ -403,10 +457,10 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,  				err);  			goto error;  		} -		d_instantiate(dentry, inode);  		err = v9fs_fid_add(dentry, fid);  		if (err < 0)  			goto error; +		d_instantiate(dentry, inode);  		fid = NULL;  	} else {  		/* @@ -414,7 +468,7 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,  		 * inode with stat. We need to get an inode  		 * so that we can set the acl with dentry  		 */ -		inode = v9fs_get_inode(dir->i_sb, mode); +		inode = v9fs_get_inode(dir->i_sb, mode, 0);  		if (IS_ERR(inode)) {  			err = PTR_ERR(inode);  			goto error; @@ -540,6 +594,7 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)  void  v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)  { +	mode_t mode;  	struct v9fs_inode *v9inode = V9FS_I(inode);  	if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) { @@ -552,11 +607,10 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)  		inode->i_uid = stat->st_uid;  		inode->i_gid = stat->st_gid;  		inode->i_nlink = stat->st_nlink; -		inode->i_mode = stat->st_mode; -		inode->i_rdev = new_decode_dev(stat->st_rdev); -		if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) -			init_special_inode(inode, inode->i_mode, inode->i_rdev); +		mode = stat->st_mode & S_IALLUGO; +		mode |= inode->i_mode & ~S_IALLUGO; +		inode->i_mode = mode;  		i_size_write(inode, stat->st_size);  		inode->i_blocks = stat->st_blocks; @@ -657,14 +711,14 @@ v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry,  					err);  			goto error;  		} -		d_instantiate(dentry, inode);  		err = v9fs_fid_add(dentry, fid);  		if (err < 0)  			goto error; +		d_instantiate(dentry, inode);  		fid = NULL;  	} else {  		/* Not in cached mode. No need to populate inode with stat */ -		inode = v9fs_get_inode(dir->i_sb, S_IFLNK); +		inode = v9fs_get_inode(dir->i_sb, S_IFLNK, 0);  		if (IS_ERR(inode)) {  			err = PTR_ERR(inode);  			goto error; @@ -810,17 +864,17 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode,  				err);  			goto error;  		} -		d_instantiate(dentry, inode);  		err = v9fs_fid_add(dentry, fid);  		if (err < 0)  			goto error; +		d_instantiate(dentry, inode);  		fid = NULL;  	} else {  		/*  		 * Not in cached mode. No need to populate inode with stat.  		 * socket syscall returns a fd, so we need instantiate  		 */ -		inode = v9fs_get_inode(dir->i_sb, mode); +		inode = v9fs_get_inode(dir->i_sb, mode, rdev);  		if (IS_ERR(inode)) {  			err = PTR_ERR(inode);  			goto error; @@ -886,6 +940,11 @@ int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)  	st = p9_client_getattr_dotl(fid, P9_STATS_ALL);  	if (IS_ERR(st))  		return PTR_ERR(st); +	/* +	 * Don't update inode if the file type is different +	 */ +	if ((inode->i_mode & S_IFMT) != (st->st_mode & S_IFMT)) +		goto out;  	spin_lock(&inode->i_lock);  	/* @@ -897,6 +956,7 @@ int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)  	if (v9ses->cache)  		inode->i_size = i_size;  	spin_unlock(&inode->i_lock); +out:  	kfree(st);  	return 0;  } diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index feef6cdc1fd..c70251d47ed 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -149,7 +149,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,  	else  		sb->s_d_op = &v9fs_dentry_operations; -	inode = v9fs_get_inode(sb, S_IFDIR | mode); +	inode = v9fs_get_inode(sb, S_IFDIR | mode, 0);  	if (IS_ERR(inode)) {  		retval = PTR_ERR(inode);  		goto release_sb; diff --git a/fs/attr.c b/fs/attr.c index 538e27959d3..7ee7ba48831 100644 --- a/fs/attr.c +++ b/fs/attr.c @@ -13,6 +13,7 @@  #include <linux/fsnotify.h>  #include <linux/fcntl.h>  #include <linux/security.h> +#include <linux/evm.h>  /**   * inode_change_ok - check if attribute changes to an inode are allowed @@ -237,8 +238,10 @@ int notify_change(struct dentry * dentry, struct iattr * attr)  	else  		error = simple_setattr(dentry, attr); -	if (!error) +	if (!error) {  		fsnotify_change(dentry, ia_valid); +		evm_inode_post_setattr(dentry, ia_valid); +	}  	return error;  } diff --git a/fs/block_dev.c b/fs/block_dev.c index ff77262e887..95f786ec7f0 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1429,6 +1429,11 @@ static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)  		WARN_ON_ONCE(bdev->bd_holders);  		sync_blockdev(bdev);  		kill_bdev(bdev); +		/* ->release can cause the old bdi to disappear, +		 * so must switch it out first +		 */ +		bdev_inode_switch_bdi(bdev->bd_inode, +					&default_backing_dev_info);  	}  	if (bdev->bd_contains == bdev) {  		if (disk->fops->release) @@ -1442,8 +1447,6 @@ static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)  		disk_put_part(bdev->bd_part);  		bdev->bd_part = NULL;  		bdev->bd_disk = NULL; -		bdev_inode_switch_bdi(bdev->bd_inode, -					&default_backing_dev_info);  		if (bdev != bdev->bd_contains)  			victim = bdev->bd_contains;  		bdev->bd_contains = NULL; diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index 502b9e98867..d9f99a16edd 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h @@ -176,7 +176,11 @@ static inline u64 btrfs_ino(struct inode *inode)  {  	u64 ino = BTRFS_I(inode)->location.objectid; -	if (ino <= BTRFS_FIRST_FREE_OBJECTID) +	/* +	 * !ino: btree_inode +	 * type == BTRFS_ROOT_ITEM_KEY: subvol dir +	 */ +	if (!ino || BTRFS_I(inode)->location.type == BTRFS_ROOT_ITEM_KEY)  		ino = inode->i_ino;  	return ino;  } diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index b910694f61e..a1cb7821bec 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c @@ -183,8 +183,10 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,  	 * read from the commit root and sidestep a nasty deadlock  	 * between reading the free space cache and updating the csum tree.  	 */ -	if (btrfs_is_free_space_inode(root, inode)) +	if (btrfs_is_free_space_inode(root, inode)) {  		path->search_commit_root = 1; +		path->skip_locking = 1; +	}  	disk_bytenr = (u64)bio->bi_sector << 9;  	if (dio) diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index e7872e485f1..e4e57d59edb 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1036,11 +1036,13 @@ out:   * on error we return an unlocked page and the error value   * on success we return a locked page and 0   */ -static int prepare_uptodate_page(struct page *page, u64 pos) +static int prepare_uptodate_page(struct page *page, u64 pos, +				 bool force_uptodate)  {  	int ret = 0; -	if ((pos & (PAGE_CACHE_SIZE - 1)) && !PageUptodate(page)) { +	if (((pos & (PAGE_CACHE_SIZE - 1)) || force_uptodate) && +	    !PageUptodate(page)) {  		ret = btrfs_readpage(NULL, page);  		if (ret)  			return ret; @@ -1061,7 +1063,7 @@ static int prepare_uptodate_page(struct page *page, u64 pos)  static noinline int prepare_pages(struct btrfs_root *root, struct file *file,  			 struct page **pages, size_t num_pages,  			 loff_t pos, unsigned long first_index, -			 size_t write_bytes) +			 size_t write_bytes, bool force_uptodate)  {  	struct extent_state *cached_state = NULL;  	int i; @@ -1075,12 +1077,6 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file,  	start_pos = pos & ~((u64)root->sectorsize - 1);  	last_pos = ((u64)index + num_pages) << PAGE_CACHE_SHIFT; -	if (start_pos > inode->i_size) { -		err = btrfs_cont_expand(inode, i_size_read(inode), start_pos); -		if (err) -			return err; -	} -  again:  	for (i = 0; i < num_pages; i++) {  		pages[i] = find_or_create_page(inode->i_mapping, index + i, @@ -1092,10 +1088,11 @@ again:  		}  		if (i == 0) -			err = prepare_uptodate_page(pages[i], pos); +			err = prepare_uptodate_page(pages[i], pos, +						    force_uptodate);  		if (i == num_pages - 1)  			err = prepare_uptodate_page(pages[i], -						    pos + write_bytes); +						    pos + write_bytes, false);  		if (err) {  			page_cache_release(pages[i]);  			faili = i - 1; @@ -1164,6 +1161,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,  	size_t num_written = 0;  	int nrptrs;  	int ret = 0; +	bool force_page_uptodate = false;  	nrptrs = min((iov_iter_count(i) + PAGE_CACHE_SIZE - 1) /  		     PAGE_CACHE_SIZE, PAGE_CACHE_SIZE / @@ -1206,7 +1204,8 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,  		 * contents of pages from loop to loop  		 */  		ret = prepare_pages(root, file, pages, num_pages, -				    pos, first_index, write_bytes); +				    pos, first_index, write_bytes, +				    force_page_uptodate);  		if (ret) {  			btrfs_delalloc_release_space(inode,  					num_pages << PAGE_CACHE_SHIFT); @@ -1223,12 +1222,15 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,  		if (copied < write_bytes)  			nrptrs = 1; -		if (copied == 0) +		if (copied == 0) { +			force_page_uptodate = true;  			dirty_pages = 0; -		else +		} else { +			force_page_uptodate = false;  			dirty_pages = (copied + offset +  				       PAGE_CACHE_SIZE - 1) >>  				       PAGE_CACHE_SHIFT; +		}  		/*  		 * If we had a short copy we need to release the excess delaloc @@ -1338,6 +1340,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,  	struct inode *inode = fdentry(file)->d_inode;  	struct btrfs_root *root = BTRFS_I(inode)->root;  	loff_t *ppos = &iocb->ki_pos; +	u64 start_pos;  	ssize_t num_written = 0;  	ssize_t err = 0;  	size_t count, ocount; @@ -1386,6 +1389,15 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,  	file_update_time(file);  	BTRFS_I(inode)->sequence++; +	start_pos = round_down(pos, root->sectorsize); +	if (start_pos > i_size_read(inode)) { +		err = btrfs_cont_expand(inode, i_size_read(inode), start_pos); +		if (err) { +			mutex_unlock(&inode->i_mutex); +			goto out; +		} +	} +  	if (unlikely(file->f_flags & O_DIRECT)) {  		num_written = __btrfs_direct_write(iocb, iov, nr_segs,  						   pos, ppos, count, ocount); @@ -1813,6 +1825,11 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int origin)  		goto out;  	case SEEK_DATA:  	case SEEK_HOLE: +		if (offset >= i_size_read(inode)) { +			mutex_unlock(&inode->i_mutex); +			return -ENXIO; +		} +  		ret = find_desired_extent(inode, &offset, origin);  		if (ret) {  			mutex_unlock(&inode->i_mutex); @@ -1821,11 +1838,11 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int origin)  	}  	if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET)) { -		ret = -EINVAL; +		offset = -EINVAL;  		goto out;  	}  	if (offset > inode->i_sb->s_maxbytes) { -		ret = -EINVAL; +		offset = -EINVAL;  		goto out;  	} diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 6a265b9f85f..41ac927401d 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -190,9 +190,11 @@ int btrfs_truncate_free_space_cache(struct btrfs_root *root,  				    struct btrfs_path *path,  				    struct inode *inode)  { +	struct btrfs_block_rsv *rsv;  	loff_t oldsize;  	int ret = 0; +	rsv = trans->block_rsv;  	trans->block_rsv = root->orphan_block_rsv;  	ret = btrfs_block_rsv_check(trans, root,  				    root->orphan_block_rsv, @@ -210,6 +212,8 @@ int btrfs_truncate_free_space_cache(struct btrfs_root *root,  	 */  	ret = btrfs_truncate_inode_items(trans, root, inode,  					 0, BTRFS_EXTENT_DATA_KEY); + +	trans->block_rsv = rsv;  	if (ret) {  		WARN_ON(1);  		return ret; diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 0ccc7438ad3..b2d004ad66a 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1786,7 +1786,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)  			  &ordered_extent->list);  	ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent); -	if (!ret) { +	if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) {  		ret = btrfs_update_inode(trans, root, inode);  		BUG_ON(ret);  	} @@ -3510,15 +3510,19 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size)  			err = btrfs_drop_extents(trans, inode, cur_offset,  						 cur_offset + hole_size,  						 &hint_byte, 1); -			if (err) +			if (err) { +				btrfs_end_transaction(trans, root);  				break; +			}  			err = btrfs_insert_file_extent(trans, root,  					btrfs_ino(inode), cur_offset, 0,  					0, hole_size, 0, hole_size,  					0, 0, 0); -			if (err) +			if (err) { +				btrfs_end_transaction(trans, root);  				break; +			}  			btrfs_drop_extent_cache(inode, hole_start,  					last_byte - 1, 0); @@ -3952,7 +3956,6 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,  			 struct btrfs_root *root, int *new)  {  	struct inode *inode; -	int bad_inode = 0;  	inode = btrfs_iget_locked(s, location->objectid, root);  	if (!inode) @@ -3968,15 +3971,12 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,  			if (new)  				*new = 1;  		} else { -			bad_inode = 1; +			unlock_new_inode(inode); +			iput(inode); +			inode = ERR_PTR(-ESTALE);  		}  	} -	if (bad_inode) { -		iput(inode); -		inode = ERR_PTR(-ESTALE); -	} -  	return inode;  } @@ -4018,7 +4018,8 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)  		memcpy(&location, dentry->d_fsdata, sizeof(struct btrfs_key));  		kfree(dentry->d_fsdata);  		dentry->d_fsdata = NULL; -		d_clear_need_lookup(dentry); +		/* This thing is hashed, drop it for now */ +		d_drop(dentry);  	} else {  		ret = btrfs_inode_by_name(dir, dentry, &location);  	} @@ -4085,7 +4086,15 @@ static void btrfs_dentry_release(struct dentry *dentry)  static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,  				   struct nameidata *nd)  { -	return d_splice_alias(btrfs_lookup_dentry(dir, dentry), dentry); +	struct dentry *ret; + +	ret = d_splice_alias(btrfs_lookup_dentry(dir, dentry), dentry); +	if (unlikely(d_need_lookup(dentry))) { +		spin_lock(&dentry->d_lock); +		dentry->d_flags &= ~DCACHE_NEED_LOOKUP; +		spin_unlock(&dentry->d_lock); +	} +	return ret;  }  unsigned char btrfs_filetype_table[] = { @@ -4125,7 +4134,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,  	/* special case for "." */  	if (filp->f_pos == 0) { -		over = filldir(dirent, ".", 1, 1, btrfs_ino(inode), DT_DIR); +		over = filldir(dirent, ".", 1, +			       filp->f_pos, btrfs_ino(inode), DT_DIR);  		if (over)  			return 0;  		filp->f_pos = 1; @@ -4134,7 +4144,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,  	if (filp->f_pos == 1) {  		u64 pino = parent_ino(filp->f_path.dentry);  		over = filldir(dirent, "..", 2, -			       2, pino, DT_DIR); +			       filp->f_pos, pino, DT_DIR);  		if (over)  			return 0;  		filp->f_pos = 2; @@ -5823,7 +5833,7 @@ again:  	add_pending_csums(trans, inode, ordered->file_offset, &ordered->list);  	ret = btrfs_ordered_update_i_size(inode, 0, ordered); -	if (!ret) +	if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags))  		btrfs_update_inode(trans, root, inode);  	ret = 0;  out_unlock: diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 970977aab22..dae5dfe41ba 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1047,7 +1047,16 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,  	if (!max_to_defrag)  		max_to_defrag = last_index - 1; -	while (i <= last_index && defrag_count < max_to_defrag) { +	/* +	 * make writeback starts from i, so the defrag range can be +	 * written sequentially. +	 */ +	if (i < inode->i_mapping->writeback_index) +		inode->i_mapping->writeback_index = i; + +	while (i <= last_index && defrag_count < max_to_defrag && +	       (i < (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> +		PAGE_CACHE_SHIFT)) {  		/*  		 * make sure we stop running if someone unmounts  		 * the FS @@ -2177,6 +2186,11 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,  	if (!(src_file->f_mode & FMODE_READ))  		goto out_fput; +	/* don't make the dst file partly checksummed */ +	if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) != +	    (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) +		goto out_fput; +  	ret = -EISDIR;  	if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode))  		goto out_fput; @@ -2220,6 +2234,16 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,  	    !IS_ALIGNED(destoff, bs))  		goto out_unlock; +	if (destoff > inode->i_size) { +		ret = btrfs_cont_expand(inode, inode->i_size, destoff); +		if (ret) +			goto out_unlock; +	} + +	/* truncate page cache pages from target inode range */ +	truncate_inode_pages_range(&inode->i_data, destoff, +				   PAGE_CACHE_ALIGN(destoff + len) - 1); +  	/* do any pending delalloc/csum calc on src, one way or  	   another, and lock file content */  	while (1) { @@ -2236,10 +2260,6 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,  		btrfs_wait_ordered_range(src, off, len);  	} -	/* truncate page cache pages from target inode range */ -	truncate_inode_pages_range(&inode->i_data, off, -				   ALIGN(off + len, PAGE_CACHE_SIZE) - 1); -  	/* clone data */  	key.objectid = btrfs_ino(src);  	key.type = BTRFS_EXTENT_DATA_KEY; @@ -2317,7 +2337,12 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,  			else  				new_key.offset = destoff; -			trans = btrfs_start_transaction(root, 1); +			/* +			 * 1 - adjusting old extent (we may have to split it) +			 * 1 - add new extent +			 * 1 - inode update +			 */ +			trans = btrfs_start_transaction(root, 3);  			if (IS_ERR(trans)) {  				ret = PTR_ERR(trans);  				goto out; @@ -2325,14 +2350,21 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,  			if (type == BTRFS_FILE_EXTENT_REG ||  			    type == BTRFS_FILE_EXTENT_PREALLOC) { +				/* +				 *    a  | --- range to clone ---|  b +				 * | ------------- extent ------------- | +				 */ + +				/* substract range b */ +				if (key.offset + datal > off + len) +					datal = off + len - key.offset; + +				/* substract range a */  				if (off > key.offset) {  					datao += off - key.offset;  					datal -= off - key.offset;  				} -				if (key.offset + datal > off + len) -					datal = off + len - key.offset; -  				ret = btrfs_drop_extents(trans, inode,  							 new_key.offset,  							 new_key.offset + datal, @@ -2429,7 +2461,6 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,  			if (endoff > inode->i_size)  				btrfs_i_size_write(inode, endoff); -			BTRFS_I(inode)->flags = BTRFS_I(src)->flags;  			ret = btrfs_update_inode(trans, root, inode);  			BUG_ON(ret);  			btrfs_end_transaction(trans, root); diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 7dc36fab4af..e24b7964a15 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -884,6 +884,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,  	struct btrfs_root *tree_root = fs_info->tree_root;  	struct btrfs_root *root = pending->root;  	struct btrfs_root *parent_root; +	struct btrfs_block_rsv *rsv;  	struct inode *parent_inode;  	struct dentry *parent;  	struct dentry *dentry; @@ -895,6 +896,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,  	u64 objectid;  	u64 root_flags; +	rsv = trans->block_rsv; +  	new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS);  	if (!new_root_item) {  		pending->error = -ENOMEM; @@ -1002,6 +1005,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,  	btrfs_orphan_post_snapshot(trans, pending);  fail:  	kfree(new_root_item); +	trans->block_rsv = rsv;  	btrfs_block_rsv_release(root, &pending->block_rsv, (u64)-1);  	return 0;  } diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index d733b9cfea3..426aa464f1a 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -116,6 +116,12 @@ static int do_setxattr(struct btrfs_trans_handle *trans,  		if (ret)  			goto out;  		btrfs_release_path(path); + +		/* +		 * remove the attribute +		 */ +		if (!value) +			goto out;  	}  again: @@ -158,6 +164,9 @@ out:  	return ret;  } +/* + * @value: "" makes the attribute to empty, NULL removes it + */  int __btrfs_setxattr(struct btrfs_trans_handle *trans,  		     struct inode *inode, const char *name,  		     const void *value, size_t size, int flags) @@ -374,36 +383,36 @@ int btrfs_removexattr(struct dentry *dentry, const char *name)  				XATTR_REPLACE);  } -int btrfs_xattr_security_init(struct btrfs_trans_handle *trans, -			      struct inode *inode, struct inode *dir, -			      const struct qstr *qstr) +int btrfs_initxattrs(struct inode *inode, const struct xattr *xattr_array, +		     void *fs_info)  { -	int err; -	size_t len; -	void *value; -	char *suffix; +	const struct xattr *xattr; +	struct btrfs_trans_handle *trans = fs_info;  	char *name; +	int err = 0; -	err = security_inode_init_security(inode, dir, qstr, &suffix, &value, -					   &len); -	if (err) { -		if (err == -EOPNOTSUPP) -			return 0; -		return err; -	} - -	name = kmalloc(XATTR_SECURITY_PREFIX_LEN + strlen(suffix) + 1, -		       GFP_NOFS); -	if (!name) { -		err = -ENOMEM; -	} else { +	for (xattr = xattr_array; xattr->name != NULL; xattr++) { +		name = kmalloc(XATTR_SECURITY_PREFIX_LEN + +			       strlen(xattr->name) + 1, GFP_NOFS); +		if (!name) { +			err = -ENOMEM; +			break; +		}  		strcpy(name, XATTR_SECURITY_PREFIX); -		strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix); -		err = __btrfs_setxattr(trans, inode, name, value, len, 0); +		strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name); +		err = __btrfs_setxattr(trans, inode, name, +				       xattr->value, xattr->value_len, 0);  		kfree(name); +		if (err < 0) +			break;  	} - -	kfree(suffix); -	kfree(value);  	return err;  } + +int btrfs_xattr_security_init(struct btrfs_trans_handle *trans, +			      struct inode *inode, struct inode *dir, +			      const struct qstr *qstr) +{ +	return security_inode_init_security(inode, dir, qstr, +					    &btrfs_initxattrs, trans); +} diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index fee028b5332..86c59e16ba7 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -1595,7 +1595,7 @@ static int set_request_path_attr(struct inode *rinode, struct dentry *rdentry,  		r = build_dentry_path(rdentry, ppath, pathlen, ino, freepath);  		dout(" dentry %p %llx/%.*s\n", rdentry, *ino, *pathlen,  		     *ppath); -	} else if (rpath) { +	} else if (rpath || rino) {  		*ino = rino;  		*ppath = rpath;  		*pathlen = strlen(rpath); diff --git a/fs/ceph/super.c b/fs/ceph/super.c index d47c5ec7fb1..88bacaf385d 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c @@ -813,8 +813,8 @@ static struct dentry *ceph_mount(struct file_system_type *fs_type,  	fsc = create_fs_client(fsopt, opt);  	if (IS_ERR(fsc)) {  		res = ERR_CAST(fsc); -		kfree(fsopt); -		kfree(opt); +		destroy_mount_options(fsopt); +		ceph_destroy_options(opt);  		goto out_final;  	} diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index e76bfeb6826..30acd22147e 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -351,9 +351,7 @@ static int  build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp)  {  	unsigned int dlen; -	unsigned int wlen; -	unsigned int size = 6 * sizeof(struct ntlmssp2_name); -	__le64  curtime; +	unsigned int size = 2 * sizeof(struct ntlmssp2_name);  	char *defdmname = "WORKGROUP";  	unsigned char *blobptr;  	struct ntlmssp2_name *attrptr; @@ -365,15 +363,14 @@ build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp)  	}  	dlen = strlen(ses->domainName); -	wlen = strlen(ses->server->hostname); -	/* The length of this blob is a size which is -	 * six times the size of a structure which holds name/size + -	 * two times the unicode length of a domain name + -	 * two times the unicode length of a server name + -	 * size of a timestamp (which is 8 bytes). +	/* +	 * The length of this blob is two times the size of a +	 * structure (av pair) which holds name/size +	 * ( for NTLMSSP_AV_NB_DOMAIN_NAME followed by NTLMSSP_AV_EOL ) + +	 * unicode length of a netbios domain name  	 */ -	ses->auth_key.len = size + 2 * (2 * dlen) + 2 * (2 * wlen) + 8; +	ses->auth_key.len = size + 2 * dlen;  	ses->auth_key.response = kzalloc(ses->auth_key.len, GFP_KERNEL);  	if (!ses->auth_key.response) {  		ses->auth_key.len = 0; @@ -384,44 +381,15 @@ build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp)  	blobptr = ses->auth_key.response;  	attrptr = (struct ntlmssp2_name *) blobptr; +	/* +	 * As defined in MS-NTLM 3.3.2, just this av pair field +	 * is sufficient as part of the temp +	 */  	attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME);  	attrptr->length = cpu_to_le16(2 * dlen);  	blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);  	cifs_strtoUCS((__le16 *)blobptr, ses->domainName, dlen, nls_cp); -	blobptr += 2 * dlen; -	attrptr = (struct ntlmssp2_name *) blobptr; - -	attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_COMPUTER_NAME); -	attrptr->length = cpu_to_le16(2 * wlen); -	blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name); -	cifs_strtoUCS((__le16 *)blobptr, ses->server->hostname, wlen, nls_cp); - -	blobptr += 2 * wlen; -	attrptr = (struct ntlmssp2_name *) blobptr; - -	attrptr->type = cpu_to_le16(NTLMSSP_AV_DNS_DOMAIN_NAME); -	attrptr->length = cpu_to_le16(2 * dlen); -	blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name); -	cifs_strtoUCS((__le16 *)blobptr, ses->domainName, dlen, nls_cp); - -	blobptr += 2 * dlen; -	attrptr = (struct ntlmssp2_name *) blobptr; - -	attrptr->type = cpu_to_le16(NTLMSSP_AV_DNS_COMPUTER_NAME); -	attrptr->length = cpu_to_le16(2 * wlen); -	blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name); -	cifs_strtoUCS((__le16 *)blobptr, ses->server->hostname, wlen, nls_cp); - -	blobptr += 2 * wlen; -	attrptr = (struct ntlmssp2_name *) blobptr; - -	attrptr->type = cpu_to_le16(NTLMSSP_AV_TIMESTAMP); -	attrptr->length = cpu_to_le16(sizeof(__le64)); -	blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name); -	curtime = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); -	memcpy(blobptr, &curtime, sizeof(__le64)); -  	return 0;  } diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index f93eb948d07..54b8f1e7da9 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -548,6 +548,12 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)  		struct inode *dir = dentry->d_inode;  		struct dentry *child; +		if (!dir) { +			dput(dentry); +			dentry = ERR_PTR(-ENOENT); +			break; +		} +  		/* skip separators */  		while (*s == sep)  			s++; @@ -563,10 +569,6 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)  		mutex_unlock(&dir->i_mutex);  		dput(dentry);  		dentry = child; -		if (!dentry->d_inode) { -			dput(dentry); -			dentry = ERR_PTR(-ENOENT); -		}  	} while (!IS_ERR(dentry));  	_FreeXid(xid);  	kfree(full_path); diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index aac37d99a48..a80f7bd97b9 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -4079,7 +4079,8 @@ int CIFSFindNext(const int xid, struct cifs_tcon *tcon,  	T2_FNEXT_RSP_PARMS *parms;  	char *response_data;  	int rc = 0; -	int bytes_returned, name_len; +	int bytes_returned; +	unsigned int name_len;  	__u16 params, byte_count;  	cFYI(1, "In FindNext"); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 633c246b677..62abf9fd6ff 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1298,7 +1298,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,  			/* ignore */  		} else if (strnicmp(data, "guest", 5) == 0) {  			/* ignore */ -		} else if (strnicmp(data, "rw", 2) == 0) { +		} else if (strnicmp(data, "rw", 2) == 0 && strlen(data) == 2) {  			/* ignore */  		} else if (strnicmp(data, "ro", 2) == 0) {  			/* ignore */ @@ -1401,7 +1401,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,  			vol->server_ino = 1;  		} else if (strnicmp(data, "noserverino", 9) == 0) {  			vol->server_ino = 0; -		} else if (strnicmp(data, "rwpidforward", 4) == 0) { +		} else if (strnicmp(data, "rwpidforward", 12) == 0) {  			vol->rwpidforward = 1;  		} else if (strnicmp(data, "cifsacl", 7) == 0) {  			vol->cifs_acl = 1; @@ -2018,7 +2018,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)  		warned_on_ntlm = true;  		cERROR(1, "default security mechanism requested.  The default "  			"security mechanism will be upgraded from ntlm to " -			"ntlmv2 in kernel release 3.1"); +			"ntlmv2 in kernel release 3.2");  	}  	ses->overrideSecFlg = volume_info->secFlg; @@ -2877,9 +2877,9 @@ cleanup_volume_info_contents(struct smb_vol *volume_info)  {  	kfree(volume_info->username);  	kzfree(volume_info->password); -	kfree(volume_info->UNC);  	if (volume_info->UNCip != volume_info->UNC + 2)  		kfree(volume_info->UNCip); +	kfree(volume_info->UNC);  	kfree(volume_info->domainname);  	kfree(volume_info->iocharset);  	kfree(volume_info->prepath); diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index 2a22fb2989e..c3230888214 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -22,6 +22,7 @@  #include <linux/fs.h>  #include <linux/posix_acl_xattr.h>  #include <linux/slab.h> +#include <linux/xattr.h>  #include "cifsfs.h"  #include "cifspdu.h"  #include "cifsglob.h" @@ -31,16 +32,8 @@  #define MAX_EA_VALUE_SIZE 65535  #define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib"  #define CIFS_XATTR_CIFS_ACL "system.cifs_acl" -#define CIFS_XATTR_USER_PREFIX "user." -#define CIFS_XATTR_SYSTEM_PREFIX "system." -#define CIFS_XATTR_OS2_PREFIX "os2." -#define CIFS_XATTR_SECURITY_PREFIX "security." -#define CIFS_XATTR_TRUSTED_PREFIX "trusted." -#define XATTR_TRUSTED_PREFIX_LEN  8 -#define XATTR_SECURITY_PREFIX_LEN 9 -/* BB need to add server (Samba e.g) support for security and trusted prefix */ - +/* BB need to add server (Samba e.g) support for security and trusted prefix */  int cifs_removexattr(struct dentry *direntry, const char *ea_name)  { @@ -76,8 +69,8 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name)  	}  	if (ea_name == NULL) {  		cFYI(1, "Null xattr names not supported"); -	} else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) -		&& (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4))) { +	} else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) +		&& (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN))) {  		cFYI(1,  		     "illegal xattr request %s (only user namespace supported)",  		     ea_name); @@ -88,7 +81,7 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name)  		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)  			goto remove_ea_exit; -		ea_name += 5; /* skip past user. prefix */ +		ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */  		rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, NULL,  			(__u16)0, cifs_sb->local_nls,  			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); @@ -149,21 +142,23 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,  	if (ea_name == NULL) {  		cFYI(1, "Null xattr names not supported"); -	} else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) == 0) { +	} else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) +		   == 0) {  		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)  			goto set_ea_exit;  		if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0)  			cFYI(1, "attempt to set cifs inode metadata"); -		ea_name += 5; /* skip past user. prefix */ +		ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */  		rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value,  			(__u16)value_size, cifs_sb->local_nls,  			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); -	} else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) { +	} else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) +		   == 0) {  		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)  			goto set_ea_exit; -		ea_name += 4; /* skip past os2. prefix */ +		ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */  		rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value,  			(__u16)value_size, cifs_sb->local_nls,  			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); @@ -269,7 +264,8 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,  	/* return alt name if available as pseudo attr */  	if (ea_name == NULL) {  		cFYI(1, "Null xattr names not supported"); -	} else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) == 0) { +	} else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) +		   == 0) {  		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)  			goto get_ea_exit; @@ -277,15 +273,15 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,  			cFYI(1, "attempt to query cifs inode metadata");  			/* revalidate/getattr then populate from inode */  		} /* BB add else when above is implemented */ -		ea_name += 5; /* skip past user. prefix */ +		ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */  		rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value,  			buf_size, cifs_sb->local_nls,  			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); -	} else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) { +	} else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {  		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)  			goto get_ea_exit; -		ea_name += 4; /* skip past os2. prefix */ +		ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */  		rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value,  			buf_size, cifs_sb->local_nls,  			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); @@ -339,10 +335,10 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,  		cFYI(1, "Query CIFS ACL not supported yet");  #endif /* CONFIG_CIFS_ACL */  	} else if (strncmp(ea_name, -		  CIFS_XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) { +		  XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) {  		cFYI(1, "Trusted xattr namespace not supported yet");  	} else if (strncmp(ea_name, -		  CIFS_XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) { +		  XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) {  		cFYI(1, "Security xattr namespace not supported yet");  	} else  		cFYI(1, diff --git a/fs/coda/coda_linux.h b/fs/coda/coda_linux.h index 44e17e9c21a..cc0ea9fe5ec 100644 --- a/fs/coda/coda_linux.h +++ b/fs/coda/coda_linux.h @@ -59,12 +59,11 @@ void coda_sysctl_clean(void);  #define CODA_ALLOC(ptr, cast, size) do { \      if (size < PAGE_SIZE) \ -        ptr = kmalloc((unsigned long) size, GFP_KERNEL); \ +        ptr = kzalloc((unsigned long) size, GFP_KERNEL); \      else \ -        ptr = (cast)vmalloc((unsigned long) size); \ +        ptr = (cast)vzalloc((unsigned long) size); \      if (!ptr) \          printk("kernel malloc returns 0 at %s:%d\n", __FILE__, __LINE__); \ -    else memset( ptr, 0, size ); \  } while (0) diff --git a/fs/compat.c b/fs/compat.c index 0b48d018e38..58b1da45989 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -1675,11 +1675,6 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,  }  #endif /* HAVE_SET_RESTORE_SIGMASK */ -long asmlinkage compat_sys_nfsservctl(int cmd, void *notused, void *notused2) -{ -	return sys_ni_syscall(); -} -  #ifdef CONFIG_EPOLL  #ifdef HAVE_SET_RESTORE_SIGMASK diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c index c83f4768eea..ca418aaf635 100644 --- a/fs/configfs/inode.c +++ b/fs/configfs/inode.c @@ -23,7 +23,8 @@   *   * configfs Copyright (C) 2005 Oracle.  All rights reserved.   * - * Please see Documentation/filesystems/configfs.txt for more information. + * Please see Documentation/filesystems/configfs/configfs.txt for more + * information.   */  #undef DEBUG diff --git a/fs/configfs/item.c b/fs/configfs/item.c index 76dc4c3e5d5..50cee7f9110 100644 --- a/fs/configfs/item.c +++ b/fs/configfs/item.c @@ -23,7 +23,7 @@   *   * configfs Copyright (C) 2005 Oracle.  All rights reserved.   * - * Please see the file Documentation/filesystems/configfs.txt for + * Please see the file Documentation/filesystems/configfs/configfs.txt for   * critical information about using the config_item interface.   */ diff --git a/fs/eventpoll.c b/fs/eventpoll.c index fe047d966dc..9026fc91fe3 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -700,7 +700,7 @@ static const struct file_operations eventpoll_fops = {  	.llseek		= noop_llseek,  }; -/* Fast test to see if the file is an evenpoll file */ +/* Fast test to see if the file is an eventpoll file */  static inline int is_file_epoll(struct file *f)  {  	return f->f_op == &eventpoll_fops; diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c index 5d979b4347b..c922adc8ef4 100644 --- a/fs/ext2/xattr_security.c +++ b/fs/ext2/xattr_security.c @@ -46,28 +46,30 @@ ext2_xattr_security_set(struct dentry *dentry, const char *name,  			      value, size, flags);  } -int -ext2_init_security(struct inode *inode, struct inode *dir, -		   const struct qstr *qstr) +int ext2_initxattrs(struct inode *inode, const struct xattr *xattr_array, +		    void *fs_info)  { -	int err; -	size_t len; -	void *value; -	char *name; +	const struct xattr *xattr; +	int err = 0; -	err = security_inode_init_security(inode, dir, qstr, &name, &value, &len); -	if (err) { -		if (err == -EOPNOTSUPP) -			return 0; -		return err; +	for (xattr = xattr_array; xattr->name != NULL; xattr++) { +		err = ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY, +				     xattr->name, xattr->value, +				     xattr->value_len, 0); +		if (err < 0) +			break;  	} -	err = ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY, -			     name, value, len, 0); -	kfree(name); -	kfree(value);  	return err;  } +int +ext2_init_security(struct inode *inode, struct inode *dir, +		   const struct qstr *qstr) +{ +	return security_inode_init_security(inode, dir, qstr, +					    &ext2_initxattrs, NULL); +} +  const struct xattr_handler ext2_xattr_security_handler = {  	.prefix	= XATTR_SECURITY_PREFIX,  	.list	= ext2_xattr_security_list, diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 04da6acde85..12661e1deed 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -1134,7 +1134,7 @@ struct buffer_head *ext3_bread(handle_t *handle, struct inode *inode,  		return bh;  	if (buffer_uptodate(bh))  		return bh; -	ll_rw_block(READ_META, 1, &bh); +	ll_rw_block(READ | REQ_META | REQ_PRIO, 1, &bh);  	wait_on_buffer(bh);  	if (buffer_uptodate(bh))  		return bh; @@ -2807,7 +2807,7 @@ make_io:  		trace_ext3_load_inode(inode);  		get_bh(bh);  		bh->b_end_io = end_buffer_read_sync; -		submit_bh(READ_META, bh); +		submit_bh(READ | REQ_META | REQ_PRIO, bh);  		wait_on_buffer(bh);  		if (!buffer_uptodate(bh)) {  			ext3_error(inode->i_sb, "ext3_get_inode_loc", diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 5571708b6a5..0629e09f651 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -922,7 +922,8 @@ restart:  				bh = ext3_getblk(NULL, dir, b++, 0, &err);  				bh_use[ra_max] = bh;  				if (bh) -					ll_rw_block(READ_META, 1, &bh); +					ll_rw_block(READ | REQ_META | REQ_PRIO, +						    1, &bh);  			}  		}  		if ((bh = bh_use[ra_ptr++]) == NULL) diff --git a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c index b8d9f83aa5c..3c218b8a51d 100644 --- a/fs/ext3/xattr_security.c +++ b/fs/ext3/xattr_security.c @@ -48,28 +48,32 @@ ext3_xattr_security_set(struct dentry *dentry, const char *name,  			      name, value, size, flags);  } -int -ext3_init_security(handle_t *handle, struct inode *inode, struct inode *dir, -		   const struct qstr *qstr) +int ext3_initxattrs(struct inode *inode, const struct xattr *xattr_array, +		    void *fs_info)  { -	int err; -	size_t len; -	void *value; -	char *name; +	const struct xattr *xattr; +	handle_t *handle = fs_info; +	int err = 0; -	err = security_inode_init_security(inode, dir, qstr, &name, &value, &len); -	if (err) { -		if (err == -EOPNOTSUPP) -			return 0; -		return err; +	for (xattr = xattr_array; xattr->name != NULL; xattr++) { +		err = ext3_xattr_set_handle(handle, inode, +					    EXT3_XATTR_INDEX_SECURITY, +					    xattr->name, xattr->value, +					    xattr->value_len, 0); +		if (err < 0) +			break;  	} -	err = ext3_xattr_set_handle(handle, inode, EXT3_XATTR_INDEX_SECURITY, -				    name, value, len, 0); -	kfree(name); -	kfree(value);  	return err;  } +int +ext3_init_security(handle_t *handle, struct inode *inode, struct inode *dir, +		   const struct qstr *qstr) +{ +	return security_inode_init_security(inode, dir, qstr, +					    &ext3_initxattrs, handle); +} +  const struct xattr_handler ext3_xattr_security_handler = {  	.prefix	= XATTR_SECURITY_PREFIX,  	.list	= ext3_xattr_security_list, diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index e717dfd2f2b..b7d7bd0f066 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -175,6 +175,7 @@ struct mpage_da_data {   */  #define	EXT4_IO_END_UNWRITTEN	0x0001  #define EXT4_IO_END_ERROR	0x0002 +#define EXT4_IO_END_QUEUED	0x0004  struct ext4_io_page {  	struct page	*p_page; diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index c4da98a959a..986e2388f03 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -121,9 +121,6 @@ void ext4_evict_inode(struct inode *inode)  	trace_ext4_evict_inode(inode); -	mutex_lock(&inode->i_mutex); -	ext4_flush_completed_IO(inode); -	mutex_unlock(&inode->i_mutex);  	ext4_ioend_wait(inode);  	if (inode->i_nlink) { @@ -650,7 +647,7 @@ struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode,  		return bh;  	if (buffer_uptodate(bh))  		return bh; -	ll_rw_block(READ_META, 1, &bh); +	ll_rw_block(READ | REQ_META | REQ_PRIO, 1, &bh);  	wait_on_buffer(bh);  	if (buffer_uptodate(bh))  		return bh; @@ -3301,7 +3298,7 @@ make_io:  		trace_ext4_load_inode(inode);  		get_bh(bh);  		bh->b_end_io = end_buffer_read_sync; -		submit_bh(READ_META, bh); +		submit_bh(READ | REQ_META | REQ_PRIO, bh);  		wait_on_buffer(bh);  		if (!buffer_uptodate(bh)) {  			EXT4_ERROR_INODE_BLOCK(inode, block, diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index f8068c7bae9..1c924faeb6c 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -922,7 +922,8 @@ restart:  				bh = ext4_getblk(NULL, dir, b++, 0, &err);  				bh_use[ra_max] = bh;  				if (bh) -					ll_rw_block(READ_META, 1, &bh); +					ll_rw_block(READ | REQ_META | REQ_PRIO, +						    1, &bh);  			}  		}  		if ((bh = bh_use[ra_ptr++]) == NULL) diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 78839af7ce2..92f38ee13f8 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -142,7 +142,23 @@ static void ext4_end_io_work(struct work_struct *work)  	unsigned long		flags;  	int			ret; -	mutex_lock(&inode->i_mutex); +	if (!mutex_trylock(&inode->i_mutex)) { +		/* +		 * Requeue the work instead of waiting so that the work +		 * items queued after this can be processed. +		 */ +		queue_work(EXT4_SB(inode->i_sb)->dio_unwritten_wq, &io->work); +		/* +		 * To prevent the ext4-dio-unwritten thread from keeping +		 * requeueing end_io requests and occupying cpu for too long, +		 * yield the cpu if it sees an end_io request that has already +		 * been requeued. +		 */ +		if (io->flag & EXT4_IO_END_QUEUED) +			yield(); +		io->flag |= EXT4_IO_END_QUEUED; +		return; +	}  	ret = ext4_end_io_nolock(io);  	if (ret < 0) {  		mutex_unlock(&inode->i_mutex); diff --git a/fs/ext4/xattr_security.c b/fs/ext4/xattr_security.c index 007c3bfbf09..34e4350dd4d 100644 --- a/fs/ext4/xattr_security.c +++ b/fs/ext4/xattr_security.c @@ -48,28 +48,32 @@ ext4_xattr_security_set(struct dentry *dentry, const char *name,  			      name, value, size, flags);  } -int -ext4_init_security(handle_t *handle, struct inode *inode, struct inode *dir, -		   const struct qstr *qstr) +int ext4_initxattrs(struct inode *inode, const struct xattr *xattr_array, +		    void *fs_info)  { -	int err; -	size_t len; -	void *value; -	char *name; +	const struct xattr *xattr; +	handle_t *handle = fs_info; +	int err = 0; -	err = security_inode_init_security(inode, dir, qstr, &name, &value, &len); -	if (err) { -		if (err == -EOPNOTSUPP) -			return 0; -		return err; +	for (xattr = xattr_array; xattr->name != NULL; xattr++) { +		err = ext4_xattr_set_handle(handle, inode, +					    EXT4_XATTR_INDEX_SECURITY, +					    xattr->name, xattr->value, +					    xattr->value_len, 0); +		if (err < 0) +			break;  	} -	err = ext4_xattr_set_handle(handle, inode, EXT4_XATTR_INDEX_SECURITY, -				    name, value, len, 0); -	kfree(name); -	kfree(value);  	return err;  } +int +ext4_init_security(handle_t *handle, struct inode *inode, struct inode *dir, +		   const struct qstr *qstr) +{ +	return security_inode_init_security(inode, dir, qstr, +					    &ext4_initxattrs, handle); +} +  const struct xattr_handler ext4_xattr_security_handler = {  	.prefix	= XATTR_SECURITY_PREFIX,  	.list	= ext4_xattr_security_list, diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 640fc229df1..5cb8614508c 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -258,10 +258,14 @@ void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget,  	forget->forget_one.nlookup = nlookup;  	spin_lock(&fc->lock); -	fc->forget_list_tail->next = forget; -	fc->forget_list_tail = forget; -	wake_up(&fc->waitq); -	kill_fasync(&fc->fasync, SIGIO, POLL_IN); +	if (fc->connected) { +		fc->forget_list_tail->next = forget; +		fc->forget_list_tail = forget; +		wake_up(&fc->waitq); +		kill_fasync(&fc->fasync, SIGIO, POLL_IN); +	} else { +		kfree(forget); +	}  	spin_unlock(&fc->lock);  } @@ -1358,6 +1362,10 @@ static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size,  	if (outarg.namelen > FUSE_NAME_MAX)  		goto err; +	err = -EINVAL; +	if (size != sizeof(outarg) + outarg.namelen + 1) +		goto err; +  	name.name = buf;  	name.len = outarg.namelen;  	err = fuse_copy_one(cs, buf, outarg.namelen + 1); diff --git a/fs/fuse/file.c b/fs/fuse/file.c index d480d9af46c..594f07a81c2 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -14,6 +14,7 @@  #include <linux/sched.h>  #include <linux/module.h>  #include <linux/compat.h> +#include <linux/swap.h>  static const struct file_operations fuse_direct_io_file_operations; @@ -245,6 +246,12 @@ void fuse_release_common(struct file *file, int opcode)  	req = ff->reserved_req;  	fuse_prepare_release(ff, file->f_flags, opcode); +	if (ff->flock) { +		struct fuse_release_in *inarg = &req->misc.release.in; +		inarg->release_flags |= FUSE_RELEASE_FLOCK_UNLOCK; +		inarg->lock_owner = fuse_lock_owner_id(ff->fc, +						       (fl_owner_t) file); +	}  	/* Hold vfsmount and dentry until release is finished */  	path_get(&file->f_path);  	req->misc.release.path = file->f_path; @@ -755,18 +762,6 @@ static size_t fuse_send_write(struct fuse_req *req, struct file *file,  	return req->misc.write.out.size;  } -static int fuse_write_begin(struct file *file, struct address_space *mapping, -			loff_t pos, unsigned len, unsigned flags, -			struct page **pagep, void **fsdata) -{ -	pgoff_t index = pos >> PAGE_CACHE_SHIFT; - -	*pagep = grab_cache_page_write_begin(mapping, index, flags); -	if (!*pagep) -		return -ENOMEM; -	return 0; -} -  void fuse_write_update_size(struct inode *inode, loff_t pos)  {  	struct fuse_conn *fc = get_fuse_conn(inode); @@ -779,62 +774,6 @@ void fuse_write_update_size(struct inode *inode, loff_t pos)  	spin_unlock(&fc->lock);  } -static int fuse_buffered_write(struct file *file, struct inode *inode, -			       loff_t pos, unsigned count, struct page *page) -{ -	int err; -	size_t nres; -	struct fuse_conn *fc = get_fuse_conn(inode); -	unsigned offset = pos & (PAGE_CACHE_SIZE - 1); -	struct fuse_req *req; - -	if (is_bad_inode(inode)) -		return -EIO; - -	/* -	 * Make sure writepages on the same page are not mixed up with -	 * plain writes. -	 */ -	fuse_wait_on_page_writeback(inode, page->index); - -	req = fuse_get_req(fc); -	if (IS_ERR(req)) -		return PTR_ERR(req); - -	req->in.argpages = 1; -	req->num_pages = 1; -	req->pages[0] = page; -	req->page_offset = offset; -	nres = fuse_send_write(req, file, pos, count, NULL); -	err = req->out.h.error; -	fuse_put_request(fc, req); -	if (!err && !nres) -		err = -EIO; -	if (!err) { -		pos += nres; -		fuse_write_update_size(inode, pos); -		if (count == PAGE_CACHE_SIZE) -			SetPageUptodate(page); -	} -	fuse_invalidate_attr(inode); -	return err ? err : nres; -} - -static int fuse_write_end(struct file *file, struct address_space *mapping, -			loff_t pos, unsigned len, unsigned copied, -			struct page *page, void *fsdata) -{ -	struct inode *inode = mapping->host; -	int res = 0; - -	if (copied) -		res = fuse_buffered_write(file, inode, pos, copied, page); - -	unlock_page(page); -	page_cache_release(page); -	return res; -} -  static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file,  				    struct inode *inode, loff_t pos,  				    size_t count) @@ -908,6 +847,8 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req,  		pagefault_enable();  		flush_dcache_page(page); +		mark_page_accessed(page); +  		if (!tmp) {  			unlock_page(page);  			page_cache_release(page); @@ -1559,11 +1500,14 @@ static int fuse_file_flock(struct file *file, int cmd, struct file_lock *fl)  	struct fuse_conn *fc = get_fuse_conn(inode);  	int err; -	if (fc->no_lock) { +	if (fc->no_flock) {  		err = flock_lock_file_wait(file, fl);  	} else { +		struct fuse_file *ff = file->private_data; +  		/* emulate flock with POSIX locks */  		fl->fl_owner = (fl_owner_t) file; +		ff->flock = true;  		err = fuse_setlk(file, fl, 1);  	} @@ -2201,8 +2145,6 @@ static const struct address_space_operations fuse_file_aops  = {  	.readpage	= fuse_readpage,  	.writepage	= fuse_writepage,  	.launder_page	= fuse_launder_page, -	.write_begin	= fuse_write_begin, -	.write_end	= fuse_write_end,  	.readpages	= fuse_readpages,  	.set_page_dirty	= __set_page_dirty_nobuffers,  	.bmap		= fuse_bmap, diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index c6aa2d4b851..cf6db0a9321 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -135,6 +135,9 @@ struct fuse_file {  	/** Wait queue head for poll */  	wait_queue_head_t poll_wait; + +	/** Has flock been performed on this file? */ +	bool flock:1;  };  /** One input argument of a request */ @@ -448,7 +451,7 @@ struct fuse_conn {  	/** Is removexattr not implemented by fs? */  	unsigned no_removexattr:1; -	/** Are file locking primitives not implemented by fs? */ +	/** Are posix file locking primitives not implemented by fs? */  	unsigned no_lock:1;  	/** Is access not implemented by fs? */ @@ -472,6 +475,9 @@ struct fuse_conn {  	/** Don't apply umask to creation modes */  	unsigned dont_mask:1; +	/** Are BSD file locking primitives not implemented by fs? */ +	unsigned no_flock:1; +  	/** The number of requests waiting for completion */  	atomic_t num_waiting; diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 38f84cd48b6..add96f6ffda 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -71,7 +71,7 @@ struct fuse_mount_data {  	unsigned blksize;  }; -struct fuse_forget_link *fuse_alloc_forget() +struct fuse_forget_link *fuse_alloc_forget(void)  {  	return kzalloc(sizeof(struct fuse_forget_link), GFP_KERNEL);  } @@ -809,6 +809,13 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)  				fc->async_read = 1;  			if (!(arg->flags & FUSE_POSIX_LOCKS))  				fc->no_lock = 1; +			if (arg->minor >= 17) { +				if (!(arg->flags & FUSE_FLOCK_LOCKS)) +					fc->no_flock = 1; +			} else { +				if (!(arg->flags & FUSE_POSIX_LOCKS)) +					fc->no_flock = 1; +			}  			if (arg->flags & FUSE_ATOMIC_O_TRUNC)  				fc->atomic_o_trunc = 1;  			if (arg->minor >= 9) { @@ -823,6 +830,7 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)  		} else {  			ra_pages = fc->max_read / PAGE_CACHE_SIZE;  			fc->no_lock = 1; +			fc->no_flock = 1;  		}  		fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages); @@ -843,7 +851,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)  	arg->minor = FUSE_KERNEL_MINOR_VERSION;  	arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE;  	arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | -		FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK; +		FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK | +		FUSE_FLOCK_LOCKS;  	req->in.h.opcode = FUSE_INIT;  	req->in.numargs = 1;  	req->in.args[0].size = sizeof(*arg); diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 900cf986aad..6525b804d5e 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -624,31 +624,29 @@ fail:  	return error;  } -static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip, -			      const struct qstr *qstr) +int gfs2_initxattrs(struct inode *inode, const struct xattr *xattr_array, +		    void *fs_info)  { -	int err; -	size_t len; -	void *value; -	char *name; - -	err = security_inode_init_security(&ip->i_inode, &dip->i_inode, qstr, -					   &name, &value, &len); +	const struct xattr *xattr; +	int err = 0; -	if (err) { -		if (err == -EOPNOTSUPP) -			return 0; -		return err; +	for (xattr = xattr_array; xattr->name != NULL; xattr++) { +		err = __gfs2_xattr_set(inode, xattr->name, xattr->value, +				       xattr->value_len, 0, +				       GFS2_EATYPE_SECURITY); +		if (err < 0) +			break;  	} - -	err = __gfs2_xattr_set(&ip->i_inode, name, value, len, 0, -			       GFS2_EATYPE_SECURITY); -	kfree(value); -	kfree(name); -  	return err;  } +static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip, +			      const struct qstr *qstr) +{ +	return security_inode_init_security(&ip->i_inode, &dip->i_inode, qstr, +					    &gfs2_initxattrs, NULL); +} +  /**   * gfs2_create_inode - Create a new inode   * @dir: The parent directory diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 85c62923ee2..59864643436 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -624,9 +624,9 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull)  	bh->b_end_io = end_buffer_write_sync;  	get_bh(bh);  	if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags)) -		submit_bh(WRITE_SYNC | REQ_META, bh); +		submit_bh(WRITE_SYNC | REQ_META | REQ_PRIO, bh);  	else -		submit_bh(WRITE_FLUSH_FUA | REQ_META, bh); +		submit_bh(WRITE_FLUSH_FUA | REQ_META | REQ_PRIO, bh);  	wait_on_buffer(bh);  	if (!buffer_uptodate(bh)) diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 747238cd9f9..be29858900f 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -37,7 +37,7 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb  {  	struct buffer_head *bh, *head;  	int nr_underway = 0; -	int write_op = REQ_META | +	int write_op = REQ_META | REQ_PRIO |  		(wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE);  	BUG_ON(!PageLocked(page)); @@ -225,7 +225,7 @@ int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,  	}  	bh->b_end_io = end_buffer_read_sync;  	get_bh(bh); -	submit_bh(READ_SYNC | REQ_META, bh); +	submit_bh(READ_SYNC | REQ_META | REQ_PRIO, bh);  	if (!(flags & DIO_WAIT))  		return 0; @@ -435,7 +435,7 @@ struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen)  	if (buffer_uptodate(first_bh))  		goto out;  	if (!buffer_locked(first_bh)) -		ll_rw_block(READ_SYNC | REQ_META, 1, &first_bh); +		ll_rw_block(READ_SYNC | REQ_META | REQ_PRIO, 1, &first_bh);  	dblock++;  	extlen--; diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 3bc073a4cf8..079587e5384 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -224,7 +224,7 @@ static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector, int silent)  	bio->bi_end_io = end_bio_io_page;  	bio->bi_private = page; -	submit_bio(READ_SYNC | REQ_META, bio); +	submit_bio(READ_SYNC | REQ_META | REQ_PRIO, bio);  	wait_on_page_locked(page);  	bio_put(bio);  	if (!PageUptodate(page)) { diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 42e8d23bc04..0e8bb13381e 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -709,7 +709,7 @@ get_a_page:  		set_buffer_uptodate(bh);  	if (!buffer_uptodate(bh)) { -		ll_rw_block(READ_META, 1, &bh); +		ll_rw_block(READ | REQ_META | REQ_PRIO, 1, &bh);  		wait_on_buffer(bh);  		if (!buffer_uptodate(bh))  			goto unlock_out; diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index c106ca22e81..d24a9b666a2 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -344,6 +344,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)  	struct inode *root, *inode;  	struct qstr str;  	struct nls_table *nls = NULL; +	u64 last_fs_block, last_fs_page;  	int err;  	err = -EINVAL; @@ -399,9 +400,13 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)  	if (!sbi->rsrc_clump_blocks)  		sbi->rsrc_clump_blocks = 1; -	err = generic_check_addressable(sbi->alloc_blksz_shift, -					sbi->total_blocks); -	if (err) { +	err = -EFBIG; +	last_fs_block = sbi->total_blocks - 1; +	last_fs_page = (last_fs_block << sbi->alloc_blksz_shift) >> +			PAGE_CACHE_SHIFT; + +	if ((last_fs_block > (sector_t)(~0ULL) >> (sbi->alloc_blksz_shift - 9)) || +	    (last_fs_page > (pgoff_t)(~0ULL))) {  		printk(KERN_ERR "hfs: filesystem size too large.\n");  		goto out_free_vhdr;  	} @@ -525,8 +530,8 @@ out_close_cat_tree:  out_close_ext_tree:  	hfs_btree_close(sbi->ext_tree);  out_free_vhdr: -	kfree(sbi->s_vhdr); -	kfree(sbi->s_backup_vhdr); +	kfree(sbi->s_vhdr_buf); +	kfree(sbi->s_backup_vhdr_buf);  out_unload_nls:  	unload_nls(sbi->nls);  	unload_nls(nls); diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c index 10e515a0d45..7daf4b852d1 100644 --- a/fs/hfsplus/wrapper.c +++ b/fs/hfsplus/wrapper.c @@ -272,9 +272,9 @@ reread:  	return 0;  out_free_backup_vhdr: -	kfree(sbi->s_backup_vhdr); +	kfree(sbi->s_backup_vhdr_buf);  out_free_vhdr: -	kfree(sbi->s_vhdr); +	kfree(sbi->s_vhdr_buf);  out:  	return error;  } diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 87b6e0421c1..ec889538e5a 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -491,6 +491,7 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid,  			inode->i_op = &page_symlink_inode_operations;  			break;  		} +		lockdep_annotate_inode_mutex_key(inode);  	}  	return inode;  } diff --git a/fs/inode.c b/fs/inode.c index 73920d555c8..ec7924696a1 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -848,16 +848,9 @@ struct inode *new_inode(struct super_block *sb)  }  EXPORT_SYMBOL(new_inode); -/** - * unlock_new_inode - clear the I_NEW state and wake up any waiters - * @inode:	new inode to unlock - * - * Called when the inode is fully initialised to clear the new state of the - * inode and wake up anyone waiting for the inode to finish initialisation. - */ -void unlock_new_inode(struct inode *inode) -{  #ifdef CONFIG_DEBUG_LOCK_ALLOC +void lockdep_annotate_inode_mutex_key(struct inode *inode) +{  	if (S_ISDIR(inode->i_mode)) {  		struct file_system_type *type = inode->i_sb->s_type; @@ -873,7 +866,20 @@ void unlock_new_inode(struct inode *inode)  					  &type->i_mutex_dir_key);  		}  	} +} +EXPORT_SYMBOL(lockdep_annotate_inode_mutex_key);  #endif + +/** + * unlock_new_inode - clear the I_NEW state and wake up any waiters + * @inode:	new inode to unlock + * + * Called when the inode is fully initialised to clear the new state of the + * inode and wake up anyone waiting for the inode to finish initialisation. + */ +void unlock_new_inode(struct inode *inode) +{ +	lockdep_annotate_inode_mutex_key(inode);  	spin_lock(&inode->i_lock);  	WARN_ON(!(inode->i_state & I_NEW));  	inode->i_state &= ~I_NEW; diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c index cfeb7164b08..0f20208df60 100644 --- a/fs/jffs2/security.c +++ b/fs/jffs2/security.c @@ -22,26 +22,29 @@  #include <linux/security.h>  #include "nodelist.h" -/* ---- Initial Security Label Attachment -------------- */ -int jffs2_init_security(struct inode *inode, struct inode *dir, -			const struct qstr *qstr) +/* ---- Initial Security Label(s) Attachment callback --- */ +int jffs2_initxattrs(struct inode *inode, const struct xattr *xattr_array, +		     void *fs_info)  { -	int rc; -	size_t len; -	void *value; -	char *name; +	const struct xattr *xattr; +	int err = 0; -	rc = security_inode_init_security(inode, dir, qstr, &name, &value, &len); -	if (rc) { -		if (rc == -EOPNOTSUPP) -			return 0; -		return rc; +	for (xattr = xattr_array; xattr->name != NULL; xattr++) { +		err = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, +					xattr->name, xattr->value, +					xattr->value_len, 0); +		if (err < 0) +			break;  	} -	rc = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, value, len, 0); +	return err; +} -	kfree(name); -	kfree(value); -	return rc; +/* ---- Initial Security Label(s) Attachment ----------- */ +int jffs2_init_security(struct inode *inode, struct inode *dir, +			const struct qstr *qstr) +{ +	return security_inode_init_security(inode, dir, qstr, +					    &jffs2_initxattrs, NULL);  }  /* ---- XATTR Handler for "security.*" ----------------- */ diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index e87fedef23d..26683e15b3a 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c @@ -1089,38 +1089,37 @@ int jfs_removexattr(struct dentry *dentry, const char *name)  }  #ifdef CONFIG_JFS_SECURITY -int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir, -		      const struct qstr *qstr) +int jfs_initxattrs(struct inode *inode, const struct xattr *xattr_array, +		   void *fs_info)  { -	int rc; -	size_t len; -	void *value; -	char *suffix; +	const struct xattr *xattr; +	tid_t *tid = fs_info;  	char *name; +	int err = 0; -	rc = security_inode_init_security(inode, dir, qstr, &suffix, &value, -					  &len); -	if (rc) { -		if (rc == -EOPNOTSUPP) -			return 0; -		return rc; -	} -	name = kmalloc(XATTR_SECURITY_PREFIX_LEN + 1 + strlen(suffix), -		       GFP_NOFS); -	if (!name) { -		rc = -ENOMEM; -		goto kmalloc_failed; -	} -	strcpy(name, XATTR_SECURITY_PREFIX); -	strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix); - -	rc = __jfs_setxattr(tid, inode, name, value, len, 0); +	for (xattr = xattr_array; xattr->name != NULL; xattr++) { +		name = kmalloc(XATTR_SECURITY_PREFIX_LEN + +			       strlen(xattr->name) + 1, GFP_NOFS); +		if (!name) { +			err = -ENOMEM; +			break; +		} +		strcpy(name, XATTR_SECURITY_PREFIX); +		strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name); -	kfree(name); -kmalloc_failed: -	kfree(suffix); -	kfree(value); +		err = __jfs_setxattr(*tid, inode, name, +				     xattr->value, xattr->value_len, 0); +		kfree(name); +		if (err < 0) +			break; +	} +	return err; +} -	return rc; +int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir, +		      const struct qstr *qstr) +{ +	return security_inode_init_security(inode, dir, qstr, +					    &jfs_initxattrs, &tid);  }  #endif diff --git a/fs/locks.c b/fs/locks.c index 703f545097d..96b33989147 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -60,7 +60,7 @@   *   *  Initial implementation of mandatory locks. SunOS turned out to be   *  a rotten model, so I implemented the "obvious" semantics. - *  See 'Documentation/mandatory.txt' for details. + *  See 'Documentation/filesystems/mandatory-locking.txt' for details.   *  Andy Walker (andy@lysaker.kvaerner.no), April 06, 1996.   *   *  Don't allow mandatory locks on mmap()'ed files. Added simple functions to diff --git a/fs/namei.c b/fs/namei.c index 2826db35dc2..0b3138de2a3 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -721,31 +721,22 @@ static int follow_automount(struct path *path, unsigned flags,  	if (!path->dentry->d_op || !path->dentry->d_op->d_automount)  		return -EREMOTE; -	/* We don't want to mount if someone supplied AT_NO_AUTOMOUNT -	 * and this is the terminal part of the path. +	/* We don't want to mount if someone's just doing a stat - +	 * unless they're stat'ing a directory and appended a '/' to +	 * the name. +	 * +	 * We do, however, want to mount if someone wants to open or +	 * create a file of any type under the mountpoint, wants to +	 * traverse through the mountpoint or wants to open the +	 * mounted directory.  Also, autofs may mark negative dentries +	 * as being automount points.  These will need the attentions +	 * of the daemon to instantiate them before they can be used.  	 */ -	if ((flags & LOOKUP_NO_AUTOMOUNT) && !(flags & LOOKUP_PARENT)) -		return -EISDIR; /* we actually want to stop here */ +	if (!(flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY | +		     LOOKUP_OPEN | LOOKUP_CREATE | LOOKUP_AUTOMOUNT)) && +	    path->dentry->d_inode) +		return -EISDIR; -	/* -	 * We don't want to mount if someone's just doing a stat and they've -	 * set AT_SYMLINK_NOFOLLOW - unless they're stat'ing a directory and -	 * appended a '/' to the name. -	 */ -	if (!(flags & LOOKUP_FOLLOW)) { -		/* We do, however, want to mount if someone wants to open or -		 * create a file of any type under the mountpoint, wants to -		 * traverse through the mountpoint or wants to open the mounted -		 * directory. -		 * Also, autofs may mark negative dentries as being automount -		 * points.  These will need the attentions of the daemon to -		 * instantiate them before they can be used. -		 */ -		if (!(flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY | -			     LOOKUP_OPEN | LOOKUP_CREATE)) && -		    path->dentry->d_inode) -			return -EISDIR; -	}  	current->total_link_count++;  	if (current->total_link_count >= 40)  		return -ELOOP; @@ -2619,6 +2610,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)  	if (!dir->i_op->rmdir)  		return -EPERM; +	dget(dentry);  	mutex_lock(&dentry->d_inode->i_mutex);  	error = -EBUSY; @@ -2639,6 +2631,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)  out:  	mutex_unlock(&dentry->d_inode->i_mutex); +	dput(dentry);  	if (!error)  		d_delete(dentry);  	return error; @@ -3028,6 +3021,7 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,  	if (error)  		return error; +	dget(new_dentry);  	if (target)  		mutex_lock(&target->i_mutex); @@ -3048,6 +3042,7 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,  out:  	if (target)  		mutex_unlock(&target->i_mutex); +	dput(new_dentry);  	if (!error)  		if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE))  			d_move(old_dentry,new_dentry); diff --git a/fs/namespace.c b/fs/namespace.c index 22bfe8273c6..b4febb29d3b 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1757,7 +1757,7 @@ static int do_loopback(struct path *path, char *old_name,  		return err;  	if (!old_name || !*old_name)  		return -EINVAL; -	err = kern_path(old_name, LOOKUP_FOLLOW, &old_path); +	err = kern_path(old_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);  	if (err)  		return err; diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 1ec1a85fa71..3e93e9a1bee 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -56,6 +56,9 @@ enum nfs4_session_state {  	NFS4_SESSION_DRAINING,  }; +#define NFS4_RENEW_TIMEOUT		0x01 +#define NFS4_RENEW_DELEGATION_CB	0x02 +  struct nfs4_minor_version_ops {  	u32	minor_version; @@ -225,7 +228,7 @@ struct nfs4_state_recovery_ops {  };  struct nfs4_state_maintenance_ops { -	int (*sched_state_renewal)(struct nfs_client *, struct rpc_cred *); +	int (*sched_state_renewal)(struct nfs_client *, struct rpc_cred *, unsigned);  	struct rpc_cred * (*get_state_renewal_cred_locked)(struct nfs_client *);  	int (*renew_lease)(struct nfs_client *, struct rpc_cred *);  }; @@ -237,8 +240,6 @@ extern const struct inode_operations nfs4_dir_inode_operations;  extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *);  extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *);  extern int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred); -extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *); -extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);  extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *);  extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *);  extern int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc); @@ -349,6 +350,7 @@ extern void nfs4_close_sync(struct nfs4_state *, fmode_t);  extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t);  extern void nfs4_schedule_lease_recovery(struct nfs_client *);  extern void nfs4_schedule_state_manager(struct nfs_client *); +extern void nfs4_schedule_path_down_recovery(struct nfs_client *clp);  extern void nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *);  extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags);  extern void nfs41_handle_recall_slot(struct nfs_client *clp); diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 8c77039e7a8..4700fae1ada 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3374,9 +3374,13 @@ static void nfs4_renew_done(struct rpc_task *task, void *calldata)  	if (task->tk_status < 0) {  		/* Unless we're shutting down, schedule state recovery! */ -		if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) != 0) +		if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) == 0) +			return; +		if (task->tk_status != NFS4ERR_CB_PATH_DOWN) {  			nfs4_schedule_lease_recovery(clp); -		return; +			return; +		} +		nfs4_schedule_path_down_recovery(clp);  	}  	do_renew_lease(clp, timestamp);  } @@ -3386,7 +3390,7 @@ static const struct rpc_call_ops nfs4_renew_ops = {  	.rpc_release = nfs4_renew_release,  }; -int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred) +static int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred, unsigned renew_flags)  {  	struct rpc_message msg = {  		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_RENEW], @@ -3395,9 +3399,11 @@ int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred)  	};  	struct nfs4_renewdata *data; +	if (renew_flags == 0) +		return 0;  	if (!atomic_inc_not_zero(&clp->cl_count))  		return -EIO; -	data = kmalloc(sizeof(*data), GFP_KERNEL); +	data = kmalloc(sizeof(*data), GFP_NOFS);  	if (data == NULL)  		return -ENOMEM;  	data->client = clp; @@ -3406,7 +3412,7 @@ int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred)  			&nfs4_renew_ops, data);  } -int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred) +static int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred)  {  	struct rpc_message msg = {  		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_RENEW], @@ -5504,11 +5510,13 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_  	return rpc_run_task(&task_setup_data);  } -static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cred) +static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cred, unsigned renew_flags)  {  	struct rpc_task *task;  	int ret = 0; +	if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0) +		return 0;  	task = _nfs41_proc_sequence(clp, cred);  	if (IS_ERR(task))  		ret = PTR_ERR(task); diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c index df8e7f3ca56..dc484c0eae7 100644 --- a/fs/nfs/nfs4renewd.c +++ b/fs/nfs/nfs4renewd.c @@ -60,6 +60,7 @@ nfs4_renew_state(struct work_struct *work)  	struct rpc_cred *cred;  	long lease;  	unsigned long last, now; +	unsigned renew_flags = 0;  	ops = clp->cl_mvops->state_renewal_ops;  	dprintk("%s: start\n", __func__); @@ -72,18 +73,23 @@ nfs4_renew_state(struct work_struct *work)  	last = clp->cl_last_renewal;  	now = jiffies;  	/* Are we close to a lease timeout? */ -	if (time_after(now, last + lease/3)) { +	if (time_after(now, last + lease/3)) +		renew_flags |= NFS4_RENEW_TIMEOUT; +	if (nfs_delegations_present(clp)) +		renew_flags |= NFS4_RENEW_DELEGATION_CB; + +	if (renew_flags != 0) {  		cred = ops->get_state_renewal_cred_locked(clp);  		spin_unlock(&clp->cl_lock);  		if (cred == NULL) { -			if (!nfs_delegations_present(clp)) { +			if (!(renew_flags & NFS4_RENEW_DELEGATION_CB)) {  				set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);  				goto out;  			}  			nfs_expire_all_delegations(clp);  		} else {  			/* Queue an asynchronous RENEW. */ -			ops->sched_state_renewal(clp, cred); +			ops->sched_state_renewal(clp, cred, renew_flags);  			put_rpccred(cred);  			goto out_exp;  		} diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 72ab97ef3d6..39914be40b0 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1038,6 +1038,12 @@ void nfs4_schedule_lease_recovery(struct nfs_client *clp)  	nfs4_schedule_state_manager(clp);  } +void nfs4_schedule_path_down_recovery(struct nfs_client *clp) +{ +	nfs_handle_cb_pathdown(clp); +	nfs4_schedule_state_manager(clp); +} +  static int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state)  { diff --git a/fs/nfs/super.c b/fs/nfs/super.c index b961ceac66b..5b19b6aabe1 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -2035,9 +2035,6 @@ static inline void nfs_initialise_sb(struct super_block *sb)  		sb->s_blocksize = nfs_block_bits(server->wsize,  						 &sb->s_blocksize_bits); -	if (server->flags & NFS_MOUNT_NOAC) -		sb->s_flags |= MS_SYNCHRONOUS; -  	sb->s_bdi = &server->backing_dev_info;  	nfs_super_set_maxbytes(sb, server->maxfilesize); @@ -2249,6 +2246,10 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,  	if (server->flags & NFS_MOUNT_UNSHARED)  		compare_super = NULL; +	/* -o noac implies -o sync */ +	if (server->flags & NFS_MOUNT_NOAC) +		sb_mntdata.mntflags |= MS_SYNCHRONOUS; +  	/* Get a superblock - note that we may end up sharing one that already exists */  	s = sget(fs_type, compare_super, nfs_set_super, &sb_mntdata);  	if (IS_ERR(s)) { @@ -2361,6 +2362,10 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,  	if (server->flags & NFS_MOUNT_UNSHARED)  		compare_super = NULL; +	/* -o noac implies -o sync */ +	if (server->flags & NFS_MOUNT_NOAC) +		sb_mntdata.mntflags |= MS_SYNCHRONOUS; +  	/* Get a superblock - note that we may end up sharing one that already exists */  	s = sget(&nfs_fs_type, compare_super, nfs_set_super, &sb_mntdata);  	if (IS_ERR(s)) { @@ -2628,6 +2633,10 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags,  	if (server->flags & NFS4_MOUNT_UNSHARED)  		compare_super = NULL; +	/* -o noac implies -o sync */ +	if (server->flags & NFS_MOUNT_NOAC) +		sb_mntdata.mntflags |= MS_SYNCHRONOUS; +  	/* Get a superblock - note that we may end up sharing one that already exists */  	s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata);  	if (IS_ERR(s)) { @@ -2789,7 +2798,7 @@ static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt,  		goto out_put_mnt_ns;  	ret = vfs_path_lookup(root_mnt->mnt_root, root_mnt, -			export_path, LOOKUP_FOLLOW, &path); +			export_path, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path);  	nfs_referral_loop_unprotect();  	put_mnt_ns(ns_private); @@ -2916,6 +2925,10 @@ nfs4_xdev_mount(struct file_system_type *fs_type, int flags,  	if (server->flags & NFS4_MOUNT_UNSHARED)  		compare_super = NULL; +	/* -o noac implies -o sync */ +	if (server->flags & NFS_MOUNT_NOAC) +		sb_mntdata.mntflags |= MS_SYNCHRONOUS; +  	/* Get a superblock - note that we may end up sharing one that already exists */  	s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata);  	if (IS_ERR(s)) { @@ -3003,6 +3016,10 @@ nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,  	if (server->flags & NFS4_MOUNT_UNSHARED)  		compare_super = NULL; +	/* -o noac implies -o sync */ +	if (server->flags & NFS_MOUNT_NOAC) +		sb_mntdata.mntflags |= MS_SYNCHRONOUS; +  	/* Get a superblock - note that we may end up sharing one that already exists */  	s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata);  	if (IS_ERR(s)) { diff --git a/fs/nfs/write.c b/fs/nfs/write.c index b39b37f8091..c9bd2a6b7d4 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -958,7 +958,7 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc, struct list_head  		if (!data)  			goto out_bad;  		data->pagevec[0] = page; -		nfs_write_rpcsetup(req, data, wsize, offset, desc->pg_ioflags); +		nfs_write_rpcsetup(req, data, len, offset, desc->pg_ioflags);  		list_add(&data->list, res);  		requests++;  		nbytes -= len; diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 81ecf9c0bf0..194fb22ef79 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -7185,20 +7185,9 @@ int ocfs2_init_security_and_acl(struct inode *dir,  {  	int ret = 0;  	struct buffer_head *dir_bh = NULL; -	struct ocfs2_security_xattr_info si = { -		.enable = 1, -	}; -	ret = ocfs2_init_security_get(inode, dir, qstr, &si); +	ret = ocfs2_init_security_get(inode, dir, qstr, NULL);  	if (!ret) { -		ret = ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY, -				      si.name, si.value, si.value_len, -				      XATTR_CREATE); -		if (ret) { -			mlog_errno(ret); -			goto leave; -		} -	} else if (ret != -EOPNOTSUPP) {  		mlog_errno(ret);  		goto leave;  	} @@ -7255,6 +7244,22 @@ static int ocfs2_xattr_security_set(struct dentry *dentry, const char *name,  			       name, value, size, flags);  } +int ocfs2_initxattrs(struct inode *inode, const struct xattr *xattr_array, +		     void *fs_info) +{ +	const struct xattr *xattr; +	int err = 0; + +	for (xattr = xattr_array; xattr->name != NULL; xattr++) { +		err = ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY, +				      xattr->name, xattr->value, +				      xattr->value_len, XATTR_CREATE); +		if (err) +			break; +	} +	return err; +} +  int ocfs2_init_security_get(struct inode *inode,  			    struct inode *dir,  			    const struct qstr *qstr, @@ -7263,8 +7268,13 @@ int ocfs2_init_security_get(struct inode *inode,  	/* check whether ocfs2 support feature xattr */  	if (!ocfs2_supports_xattr(OCFS2_SB(dir->i_sb)))  		return -EOPNOTSUPP; -	return security_inode_init_security(inode, dir, qstr, &si->name, -					    &si->value, &si->value_len); +	if (si) +		return security_old_inode_init_security(inode, dir, qstr, +							&si->name, &si->value, +							&si->value_len); + +	return security_inode_init_security(inode, dir, qstr, +					    &ocfs2_initxattrs, NULL);  }  int ocfs2_init_security_set(handle_t *handle, diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 25b6a887adb..5afaa58a863 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -877,30 +877,54 @@ struct numa_maps_private {  	struct numa_maps md;  }; -static void gather_stats(struct page *page, struct numa_maps *md, int pte_dirty) +static void gather_stats(struct page *page, struct numa_maps *md, int pte_dirty, +			unsigned long nr_pages)  {  	int count = page_mapcount(page); -	md->pages++; +	md->pages += nr_pages;  	if (pte_dirty || PageDirty(page)) -		md->dirty++; +		md->dirty += nr_pages;  	if (PageSwapCache(page)) -		md->swapcache++; +		md->swapcache += nr_pages;  	if (PageActive(page) || PageUnevictable(page)) -		md->active++; +		md->active += nr_pages;  	if (PageWriteback(page)) -		md->writeback++; +		md->writeback += nr_pages;  	if (PageAnon(page)) -		md->anon++; +		md->anon += nr_pages;  	if (count > md->mapcount_max)  		md->mapcount_max = count; -	md->node[page_to_nid(page)]++; +	md->node[page_to_nid(page)] += nr_pages; +} + +static struct page *can_gather_numa_stats(pte_t pte, struct vm_area_struct *vma, +		unsigned long addr) +{ +	struct page *page; +	int nid; + +	if (!pte_present(pte)) +		return NULL; + +	page = vm_normal_page(vma, addr, pte); +	if (!page) +		return NULL; + +	if (PageReserved(page)) +		return NULL; + +	nid = page_to_nid(page); +	if (!node_isset(nid, node_states[N_HIGH_MEMORY])) +		return NULL; + +	return page;  }  static int gather_pte_stats(pmd_t *pmd, unsigned long addr, @@ -912,26 +936,32 @@ static int gather_pte_stats(pmd_t *pmd, unsigned long addr,  	pte_t *pte;  	md = walk->private; -	orig_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl); -	do { -		struct page *page; -		int nid; +	spin_lock(&walk->mm->page_table_lock); +	if (pmd_trans_huge(*pmd)) { +		if (pmd_trans_splitting(*pmd)) { +			spin_unlock(&walk->mm->page_table_lock); +			wait_split_huge_page(md->vma->anon_vma, pmd); +		} else { +			pte_t huge_pte = *(pte_t *)pmd; +			struct page *page; -		if (!pte_present(*pte)) -			continue; +			page = can_gather_numa_stats(huge_pte, md->vma, addr); +			if (page) +				gather_stats(page, md, pte_dirty(huge_pte), +						HPAGE_PMD_SIZE/PAGE_SIZE); +			spin_unlock(&walk->mm->page_table_lock); +			return 0; +		} +	} else { +		spin_unlock(&walk->mm->page_table_lock); +	} -		page = vm_normal_page(md->vma, addr, *pte); +	orig_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl); +	do { +		struct page *page = can_gather_numa_stats(*pte, md->vma, addr);  		if (!page)  			continue; - -		if (PageReserved(page)) -			continue; - -		nid = page_to_nid(page); -		if (!node_isset(nid, node_states[N_HIGH_MEMORY])) -			continue; - -		gather_stats(page, md, pte_dirty(*pte)); +		gather_stats(page, md, pte_dirty(*pte), 1);  	} while (pte++, addr += PAGE_SIZE, addr != end);  	pte_unmap_unlock(orig_pte, ptl); @@ -952,7 +982,7 @@ static int gather_hugetbl_stats(pte_t *pte, unsigned long hmask,  		return 0;  	md = walk->private; -	gather_stats(page, md, pte_dirty(*pte)); +	gather_stats(page, md, pte_dirty(*pte), 1);  	return 0;  } diff --git a/fs/quota/quota.c b/fs/quota/quota.c index b34bdb25490..10b6be3ca28 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c @@ -355,7 +355,7 @@ SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,  	 * resolution (think about autofs) and thus deadlocks could arise.  	 */  	if (cmds == Q_QUOTAON) { -		ret = user_path_at(AT_FDCWD, addr, LOOKUP_FOLLOW, &path); +		ret = user_path_at(AT_FDCWD, addr, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path);  		if (ret)  			pathp = ERR_PTR(ret);  		else diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index a159ba5a35e..eb711060a6f 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -291,14 +291,13 @@ int reiserfs_allocate_list_bitmaps(struct super_block *sb,  	for (i = 0; i < JOURNAL_NUM_BITMAPS; i++) {  		jb = jb_array + i;  		jb->journal_list = NULL; -		jb->bitmaps = vmalloc(mem); +		jb->bitmaps = vzalloc(mem);  		if (!jb->bitmaps) {  			reiserfs_warning(sb, "clm-2000", "unable to "  					 "allocate bitmaps for journal lists");  			failed = 1;  			break;  		} -		memset(jb->bitmaps, 0, mem);  	}  	if (failed) {  		free_list_bitmaps(sb, jb_array); @@ -353,11 +352,10 @@ static struct reiserfs_journal_cnode *allocate_cnodes(int num_cnodes)  	if (num_cnodes <= 0) {  		return NULL;  	} -	head = vmalloc(num_cnodes * sizeof(struct reiserfs_journal_cnode)); +	head = vzalloc(num_cnodes * sizeof(struct reiserfs_journal_cnode));  	if (!head) {  		return NULL;  	} -	memset(head, 0, num_cnodes * sizeof(struct reiserfs_journal_cnode));  	head[0].prev = NULL;  	head[0].next = head + 1;  	for (i = 1; i < num_cnodes; i++) { @@ -2685,14 +2683,13 @@ int journal_init(struct super_block *sb, const char *j_dev_name,  	 * dependency inversion warnings.  	 */  	reiserfs_write_unlock(sb); -	journal = SB_JOURNAL(sb) = vmalloc(sizeof(struct reiserfs_journal)); +	journal = SB_JOURNAL(sb) = vzalloc(sizeof(struct reiserfs_journal));  	if (!journal) {  		reiserfs_warning(sb, "journal-1256",  				 "unable to get memory for journal structure");  		reiserfs_write_lock(sb);  		return 1;  	} -	memset(journal, 0, sizeof(struct reiserfs_journal));  	INIT_LIST_HEAD(&journal->j_bitmap_nodes);  	INIT_LIST_HEAD(&journal->j_prealloc_list);  	INIT_LIST_HEAD(&journal->j_working_list); diff --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c index b6b9b1fe33b..7483279b482 100644 --- a/fs/reiserfs/resize.c +++ b/fs/reiserfs/resize.c @@ -111,15 +111,13 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)  		/* allocate additional bitmap blocks, reallocate array of bitmap  		 * block pointers */  		bitmap = -		    vmalloc(sizeof(struct reiserfs_bitmap_info) * bmap_nr_new); +		    vzalloc(sizeof(struct reiserfs_bitmap_info) * bmap_nr_new);  		if (!bitmap) {  			/* Journal bitmaps are still supersized, but the memory isn't  			 * leaked, so I guess it's ok */  			printk("reiserfs_resize: unable to allocate memory.\n");  			return -ENOMEM;  		} -		memset(bitmap, 0, -		       sizeof(struct reiserfs_bitmap_info) * bmap_nr_new);  		for (i = 0; i < bmap_nr; i++)  			bitmap[i] = old_bitmap[i]; diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c index ef66c18a933..534668fa41b 100644 --- a/fs/reiserfs/xattr_security.c +++ b/fs/reiserfs/xattr_security.c @@ -66,8 +66,8 @@ int reiserfs_security_init(struct inode *dir, struct inode *inode,  	if (IS_PRIVATE(dir))  		return 0; -	error = security_inode_init_security(inode, dir, qstr, &sec->name, -					     &sec->value, &sec->length); +	error = security_old_inode_init_security(inode, dir, qstr, &sec->name, +						 &sec->value, &sec->length);  	if (error) {  		if (error == -EOPNOTSUPP)  			error = 0; diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig index 1360d4f88f4..048b59d5b2f 100644 --- a/fs/squashfs/Kconfig +++ b/fs/squashfs/Kconfig @@ -19,9 +19,9 @@ config SQUASHFS  	  If you want to compile this as a module ( = code which can be  	  inserted in and removed from the running kernel whenever you want), -	  say M here and read <file:Documentation/modules.txt>.  The module -	  will be called squashfs.  Note that the root file system (the one -	  containing the directory /) cannot be compiled as a module. +	  say M here.  The module will be called squashfs.  Note that the root +	  file system (the one containing the directory /) cannot be compiled +	  as a module.  	  If unsure, say N. diff --git a/fs/stat.c b/fs/stat.c index ba5316ffac6..78a3aa83c7e 100644 --- a/fs/stat.c +++ b/fs/stat.c @@ -81,8 +81,6 @@ int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,  	if (!(flag & AT_SYMLINK_NOFOLLOW))  		lookup_flags |= LOOKUP_FOLLOW; -	if (flag & AT_NO_AUTOMOUNT) -		lookup_flags |= LOOKUP_NO_AUTOMOUNT;  	if (flag & AT_EMPTY_PATH)  		lookup_flags |= LOOKUP_EMPTY; diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h index 45174b53437..feb361e252a 100644 --- a/fs/ubifs/debug.h +++ b/fs/ubifs/debug.h @@ -335,9 +335,9 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c);  #define DBGKEY(key)  ((char *)(key))  #define DBGKEY1(key) ((char *)(key)) -#define ubifs_dbg_msg(fmt, ...) do {               \ -	if (0)                                     \ -		pr_debug(fmt "\n", ##__VA_ARGS__); \ +#define ubifs_dbg_msg(fmt, ...) do {                        \ +	if (0)                                              \ +		printk(KERN_DEBUG fmt "\n", ##__VA_ARGS__); \  } while (0)  #define dbg_dump_stack() diff --git a/fs/xattr.c b/fs/xattr.c index f060663ab70..67583de8218 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -14,6 +14,7 @@  #include <linux/mount.h>  #include <linux/namei.h>  #include <linux/security.h> +#include <linux/evm.h>  #include <linux/syscalls.h>  #include <linux/module.h>  #include <linux/fsnotify.h> @@ -166,6 +167,64 @@ out_noalloc:  }  EXPORT_SYMBOL_GPL(xattr_getsecurity); +/* + * vfs_getxattr_alloc - allocate memory, if necessary, before calling getxattr + * + * Allocate memory, if not already allocated, or re-allocate correct size, + * before retrieving the extended attribute. + * + * Returns the result of alloc, if failed, or the getxattr operation. + */ +ssize_t +vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value, +		   size_t xattr_size, gfp_t flags) +{ +	struct inode *inode = dentry->d_inode; +	char *value = *xattr_value; +	int error; + +	error = xattr_permission(inode, name, MAY_READ); +	if (error) +		return error; + +	if (!inode->i_op->getxattr) +		return -EOPNOTSUPP; + +	error = inode->i_op->getxattr(dentry, name, NULL, 0); +	if (error < 0) +		return error; + +	if (!value || (error > xattr_size)) { +		value = krealloc(*xattr_value, error + 1, flags); +		if (!value) +			return -ENOMEM; +		memset(value, 0, error + 1); +	} + +	error = inode->i_op->getxattr(dentry, name, value, error); +	*xattr_value = value; +	return error; +} + +/* Compare an extended attribute value with the given value */ +int vfs_xattr_cmp(struct dentry *dentry, const char *xattr_name, +		  const char *value, size_t size, gfp_t flags) +{ +	char *xattr_value = NULL; +	int rc; + +	rc = vfs_getxattr_alloc(dentry, xattr_name, &xattr_value, 0, flags); +	if (rc < 0) +		return rc; + +	if ((rc != size) || (memcmp(xattr_value, value, rc) != 0)) +		rc = -EINVAL; +	else +		rc = 0; +	kfree(xattr_value); +	return rc; +} +  ssize_t  vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)  { @@ -243,8 +302,10 @@ vfs_removexattr(struct dentry *dentry, const char *name)  	error = inode->i_op->removexattr(dentry, name);  	mutex_unlock(&inode->i_mutex); -	if (!error) +	if (!error) {  		fsnotify_xattr(dentry); +		evm_inode_post_removexattr(dentry, name); +	}  	return error;  }  EXPORT_SYMBOL_GPL(vfs_removexattr); diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 75bb316529d..427a4e82a58 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -16,44 +16,53 @@  # Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA  # -ccflags-y := -I$(src) -I$(src)/linux-2.6 -ccflags-$(CONFIG_XFS_DEBUG) += -g +ccflags-y += -I$(src)			# needed for trace events -XFS_LINUX := linux-2.6 +ccflags-$(CONFIG_XFS_DEBUG) += -g  obj-$(CONFIG_XFS_FS)		+= xfs.o -xfs-y				+= linux-2.6/xfs_trace.o - -xfs-$(CONFIG_XFS_QUOTA)		+= $(addprefix quota/, \ -				   xfs_dquot.o \ -				   xfs_dquot_item.o \ -				   xfs_trans_dquot.o \ -				   xfs_qm_syscalls.o \ -				   xfs_qm_bhv.o \ -				   xfs_qm.o) -xfs-$(CONFIG_XFS_QUOTA)		+= linux-2.6/xfs_quotaops.o - -ifeq ($(CONFIG_XFS_QUOTA),y) -xfs-$(CONFIG_PROC_FS)		+= quota/xfs_qm_stats.o -endif - -xfs-$(CONFIG_XFS_RT)		+= xfs_rtalloc.o -xfs-$(CONFIG_XFS_POSIX_ACL)	+= $(XFS_LINUX)/xfs_acl.o -xfs-$(CONFIG_PROC_FS)		+= $(XFS_LINUX)/xfs_stats.o -xfs-$(CONFIG_SYSCTL)		+= $(XFS_LINUX)/xfs_sysctl.o -xfs-$(CONFIG_COMPAT)		+= $(XFS_LINUX)/xfs_ioctl32.o +# this one should be compiled first, as the tracing macros can easily blow up +xfs-y				+= xfs_trace.o +# highlevel code +xfs-y				+= xfs_aops.o \ +				   xfs_bit.o \ +				   xfs_buf.o \ +				   xfs_dfrag.o \ +				   xfs_discard.o \ +				   xfs_error.o \ +				   xfs_export.o \ +				   xfs_file.o \ +				   xfs_filestream.o \ +				   xfs_fsops.o \ +				   xfs_fs_subr.o \ +				   xfs_globals.o \ +				   xfs_iget.o \ +				   xfs_ioctl.o \ +				   xfs_iomap.o \ +				   xfs_iops.o \ +				   xfs_itable.o \ +				   xfs_message.o \ +				   xfs_mru_cache.o \ +				   xfs_super.o \ +				   xfs_sync.o \ +				   xfs_xattr.o \ +				   xfs_rename.o \ +				   xfs_rw.o \ +				   xfs_utils.o \ +				   xfs_vnodeops.o \ +				   kmem.o \ +				   uuid.o +# code shared with libxfs  xfs-y				+= xfs_alloc.o \  				   xfs_alloc_btree.o \  				   xfs_attr.o \  				   xfs_attr_leaf.o \ -				   xfs_bit.o \  				   xfs_bmap.o \  				   xfs_bmap_btree.o \  				   xfs_btree.o \ -				   xfs_buf_item.o \  				   xfs_da_btree.o \  				   xfs_dir2.o \  				   xfs_dir2_block.o \ @@ -61,49 +70,37 @@ xfs-y				+= xfs_alloc.o \  				   xfs_dir2_leaf.o \  				   xfs_dir2_node.o \  				   xfs_dir2_sf.o \ -				   xfs_error.o \ -				   xfs_extfree_item.o \ -				   xfs_filestream.o \ -				   xfs_fsops.o \  				   xfs_ialloc.o \  				   xfs_ialloc_btree.o \ -				   xfs_iget.o \  				   xfs_inode.o \ -				   xfs_inode_item.o \ -				   xfs_iomap.o \ -				   xfs_itable.o \ -				   xfs_dfrag.o \ -				   xfs_log.o \ -				   xfs_log_cil.o \  				   xfs_log_recover.o \  				   xfs_mount.o \ -				   xfs_mru_cache.o \ -				   xfs_rename.o \ -				   xfs_trans.o \ +				   xfs_trans.o + +# low-level transaction/log code +xfs-y				+= xfs_log.o \ +				   xfs_log_cil.o \ +				   xfs_buf_item.o \ +				   xfs_extfree_item.o \ +				   xfs_inode_item.o \  				   xfs_trans_ail.o \  				   xfs_trans_buf.o \  				   xfs_trans_extfree.o \  				   xfs_trans_inode.o \ -				   xfs_utils.o \ -				   xfs_vnodeops.o \ -				   xfs_rw.o - -# Objects in linux/ -xfs-y				+= $(addprefix $(XFS_LINUX)/, \ -				   kmem.o \ -				   xfs_aops.o \ -				   xfs_buf.o \ -				   xfs_discard.o \ -				   xfs_export.o \ -				   xfs_file.o \ -				   xfs_fs_subr.o \ -				   xfs_globals.o \ -				   xfs_ioctl.o \ -				   xfs_iops.o \ -				   xfs_message.o \ -				   xfs_super.o \ -				   xfs_sync.o \ -				   xfs_xattr.o) -# Objects in support/ -xfs-y				+= support/uuid.o +# optional features +xfs-$(CONFIG_XFS_QUOTA)		+= xfs_dquot.o \ +				   xfs_dquot_item.o \ +				   xfs_trans_dquot.o \ +				   xfs_qm_syscalls.o \ +				   xfs_qm_bhv.o \ +				   xfs_qm.o \ +				   xfs_quotaops.o +ifeq ($(CONFIG_XFS_QUOTA),y) +xfs-$(CONFIG_PROC_FS)		+= xfs_qm_stats.o +endif +xfs-$(CONFIG_XFS_RT)		+= xfs_rtalloc.o +xfs-$(CONFIG_XFS_POSIX_ACL)	+= xfs_acl.o +xfs-$(CONFIG_PROC_FS)		+= xfs_stats.o +xfs-$(CONFIG_SYSCTL)		+= xfs_sysctl.o +xfs-$(CONFIG_COMPAT)		+= xfs_ioctl32.o diff --git a/fs/xfs/linux-2.6/kmem.c b/fs/xfs/kmem.c index a907de565db..a907de565db 100644 --- a/fs/xfs/linux-2.6/kmem.c +++ b/fs/xfs/kmem.c diff --git a/fs/xfs/linux-2.6/kmem.h b/fs/xfs/kmem.h index f7c8f7a9ea6..292eff19803 100644 --- a/fs/xfs/linux-2.6/kmem.h +++ b/fs/xfs/kmem.h @@ -61,12 +61,7 @@ extern void  kmem_free(const void *);  static inline void *kmem_zalloc_large(size_t size)  { -	void *ptr; - -	ptr = vmalloc(size); -	if (ptr) -		memset(ptr, 0, size); -	return ptr; +	return vzalloc(size);  }  static inline void kmem_free_large(void *ptr)  { diff --git a/fs/xfs/linux-2.6/mrlock.h b/fs/xfs/mrlock.h index ff6a19873e5..ff6a19873e5 100644 --- a/fs/xfs/linux-2.6/mrlock.h +++ b/fs/xfs/mrlock.h diff --git a/fs/xfs/linux-2.6/time.h b/fs/xfs/time.h index 387e695a184..387e695a184 100644 --- a/fs/xfs/linux-2.6/time.h +++ b/fs/xfs/time.h diff --git a/fs/xfs/support/uuid.c b/fs/xfs/uuid.c index b83f76b6d41..b83f76b6d41 100644 --- a/fs/xfs/support/uuid.c +++ b/fs/xfs/uuid.c diff --git a/fs/xfs/support/uuid.h b/fs/xfs/uuid.h index 4732d71262c..4732d71262c 100644 --- a/fs/xfs/support/uuid.h +++ b/fs/xfs/uuid.h diff --git a/fs/xfs/xfs.h b/fs/xfs/xfs.h index 53ec3ea9a62..d8b11b7f94a 100644 --- a/fs/xfs/xfs.h +++ b/fs/xfs/xfs.h @@ -24,5 +24,6 @@  #define XFS_BUF_LOCK_TRACKING 1  #endif -#include <linux-2.6/xfs_linux.h> +#include "xfs_linux.h" +  #endif	/* __XFS_H__ */ diff --git a/fs/xfs/linux-2.6/xfs_acl.c b/fs/xfs/xfs_acl.c index b6c4b3795c4..b6c4b3795c4 100644 --- a/fs/xfs/linux-2.6/xfs_acl.c +++ b/fs/xfs/xfs_acl.c diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/xfs_aops.c index 63e971e2b83..8c37dde4c52 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -1300,6 +1300,7 @@ xfs_end_io_direct_write(  	bool			is_async)  {  	struct xfs_ioend	*ioend = iocb->private; +	struct inode		*inode = ioend->io_inode;  	/*  	 * blockdev_direct_IO can return an error even after the I/O @@ -1331,7 +1332,7 @@ xfs_end_io_direct_write(  	}  	/* XXX: probably should move into the real I/O completion handler */ -	inode_dio_done(ioend->io_inode); +	inode_dio_done(inode);  }  STATIC ssize_t diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/xfs_aops.h index 71f721e1a71..71f721e1a71 100644 --- a/fs/xfs/linux-2.6/xfs_aops.h +++ b/fs/xfs/xfs_aops.h diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/xfs_buf.c index c57836dc778..c57836dc778 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/xfs_buf.c diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/xfs_buf.h index 620972b8094..620972b8094 100644 --- a/fs/xfs/linux-2.6/xfs_buf.h +++ b/fs/xfs/xfs_buf.h diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index cac2ecfa674..ef43fce519a 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -629,7 +629,7 @@ xfs_buf_item_push(   * the xfsbufd to get this buffer written. We have to unlock the buffer   * to allow the xfsbufd to write it, too.   */ -STATIC void +STATIC bool  xfs_buf_item_pushbuf(  	struct xfs_log_item	*lip)  { @@ -643,6 +643,7 @@ xfs_buf_item_pushbuf(  	xfs_buf_delwri_promote(bp);  	xfs_buf_relse(bp); +	return true;  }  STATIC void diff --git a/fs/xfs/linux-2.6/xfs_discard.c b/fs/xfs/xfs_discard.c index 244e797dae3..244e797dae3 100644 --- a/fs/xfs/linux-2.6/xfs_discard.c +++ b/fs/xfs/xfs_discard.c diff --git a/fs/xfs/linux-2.6/xfs_discard.h b/fs/xfs/xfs_discard.h index 344879aea64..344879aea64 100644 --- a/fs/xfs/linux-2.6/xfs_discard.h +++ b/fs/xfs/xfs_discard.h diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/xfs_dquot.c index db62959bed1..db62959bed1 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/xfs_dquot.h index 34b7e945dbf..34b7e945dbf 100644 --- a/fs/xfs/quota/xfs_dquot.h +++ b/fs/xfs/xfs_dquot.h diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/xfs_dquot_item.c index 9e0e2fa3f2c..bb3f71d236d 100644 --- a/fs/xfs/quota/xfs_dquot_item.c +++ b/fs/xfs/xfs_dquot_item.c @@ -183,13 +183,14 @@ xfs_qm_dqunpin_wait(   * search the buffer cache can be a time consuming thing, and AIL lock is a   * spinlock.   */ -STATIC void +STATIC bool  xfs_qm_dquot_logitem_pushbuf(  	struct xfs_log_item	*lip)  {  	struct xfs_dq_logitem	*qlip = DQUOT_ITEM(lip);  	struct xfs_dquot	*dqp = qlip->qli_dquot;  	struct xfs_buf		*bp; +	bool			ret = true;  	ASSERT(XFS_DQ_IS_LOCKED(dqp)); @@ -201,17 +202,20 @@ xfs_qm_dquot_logitem_pushbuf(  	if (completion_done(&dqp->q_flush) ||  	    !(lip->li_flags & XFS_LI_IN_AIL)) {  		xfs_dqunlock(dqp); -		return; +		return true;  	}  	bp = xfs_incore(dqp->q_mount->m_ddev_targp, qlip->qli_format.qlf_blkno,  			dqp->q_mount->m_quotainfo->qi_dqchunklen, XBF_TRYLOCK);  	xfs_dqunlock(dqp);  	if (!bp) -		return; +		return true;  	if (XFS_BUF_ISDELAYWRITE(bp))  		xfs_buf_delwri_promote(bp); +	if (xfs_buf_ispinned(bp)) +		ret = false;  	xfs_buf_relse(bp); +	return ret;  }  /* diff --git a/fs/xfs/quota/xfs_dquot_item.h b/fs/xfs/xfs_dquot_item.h index 5acae2ada70..5acae2ada70 100644 --- a/fs/xfs/quota/xfs_dquot_item.h +++ b/fs/xfs/xfs_dquot_item.h diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/xfs_export.c index 75e5d322e48..75e5d322e48 100644 --- a/fs/xfs/linux-2.6/xfs_export.c +++ b/fs/xfs/xfs_export.c diff --git a/fs/xfs/linux-2.6/xfs_export.h b/fs/xfs/xfs_export.h index 3272b6ae7a3..3272b6ae7a3 100644 --- a/fs/xfs/linux-2.6/xfs_export.h +++ b/fs/xfs/xfs_export.h diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/xfs_file.c index 7f7b42469ea..7f7b42469ea 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/xfs_file.c diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/xfs_fs_subr.c index ed88ed16811..ed88ed16811 100644 --- a/fs/xfs/linux-2.6/xfs_fs_subr.c +++ b/fs/xfs/xfs_fs_subr.c diff --git a/fs/xfs/linux-2.6/xfs_globals.c b/fs/xfs/xfs_globals.c index 76e81cff70b..76e81cff70b 100644 --- a/fs/xfs/linux-2.6/xfs_globals.c +++ b/fs/xfs/xfs_globals.c diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 588406dc6a3..836ad80d4f2 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -708,13 +708,14 @@ xfs_inode_item_committed(   * marked delayed write. If that's the case, we'll promote it and that will   * allow the caller to write the buffer by triggering the xfsbufd to run.   */ -STATIC void +STATIC bool  xfs_inode_item_pushbuf(  	struct xfs_log_item	*lip)  {  	struct xfs_inode_log_item *iip = INODE_ITEM(lip);  	struct xfs_inode	*ip = iip->ili_inode;  	struct xfs_buf		*bp; +	bool			ret = true;  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED)); @@ -725,7 +726,7 @@ xfs_inode_item_pushbuf(  	if (completion_done(&ip->i_flush) ||  	    !(lip->li_flags & XFS_LI_IN_AIL)) {  		xfs_iunlock(ip, XFS_ILOCK_SHARED); -		return; +		return true;  	}  	bp = xfs_incore(ip->i_mount->m_ddev_targp, iip->ili_format.ilf_blkno, @@ -733,10 +734,13 @@ xfs_inode_item_pushbuf(  	xfs_iunlock(ip, XFS_ILOCK_SHARED);  	if (!bp) -		return; +		return true;  	if (XFS_BUF_ISDELAYWRITE(bp))  		xfs_buf_delwri_promote(bp); +	if (xfs_buf_ispinned(bp)) +		ret = false;  	xfs_buf_relse(bp); +	return ret;  }  /* diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index f7ce7debe14..f7ce7debe14 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c diff --git a/fs/xfs/linux-2.6/xfs_ioctl.h b/fs/xfs/xfs_ioctl.h index d56173b34a2..d56173b34a2 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.h +++ b/fs/xfs/xfs_ioctl.h diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c index 54e623bfbb8..54e623bfbb8 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.c +++ b/fs/xfs/xfs_ioctl32.c diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.h b/fs/xfs/xfs_ioctl32.h index 80f4060e897..80f4060e897 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.h +++ b/fs/xfs/xfs_ioctl32.h diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/xfs_iops.c index b9c172b3fbb..28856accb4f 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -70,9 +70,8 @@ xfs_synchronize_times(  }  /* - * If the linux inode is valid, mark it dirty. - * Used when committing a dirty inode into a transaction so that - * the inode will get written back by the linux code + * If the linux inode is valid, mark it dirty, else mark the dirty state + * in the XFS inode to make sure we pick it up when reclaiming the inode.   */  void  xfs_mark_inode_dirty_sync( @@ -82,6 +81,10 @@ xfs_mark_inode_dirty_sync(  	if (!(inode->i_state & (I_WILL_FREE|I_FREEING)))  		mark_inode_dirty_sync(inode); +	else { +		barrier(); +		ip->i_update_core = 1; +	}  }  void @@ -92,6 +95,28 @@ xfs_mark_inode_dirty(  	if (!(inode->i_state & (I_WILL_FREE|I_FREEING)))  		mark_inode_dirty(inode); +	else { +		barrier(); +		ip->i_update_core = 1; +	} + +} + + +int xfs_initxattrs(struct inode *inode, const struct xattr *xattr_array, +		   void *fs_info) +{ +	const struct xattr *xattr; +	struct xfs_inode *ip = XFS_I(inode); +	int error = 0; + +	for (xattr = xattr_array; xattr->name != NULL; xattr++) { +		error = xfs_attr_set(ip, xattr->name, xattr->value, +				     xattr->value_len, ATTR_SECURE); +		if (error < 0) +			break; +	} +	return error;  }  /* @@ -100,31 +125,15 @@ xfs_mark_inode_dirty(   * these attrs can be journalled at inode creation time (along with the   * inode, of course, such that log replay can't cause these to be lost).   */ +  STATIC int  xfs_init_security(  	struct inode	*inode,  	struct inode	*dir,  	const struct qstr *qstr)  { -	struct xfs_inode *ip = XFS_I(inode); -	size_t		length; -	void		*value; -	unsigned char	*name; -	int		error; - -	error = security_inode_init_security(inode, dir, qstr, (char **)&name, -					     &value, &length); -	if (error) { -		if (error == -EOPNOTSUPP) -			return 0; -		return -error; -	} - -	error = xfs_attr_set(ip, name, value, length, ATTR_SECURE); - -	kfree(name); -	kfree(value); -	return error; +	return security_inode_init_security(inode, dir, qstr, +					    &xfs_initxattrs, NULL);  }  static void diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/xfs_iops.h index ef41c92ce66..ef41c92ce66 100644 --- a/fs/xfs/linux-2.6/xfs_iops.h +++ b/fs/xfs/xfs_iops.h diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/xfs_linux.h index d42f814e4d3..828662f70d6 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/xfs_linux.h @@ -32,13 +32,12 @@  # define XFS_BIG_INUMS	0  #endif -#include <xfs_types.h> +#include "xfs_types.h" -#include <kmem.h> -#include <mrlock.h> -#include <time.h> - -#include <support/uuid.h> +#include "kmem.h" +#include "mrlock.h" +#include "time.h" +#include "uuid.h"  #include <linux/semaphore.h>  #include <linux/mm.h> @@ -69,6 +68,8 @@  #include <linux/ctype.h>  #include <linux/writeback.h>  #include <linux/capability.h> +#include <linux/kthread.h> +#include <linux/freezer.h>  #include <linux/list_sort.h>  #include <asm/page.h> @@ -78,14 +79,14 @@  #include <asm/byteorder.h>  #include <asm/unaligned.h> -#include <xfs_vnode.h> -#include <xfs_stats.h> -#include <xfs_sysctl.h> -#include <xfs_iops.h> -#include <xfs_aops.h> -#include <xfs_super.h> -#include <xfs_buf.h> -#include <xfs_message.h> +#include "xfs_vnode.h" +#include "xfs_stats.h" +#include "xfs_sysctl.h" +#include "xfs_iops.h" +#include "xfs_aops.h" +#include "xfs_super.h" +#include "xfs_buf.h" +#include "xfs_message.h"  #ifdef __BIG_ENDIAN  #define XFS_NATIVE_HOST 1 diff --git a/fs/xfs/linux-2.6/xfs_message.c b/fs/xfs/xfs_message.c index bd672def95a..bd672def95a 100644 --- a/fs/xfs/linux-2.6/xfs_message.c +++ b/fs/xfs/xfs_message.c diff --git a/fs/xfs/linux-2.6/xfs_message.h b/fs/xfs/xfs_message.h index 7fb7ea00767..7fb7ea00767 100644 --- a/fs/xfs/linux-2.6/xfs_message.h +++ b/fs/xfs/xfs_message.h diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/xfs_qm.c index 9a0aa76facd..9a0aa76facd 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/xfs_qm.c diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/xfs_qm.h index 43b9abe1052..43b9abe1052 100644 --- a/fs/xfs/quota/xfs_qm.h +++ b/fs/xfs/xfs_qm.h diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/xfs_qm_bhv.c index a0a829addca..a0a829addca 100644 --- a/fs/xfs/quota/xfs_qm_bhv.c +++ b/fs/xfs/xfs_qm_bhv.c diff --git a/fs/xfs/quota/xfs_qm_stats.c b/fs/xfs/xfs_qm_stats.c index 8671a0b3264..8671a0b3264 100644 --- a/fs/xfs/quota/xfs_qm_stats.c +++ b/fs/xfs/xfs_qm_stats.c diff --git a/fs/xfs/quota/xfs_qm_stats.h b/fs/xfs/xfs_qm_stats.h index 5b964fc0dc0..5b964fc0dc0 100644 --- a/fs/xfs/quota/xfs_qm_stats.h +++ b/fs/xfs/xfs_qm_stats.h diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c index 609246f42e6..609246f42e6 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/xfs_qm_syscalls.c diff --git a/fs/xfs/quota/xfs_quota_priv.h b/fs/xfs/xfs_quota_priv.h index 94a3d927d71..94a3d927d71 100644 --- a/fs/xfs/quota/xfs_quota_priv.h +++ b/fs/xfs/xfs_quota_priv.h diff --git a/fs/xfs/linux-2.6/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c index 29b9d642e93..7e76f537abb 100644 --- a/fs/xfs/linux-2.6/xfs_quotaops.c +++ b/fs/xfs/xfs_quotaops.c @@ -25,7 +25,7 @@  #include "xfs_trans.h"  #include "xfs_bmap_btree.h"  #include "xfs_inode.h" -#include "quota/xfs_qm.h" +#include "xfs_qm.h"  #include <linux/quota.h> diff --git a/fs/xfs/linux-2.6/xfs_stats.c b/fs/xfs/xfs_stats.c index 76fdc586193..76fdc586193 100644 --- a/fs/xfs/linux-2.6/xfs_stats.c +++ b/fs/xfs/xfs_stats.c diff --git a/fs/xfs/linux-2.6/xfs_stats.h b/fs/xfs/xfs_stats.h index 736854b1ca1..736854b1ca1 100644 --- a/fs/xfs/linux-2.6/xfs_stats.h +++ b/fs/xfs/xfs_stats.h diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/xfs_super.c index 9a72dda58bd..5cf06b85fd9 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -356,6 +356,8 @@ xfs_parseargs(  			mp->m_flags |= XFS_MOUNT_DELAYLOG;  		} else if (!strcmp(this_char, MNTOPT_NODELAYLOG)) {  			mp->m_flags &= ~XFS_MOUNT_DELAYLOG; +			xfs_warn(mp, +	"nodelaylog is deprecated and will be removed in Linux 3.3");  		} else if (!strcmp(this_char, MNTOPT_DISCARD)) {  			mp->m_flags |= XFS_MOUNT_DISCARD;  		} else if (!strcmp(this_char, MNTOPT_NODISCARD)) { @@ -877,33 +879,17 @@ xfs_log_inode(  	struct xfs_trans	*tp;  	int			error; -	xfs_iunlock(ip, XFS_ILOCK_SHARED);  	tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS);  	error = xfs_trans_reserve(tp, 0, XFS_FSYNC_TS_LOG_RES(mp), 0, 0, 0); -  	if (error) {  		xfs_trans_cancel(tp, 0); -		/* we need to return with the lock hold shared */ -		xfs_ilock(ip, XFS_ILOCK_SHARED);  		return error;  	}  	xfs_ilock(ip, XFS_ILOCK_EXCL); - -	/* -	 * Note - it's possible that we might have pushed ourselves out of the -	 * way during trans_reserve which would flush the inode.  But there's -	 * no guarantee that the inode buffer has actually gone out yet (it's -	 * delwri).  Plus the buffer could be pinned anyway if it's part of -	 * an inode in another recent transaction.  So we play it safe and -	 * fire off the transaction anyway. -	 */ -	xfs_trans_ijoin(tp, ip); +	xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL);  	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); -	error = xfs_trans_commit(tp, 0); -	xfs_ilock_demote(ip, XFS_ILOCK_EXCL); - -	return error; +	return xfs_trans_commit(tp, 0);  }  STATIC int @@ -918,7 +904,9 @@ xfs_fs_write_inode(  	trace_xfs_write_inode(ip);  	if (XFS_FORCED_SHUTDOWN(mp)) -		return XFS_ERROR(EIO); +		return -XFS_ERROR(EIO); +	if (!ip->i_update_core) +		return 0;  	if (wbc->sync_mode == WB_SYNC_ALL) {  		/* @@ -929,12 +917,10 @@ xfs_fs_write_inode(  		 * of synchronous log foces dramatically.  		 */  		xfs_ioend_wait(ip); -		xfs_ilock(ip, XFS_ILOCK_SHARED); -		if (ip->i_update_core) { -			error = xfs_log_inode(ip); -			if (error) -				goto out_unlock; -		} +		error = xfs_log_inode(ip); +		if (error) +			goto out; +		return 0;  	} else {  		/*  		 * We make this non-blocking if the inode is contended, return @@ -1666,24 +1652,13 @@ xfs_init_workqueues(void)  	 */  	xfs_syncd_wq = alloc_workqueue("xfssyncd", WQ_CPU_INTENSIVE, 8);  	if (!xfs_syncd_wq) -		goto out; - -	xfs_ail_wq = alloc_workqueue("xfsail", WQ_CPU_INTENSIVE, 8); -	if (!xfs_ail_wq) -		goto out_destroy_syncd; - +		return -ENOMEM;  	return 0; - -out_destroy_syncd: -	destroy_workqueue(xfs_syncd_wq); -out: -	return -ENOMEM;  }  STATIC void  xfs_destroy_workqueues(void)  { -	destroy_workqueue(xfs_ail_wq);  	destroy_workqueue(xfs_syncd_wq);  } diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/xfs_super.h index 50a3266c999..50a3266c999 100644 --- a/fs/xfs/linux-2.6/xfs_super.h +++ b/fs/xfs/xfs_super.h diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/xfs_sync.c index 4604f90f86a..4604f90f86a 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/xfs_sync.c diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/xfs_sync.h index 941202e7ac6..941202e7ac6 100644 --- a/fs/xfs/linux-2.6/xfs_sync.h +++ b/fs/xfs/xfs_sync.h diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/xfs_sysctl.c index ee2d2adaa43..ee2d2adaa43 100644 --- a/fs/xfs/linux-2.6/xfs_sysctl.c +++ b/fs/xfs/xfs_sysctl.c diff --git a/fs/xfs/linux-2.6/xfs_sysctl.h b/fs/xfs/xfs_sysctl.h index b9937d450f8..b9937d450f8 100644 --- a/fs/xfs/linux-2.6/xfs_sysctl.h +++ b/fs/xfs/xfs_sysctl.h diff --git a/fs/xfs/linux-2.6/xfs_trace.c b/fs/xfs/xfs_trace.c index 88d25d4aa56..9010ce885e6 100644 --- a/fs/xfs/linux-2.6/xfs_trace.c +++ b/fs/xfs/xfs_trace.c @@ -43,8 +43,8 @@  #include "xfs_quota.h"  #include "xfs_iomap.h"  #include "xfs_aops.h" -#include "quota/xfs_dquot_item.h" -#include "quota/xfs_dquot.h" +#include "xfs_dquot_item.h" +#include "xfs_dquot.h"  #include "xfs_log_recover.h"  #include "xfs_inode_item.h" diff --git a/fs/xfs/linux-2.6/xfs_trace.h b/fs/xfs/xfs_trace.h index 690fc7a7bd7..690fc7a7bd7 100644 --- a/fs/xfs/linux-2.6/xfs_trace.h +++ b/fs/xfs/xfs_trace.h diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 06a9759b635..53597f4db9b 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -350,7 +350,7 @@ typedef struct xfs_item_ops {  	void (*iop_unlock)(xfs_log_item_t *);  	xfs_lsn_t (*iop_committed)(xfs_log_item_t *, xfs_lsn_t);  	void (*iop_push)(xfs_log_item_t *); -	void (*iop_pushbuf)(xfs_log_item_t *); +	bool (*iop_pushbuf)(xfs_log_item_t *);  	void (*iop_committing)(xfs_log_item_t *, xfs_lsn_t);  } xfs_item_ops_t; diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index c15aa29fa16..3a1e7ca54c2 100644 --- a/fs/xfs/xfs_trans_ail.c +++ b/fs/xfs/xfs_trans_ail.c @@ -28,8 +28,6 @@  #include "xfs_trans_priv.h"  #include "xfs_error.h" -struct workqueue_struct	*xfs_ail_wq;	/* AIL workqueue */ -  #ifdef DEBUG  /*   * Check that the list is sorted as it should be. @@ -356,16 +354,10 @@ xfs_ail_delete(  	xfs_trans_ail_cursor_clear(ailp, lip);  } -/* - * xfs_ail_worker does the work of pushing on the AIL. It will requeue itself - * to run at a later time if there is more work to do to complete the push. - */ -STATIC void -xfs_ail_worker( -	struct work_struct	*work) +static long +xfsaild_push( +	struct xfs_ail		*ailp)  { -	struct xfs_ail		*ailp = container_of(to_delayed_work(work), -					struct xfs_ail, xa_work);  	xfs_mount_t		*mp = ailp->xa_mount;  	struct xfs_ail_cursor	cur;  	xfs_log_item_t		*lip; @@ -427,8 +419,13 @@ xfs_ail_worker(  		case XFS_ITEM_PUSHBUF:  			XFS_STATS_INC(xs_push_ail_pushbuf); -			IOP_PUSHBUF(lip); -			ailp->xa_last_pushed_lsn = lsn; + +			if (!IOP_PUSHBUF(lip)) { +				stuck++; +				flush_log = 1; +			} else { +				ailp->xa_last_pushed_lsn = lsn; +			}  			push_xfsbufd = 1;  			break; @@ -440,7 +437,6 @@ xfs_ail_worker(  		case XFS_ITEM_LOCKED:  			XFS_STATS_INC(xs_push_ail_locked); -			ailp->xa_last_pushed_lsn = lsn;  			stuck++;  			break; @@ -501,20 +497,6 @@ out_done:  		/* We're past our target or empty, so idle */  		ailp->xa_last_pushed_lsn = 0; -		/* -		 * We clear the XFS_AIL_PUSHING_BIT first before checking -		 * whether the target has changed. If the target has changed, -		 * this pushes the requeue race directly onto the result of the -		 * atomic test/set bit, so we are guaranteed that either the -		 * the pusher that changed the target or ourselves will requeue -		 * the work (but not both). -		 */ -		clear_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags); -		smp_rmb(); -		if (XFS_LSN_CMP(ailp->xa_target, target) == 0 || -		    test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags)) -			return; -  		tout = 50;  	} else if (XFS_LSN_CMP(lsn, target) >= 0) {  		/* @@ -537,9 +519,30 @@ out_done:  		tout = 20;  	} -	/* There is more to do, requeue us.  */ -	queue_delayed_work(xfs_syncd_wq, &ailp->xa_work, -					msecs_to_jiffies(tout)); +	return tout; +} + +static int +xfsaild( +	void		*data) +{ +	struct xfs_ail	*ailp = data; +	long		tout = 0;	/* milliseconds */ + +	while (!kthread_should_stop()) { +		if (tout && tout <= 20) +			__set_current_state(TASK_KILLABLE); +		else +			__set_current_state(TASK_INTERRUPTIBLE); +		schedule_timeout(tout ? +				 msecs_to_jiffies(tout) : MAX_SCHEDULE_TIMEOUT); + +		try_to_freeze(); + +		tout = xfsaild_push(ailp); +	} + +	return 0;  }  /* @@ -574,8 +577,9 @@ xfs_ail_push(  	 */  	smp_wmb();  	xfs_trans_ail_copy_lsn(ailp, &ailp->xa_target, &threshold_lsn); -	if (!test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags)) -		queue_delayed_work(xfs_syncd_wq, &ailp->xa_work, 0); +	smp_wmb(); + +	wake_up_process(ailp->xa_task);  }  /* @@ -813,9 +817,18 @@ xfs_trans_ail_init(  	INIT_LIST_HEAD(&ailp->xa_ail);  	INIT_LIST_HEAD(&ailp->xa_cursors);  	spin_lock_init(&ailp->xa_lock); -	INIT_DELAYED_WORK(&ailp->xa_work, xfs_ail_worker); + +	ailp->xa_task = kthread_run(xfsaild, ailp, "xfsaild/%s", +			ailp->xa_mount->m_fsname); +	if (IS_ERR(ailp->xa_task)) +		goto out_free_ailp; +  	mp->m_ail = ailp;  	return 0; + +out_free_ailp: +	kmem_free(ailp); +	return ENOMEM;  }  void @@ -824,6 +837,6 @@ xfs_trans_ail_destroy(  {  	struct xfs_ail	*ailp = mp->m_ail; -	cancel_delayed_work_sync(&ailp->xa_work); +	kthread_stop(ailp->xa_task);  	kmem_free(ailp);  } diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c index 4d00ee67792..4d00ee67792 100644 --- a/fs/xfs/quota/xfs_trans_dquot.c +++ b/fs/xfs/xfs_trans_dquot.c diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h index 212946b9723..22750b5e4a8 100644 --- a/fs/xfs/xfs_trans_priv.h +++ b/fs/xfs/xfs_trans_priv.h @@ -64,23 +64,17 @@ struct xfs_ail_cursor {   */  struct xfs_ail {  	struct xfs_mount	*xa_mount; +	struct task_struct	*xa_task;  	struct list_head	xa_ail;  	xfs_lsn_t		xa_target;  	struct list_head	xa_cursors;  	spinlock_t		xa_lock; -	struct delayed_work	xa_work;  	xfs_lsn_t		xa_last_pushed_lsn; -	unsigned long		xa_flags;  }; -#define XFS_AIL_PUSHING_BIT	0 -  /*   * From xfs_trans_ail.c   */ - -extern struct workqueue_struct	*xfs_ail_wq;	/* AIL workqueue */ -  void	xfs_trans_ail_update_bulk(struct xfs_ail *ailp,  				struct xfs_ail_cursor *cur,  				struct xfs_log_item **log_items, int nr_items, diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/xfs_vnode.h index 7c220b4227b..7c220b4227b 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/xfs_vnode.h diff --git a/fs/xfs/linux-2.6/xfs_xattr.c b/fs/xfs/xfs_xattr.c index 87d3e03878c..87d3e03878c 100644 --- a/fs/xfs/linux-2.6/xfs_xattr.c +++ b/fs/xfs/xfs_xattr.c  |