summary refs log tree commit diff
path: root/fs/gfs2/acl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2/acl.c')
-rw-r--r--fs/gfs2/acl.c58
1 files changed, 47 insertions, 11 deletions
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index 791932617d1a..363ba9e9d8d0 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -24,6 +24,7 @@
 #include "glock.h"
 #include "inode.h"
 #include "meta_io.h"
+#include "rgrp.h"
 #include "trans.h"
 #include "util.h"
 
@@ -38,7 +39,7 @@ static const char *gfs2_acl_name(int type)
 	return NULL;
 }
 
-struct posix_acl *gfs2_get_acl(struct inode *inode, int type)
+static struct posix_acl *__gfs2_get_acl(struct inode *inode, int type)
 {
 	struct gfs2_inode *ip = GFS2_I(inode);
 	struct posix_acl *acl;
@@ -50,29 +51,41 @@ struct posix_acl *gfs2_get_acl(struct inode *inode, int type)
 		return NULL;
 
 	name = gfs2_acl_name(type);
-	if (name == NULL)
-		return ERR_PTR(-EINVAL);
-
 	len = gfs2_xattr_acl_get(ip, name, &data);
-	if (len < 0)
+	if (len <= 0)
 		return ERR_PTR(len);
-	if (len == 0)
-		return NULL;
-
 	acl = posix_acl_from_xattr(&init_user_ns, data, len);
 	kfree(data);
 	return acl;
 }
 
-int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
+struct posix_acl *gfs2_get_acl(struct inode *inode, int type)
+{
+	struct gfs2_inode *ip = GFS2_I(inode);
+	struct gfs2_holder gh;
+	bool need_unlock = false;
+	struct posix_acl *acl;
+
+	if (!gfs2_glock_is_locked_by_me(ip->i_gl)) {
+		int ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED,
+					     LM_FLAG_ANY, &gh);
+		if (ret)
+			return ERR_PTR(ret);
+		need_unlock = true;
+	}
+	acl = __gfs2_get_acl(inode, type);
+	if (need_unlock)
+		gfs2_glock_dq_uninit(&gh);
+	return acl;
+}
+
+int __gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 {
 	int error;
 	int len;
 	char *data;
 	const char *name = gfs2_acl_name(type);
 
-	BUG_ON(name == NULL);
-
 	if (acl && acl->a_count > GFS2_ACL_MAX_ENTRIES(GFS2_SB(inode)))
 		return -E2BIG;
 
@@ -115,3 +128,26 @@ out:
 	kfree(data);
 	return error;
 }
+
+int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
+{
+	struct gfs2_inode *ip = GFS2_I(inode);
+	struct gfs2_holder gh;
+	bool need_unlock = false;
+	int ret;
+
+	ret = gfs2_rsqa_alloc(ip);
+	if (ret)
+		return ret;
+
+	if (!gfs2_glock_is_locked_by_me(ip->i_gl)) {
+		ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
+		if (ret)
+			return ret;
+		need_unlock = true;
+	}
+	ret = __gfs2_set_acl(inode, acl, type);
+	if (need_unlock)
+		gfs2_glock_dq_uninit(&gh);
+	return ret;
+}