Re: [PATCH v10 38/46] richacl: Add support for unmapped identifiers

2015-10-11 Thread Andreas Grünbacher
2015-10-12 2:22 GMT+02:00 Dave Chinner :
> This was used by the XFS support patch earlier in the series. Bisect
> problem here...

Yes, I'll fix that up as well.

Thanks,
Andreas
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v10 38/46] richacl: Add support for unmapped identifiers

2015-10-11 Thread Dave Chinner
On Mon, Oct 12, 2015 at 12:58:49AM +0200, Andreas Gruenbacher wrote:
> From: Andreas Gruenbacher 
> 
> Some remote file systems like nfs may return user or group identifiers
> that cannot be mapped to local uids / gids.  Allow to represent such
> unmapped identifiers in richacls.  (We still cannot represent unmapped
> owners and owning groups, however.)
> 
> In the in-memory representation, the richacl is followed by a list of
> NUL-terminated strings, with no padding.  Entries with an unmapped
> identifier have the RICHACE_UNMAPPED_WHO flag set, and ace->e_id.offs
> specifies the offset into this list.  Multiple entries can refer to the
> same offset.
> 
> The xattr representation is similar, but ace->e_id is ignored, and the
> list of unmapped identifier strings contains a string for each acl entry
> whose RICHACE_UNMAPPED_WHO flag is set.
> 
> Signed-off-by: Andreas Gruenbacher 

> +/**
> + * richacl_has_unmapped_identifiers
> + *
> + * Check if an acl has unmapped identifiers.
> + */
> +bool richacl_has_unmapped_identifiers(struct richacl *acl)
> +{
> + struct richace *ace;
> +
> + richacl_for_each_entry(ace, acl) {
> + if (ace->e_flags & RICHACE_UNMAPPED_WHO)
> + return true;
> + }
> + return false;
> +}
> +EXPORT_SYMBOL_GPL(richacl_has_unmapped_identifiers);

This was used by the XFS support patch earlier in the series. Bisect
problem here...

Cheers,

Dave.
-- 
Dave Chinner
da...@fromorbit.com
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v10 38/46] richacl: Add support for unmapped identifiers

2015-10-11 Thread Andreas Gruenbacher
From: Andreas Gruenbacher 

Some remote file systems like nfs may return user or group identifiers
that cannot be mapped to local uids / gids.  Allow to represent such
unmapped identifiers in richacls.  (We still cannot represent unmapped
owners and owning groups, however.)

In the in-memory representation, the richacl is followed by a list of
NUL-terminated strings, with no padding.  Entries with an unmapped
identifier have the RICHACE_UNMAPPED_WHO flag set, and ace->e_id.offs
specifies the offset into this list.  Multiple entries can refer to the
same offset.

The xattr representation is similar, but ace->e_id is ignored, and the
list of unmapped identifier strings contains a string for each acl entry
whose RICHACE_UNMAPPED_WHO flag is set.

Signed-off-by: Andreas Gruenbacher 
---
 fs/richacl_base.c   | 139 
 fs/richacl_compat.c |  18 +++
 fs/richacl_inode.c  |   4 +-
 fs/richacl_xattr.c  |  69 
 include/linux/richacl.h |  33 ++--
 5 files changed, 227 insertions(+), 36 deletions(-)

diff --git a/fs/richacl_base.c b/fs/richacl_base.c
index 3a97a82..f88d19b 100644
--- a/fs/richacl_base.c
+++ b/fs/richacl_base.c
@@ -23,22 +23,25 @@
 MODULE_LICENSE("GPL");
 
 /**
- * richacl_alloc  -  allocate a richacl
+ * __richacl_alloc  -  allocate a richacl
  * @count: number of entries
+ * @unmapped_size: size to reserve for unmapped identifiers
  */
 struct richacl *
-richacl_alloc(int count, gfp_t gfp)
+__richacl_alloc(unsigned int count, size_t unmapped_size, gfp_t gfp)
 {
-   size_t size = sizeof(struct richacl) + count * sizeof(struct richace);
+   size_t size = sizeof(struct richacl) + count * sizeof(struct richace) +
+ unmapped_size;
struct richacl *acl = kzalloc(size, gfp);
 
if (acl) {
atomic_set(&acl->a_base.ba_refcount, 1);
acl->a_count = count;
+   acl->a_unmapped_size = unmapped_size;
}
return acl;
 }
-EXPORT_SYMBOL_GPL(richacl_alloc);
+EXPORT_SYMBOL_GPL(__richacl_alloc);
 
 /**
  * richacl_clone  -  create a copy of a richacl
@@ -47,7 +50,8 @@ struct richacl *
 richacl_clone(const struct richacl *acl, gfp_t gfp)
 {
int count = acl->a_count;
-   size_t size = sizeof(struct richacl) + count * sizeof(struct richace);
+   size_t size = sizeof(struct richacl) + count * sizeof(struct richace) +
+ acl->a_unmapped_size;
struct richacl *dup = kmalloc(size, gfp);
 
if (dup) {
@@ -59,6 +63,9 @@ richacl_clone(const struct richacl *acl, gfp_t gfp)
 
 /**
  * richace_copy  -  copy an acl entry
+ *
+ * If @from has an unmapped who value (from->e_flags & RICHACE_UNMAPPED_WHO),
+ * it can only be copied within the same acl!
  */
 void
 richace_copy(struct richace *to, const struct richace *from)
@@ -66,6 +73,82 @@ richace_copy(struct richace *to, const struct richace *from)
memcpy(to, from, sizeof(struct richace));
 }
 
+/**
+ * richacl_add_unmapped_identifier
+ * @pacl:  Pointer to an acl
+ * @pace:  acl entry within @acl
+ * @who:   unmapped identifier
+ * @len:   length of @who
+ * @gfp:   memory allocation flags
+ *
+ * Add an unmapped identifier to an acl, possibly reallocating the acl.
+ */
+int richacl_add_unmapped_identifier(struct richacl **pacl,
+   struct richace **pace,
+   const char *who,
+   unsigned int len, gfp_t gfp)
+{
+   struct richacl *acl = *pacl;
+   size_t size = sizeof(struct richacl) +
+ acl->a_count * sizeof(struct richace) +
+ acl->a_unmapped_size + len + 1;
+   unsigned int index = *pace - acl->a_entries;
+
+   acl = krealloc(*pacl, size, gfp);
+   if (acl) {
+   char *unmapped = (char *)(acl->a_entries + acl->a_count);
+   struct richace *ace = acl->a_entries + index;
+
+   ace->e_flags |= RICHACE_UNMAPPED_WHO;
+   ace->e_flags &= ~RICHACE_SPECIAL_WHO;
+   ace->e_id.offs = acl->a_unmapped_size;
+   memcpy(unmapped + ace->e_id.offs, who, len);
+   unmapped[ace->e_id.offs + len] = 0;
+   acl->a_unmapped_size += len + 1;
+   *pace = ace;
+   *pacl = acl;
+   return 0;
+   }
+   return -1;
+}
+EXPORT_SYMBOL_GPL(richacl_add_unmapped_identifier);
+
+/**
+ * richace_unmapped_identifier  -  get unmapped identifier
+ * @acl:   acl containing @ace
+ * @ace:   acl entry
+ *
+ * Get the unmapped identifier of @ace as a NUL-terminated string, or NULL if
+ * @ace doesn't have an unmapped identifier.
+ */
+const char *richace_unmapped_identifier(const struct richace *ace,
+   const struct richacl *acl)
+{
+   const char *unmapped = (char *)(acl->a_entries + acl->a_count);
+
+