Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a2ccb68b authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'akpm' (patches from Andrew)

Merge fixes from Andrew Morton:
 "4 fixes"

* emailed patches from Andrew Morton <akpm@linux-foundation.org>:
  mm: thp: calculate the mapcount correctly for THP pages during WP faults
  ksm: fix conflict between mmput and scan_get_next_rmap_item
  ocfs2: fix posix_acl_create deadlock
  ocfs2: revert using ocfs2_acl_chmod to avoid inode cluster lock hang
parents 02c9c0e9 6d0a07ed
Loading
Loading
Loading
Loading
+87 −0
Original line number Diff line number Diff line
@@ -322,3 +322,90 @@ struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type)
	brelse(di_bh);
	return acl;
}

int ocfs2_acl_chmod(struct inode *inode, struct buffer_head *bh)
{
	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
	struct posix_acl *acl;
	int ret;

	if (S_ISLNK(inode->i_mode))
		return -EOPNOTSUPP;

	if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
		return 0;

	acl = ocfs2_get_acl_nolock(inode, ACL_TYPE_ACCESS, bh);
	if (IS_ERR(acl) || !acl)
		return PTR_ERR(acl);
	ret = __posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
	if (ret)
		return ret;
	ret = ocfs2_set_acl(NULL, inode, NULL, ACL_TYPE_ACCESS,
			    acl, NULL, NULL);
	posix_acl_release(acl);
	return ret;
}

/*
 * Initialize the ACLs of a new inode. If parent directory has default ACL,
 * then clone to new inode. Called from ocfs2_mknod.
 */
int ocfs2_init_acl(handle_t *handle,
		   struct inode *inode,
		   struct inode *dir,
		   struct buffer_head *di_bh,
		   struct buffer_head *dir_bh,
		   struct ocfs2_alloc_context *meta_ac,
		   struct ocfs2_alloc_context *data_ac)
{
	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
	struct posix_acl *acl = NULL;
	int ret = 0, ret2;
	umode_t mode;

	if (!S_ISLNK(inode->i_mode)) {
		if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) {
			acl = ocfs2_get_acl_nolock(dir, ACL_TYPE_DEFAULT,
						   dir_bh);
			if (IS_ERR(acl))
				return PTR_ERR(acl);
		}
		if (!acl) {
			mode = inode->i_mode & ~current_umask();
			ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
			if (ret) {
				mlog_errno(ret);
				goto cleanup;
			}
		}
	}
	if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) {
		if (S_ISDIR(inode->i_mode)) {
			ret = ocfs2_set_acl(handle, inode, di_bh,
					    ACL_TYPE_DEFAULT, acl,
					    meta_ac, data_ac);
			if (ret)
				goto cleanup;
		}
		mode = inode->i_mode;
		ret = __posix_acl_create(&acl, GFP_NOFS, &mode);
		if (ret < 0)
			return ret;

		ret2 = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
		if (ret2) {
			mlog_errno(ret2);
			ret = ret2;
			goto cleanup;
		}
		if (ret > 0) {
			ret = ocfs2_set_acl(handle, inode,
					    di_bh, ACL_TYPE_ACCESS,
					    acl, meta_ac, data_ac);
		}
	}
cleanup:
	posix_acl_release(acl);
	return ret;
}
+5 −0
Original line number Diff line number Diff line
@@ -35,5 +35,10 @@ int ocfs2_set_acl(handle_t *handle,
			 struct posix_acl *acl,
			 struct ocfs2_alloc_context *meta_ac,
			 struct ocfs2_alloc_context *data_ac);
extern int ocfs2_acl_chmod(struct inode *, struct buffer_head *);
extern int ocfs2_init_acl(handle_t *, struct inode *, struct inode *,
			  struct buffer_head *, struct buffer_head *,
			  struct ocfs2_alloc_context *,
			  struct ocfs2_alloc_context *);

#endif /* OCFS2_ACL_H */
+2 −2
Original line number Diff line number Diff line
@@ -1268,20 +1268,20 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
	if (size_change)
		ocfs2_rw_unlock(inode, 1);
bail:
	brelse(bh);

	/* Release quota pointers in case we acquired them */
	for (qtype = 0; qtype < OCFS2_MAXQUOTAS; qtype++)
		dqput(transfer_to[qtype]);

	if (!status && attr->ia_valid & ATTR_MODE) {
		status = posix_acl_chmod(inode, inode->i_mode);
		status = ocfs2_acl_chmod(inode, bh);
		if (status < 0)
			mlog_errno(status);
	}
	if (inode_locked)
		ocfs2_inode_unlock(inode, 1);

	brelse(bh);
	return status;
}

+2 −21
Original line number Diff line number Diff line
@@ -259,7 +259,6 @@ static int ocfs2_mknod(struct inode *dir,
	struct ocfs2_dir_lookup_result lookup = { NULL, };
	sigset_t oldset;
	int did_block_signals = 0;
	struct posix_acl *default_acl = NULL, *acl = NULL;
	struct ocfs2_dentry_lock *dl = NULL;

	trace_ocfs2_mknod(dir, dentry, dentry->d_name.len, dentry->d_name.name,
@@ -367,12 +366,6 @@ static int ocfs2_mknod(struct inode *dir,
		goto leave;
	}

	status = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
	if (status) {
		mlog_errno(status);
		goto leave;
	}

	handle = ocfs2_start_trans(osb, ocfs2_mknod_credits(osb->sb,
							    S_ISDIR(mode),
							    xattr_credits));
@@ -421,16 +414,8 @@ static int ocfs2_mknod(struct inode *dir,
		inc_nlink(dir);
	}

	if (default_acl) {
		status = ocfs2_set_acl(handle, inode, new_fe_bh,
				       ACL_TYPE_DEFAULT, default_acl,
				       meta_ac, data_ac);
	}
	if (!status && acl) {
		status = ocfs2_set_acl(handle, inode, new_fe_bh,
				       ACL_TYPE_ACCESS, acl,
	status = ocfs2_init_acl(handle, inode, dir, new_fe_bh, parent_fe_bh,
			 meta_ac, data_ac);
	}

	if (status < 0) {
		mlog_errno(status);
@@ -472,10 +457,6 @@ static int ocfs2_mknod(struct inode *dir,
	d_instantiate(dentry, inode);
	status = 0;
leave:
	if (default_acl)
		posix_acl_release(default_acl);
	if (acl)
		posix_acl_release(acl);
	if (status < 0 && did_quota_inode)
		dquot_free_inode(inode);
	if (handle)
+2 −15
Original line number Diff line number Diff line
@@ -4248,20 +4248,12 @@ static int ocfs2_reflink(struct dentry *old_dentry, struct inode *dir,
	struct inode *inode = d_inode(old_dentry);
	struct buffer_head *old_bh = NULL;
	struct inode *new_orphan_inode = NULL;
	struct posix_acl *default_acl, *acl;
	umode_t mode;

	if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb)))
		return -EOPNOTSUPP;

	mode = inode->i_mode;
	error = posix_acl_create(dir, &mode, &default_acl, &acl);
	if (error) {
		mlog_errno(error);
		return error;
	}

	error = ocfs2_create_inode_in_orphan(dir, mode,
	error = ocfs2_create_inode_in_orphan(dir, inode->i_mode,
					     &new_orphan_inode);
	if (error) {
		mlog_errno(error);
@@ -4300,16 +4292,11 @@ static int ocfs2_reflink(struct dentry *old_dentry, struct inode *dir,
	/* If the security isn't preserved, we need to re-initialize them. */
	if (!preserve) {
		error = ocfs2_init_security_and_acl(dir, new_orphan_inode,
						    &new_dentry->d_name,
						    default_acl, acl);
						    &new_dentry->d_name);
		if (error)
			mlog_errno(error);
	}
out:
	if (default_acl)
		posix_acl_release(default_acl);
	if (acl)
		posix_acl_release(acl);
	if (!error) {
		error = ocfs2_mv_orphaned_inode_to_new(dir, new_orphan_inode,
						       new_dentry);
Loading