* [RFC v4 08/31] richacl: Compute maximum file masks from an acl
From: Andreas Gruenbacher @ 2015-06-24 21:56 UTC (permalink / raw)
To: linux-kernel, linux-fsdevel, linux-nfs, linux-api,
samba-technical, linux-security-module
In-Reply-To: <1435183040-22726-1-git-send-email-agruenba@redhat.com>
Compute upper bound owner, group, and other file masks with as few
permissions as possible without denying any permissions that the NFSv4
acl in a richacl grants.
This algorithm is used when a file inherits an acl at create time and
when an acl is set via a mechanism that does not provide file masks
(such as setting an acl via nfsd). When user-space sets an acl via
setxattr, the extended attribute already includes the file masks.
Setting an acl also sets the file mode permission bits: they are
determined by the file masks; see richacl_masks_to_mode().
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Reviewed-by: J. Bruce Fields <bfields@redhat.com>
---
fs/richacl_base.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/richacl.h | 1 +
2 files changed, 157 insertions(+)
diff --git a/fs/richacl_base.c b/fs/richacl_base.c
index 032c756..fda0568 100644
--- a/fs/richacl_base.c
+++ b/fs/richacl_base.c
@@ -169,3 +169,159 @@ richacl_want_to_mask(unsigned int want)
return mask;
}
EXPORT_SYMBOL_GPL(richacl_want_to_mask);
+
+/*
+ * Note: functions like richacl_allowed_to_who(), richacl_group_class_allowed(),
+ * and richacl_compute_max_masks() iterate through the entire acl in reverse
+ * order as an optimization.
+ *
+ * In the standard algorithm, aces are considered in forward order. When a
+ * process matches an ace, the permissions in the ace are either allowed or
+ * denied depending on the ace type. Once a permission has been allowed or
+ * denied, it is no longer considered in further aces.
+ *
+ * By iterating through the acl in reverse order, we can compute the same
+ * result without having to keep track of which permissions have been allowed
+ * and denied already.
+ */
+
+/**
+ * richacl_allowed_to_who - permissions allowed to a specific who value
+ *
+ * Compute the maximum mask values allowed to a specific who value, taking
+ * everyone@ aces into account.
+ */
+static unsigned int richacl_allowed_to_who(struct richacl *acl,
+ struct richace *who)
+{
+ struct richace *ace;
+ unsigned int allowed = 0;
+
+ richacl_for_each_entry_reverse(ace, acl) {
+ if (richace_is_inherit_only(ace))
+ continue;
+ if (richace_is_same_identifier(ace, who) ||
+ richace_is_everyone(ace)) {
+ if (richace_is_allow(ace))
+ allowed |= ace->e_mask;
+ else if (richace_is_deny(ace))
+ allowed &= ~ace->e_mask;
+ }
+ }
+ return allowed;
+}
+
+/**
+ * richacl_group_class_allowed - maximum permissions the group class is allowed
+ *
+ * Compute the maximum mask values allowed to a process in the group class
+ * (i.e., a process which is not the owner but is in the owning group or
+ * matches a user or group acl entry). This includes permissions granted or
+ * denied by everyone@ aces.
+ *
+ * See richacl_compute_max_masks().
+ */
+static unsigned int richacl_group_class_allowed(struct richacl *acl)
+{
+ struct richace *ace;
+ unsigned int everyone_allowed = 0, group_class_allowed = 0;
+ int had_group_ace = 0;
+
+ richacl_for_each_entry_reverse(ace, acl) {
+ if (richace_is_inherit_only(ace) ||
+ richace_is_owner(ace))
+ continue;
+
+ if (richace_is_everyone(ace)) {
+ if (richace_is_allow(ace))
+ everyone_allowed |= ace->e_mask;
+ else if (richace_is_deny(ace))
+ everyone_allowed &= ~ace->e_mask;
+ } else {
+ group_class_allowed |=
+ richacl_allowed_to_who(acl, ace);
+
+ if (richace_is_group(ace))
+ had_group_ace = 1;
+ }
+ }
+ /*
+ * If the acl doesn't contain any group@ aces, richacl_allowed_to_who()
+ * wasn't called for the owning group. We could make that call now, but
+ * we already know the result (everyone_allowed).
+ */
+ if (!had_group_ace)
+ group_class_allowed |= everyone_allowed;
+ return group_class_allowed;
+}
+
+/**
+ * richacl_compute_max_masks - compute upper bound masks
+ *
+ * Computes upper bound owner, group, and other masks so that none of
+ * the mask flags allowed by the acl are disabled (for any choice of the
+ * file owner or group membership).
+ */
+void richacl_compute_max_masks(struct richacl *acl, kuid_t owner)
+{
+ unsigned int gmask = ~0;
+ struct richace *ace;
+
+ /*
+ * @gmask contains all permissions which the group class is ever
+ * allowed. We use it to avoid adding permissions to the group mask
+ * from everyone@ allow aces which the group class is always denied
+ * through other aces. For example, the following acl would otherwise
+ * result in a group mask of rw:
+ *
+ * group@:w::deny
+ * everyone@:rw::allow
+ *
+ * Avoid computing @gmask for acls which do not include any group class
+ * deny aces: in such acls, the group class is never denied any
+ * permissions from everyone@ allow aces, and the group class cannot
+ * have fewer permissions than the other class.
+ */
+
+restart:
+ acl->a_owner_mask = 0;
+ acl->a_group_mask = 0;
+ acl->a_other_mask = 0;
+
+ richacl_for_each_entry_reverse(ace, acl) {
+ if (richace_is_inherit_only(ace))
+ continue;
+
+ if (richace_is_owner(ace) ||
+ (richace_is_unix_user(ace) &&
+ uid_eq(ace->e_id.uid, owner))) {
+ if (richace_is_allow(ace))
+ acl->a_owner_mask |= ace->e_mask;
+ else if (richace_is_deny(ace))
+ acl->a_owner_mask &= ~ace->e_mask;
+ } else if (richace_is_everyone(ace)) {
+ if (richace_is_allow(ace)) {
+ acl->a_owner_mask |= ace->e_mask;
+ acl->a_group_mask |= ace->e_mask & gmask;
+ acl->a_other_mask |= ace->e_mask;
+ } else if (richace_is_deny(ace)) {
+ acl->a_owner_mask &= ~ace->e_mask;
+ acl->a_group_mask &= ~ace->e_mask;
+ acl->a_other_mask &= ~ace->e_mask;
+ }
+ } else {
+ if (richace_is_allow(ace)) {
+ acl->a_owner_mask |= ace->e_mask & gmask;
+ acl->a_group_mask |= ace->e_mask & gmask;
+ } else if (richace_is_deny(ace) && gmask == ~0) {
+ gmask = richacl_group_class_allowed(acl);
+ if (likely(gmask != ~0))
+ /* should always be true */
+ goto restart;
+ }
+ }
+ }
+
+ acl->a_flags &= ~RICHACL_MASKED;
+}
+EXPORT_SYMBOL_GPL(richacl_compute_max_masks);
diff --git a/include/linux/richacl.h b/include/linux/richacl.h
index 7957bbf..3cea47a 100644
--- a/include/linux/richacl.h
+++ b/include/linux/richacl.h
@@ -300,5 +300,6 @@ extern struct richacl *richacl_clone(const struct richacl *, gfp_t);
extern int richacl_masks_to_mode(const struct richacl *);
extern unsigned int richacl_mode_to_mask(mode_t);
extern unsigned int richacl_want_to_mask(unsigned int);
+extern void richacl_compute_max_masks(struct richacl *, kuid_t);
#endif /* __RICHACL_H */
--
2.4.2
^ permalink raw reply related
* [RFC v4 07/31] richacl: Permission mapping functions
From: Andreas Gruenbacher @ 2015-06-24 21:56 UTC (permalink / raw)
To: linux-kernel, linux-fsdevel, linux-nfs, linux-api,
samba-technical, linux-security-module
In-Reply-To: <1435183040-22726-1-git-send-email-agruenba@redhat.com>
We need to map from POSIX permissions to NFSv4 permissions when a
chmod() is done, from NFSv4 permissions to POSIX permissions when an acl
is set (which implicitly sets the file permission bits), and from the
MAY_READ/MAY_WRITE/MAY_EXEC/MAY_APPEND flags to NFSv4 permissions when
doing an access check in a richacl.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
fs/richacl_base.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/richacl.h | 46 ++++++++++++++++++++
2 files changed, 159 insertions(+)
diff --git a/fs/richacl_base.c b/fs/richacl_base.c
index 164b902..032c756 100644
--- a/fs/richacl_base.c
+++ b/fs/richacl_base.c
@@ -56,3 +56,116 @@ richacl_clone(const struct richacl *acl, gfp_t gfp)
}
return dup;
}
+
+/**
+ * richacl_mask_to_mode - compute the file permission bits which correspond to @mask
+ * @mask: %RICHACE_* permission mask
+ *
+ * See richacl_masks_to_mode().
+ */
+static int
+richacl_mask_to_mode(unsigned int mask)
+{
+ int mode = 0;
+
+ if (mask & RICHACE_POSIX_MODE_READ)
+ mode |= S_IROTH;
+ if (mask & RICHACE_POSIX_MODE_WRITE)
+ mode |= S_IWOTH;
+ if (mask & RICHACE_POSIX_MODE_EXEC)
+ mode |= S_IXOTH;
+
+ return mode;
+}
+
+/**
+ * richacl_masks_to_mode - compute the file permission bits from the file masks
+ *
+ * When setting a richacl, we set the file permission bits to indicate maximum
+ * permissions: for example, we set the Write permission when a mask contains
+ * RICHACE_APPEND_DATA even if it does not also contain RICHACE_WRITE_DATA.
+ *
+ * Permissions which are not in RICHACE_POSIX_MODE_READ, RICHACE_POSIX_MODE_WRITE, or
+ * RICHACE_POSIX_MODE_EXEC cannot be represented in the file permission bits.
+ * Such permissions can still be effective, but not for new files or after a
+ * chmod(); they must be explicitly enabled in the richacl.
+ */
+int
+richacl_masks_to_mode(const struct richacl *acl)
+{
+ return richacl_mask_to_mode(acl->a_owner_mask) << 6 |
+ richacl_mask_to_mode(acl->a_group_mask) << 3 |
+ richacl_mask_to_mode(acl->a_other_mask);
+}
+EXPORT_SYMBOL_GPL(richacl_masks_to_mode);
+
+/**
+ * richacl_mode_to_mask - compute a file mask from the lowest three mode bits
+ *
+ * When the file permission bits of a file are set with chmod(), this specifies
+ * the maximum permissions that processes will get. All permissions beyond
+ * that will be removed from the file masks, and become ineffective.
+ */
+unsigned int
+richacl_mode_to_mask(mode_t mode)
+{
+ unsigned int mask = 0;
+
+ if (mode & S_IROTH)
+ mask |= RICHACE_POSIX_MODE_READ;
+ if (mode & S_IWOTH)
+ mask |= RICHACE_POSIX_MODE_WRITE;
+ if (mode & S_IXOTH)
+ mask |= RICHACE_POSIX_MODE_EXEC;
+
+ return mask;
+}
+
+/**
+ * richacl_want_to_mask - convert the iop->permission want argument to a mask
+ * @want: @want argument of the permission inode operation
+ *
+ * When checking for append, @want is (MAY_WRITE | MAY_APPEND).
+ *
+ * Richacls use the iop->may_create and iop->may_delete hooks which are
+ * used for checking if creating and deleting files is allowed. These hooks do
+ * not use richacl_want_to_mask(), so we do not have to deal with mapping
+ * MAY_WRITE to RICHACE_ADD_FILE, RICHACE_ADD_SUBDIRECTORY, and RICHACE_DELETE_CHILD
+ * here.
+ */
+unsigned int
+richacl_want_to_mask(unsigned int want)
+{
+ unsigned int mask = 0;
+
+ if (want & MAY_READ)
+ mask |= RICHACE_READ_DATA;
+ if (want & MAY_DELETE_SELF)
+ mask |= RICHACE_DELETE;
+ if (want & MAY_TAKE_OWNERSHIP)
+ mask |= RICHACE_WRITE_OWNER;
+ if (want & MAY_CHMOD)
+ mask |= RICHACE_WRITE_ACL;
+ if (want & MAY_SET_TIMES)
+ mask |= RICHACE_WRITE_ATTRIBUTES;
+ if (want & MAY_EXEC)
+ mask |= RICHACE_EXECUTE;
+ /*
+ * differentiate MAY_WRITE from these request
+ */
+ if (want & (MAY_APPEND |
+ MAY_CREATE_FILE | MAY_CREATE_DIR |
+ MAY_DELETE_CHILD)) {
+ if (want & MAY_APPEND)
+ mask |= RICHACE_APPEND_DATA;
+ if (want & MAY_CREATE_FILE)
+ mask |= RICHACE_ADD_FILE;
+ if (want & MAY_CREATE_DIR)
+ mask |= RICHACE_ADD_SUBDIRECTORY;
+ if (want & MAY_DELETE_CHILD)
+ mask |= RICHACE_DELETE_CHILD;
+ } else if (want & MAY_WRITE)
+ mask |= RICHACE_WRITE_DATA;
+ return mask;
+}
+EXPORT_SYMBOL_GPL(richacl_want_to_mask);
diff --git a/include/linux/richacl.h b/include/linux/richacl.h
index feebc2f..7957bbf 100644
--- a/include/linux/richacl.h
+++ b/include/linux/richacl.h
@@ -118,6 +118,49 @@ struct richacl {
RICHACE_WRITE_OWNER | \
RICHACE_SYNCHRONIZE)
+/*
+ * The POSIX permissions are supersets of the following NFSv4 permissions:
+ *
+ * - MAY_READ maps to READ_DATA or LIST_DIRECTORY, depending on the type
+ * of the file system object.
+ *
+ * - MAY_WRITE maps to WRITE_DATA or RICHACE_APPEND_DATA for files, and to
+ * ADD_FILE, RICHACE_ADD_SUBDIRECTORY, or RICHACE_DELETE_CHILD for directories.
+ *
+ * - MAY_EXECUTE maps to RICHACE_EXECUTE.
+ *
+ * (Some of these NFSv4 permissions have the same bit values.)
+ */
+#define RICHACE_POSIX_MODE_READ ( \
+ RICHACE_READ_DATA | \
+ RICHACE_LIST_DIRECTORY)
+#define RICHACE_POSIX_MODE_WRITE ( \
+ RICHACE_WRITE_DATA | \
+ RICHACE_ADD_FILE | \
+ RICHACE_APPEND_DATA | \
+ RICHACE_ADD_SUBDIRECTORY | \
+ RICHACE_DELETE_CHILD)
+#define RICHACE_POSIX_MODE_EXEC RICHACE_EXECUTE
+#define RICHACE_POSIX_MODE_ALL ( \
+ RICHACE_POSIX_MODE_READ | \
+ RICHACE_POSIX_MODE_WRITE | \
+ RICHACE_POSIX_MODE_EXEC)
+/*
+ * These permissions are always allowed
+ * no matter what the acl says.
+ */
+#define RICHACE_POSIX_ALWAYS_ALLOWED ( \
+ RICHACE_SYNCHRONIZE | \
+ RICHACE_READ_ATTRIBUTES | \
+ RICHACE_READ_ACL)
+/*
+ * The owner is implicitly granted
+ * these permissions under POSIX.
+ */
+#define RICHACE_POSIX_OWNER_ALLOWED ( \
+ RICHACE_WRITE_ATTRIBUTES | \
+ RICHACE_WRITE_OWNER | \
+ RICHACE_WRITE_ACL)
/**
* richacl_get - grab another reference to a richacl handle
*/
@@ -254,5 +297,8 @@ richace_is_same_identifier(const struct richace *a, const struct richace *b)
extern struct richacl *richacl_alloc(int, gfp_t);
extern struct richacl *richacl_clone(const struct richacl *, gfp_t);
+extern int richacl_masks_to_mode(const struct richacl *);
+extern unsigned int richacl_mode_to_mask(mode_t);
+extern unsigned int richacl_want_to_mask(unsigned int);
#endif /* __RICHACL_H */
--
2.4.2
^ permalink raw reply related
* [RFC v4 06/31] richacl: In-memory representation and helper functions
From: Andreas Gruenbacher @ 2015-06-24 21:56 UTC (permalink / raw)
To: linux-kernel, linux-fsdevel, linux-nfs, linux-api,
samba-technical, linux-security-module
In-Reply-To: <1435183040-22726-1-git-send-email-agruenba@redhat.com>
A richacl consists of an NFSv4 acl and an owner, group, and other mask.
These three masks correspond to the owner, group, and other file
permission bits, but they contain NFSv4 permissions instead of POSIX
permissions.
Each entry in the NFSv4 acl applies to the file owner (OWNER@), the owning
group (GROUP@), everyone (EVERYONE@), or to a specific uid or gid.
As in the standard POSIX file permission model, each process is the
owner, group, or other file class. A richacl grants a requested access
only if the NFSv4 acl in the richacl grants the access (according to the
NFSv4 permission check algorithm), and the file mask that applies to the
process includes the requested permissions.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
fs/Makefile | 2 +
fs/richacl_base.c | 58 +++++++++++
include/linux/richacl.h | 258 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 318 insertions(+)
create mode 100644 fs/richacl_base.c
create mode 100644 include/linux/richacl.h
diff --git a/fs/Makefile b/fs/Makefile
index cb92fd4..654e716 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -47,6 +47,8 @@ obj-$(CONFIG_COREDUMP) += coredump.o
obj-$(CONFIG_SYSCTL) += drop_caches.o
obj-$(CONFIG_FHANDLE) += fhandle.o
+obj-$(CONFIG_FS_RICHACL) += richacl.o
+richacl-y := richacl_base.o
obj-y += quota/
diff --git a/fs/richacl_base.c b/fs/richacl_base.c
new file mode 100644
index 0000000..164b902
--- /dev/null
+++ b/fs/richacl_base.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2006, 2010 Novell, Inc.
+ * Copyright (C) 2015 Red Hat, Inc.
+ * Written by Andreas Gruenbacher <agruen@kernel.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/richacl.h>
+
+MODULE_LICENSE("GPL");
+
+/**
+ * richacl_alloc - allocate a richacl
+ * @count: number of entries
+ */
+struct richacl *
+richacl_alloc(int count, gfp_t gfp)
+{
+ size_t size = sizeof(struct richacl) + count * sizeof(struct richace);
+ struct richacl *acl = kzalloc(size, gfp);
+
+ if (acl) {
+ atomic_set(&acl->a_refcount, 1);
+ acl->a_count = count;
+ }
+ return acl;
+}
+EXPORT_SYMBOL_GPL(richacl_alloc);
+
+/**
+ * richacl_clone - create a copy of a richacl
+ */
+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);
+ struct richacl *dup = kmalloc(size, gfp);
+
+ if (dup) {
+ memcpy(dup, acl, size);
+ atomic_set(&dup->a_refcount, 1);
+ }
+ return dup;
+}
diff --git a/include/linux/richacl.h b/include/linux/richacl.h
new file mode 100644
index 0000000..feebc2f
--- /dev/null
+++ b/include/linux/richacl.h
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2006, 2010 Novell, Inc.
+ * Copyright (C) 2015 Red Hat, Inc.
+ * Written by Andreas Gruenbacher <agruen@kernel.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __RICHACL_H
+#define __RICHACL_H
+
+#define RICHACE_OWNER_SPECIAL_ID 0
+#define RICHACE_GROUP_SPECIAL_ID 1
+#define RICHACE_EVERYONE_SPECIAL_ID 2
+
+struct richace {
+ unsigned short e_type;
+ unsigned short e_flags;
+ unsigned int e_mask;
+ union {
+ kuid_t uid;
+ kgid_t gid;
+ unsigned int special;
+ } e_id;
+};
+
+struct richacl {
+ atomic_t a_refcount;
+ unsigned int a_owner_mask;
+ unsigned int a_group_mask;
+ unsigned int a_other_mask;
+ unsigned short a_count;
+ unsigned short a_flags;
+ struct richace a_entries[0];
+};
+
+#define richacl_for_each_entry(_ace, _acl) \
+ for (_ace = (_acl)->a_entries; \
+ _ace != (_acl)->a_entries + (_acl)->a_count; \
+ _ace++)
+
+#define richacl_for_each_entry_reverse(_ace, _acl) \
+ for (_ace = (_acl)->a_entries + (_acl)->a_count - 1; \
+ _ace != (_acl)->a_entries - 1; \
+ _ace--)
+
+/* a_flag values */
+#define RICHACL_MASKED 0x80
+
+#define RICHACL_VALID_FLAGS ( \
+ RICHACL_MASKED)
+
+/* e_type values */
+#define RICHACE_ACCESS_ALLOWED_ACE_TYPE 0x0000
+#define RICHACE_ACCESS_DENIED_ACE_TYPE 0x0001
+
+/* e_flags bitflags */
+#define RICHACE_FILE_INHERIT_ACE 0x0001
+#define RICHACE_DIRECTORY_INHERIT_ACE 0x0002
+#define RICHACE_NO_PROPAGATE_INHERIT_ACE 0x0004
+#define RICHACE_INHERIT_ONLY_ACE 0x0008
+#define RICHACE_IDENTIFIER_GROUP 0x0040
+#define RICHACE_SPECIAL_WHO 0x4000
+
+#define RICHACE_VALID_FLAGS ( \
+ RICHACE_FILE_INHERIT_ACE | \
+ RICHACE_DIRECTORY_INHERIT_ACE | \
+ RICHACE_NO_PROPAGATE_INHERIT_ACE | \
+ RICHACE_INHERIT_ONLY_ACE | \
+ RICHACE_IDENTIFIER_GROUP | \
+ RICHACE_SPECIAL_WHO)
+
+/* e_mask bitflags */
+#define RICHACE_READ_DATA 0x00000001
+#define RICHACE_LIST_DIRECTORY 0x00000001
+#define RICHACE_WRITE_DATA 0x00000002
+#define RICHACE_ADD_FILE 0x00000002
+#define RICHACE_APPEND_DATA 0x00000004
+#define RICHACE_ADD_SUBDIRECTORY 0x00000004
+#define RICHACE_READ_NAMED_ATTRS 0x00000008
+#define RICHACE_WRITE_NAMED_ATTRS 0x00000010
+#define RICHACE_EXECUTE 0x00000020
+#define RICHACE_DELETE_CHILD 0x00000040
+#define RICHACE_READ_ATTRIBUTES 0x00000080
+#define RICHACE_WRITE_ATTRIBUTES 0x00000100
+#define RICHACE_WRITE_RETENTION 0x00000200
+#define RICHACE_WRITE_RETENTION_HOLD 0x00000400
+#define RICHACE_DELETE 0x00010000
+#define RICHACE_READ_ACL 0x00020000
+#define RICHACE_WRITE_ACL 0x00040000
+#define RICHACE_WRITE_OWNER 0x00080000
+#define RICHACE_SYNCHRONIZE 0x00100000
+
+/* Valid RICHACE_* flags for directories and non-directories */
+#define RICHACE_VALID_MASK ( \
+ RICHACE_READ_DATA | RICHACE_LIST_DIRECTORY | \
+ RICHACE_WRITE_DATA | RICHACE_ADD_FILE | \
+ RICHACE_APPEND_DATA | RICHACE_ADD_SUBDIRECTORY | \
+ RICHACE_READ_NAMED_ATTRS | \
+ RICHACE_WRITE_NAMED_ATTRS | \
+ RICHACE_EXECUTE | \
+ RICHACE_DELETE_CHILD | \
+ RICHACE_READ_ATTRIBUTES | \
+ RICHACE_WRITE_ATTRIBUTES | \
+ RICHACE_WRITE_RETENTION | \
+ RICHACE_WRITE_RETENTION_HOLD | \
+ RICHACE_DELETE | \
+ RICHACE_READ_ACL | \
+ RICHACE_WRITE_ACL | \
+ RICHACE_WRITE_OWNER | \
+ RICHACE_SYNCHRONIZE)
+
+/**
+ * richacl_get - grab another reference to a richacl handle
+ */
+static inline struct richacl *
+richacl_get(struct richacl *acl)
+{
+ if (acl)
+ atomic_inc(&acl->a_refcount);
+ return acl;
+}
+
+/**
+ * richacl_put - free a richacl handle
+ */
+static inline void
+richacl_put(struct richacl *acl)
+{
+ if (acl && atomic_dec_and_test(&acl->a_refcount))
+ kfree(acl);
+}
+
+/**
+ * richace_is_owner - check if @ace is an OWNER@ entry
+ */
+static inline bool
+richace_is_owner(const struct richace *ace)
+{
+ return (ace->e_flags & RICHACE_SPECIAL_WHO) &&
+ ace->e_id.special == RICHACE_OWNER_SPECIAL_ID;
+}
+
+/**
+ * richace_is_group - check if @ace is a GROUP@ entry
+ */
+static inline bool
+richace_is_group(const struct richace *ace)
+{
+ return (ace->e_flags & RICHACE_SPECIAL_WHO) &&
+ ace->e_id.special == RICHACE_GROUP_SPECIAL_ID;
+}
+
+/**
+ * richace_is_everyone - check if @ace is an EVERYONE@ entry
+ */
+static inline bool
+richace_is_everyone(const struct richace *ace)
+{
+ return (ace->e_flags & RICHACE_SPECIAL_WHO) &&
+ ace->e_id.special == RICHACE_EVERYONE_SPECIAL_ID;
+}
+
+/**
+ * richace_is_unix_user - check if @ace applies to a specific user
+ */
+static inline bool
+richace_is_unix_user(const struct richace *ace)
+{
+ return !(ace->e_flags & RICHACE_SPECIAL_WHO) &&
+ !(ace->e_flags & RICHACE_IDENTIFIER_GROUP);
+}
+
+/**
+ * richace_is_unix_group - check if @ace applies to a specific group
+ */
+static inline bool
+richace_is_unix_group(const struct richace *ace)
+{
+ return !(ace->e_flags & RICHACE_SPECIAL_WHO) &&
+ (ace->e_flags & RICHACE_IDENTIFIER_GROUP);
+}
+
+/**
+ * richace_is_inherit_only - check if @ace is for inheritance only
+ *
+ * ACEs with the %RICHACE_INHERIT_ONLY_ACE flag set have no effect during
+ * permission checking.
+ */
+static inline bool
+richace_is_inherit_only(const struct richace *ace)
+{
+ return ace->e_flags & RICHACE_INHERIT_ONLY_ACE;
+}
+
+/**
+ * richace_is_inheritable - check if @ace is inheritable
+ */
+static inline bool
+richace_is_inheritable(const struct richace *ace)
+{
+ return ace->e_flags & (RICHACE_FILE_INHERIT_ACE |
+ RICHACE_DIRECTORY_INHERIT_ACE);
+}
+
+/**
+ * richace_clear_inheritance_flags - clear all inheritance flags in @ace
+ */
+static inline void
+richace_clear_inheritance_flags(struct richace *ace)
+{
+ ace->e_flags &= ~(RICHACE_FILE_INHERIT_ACE |
+ RICHACE_DIRECTORY_INHERIT_ACE |
+ RICHACE_NO_PROPAGATE_INHERIT_ACE |
+ RICHACE_INHERIT_ONLY_ACE);
+}
+
+/**
+ * richace_is_allow - check if @ace is an %ALLOW type entry
+ */
+static inline bool
+richace_is_allow(const struct richace *ace)
+{
+ return ace->e_type == RICHACE_ACCESS_ALLOWED_ACE_TYPE;
+}
+
+/**
+ * richace_is_deny - check if @ace is a %DENY type entry
+ */
+static inline bool
+richace_is_deny(const struct richace *ace)
+{
+ return ace->e_type == RICHACE_ACCESS_DENIED_ACE_TYPE;
+}
+
+/**
+ * richace_is_same_identifier - are both identifiers the same?
+ */
+static inline bool
+richace_is_same_identifier(const struct richace *a, const struct richace *b)
+{
+ return !((a->e_flags ^ b->e_flags) &
+ (RICHACE_SPECIAL_WHO | RICHACE_IDENTIFIER_GROUP)) &&
+ !memcmp(&a->e_id, &b->e_id, sizeof(a->e_id));
+}
+
+extern struct richacl *richacl_alloc(int, gfp_t);
+extern struct richacl *richacl_clone(const struct richacl *, gfp_t);
+
+#endif /* __RICHACL_H */
--
2.4.2
^ permalink raw reply related
* [RFC v4 05/31] vfs: Add permission flags for setting file attributes
From: Andreas Gruenbacher @ 2015-06-24 21:56 UTC (permalink / raw)
To: linux-kernel, linux-fsdevel, linux-nfs, linux-api,
samba-technical, linux-security-module
In-Reply-To: <1435183040-22726-1-git-send-email-agruenba@redhat.com>
Richacls support permissions that allow to take ownership of a file, change the
file permissions, and set the file timestamps. Support that by introducing new
permission mask flags and by checking for those mask flags in
inode_change_ok().
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
fs/attr.c | 79 +++++++++++++++++++++++++++++++++++++++++++++---------
include/linux/fs.h | 3 +++
2 files changed, 70 insertions(+), 12 deletions(-)
diff --git a/fs/attr.c b/fs/attr.c
index 328be71..85483e0 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -17,6 +17,65 @@
#include <linux/ima.h>
/**
+ * inode_extended_permission - permissions beyond read/write/execute
+ *
+ * Check for permissions that only richacls can currently grant.
+ */
+static int inode_extended_permission(struct inode *inode, int mask)
+{
+ if (!IS_RICHACL(inode))
+ return -EPERM;
+ return inode_permission(inode, mask);
+}
+
+static bool inode_uid_change_ok(struct inode *inode, kuid_t ia_uid)
+{
+ if (uid_eq(current_fsuid(), inode->i_uid) &&
+ uid_eq(ia_uid, inode->i_uid))
+ return true;
+ if (uid_eq(current_fsuid(), ia_uid) &&
+ inode_extended_permission(inode, MAY_TAKE_OWNERSHIP) == 0)
+ return true;
+ if (capable_wrt_inode_uidgid(inode, CAP_CHOWN))
+ return true;
+ return false;
+}
+
+static bool inode_gid_change_ok(struct inode *inode, kgid_t ia_gid)
+{
+ int in_group = in_group_p(ia_gid);
+ if (uid_eq(current_fsuid(), inode->i_uid) &&
+ (in_group || gid_eq(ia_gid, inode->i_gid)))
+ return true;
+ if (in_group && inode_extended_permission(inode, MAY_TAKE_OWNERSHIP) == 0)
+ return true;
+ if (capable_wrt_inode_uidgid(inode, CAP_CHOWN))
+ return true;
+ return false;
+}
+
+/**
+ * inode_owner_permitted_or_capable
+ *
+ * Check for permissions implicitly granted to the owner, like MAY_CHMOD or
+ * MAY_SET_TIMES. Equivalent to inode_owner_or_capable for file systems
+ * without support for those permissions.
+ */
+static bool inode_owner_permitted_or_capable(struct inode *inode, int mask)
+{
+ struct user_namespace *ns;
+
+ if (uid_eq(current_fsuid(), inode->i_uid))
+ return true;
+ if (inode_extended_permission(inode, mask) == 0)
+ return true;
+ ns = current_user_ns();
+ if (ns_capable(ns, CAP_FOWNER) && kuid_has_mapping(ns, inode->i_uid))
+ return true;
+ return false;
+}
+
+/**
* inode_change_ok - check if attribute changes to an inode are allowed
* @inode: inode to check
* @attr: attributes to change
@@ -47,22 +106,18 @@ int inode_change_ok(struct inode *inode, struct iattr *attr)
return 0;
/* Make sure a caller can chown. */
- if ((ia_valid & ATTR_UID) &&
- (!uid_eq(current_fsuid(), inode->i_uid) ||
- !uid_eq(attr->ia_uid, inode->i_uid)) &&
- !capable_wrt_inode_uidgid(inode, CAP_CHOWN))
- return -EPERM;
+ if (ia_valid & ATTR_UID)
+ if (!inode_uid_change_ok(inode, attr->ia_uid))
+ return -EPERM;
/* Make sure caller can chgrp. */
- if ((ia_valid & ATTR_GID) &&
- (!uid_eq(current_fsuid(), inode->i_uid) ||
- (!in_group_p(attr->ia_gid) && !gid_eq(attr->ia_gid, inode->i_gid))) &&
- !capable_wrt_inode_uidgid(inode, CAP_CHOWN))
- return -EPERM;
+ if (ia_valid & ATTR_GID)
+ if (!inode_gid_change_ok(inode, attr->ia_gid))
+ return -EPERM;
/* Make sure a caller can chmod. */
if (ia_valid & ATTR_MODE) {
- if (!inode_owner_or_capable(inode))
+ if (!inode_owner_permitted_or_capable(inode, MAY_CHMOD))
return -EPERM;
/* Also check the setgid bit! */
if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
@@ -73,7 +128,7 @@ int inode_change_ok(struct inode *inode, struct iattr *attr)
/* Check for setting the inode time. */
if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) {
- if (!inode_owner_or_capable(inode))
+ if (!inode_owner_permitted_or_capable(inode, MAY_SET_TIMES))
return -EPERM;
}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b98b211..a32f37a 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -84,6 +84,9 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
#define MAY_CREATE_DIR 0x00000200
#define MAY_DELETE_CHILD 0x00000400
#define MAY_DELETE_SELF 0x00000800
+#define MAY_TAKE_OWNERSHIP 0x00001000
+#define MAY_CHMOD 0x00002000
+#define MAY_SET_TIMES 0x00004000
/*
* flags in file.f_mode. Note that FMODE_READ and FMODE_WRITE must correspond
--
2.4.2
^ permalink raw reply related
* [RFC v4 04/31] vfs: Make the inode passed to inode_change_ok non-const
From: Andreas Gruenbacher @ 2015-06-24 21:56 UTC (permalink / raw)
To: linux-kernel, linux-fsdevel, linux-nfs, linux-api,
samba-technical, linux-security-module
In-Reply-To: <1435183040-22726-1-git-send-email-agruenba@redhat.com>
We will need to call iop->permission and iop->get_acl from
inode_change_ok() for additional permission checks, and both take a
non-const inode.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
fs/attr.c | 2 +-
include/linux/fs.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/attr.c b/fs/attr.c
index 6530ced..328be71 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -28,7 +28,7 @@
* Should be called as the first thing in ->setattr implementations,
* possibly after taking additional locks.
*/
-int inode_change_ok(const struct inode *inode, struct iattr *attr)
+int inode_change_ok(struct inode *inode, struct iattr *attr)
{
unsigned int ia_valid = attr->ia_valid;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 96a9954..b98b211 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2820,7 +2820,7 @@ extern int buffer_migrate_page(struct address_space *,
#define buffer_migrate_page NULL
#endif
-extern int inode_change_ok(const struct inode *, struct iattr *);
+extern int inode_change_ok(struct inode *, struct iattr *);
extern int inode_newsize_ok(const struct inode *, loff_t offset);
extern void setattr_copy(struct inode *inode, const struct iattr *attr);
--
2.4.2
^ permalink raw reply related
* [RFC v4 03/31] vfs: Add MAY_DELETE_SELF and MAY_DELETE_CHILD permission flags
From: Andreas Gruenbacher @ 2015-06-24 21:56 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-nfs-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA,
samba-technical-w/Ol4Ecudpl8XjKLYN78aQ,
linux-security-module-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1435183040-22726-1-git-send-email-agruenba-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Normally, deleting a file requires write and execute access to the parent
directory. With Richacls, a process with MAY_DELETE_SELF access to a file may
delete the file even without write access to the parent directory.
To support that, pass the MAY_DELETE_CHILD mask flag to inode_permission() when
checking for delete access inside a directory, and MAY_DELETE_SELF when
checking for delete access to a file itelf.
The MAY_DELETE_SELF permission does not override the sticky directory check.
It probably should.
Signed-off-by: Andreas Gruenbacher <agruenba-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
fs/namei.c | 15 +++++++++++----
include/linux/fs.h | 2 ++
2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/fs/namei.c b/fs/namei.c
index c6eac96..8f91790 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -454,7 +454,7 @@ static int sb_permission(struct super_block *sb, struct inode *inode, int mask)
* changing the "normal" UIDs which are used for other things.
*
* When checking for MAY_APPEND, MAY_CREATE_FILE, MAY_CREATE_DIR,
- * MAY_WRITE must also be set in @mask.
+ * MAY_DELETE_CHILD, MAY_DELETE_SELF, MAY_WRITE must also be set in @mask.
*/
int inode_permission(struct inode *inode, int mask)
{
@@ -2459,7 +2459,7 @@ static int may_delete(struct inode *dir, struct dentry *victim,
bool isdir, bool replace)
{
struct inode *inode = victim->d_inode;
- int error, mask = MAY_WRITE | MAY_EXEC;
+ int error, mask = MAY_EXEC;
if (d_is_negative(victim))
return -ENOENT;
@@ -2469,8 +2469,15 @@ static int may_delete(struct inode *dir, struct dentry *victim,
audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
if (replace)
- mask |= isdir ? MAY_CREATE_DIR : MAY_CREATE_FILE;
- error = inode_permission(dir, mask);
+ mask |= MAY_WRITE | (isdir ? MAY_CREATE_DIR : MAY_CREATE_FILE);
+ error = inode_permission(dir, mask | MAY_WRITE | MAY_DELETE_CHILD);
+ if (error && IS_RICHACL(inode)) {
+ /* Deleting is also permitted with MAY_EXEC on the directory
+ * and MAY_DELETE_SELF on the inode. */
+ if (!inode_permission(inode, MAY_DELETE_SELF) &&
+ !inode_permission(dir, mask))
+ error = 0;
+ }
if (error)
return error;
if (IS_APPEND(dir))
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 8c78d91..96a9954 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -82,6 +82,8 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
#define MAY_NOT_BLOCK 0x00000080
#define MAY_CREATE_FILE 0x00000100
#define MAY_CREATE_DIR 0x00000200
+#define MAY_DELETE_CHILD 0x00000400
+#define MAY_DELETE_SELF 0x00000800
/*
* flags in file.f_mode. Note that FMODE_READ and FMODE_WRITE must correspond
--
2.4.2
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [RFC v4 02/31] vfs: Add MAY_CREATE_FILE and MAY_CREATE_DIR permission flags
From: Andreas Gruenbacher @ 2015-06-24 21:56 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-nfs-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA,
samba-technical-w/Ol4Ecudpl8XjKLYN78aQ,
linux-security-module-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1435183040-22726-1-git-send-email-agruenba-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Richacls distinguish between creating non-directories and directories. To
support that, add an isdir parameter to may_create(). When checking
inode_permission() for create permission, pass in an additional MAY_CREATE_FILE
or MAY_CREATE_DIR mask flag.
To allow checking for delete *and* create access when replacing an existing
file via vfs_rename(), add a replace parameter to may_delete().
Signed-off-by: Andreas Gruenbacher <agruenba-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
fs/namei.c | 42 ++++++++++++++++++++++++------------------
include/linux/fs.h | 2 ++
2 files changed, 26 insertions(+), 18 deletions(-)
diff --git a/fs/namei.c b/fs/namei.c
index f5715fb..c6eac96 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -453,7 +453,8 @@ static int sb_permission(struct super_block *sb, struct inode *inode, int mask)
* this, letting us set arbitrary permissions for filesystem access without
* changing the "normal" UIDs which are used for other things.
*
- * When checking for MAY_APPEND, MAY_WRITE must also be set in @mask.
+ * When checking for MAY_APPEND, MAY_CREATE_FILE, MAY_CREATE_DIR,
+ * MAY_WRITE must also be set in @mask.
*/
int inode_permission(struct inode *inode, int mask)
{
@@ -2454,10 +2455,11 @@ EXPORT_SYMBOL(__check_sticky);
* 10. We don't allow removal of NFS sillyrenamed files; it's handled by
* nfs_async_unlink().
*/
-static int may_delete(struct inode *dir, struct dentry *victim, bool isdir)
+static int may_delete(struct inode *dir, struct dentry *victim,
+ bool isdir, bool replace)
{
struct inode *inode = victim->d_inode;
- int error;
+ int error, mask = MAY_WRITE | MAY_EXEC;
if (d_is_negative(victim))
return -ENOENT;
@@ -2466,7 +2468,9 @@ static int may_delete(struct inode *dir, struct dentry *victim, bool isdir)
BUG_ON(victim->d_parent->d_inode != dir);
audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
- error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
+ if (replace)
+ mask |= isdir ? MAY_CREATE_DIR : MAY_CREATE_FILE;
+ error = inode_permission(dir, mask);
if (error)
return error;
if (IS_APPEND(dir))
@@ -2497,14 +2501,16 @@ static int may_delete(struct inode *dir, struct dentry *victim, bool isdir)
* 3. We should have write and exec permissions on dir
* 4. We can't do it if dir is immutable (done in permission())
*/
-static inline int may_create(struct inode *dir, struct dentry *child)
+static inline int may_create(struct inode *dir, struct dentry *child, bool isdir)
{
+ int mask = isdir ? MAY_CREATE_DIR : MAY_CREATE_FILE;
+
audit_inode_child(dir, child, AUDIT_TYPE_CHILD_CREATE);
if (child->d_inode)
return -EEXIST;
if (IS_DEADDIR(dir))
return -ENOENT;
- return inode_permission(dir, MAY_WRITE | MAY_EXEC);
+ return inode_permission(dir, MAY_WRITE | MAY_EXEC | mask);
}
/*
@@ -2554,7 +2560,7 @@ EXPORT_SYMBOL(unlock_rename);
int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
bool want_excl)
{
- int error = may_create(dir, dentry);
+ int error = may_create(dir, dentry, false);
if (error)
return error;
@@ -3430,7 +3436,7 @@ EXPORT_SYMBOL(user_path_create);
int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
{
- int error = may_create(dir, dentry);
+ int error = may_create(dir, dentry, false);
if (error)
return error;
@@ -3522,7 +3528,7 @@ SYSCALL_DEFINE3(mknod, const char __user *, filename, umode_t, mode, unsigned, d
int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
- int error = may_create(dir, dentry);
+ int error = may_create(dir, dentry, true);
unsigned max_links = dir->i_sb->s_max_links;
if (error)
@@ -3603,7 +3609,7 @@ EXPORT_SYMBOL(dentry_unhash);
int vfs_rmdir(struct inode *dir, struct dentry *dentry)
{
- int error = may_delete(dir, dentry, 1);
+ int error = may_delete(dir, dentry, true, false);
if (error)
return error;
@@ -3723,7 +3729,7 @@ SYSCALL_DEFINE1(rmdir, const char __user *, pathname)
int vfs_unlink(struct inode *dir, struct dentry *dentry, struct inode **delegated_inode)
{
struct inode *target = dentry->d_inode;
- int error = may_delete(dir, dentry, 0);
+ int error = may_delete(dir, dentry, false, false);
if (error)
return error;
@@ -3855,7 +3861,7 @@ SYSCALL_DEFINE1(unlink, const char __user *, pathname)
int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
{
- int error = may_create(dir, dentry);
+ int error = may_create(dir, dentry, false);
if (error)
return error;
@@ -3938,7 +3944,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
if (!inode)
return -ENOENT;
- error = may_create(dir, new_dentry);
+ error = may_create(dir, new_dentry, false);
if (error)
return error;
@@ -4126,19 +4132,19 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (source == target)
return 0;
- error = may_delete(old_dir, old_dentry, is_dir);
+ error = may_delete(old_dir, old_dentry, is_dir, false);
if (error)
return error;
if (!target) {
- error = may_create(new_dir, new_dentry);
+ error = may_create(new_dir, new_dentry, is_dir);
} else {
new_is_dir = d_is_dir(new_dentry);
if (!(flags & RENAME_EXCHANGE))
- error = may_delete(new_dir, new_dentry, is_dir);
+ error = may_delete(new_dir, new_dentry, is_dir, true);
else
- error = may_delete(new_dir, new_dentry, new_is_dir);
+ error = may_delete(new_dir, new_dentry, new_is_dir, true);
}
if (error)
return error;
@@ -4402,7 +4408,7 @@ SYSCALL_DEFINE2(rename, const char __user *, oldname, const char __user *, newna
int vfs_whiteout(struct inode *dir, struct dentry *dentry)
{
- int error = may_create(dir, dentry);
+ int error = may_create(dir, dentry, false);
if (error)
return error;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 2b8cabb..8c78d91 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -80,6 +80,8 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
#define MAY_CHDIR 0x00000040
/* called from RCU mode, don't block */
#define MAY_NOT_BLOCK 0x00000080
+#define MAY_CREATE_FILE 0x00000100
+#define MAY_CREATE_DIR 0x00000200
/*
* flags in file.f_mode. Note that FMODE_READ and FMODE_WRITE must correspond
--
2.4.2
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [RFC v4 01/31] vfs: Add IS_ACL() and IS_RICHACL() tests
From: Andreas Gruenbacher @ 2015-06-24 21:56 UTC (permalink / raw)
To: linux-kernel, linux-fsdevel, linux-nfs, linux-api,
samba-technical, linux-security-module
In-Reply-To: <1435183040-22726-1-git-send-email-agruenba@redhat.com>
The vfs does not apply the umask for file systems that support acls. The test
used for this used to be called IS_POSIXACL(). Switch to a new IS_ACL() test to
check for either posix acls or richacls instead. Add a new MS_RICHACL flag and
IS_RICHACL() test for richacls alone. The IS_POSIXACL() test is still needed
by file systems that specifically support POSIX ACLs, like nfsd.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
fs/Kconfig | 3 +++
fs/namei.c | 8 ++++----
include/linux/fs.h | 12 ++++++++++++
include/uapi/linux/fs.h | 3 ++-
4 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/fs/Kconfig b/fs/Kconfig
index 011f433..3e09c06 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -59,6 +59,9 @@ endif # BLOCK
config FS_POSIX_ACL
def_bool n
+config FS_RICHACL
+ def_bool n
+
config EXPORTFS
tristate
diff --git a/fs/namei.c b/fs/namei.c
index fe30d3b..f5715fb 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2703,7 +2703,7 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
}
mode = op->mode;
- if ((open_flag & O_CREAT) && !IS_POSIXACL(dir))
+ if ((open_flag & O_CREAT) && !IS_ACL(dir))
mode &= ~current_umask();
excl = (open_flag & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT);
@@ -2887,7 +2887,7 @@ static int lookup_open(struct nameidata *nd, struct path *path,
/* Negative dentry, just create the file */
if (!dentry->d_inode && (op->open_flag & O_CREAT)) {
umode_t mode = op->mode;
- if (!IS_POSIXACL(dir->d_inode))
+ if (!IS_ACL(dir->d_inode))
mode &= ~current_umask();
/*
* This write is needed to ensure that a
@@ -3489,7 +3489,7 @@ retry:
if (IS_ERR(dentry))
return PTR_ERR(dentry);
- if (!IS_POSIXACL(path.dentry->d_inode))
+ if (!IS_ACL(path.dentry->d_inode))
mode &= ~current_umask();
error = security_path_mknod(&path, dentry, mode, dev);
if (error)
@@ -3558,7 +3558,7 @@ retry:
if (IS_ERR(dentry))
return PTR_ERR(dentry);
- if (!IS_POSIXACL(path.dentry->d_inode))
+ if (!IS_ACL(path.dentry->d_inode))
mode &= ~current_umask();
error = security_path_mkdir(&path, dentry, mode);
if (!error)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 35ec87e..2b8cabb 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1743,6 +1743,12 @@ struct super_operations {
#define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE)
#define IS_POSIXACL(inode) __IS_FLG(inode, MS_POSIXACL)
+#ifdef CONFIG_FS_RICHACL
+#define IS_RICHACL(inode) __IS_FLG(inode, MS_RICHACL)
+#else
+#define IS_RICHACL(inode) 0
+#endif
+
#define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD)
#define IS_NOCMTIME(inode) ((inode)->i_flags & S_NOCMTIME)
#define IS_SWAPFILE(inode) ((inode)->i_flags & S_SWAPFILE)
@@ -1756,6 +1762,12 @@ struct super_operations {
(inode)->i_rdev == WHITEOUT_DEV)
/*
+ * IS_ACL() tells the VFS to not apply the umask
+ * and use check_acl for acl permission checks when defined.
+ */
+#define IS_ACL(inode) __IS_FLG(inode, MS_POSIXACL | MS_RICHACL)
+
+/*
* Inode state bits. Protected by inode->i_lock
*
* Three bits determine the dirty state of the inode, I_DIRTY_SYNC,
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
index 9b964a5..6ac6bc9 100644
--- a/include/uapi/linux/fs.h
+++ b/include/uapi/linux/fs.h
@@ -81,7 +81,7 @@ struct inodes_stat_t {
#define MS_VERBOSE 32768 /* War is peace. Verbosity is silence.
MS_VERBOSE is deprecated. */
#define MS_SILENT 32768
-#define MS_POSIXACL (1<<16) /* VFS does not apply the umask */
+#define MS_POSIXACL (1<<16) /* Supports POSIX ACLs */
#define MS_UNBINDABLE (1<<17) /* change to unbindable */
#define MS_PRIVATE (1<<18) /* change to private */
#define MS_SLAVE (1<<19) /* change to slave */
@@ -91,6 +91,7 @@ struct inodes_stat_t {
#define MS_I_VERSION (1<<23) /* Update inode I_version field */
#define MS_STRICTATIME (1<<24) /* Always perform atime updates */
#define MS_LAZYTIME (1<<25) /* Update the on-disk [acm]times lazily */
+#define MS_RICHACL (1<<26) /* Supports richacls */
/* These sb flags are internal to the kernel */
#define MS_NOSEC (1<<28)
--
2.4.2
^ permalink raw reply related
* [RFC v4 00/31] Richacls
From: Andreas Gruenbacher @ 2015-06-24 21:56 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-nfs-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA,
samba-technical-w/Ol4Ecudpl8XjKLYN78aQ,
linux-security-module-u79uwXL29TY76Z2rM5mHXA
Hello,
here's another update of the richacl patch queue. The changes since the last
posting (https://lwn.net/Articles/641764/) include:
* The owner and other masks now determine the owner and other
permissions rather than just limiting them. For example, a
'chmod u=rw' will always grant the owner read and write access.
The group mask still behaves as before and only limits the group
class permissions. Hence, the owner, group, and other masks
now behave like the 'user::', 'group::', and 'mask::' entries in
POSIX ACLs.
* ACL entries for users matching the current owner are treated similar to
owner@ entries; they match the file owner. This differs from how such
entries are treated in POSIX ACLs but is more consistent with the
NFSv4 / Windows ACL model.
* Permissions implicitly granted to the owner ("ACo") are no longer added to
owner@ entries automatically (they are still granted though). The idea
behind adding them was to make the acl reflect the actual permissions
more closely, but that didn't turn out to be helpful.
* Various smaller improvements and bug fixes.
The complete patch queue is available here:
git://git.kernel.org/pub/scm/linux/kernel/git/agruen/linux-richacl.git \
richacl-2015-06-24
I'm leaving out patches here which have been queued for 4.2 already. Also,
the nfs patches need some more work before another round of reviews.
Thanks,
Andreas
Andreas Gruenbacher (29):
vfs: Add IS_ACL() and IS_RICHACL() tests
vfs: Add MAY_CREATE_FILE and MAY_CREATE_DIR permission flags
vfs: Add MAY_DELETE_SELF and MAY_DELETE_CHILD permission flags
vfs: Make the inode passed to inode_change_ok non-const
vfs: Add permission flags for setting file attributes
richacl: In-memory representation and helper functions
richacl: Permission mapping functions
richacl: Compute maximum file masks from an acl
richacl: Update the file masks in chmod()
richacl: Permission check algorithm
vfs: Cache base_acl objects in inodes
vfs: Cache richacl in struct inode
richacl: Check if an acl is equivalent to a file mode
richacl: Create-time inheritance
richacl: Automatic Inheritance
richacl: xattr mapping functions
vfs: Add richacl permission checking
richacl: acl editing helper functions
richacl: Move everyone@ aces down the acl
richacl: Propagate everyone@ permissions to other aces
richacl: Set the owner permissions to the owner mask
richacl: Set the other permissions to the other mask
richacl: Isolate the owner and group classes
richacl: Apply the file masks to a richacl
richacl: Create richacl from mode values
nfsd: Keep list of acls to dispose of in compoundargs
nfsd: Use richacls as internal acl representation
nfsd: Add richacl support
nfsd: Add support for the v4.1 dacl attribute
Aneesh Kumar K.V (2):
ext4: Add richacl support
ext4: Add richacl feature flag
drivers/staging/lustre/lustre/llite/llite_lib.c | 2 +-
fs/Kconfig | 9 +
fs/Makefile | 3 +
fs/attr.c | 81 ++-
fs/ext4/Kconfig | 15 +
fs/ext4/Makefile | 1 +
fs/ext4/acl.c | 6 +-
fs/ext4/acl.h | 12 +-
fs/ext4/ext4.h | 6 +-
fs/ext4/file.c | 6 +-
fs/ext4/ialloc.c | 7 +-
fs/ext4/inode.c | 10 +-
fs/ext4/namei.c | 11 +-
fs/ext4/richacl.c | 211 ++++++
fs/ext4/richacl.h | 47 ++
fs/ext4/super.c | 41 +-
fs/ext4/xattr.c | 6 +
fs/ext4/xattr.h | 1 +
fs/f2fs/acl.c | 4 +-
fs/inode.c | 15 +-
fs/namei.c | 108 ++-
fs/nfs_common/Makefile | 1 +
fs/nfs_common/nfs4acl.c | 41 ++
fs/nfsd/Kconfig | 1 +
fs/nfsd/acl.h | 23 +-
fs/nfsd/nfs4acl.c | 483 +++++++------
fs/nfsd/nfs4proc.c | 19 +-
fs/nfsd/nfs4xdr.c | 267 ++++---
fs/nfsd/nfsd.h | 6 +-
fs/nfsd/xdr4.h | 12 +-
fs/posix_acl.c | 26 +-
fs/richacl_base.c | 539 ++++++++++++++
fs/richacl_compat.c | 908 ++++++++++++++++++++++++
fs/richacl_inode.c | 264 +++++++
fs/richacl_xattr.c | 210 ++++++
fs/xattr.c | 34 +-
include/linux/fs.h | 50 +-
include/linux/nfs4.h | 24 +-
include/linux/nfs4acl.h | 7 +
include/linux/posix_acl.h | 12 +-
include/linux/richacl.h | 342 +++++++++
include/linux/richacl_compat.h | 40 ++
include/linux/richacl_xattr.h | 52 ++
include/uapi/linux/fs.h | 3 +-
include/uapi/linux/nfs4.h | 3 +-
include/uapi/linux/xattr.h | 2 +
46 files changed, 3498 insertions(+), 473 deletions(-)
create mode 100644 fs/ext4/richacl.c
create mode 100644 fs/ext4/richacl.h
create mode 100644 fs/nfs_common/nfs4acl.c
create mode 100644 fs/richacl_base.c
create mode 100644 fs/richacl_compat.c
create mode 100644 fs/richacl_inode.c
create mode 100644 fs/richacl_xattr.c
create mode 100644 include/linux/nfs4acl.h
create mode 100644 include/linux/richacl.h
create mode 100644 include/linux/richacl_compat.h
create mode 100644 include/linux/richacl_xattr.h
--
2.4.2
^ permalink raw reply
* Re: [PATCH v6 10/12] KVM: arm64: guest debug, HW assisted debug support
From: Christoffer Dall @ 2015-06-24 20:22 UTC (permalink / raw)
To: Alex Bennée
Cc: kvm-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
kvmarm-FPEHb7Xf0XXUo1n7N8X6UoWGPAHP3yOg, marc.zyngier-5wv7dgnIgG8,
peter.maydell-QSEj5FYQhm4dnm+yROfE0A, agraf-l3A5Bk7waGM,
drjones-H+wXaHxf7aLQT0dZR+AlfA, pbonzini-H+wXaHxf7aLQT0dZR+AlfA,
zhichao.huang-QSEj5FYQhm4dnm+yROfE0A,
jan.kiszka-kv7WeFo6aLtBDgjK7y7TUQ,
dahi-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8,
r65777-KZfg59tc24xl57MIdRCFDg, bp-l3A5Bk7waGM, Gleb Natapov,
Jonathan Corbet, Russell King, Catalin Marinas, Will Deacon,
Peter Zijlstra, Lorenzo Pieralisi, Ingo Molnar,
open list:DOCUMENTATION, open list, open list:ABI/API
In-Reply-To: <1434716630-18260-11-git-send-email-alex.bennee-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
On Fri, Jun 19, 2015 at 01:23:48PM +0100, Alex Bennée wrote:
> This adds support for userspace to control the HW debug registers for
> guest debug. In the debug ioctl we copy the IMPDEF defined number of
s/defined//
> registers into a new register set called host_debug_state. There is now
> a new vcpu parameter called debug_ptr which selects which register set
> is to copied into the real registers when world switch occurs.
But this patch doesn't seem to add the debug_ptr field?
s/to//
>
> I've moved some helper functions into the hw_breakpoint.h header for
> re-use.
>
> As with single step we need to tweak the guest registers to enable the
> exceptions so we need to save and restore those bits.
>
> Two new capabilities have been added to the KVM_EXTENSION ioctl to allow
> userspace to query the number of hardware break and watch points
> available on the host hardware.
>
> Signed-off-by: Alex Bennée <alex.bennee-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>
> ---
> v2
> - switched to C setup
> - replace host debug registers directly into context
> - minor tweak to api docs
> - setup right register for debug
> - add FAR_EL2 to debug exit structure
> - add support for trapping debug register access
> v3
> - remove stray trace statement
> - fix spacing around operators (various)
> - clean-up usage of trap_debug
> - introduce debug_ptr, replace excessive memcpy stuff
> - don't use memcpy in ioctl, just assign
> - update cap ioctl documentation
> - reword a number comments
> - rename host_debug_state->external_debug_state
> v4
> - use the new u32/u64 split debug_ptr approach
> - fix some wording/comments
> v5
> - don't set MDSCR_EL1.KDE (not needed)
> v6
> - update wording given change in commentary
> - KVM_GUESTDBG_USE_HW_BP->KVM_GUESTDBG_USE_HW
> ---
> Documentation/virtual/kvm/api.txt | 7 ++++++-
> arch/arm/kvm/arm.c | 7 +++++++
> arch/arm64/include/asm/hw_breakpoint.h | 12 +++++++++++
> arch/arm64/include/asm/kvm_host.h | 6 +++++-
> arch/arm64/kernel/hw_breakpoint.c | 12 -----------
> arch/arm64/kvm/debug.c | 37 +++++++++++++++++++++++++++++-----
> arch/arm64/kvm/handle_exit.c | 6 ++++++
> arch/arm64/kvm/reset.c | 12 +++++++++++
> include/uapi/linux/kvm.h | 2 ++
> 9 files changed, 82 insertions(+), 19 deletions(-)
>
> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> index 33c8143..ada57df 100644
> --- a/Documentation/virtual/kvm/api.txt
> +++ b/Documentation/virtual/kvm/api.txt
> @@ -2668,7 +2668,7 @@ The top 16 bits of the control field are architecture specific control
> flags which can include the following:
>
> - KVM_GUESTDBG_USE_SW_BP: using software breakpoints [x86, arm64]
> - - KVM_GUESTDBG_USE_HW_BP: using hardware breakpoints [x86, s390]
> + - KVM_GUESTDBG_USE_HW_BP: using hardware breakpoints [x86, s390, arm64]
> - KVM_GUESTDBG_INJECT_DB: inject DB type exception [x86]
> - KVM_GUESTDBG_INJECT_BP: inject BP type exception [x86]
> - KVM_GUESTDBG_EXIT_PENDING: trigger an immediate guest exit [s390]
> @@ -2683,6 +2683,11 @@ updated to the correct (supplied) values.
> The second part of the structure is architecture specific and
> typically contains a set of debug registers.
>
> +For arm64 the number of debug registers is implementation defined and
> +can be determined by querying the KVM_CAP_GUEST_DEBUG_HW_BPS and
> +KVM_CAP_GUEST_DEBUG_HW_WPS capabilities which return a positive number
> +indicating the number of supported registers.
> +
> When debug events exit the main run loop with the reason
> KVM_EXIT_DEBUG with the kvm_debug_exit_arch part of the kvm_run
> structure containing architecture specific debug information.
> diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
> index 0d17c7b..60c4045 100644
> --- a/arch/arm/kvm/arm.c
> +++ b/arch/arm/kvm/arm.c
> @@ -307,6 +307,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
>
> #define KVM_GUESTDBG_VALID_MASK (KVM_GUESTDBG_ENABLE | \
> KVM_GUESTDBG_USE_SW_BP | \
> + KVM_GUESTDBG_USE_HW | \
> KVM_GUESTDBG_SINGLESTEP)
>
> /**
> @@ -327,6 +328,12 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
>
> if (dbg->control & KVM_GUESTDBG_ENABLE) {
> vcpu->guest_debug = dbg->control;
> +
> + /* Hardware assisted Break and Watch points */
> + if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW) {
> + vcpu->arch.external_debug_state = dbg->arch;
> + }
> +
> } else {
> /* If not enabled clear all flags */
> vcpu->guest_debug = 0;
> diff --git a/arch/arm64/include/asm/hw_breakpoint.h b/arch/arm64/include/asm/hw_breakpoint.h
> index 52b484b..c450552 100644
> --- a/arch/arm64/include/asm/hw_breakpoint.h
> +++ b/arch/arm64/include/asm/hw_breakpoint.h
> @@ -130,6 +130,18 @@ static inline void ptrace_hw_copy_thread(struct task_struct *task)
> }
> #endif
>
> +/* Determine number of BRP registers available. */
> +static inline int get_num_brps(void)
> +{
> + return ((read_cpuid(ID_AA64DFR0_EL1) >> 12) & 0xf) + 1;
> +}
> +
> +/* Determine number of WRP registers available. */
> +static inline int get_num_wrps(void)
> +{
> + return ((read_cpuid(ID_AA64DFR0_EL1) >> 20) & 0xf) + 1;
> +}
> +
> extern struct pmu perf_ops_bp;
>
> #endif /* __KERNEL__ */
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 9697daf..0a3ee7b 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -116,13 +116,17 @@ struct kvm_vcpu_arch {
> * debugging the guest from the host and to maintain separate host and
> * guest state during world switches. vcpu_debug_state are the debug
> * registers of the vcpu as the guest sees them. host_debug_state are
> - * the host registers which are saved and restored during world switches.
> + * the host registers which are saved and restored during
> + * world switches. external_debug_state contains the debug
> + * values we want to debugging the guest. This is set via the
nit: s/debugging/debug/
> + * KVM_SET_GUEST_DEBUG ioctl.
> *
> * debug_ptr points to the set of debug registers that should be loaded
> * onto the hardware when running the guest.
> */
> struct kvm_guest_debug_arch *debug_ptr;
> struct kvm_guest_debug_arch vcpu_debug_state;
> + struct kvm_guest_debug_arch external_debug_state;
>
> /* Pointer to host CPU context */
> kvm_cpu_context_t *host_cpu_context;
> diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
> index e7d934d..3a41bbf 100644
> --- a/arch/arm64/kernel/hw_breakpoint.c
> +++ b/arch/arm64/kernel/hw_breakpoint.c
> @@ -49,18 +49,6 @@ static DEFINE_PER_CPU(int, stepping_kernel_bp);
> static int core_num_brps;
> static int core_num_wrps;
>
> -/* Determine number of BRP registers available. */
> -static int get_num_brps(void)
> -{
> - return ((read_cpuid(ID_AA64DFR0_EL1) >> 12) & 0xf) + 1;
> -}
> -
> -/* Determine number of WRP registers available. */
> -static int get_num_wrps(void)
> -{
> - return ((read_cpuid(ID_AA64DFR0_EL1) >> 20) & 0xf) + 1;
> -}
> -
> int hw_breakpoint_slots(int type)
> {
> /*
> diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c
> index d439eb8..b287bbc 100644
> --- a/arch/arm64/kvm/debug.c
> +++ b/arch/arm64/kvm/debug.c
> @@ -96,10 +96,6 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
> MDCR_EL2_TDRA |
> MDCR_EL2_TDOSA);
>
> - /* Trap on access to debug registers? */
> - if (trap_debug)
> - vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA;
> -
> /* Is Guest debugging in effect? */
> if (vcpu->guest_debug) {
> /* Route all software debug exceptions to EL2 */
> @@ -134,11 +130,42 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
> } else {
> vcpu_sys_reg(vcpu, MDSCR_EL1) &= ~DBG_MDSCR_SS;
> }
> +
> + /*
> + * HW Breakpoints and watchpoints
> + *
> + * We simply switch the debug_ptr to point to our new
> + * external_debug_state which has been populated by the
> + * debug ioctl. The existing KVM_ARM64_DEBUG_DIRTY
> + * mechanism ensures the registers are updated on the
> + * world switch.
> + */
> + if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW) {
> + /* Enable breakpoints/watchpoints */
> + vcpu_sys_reg(vcpu, MDSCR_EL1) |= DBG_MDSCR_MDE;
> +
> + vcpu->arch.debug_ptr = &vcpu->arch.external_debug_state;
> + vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
> + trap_debug = true;
> + }
> }
> +
> + /* Trap debug register access */
> + if (trap_debug)
> + vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA;
> }
>
> void kvm_arm_clear_debug(struct kvm_vcpu *vcpu)
> {
> - if (vcpu->guest_debug)
> + if (vcpu->guest_debug) {
> restore_guest_debug_regs(vcpu);
> +
> + /*
> + * If we were using HW debug we need to restore the
> + * debug_ptr to the guest debug state.
> + */
> + if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW)
> + vcpu->arch.debug_ptr = &vcpu->arch.vcpu_debug_state;
I still think this would be more cleanly done in the setup_debug
function, but ok:
Reviewed-by: Christoffer Dall <christoffer.dall-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
^ permalink raw reply
* Re: [PATCH] st: convert to using driver attr groups for sysfs
From: "Kai Mäkisara (Kolumbus)" @ 2015-06-24 20:19 UTC (permalink / raw)
To: Seymour, Shane M; +Cc: linux-scsi@vger.kernel.org, linux-api@vger.kernel.org
In-Reply-To: <DDB9C85B850785449757F9914A034FCB3BFF68D9@G9W0766.americas.hpqcorp.net>
> On 23.6.2015, at 11.11, Seymour, Shane M <shane.seymour@hp.com> wrote:
>
> This patch changes the st driver to use attribute groups so
> driver sysfs files are created automatically. See the
> following for reference:
>
> http://kroah.com/log/blog/2013/06/26/how-to-create-a-sysfs-file-correctly/
>
Acked-by: Kai Mäkisara <kai.makisara@kolumbus.fi>
Thanks,
Kai
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v2] st: convert DRIVER_ATTR macros to DRIVER_ATTR_RO
From: "Kai Mäkisara (Kolumbus)" @ 2015-06-24 20:15 UTC (permalink / raw)
To: Seymour, Shane M
Cc: linux-scsi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Greg KH <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org> (gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org),
linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <DDB9C85B850785449757F9914A034FCB3F8E9E02-MCKW7lC+H9ISZAcGdq5asR6epYMZPwEe5NbjCUgZEJk@public.gmane.org>
> On 24.6.2015, at 9.54, Seymour, Shane M <shane.seymour-VXdhtT5mjnY@public.gmane.org> wrote:
>
>
> Convert DRIVER_ATTR macros to DRIVER_ATTR_RO requested by
> Greg KH. Also switched to using scnprintf instead of snprintf
> per Documentation/filesystems/sysfs.txt.
>
> Suggested-by: Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>
> Signed-off-by: Shane Seymour <shane.seymour-VXdhtT5mjnY@public.gmane.org>
> ---
> This patch was implemented on top of the previous patch to
> convert to using driver attr groups.
>
> Changes from v1:
> - switched to scnprintf from sprintf after feedback from Sergey
> Senozhatsky.
Acked-by: Kai Mäkisara <kai.makisara-9Aww8k/80nUxHbG02/KK1g@public.gmane.org>
Thanks,
Kai
^ permalink raw reply
* Re: [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
From: Srinivas Kandagatla @ 2015-06-24 18:50 UTC (permalink / raw)
To: Stefan Wahren, linux-arm-kernel
Cc: wxt, linux-api, Rob Herring, Kumar Gala, sboyd, arnd, s.hauer,
Greg Kroah-Hartman, linux-kernel, linux-arm-msm, mporter,
Maxime Ripard, pantelis.antoniou, devicetree, Mark Brown
In-Reply-To: <1641569650.41238.1435168054323.JavaMail.open-xchange@oxbsltgw35.schlund.de>
On 24/06/15 18:47, Stefan Wahren wrote:
> Hi Srinivas,
>
>> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 24. Juni 2015 um
>> 15:03 geschrieben:
>>
>>
>>
>>
>> On 24/06/15 13:30, Stefan Wahren wrote:
>>>>> If the question is just about hexdump, then hexdump itself can read
>>>>> file from given offset and size.
>>> yes, this is my question at first. Let me show the difference between
>>> the current implementation and my expectations as a user.
>>>
>>> $ hexdump /sys/class/nvmem/mxs-ocotp/nvmem
>>>
>>> Current implementation: dump the complete register range defined in DT
>>>
>> Its dumping the range which is specified in the provider regmap. If the
>> requirement is to dump only particular range, this has to be made
>> explicit while creating regmap, which is to specify the base address to
>> start from "First data register" and max_register to be "Last data
>> register "- "First data register"
>
> i know about max_register, but i can't find the base address in regmap_config.
>
Base is not in the regmap config, its the value which you pass to the
For example, if I had to do similar change to qfprom driver It would
look like:
><-----------------------cut---------------------------------><
diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c
index 7f7a82f..26ced95 100644
--- a/drivers/nvmem/qfprom.c
+++ b/drivers/nvmem/qfprom.c
@@ -52,9 +52,9 @@ static int qfprom_probe(struct platform_device *pdev)
if (IS_ERR(base))
return PTR_ERR(base);
- qfprom_regmap_config.max_register = resource_size(res) - 1;
+ qfprom_regmap_config.max_register = my_data_size;
- regmap = devm_regmap_init_mmio(dev, base, &qfprom_regmap_config);
+ regmap = devm_regmap_init_mmio(dev, base + data_offset,
&qfprom_regmap_config);
if (IS_ERR(regmap)) {
dev_err(dev, "regmap init failed\n");
return PTR_ERR(regmap);
><-----------------------cut---------------------------------><
--srini
> Do you mean struct regmap_access_table *rd_table ?
>
>>
>>> User expectation: dump only the data from OCOTP block
>>>
>>> Let me explain it for i.MX28 OCOTP
>>>
>>> 0x8002c000 // Start of OCOTP register block (defined in DT)
>>>
>>> 0x8002c020 // First data register
>>>
>>> 0x8002c290 // Last data register
>>>
>>> 0x8002dfff // End of OCOTP register block (defined in DT)
>>>
>>> My knowledge about regmap is limited, but how can i achieve that hexdump
>>> give me only the data registers? From my understanding this should be
>>> handled in regmap and not in the read function.
>>
>> Setup the base and regmap_config correctly in the provider driver before
>> calling regmap_init_mmio().
>>
>> Let me know if you need more details.
>
> Yes, please.
>
> Stefan
>
>>
>> --srini
>>
>>>
>>> Are my expectations about the raw access wrong?
>>>
>>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply related
* Re: [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
From: Stefan Wahren @ 2015-06-24 17:47 UTC (permalink / raw)
To: Srinivas Kandagatla,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: wxt-TNX95d0MmH7DzftRWevZcw, linux-api-u79uwXL29TY76Z2rM5mHXA,
Rob Herring, Kumar Gala, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
arnd-r2nGTMty4D4, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ,
Greg Kroah-Hartman, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
mporter-OWPKS81ov/FWk0Htik3J/w, Maxime Ripard,
pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
devicetree-u79uwXL29TY76Z2rM5mHXA, Mark Brown
In-Reply-To: <558AAA8D.8030209-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Hi Srinivas,
> Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> hat am 24. Juni 2015 um
> 15:03 geschrieben:
>
>
>
>
> On 24/06/15 13:30, Stefan Wahren wrote:
> >> >If the question is just about hexdump, then hexdump itself can read
> >> >file from given offset and size.
> > yes, this is my question at first. Let me show the difference between
> > the current implementation and my expectations as a user.
> >
> > $ hexdump /sys/class/nvmem/mxs-ocotp/nvmem
> >
> > Current implementation: dump the complete register range defined in DT
> >
> Its dumping the range which is specified in the provider regmap. If the
> requirement is to dump only particular range, this has to be made
> explicit while creating regmap, which is to specify the base address to
> start from "First data register" and max_register to be "Last data
> register "- "First data register"
i know about max_register, but i can't find the base address in regmap_config.
Do you mean struct regmap_access_table *rd_table ?
>
> > User expectation: dump only the data from OCOTP block
> >
> > Let me explain it for i.MX28 OCOTP
> >
> > 0x8002c000 // Start of OCOTP register block (defined in DT)
> >
> > 0x8002c020 // First data register
> >
> > 0x8002c290 // Last data register
> >
> > 0x8002dfff // End of OCOTP register block (defined in DT)
> >
> > My knowledge about regmap is limited, but how can i achieve that hexdump
> > give me only the data registers? From my understanding this should be
> > handled in regmap and not in the read function.
>
> Setup the base and regmap_config correctly in the provider driver before
> calling regmap_init_mmio().
>
> Let me know if you need more details.
Yes, please.
Stefan
>
> --srini
>
> >
> > Are my expectations about the raw access wrong?
> >
> >
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [RFC v3 1/4] fs: Add generic file system event notifications
From: Steve French @ 2015-06-24 16:26 UTC (permalink / raw)
To: Beata Michalska
Cc: Dmitry Monakhov, LKML, linux-fsdevel, linux-api@vger.kernel.org,
Greg Kroah-Hartman, Jan Kara, Theodore Ts'o, adilger.kernel,
hughd, lczerner, Christoph Hellwig, linux-ext4@vger.kernel.org,
linux-mm, kyungmin.park, kmpark
In-Reply-To: <558ACD3A.2020508@samsung.com>
On Wed, Jun 24, 2015 at 10:31 AM, Beata Michalska
<b.michalska@samsung.com> wrote:
> On 06/24/2015 10:47 AM, Dmitry Monakhov wrote:
>> Beata Michalska <b.michalska@samsung.com> writes:
>>
>>> Introduce configurable generic interface for file
>>> system-wide event notifications, to provide file
>>> systems with a common way of reporting any potential
>>> issues as they emerge.
>>>
>>> The notifications are to be issued through generic
>>> netlink interface by newly introduced multicast group.
>>>
>>> Threshold notifications have been included, allowing
>>> triggering an event whenever the amount of free space drops
>>> below a certain level - or levels to be more precise as two
>>> of them are being supported: the lower and the upper range.
>>> The notifications work both ways: once the threshold level
>>> has been reached, an event shall be generated whenever
>>> the number of available blocks goes up again re-activating
>>> the threshold.
>>>
>>> The interface has been exposed through a vfs. Once mounted,
>>> it serves as an entry point for the set-up where one can
>>> register for particular file system events.
>>>
>>> Signed-off-by: Beata Michalska <b.michalska@samsung.com>
>>> ---
>>> Documentation/filesystems/events.txt | 232 ++++++++++
>>> fs/Kconfig | 2 +
>>> fs/Makefile | 1 +
>>> fs/events/Kconfig | 7 +
>>> fs/events/Makefile | 5 +
>>> fs/events/fs_event.c | 809 ++++++++++++++++++++++++++++++++++
>>> fs/events/fs_event.h | 22 +
>>> fs/events/fs_event_netlink.c | 104 +++++
>>> fs/namespace.c | 1 +
>>> include/linux/fs.h | 6 +-
>>> include/linux/fs_event.h | 72 +++
>>> include/uapi/linux/Kbuild | 1 +
>>> include/uapi/linux/fs_event.h | 58 +++
>>> 13 files changed, 1319 insertions(+), 1 deletion(-)
>>> create mode 100644 Documentation/filesystems/events.txt
>>> create mode 100644 fs/events/Kconfig
>>> create mode 100644 fs/events/Makefile
>>> create mode 100644 fs/events/fs_event.c
>>> create mode 100644 fs/events/fs_event.h
>>> create mode 100644 fs/events/fs_event_netlink.c
>>> create mode 100644 include/linux/fs_event.h
>>> create mode 100644 include/uapi/linux/fs_event.h
>>>
>>> diff --git a/Documentation/filesystems/events.txt b/Documentation/filesystems/events.txt
>>> new file mode 100644
>>> index 0000000..c2e6227
>>> --- /dev/null
>>> +++ b/Documentation/filesystems/events.txt
>>> @@ -0,0 +1,232 @@
>>> +
>>> + Generic file system event notification interface
>>> +
>>> +Document created 23 April 2015 by Beata Michalska <b.michalska@samsung.com>
>>> +
>>> +1. The reason behind:
>>> +=====================
>>> +
>>> +There are many corner cases when things might get messy with the filesystems.
>>> +And it is not always obvious what and when went wrong. Sometimes you might
>>> +get some subtle hints that there is something going on - but by the time
>>> +you realise it, it might be too late as you are already out-of-space
>>> +or the filesystem has been remounted as read-only (i.e.). The generic
>>> +interface for the filesystem events fills the gap by providing a rather
>>> +easy way of real-time notifications triggered whenever something interesting
>>> +happens, allowing filesystems to report events in a common way, as they occur.
>>> +
>>> +2. How does it work:
>>> +====================
>>> +
>>> +The interface itself has been exposed as fstrace-type Virtual File System,
>>> +primarily to ease the process of setting up the configuration for the
>>> +notifications. So for starters, it needs to get mounted (obviously):
>>> +
>>> + mount -t fstrace none /sys/fs/events
>>> +
>>> +This will unveil the single fstrace filesystem entry - the 'config' file,
>>> +through which the notification are being set-up.
>>> +
>>> +Activating notifications for particular filesystem is as straightforward
>>> +as writing into the 'config' file. Note that by default all events, despite
>>> +the actual filesystem type, are being disregarded.
>>> +
>>> +Synopsis of config:
>>> +------------------
>>> +
>>> + MOUNT EVENT_TYPE [L1] [L2]
>>> +
>>> + MOUNT : the filesystem's mount point
>>> + EVENT_TYPE : event types - currently two of them are being supported:
>>> +
>>> + * generic events ("G") covering most common warnings
>>> + and errors that might be reported by any filesystem;
>>> + this option does not take any arguments;
>>> +
>>> + * threshold notifications ("T") - events sent whenever
>>> + the amount of available space drops below certain level;
>>> + it is possible to specify two threshold levels though
>>> + only one is required to properly setup the notifications;
>>> + as those refer to the number of available blocks, the lower
>>> + level [L1] needs to be higher than the upper one [L2]
>>> +
>>> +Sample request could look like the following:
>>> +
>>> + echo /sample/mount/point G T 710000 500000 > /sys/fs/events/config
>>> +
>>> +Multiple request might be specified provided they are separated with semicolon.
>>> +
>>> +The configuration itself might be modified at any time. One can add/remove
>>> +particular event types for given fielsystem, modify the threshold levels,
>>> +and remove single or all entries from the 'config' file.
>>> +
>>> + - Adding new event type:
>>> +
>>> + $ echo MOUNT EVENT_TYPE > /sys/fs/events/config
>>> +
>>> +(Note that is is enough to provide the event type to be enabled without
>>> +the already set ones.)
>>> +
>>> + - Removing event type:
>>> +
>>> + $ echo '!MOUNT EVENT_TYPE' > /sys/fs/events/config
>>> +
>>> + - Updating threshold limits:
>>> +
>>> + $ echo MOUNT T L1 L2 > /sys/fs/events/config
>>> +
>>> + - Removing single entry:
>>> +
>>> + $ echo '!MOUNT' > /sys/fs/events/config
>>> +
>>> + - Removing all entries:
>>> +
>>> + $ echo > /sys/fs/events/config
>>> +
>>> +Reading the file will list all registered entries with their current set-up
>>> +along with some additional info like the filesystem type and the backing device
>>> +name if available.
>>> +
>>> +Final, though a very important note on the configuration: when and if the
>>> +actual events are being triggered falls way beyond the scope of the generic
>>> +filesystem events interface. It is up to a particular filesystem
>>> +implementation which events are to be supported - if any at all. So if
>>> +given filesystem does not support the event notifications, an attempt to
>>> +enable those through 'config' file will fail.
>>> +
>>> +
>>> +3. The generic netlink interface support:
>>> +=========================================
>>> +
>>> +Whenever an event notification is triggered (by given filesystem) the current
>>> +configuration is being validated to decide whether a userpsace notification
>>> +should be launched. If there has been no request (in a mean of 'config' file
>>> +entry) for given event, one will be silently disregarded. If, on the other
>>> +hand, someone is 'watching' given filesystem for specific events, a generic
>>> +netlink message will be sent. A dedicated multicast group has been provided
>>> +solely for this purpose so in order to receive such notifications, one should
>>> +subscribe to this new multicast group. As for now only the init network
>>> +namespace is being supported.
>>> +
>>> +3.1 Message format
>>> +
>>> +The FS_NL_C_EVENT shall be stored within the generic netlink message header
>>> +as the command field. The message payload will provide more detailed info:
>>> +the backing device major and minor numbers, the event code and the id of
>>> +the process which action led to the event occurrence. In case of threshold
>>> +notifications, the current number of available blocks will be included
>>> +in the payload as well.
>>> +
>>> +
>>> + 0 1 2 3
>>> + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
>>> + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>>> + | NETLINK MESSAGE HEADER |
>>> + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>>> + | GENERIC NETLINK MESSAGE HEADER |
>>> + | (with FS_NL_C_EVENT as genlmsghdr cdm field) |
>>> + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>>> + | Optional user specific message header |
>>> + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>>> + | GENERIC MESSAGE PAYLOAD: |
>>> + +---------------------------------------------------------------+
>>> + | FS_NL_A_EVENT_ID (NLA_U32) |
>>> + +---------------------------------------------------------------+
>>> + | FS_NL_A_DEV_MAJOR (NLA_U32) |
>>> + +---------------------------------------------------------------+
>>> + | FS_NL_A_DEV_MINOR (NLA_U32) |
>>
> ...
>
>>> +
>>> +static int create_common_msg(struct sk_buff *skb, void *data)
>>> +{
>>> + struct fs_trace_entry *en = (struct fs_trace_entry *)data;
>>> + struct super_block *sb = en->sb;
>>> +
>>> + if (nla_put_u32(skb, FS_NL_A_DEV_MAJOR, MAJOR(sb->s_dev))
>>> + || nla_put_u32(skb, FS_NL_A_DEV_MINOR, MINOR(sb->s_dev)))
>>> + return -EINVAL;
>> What about diskless(nfs,cifs,etc) filesystem? btrfs also has no
>> valid sb->s_dev
And note that filesystem notifications and also file/directory change
notification are particularly useful in the case of a a network file
system (and heavily used by Windows desktop, Mac etc.) since when a
file is shared a user may not necessarily know that a file (or file
system as a whole) changed via another client (or on the server, or on
the server via a different protocol e.g.SMB3 vs NFSv4), but is more
likely to know about local changes to the same file. In some sense
the users of mounts on network file systems get more benefit from
notifications than a mount on a local file system would.
--
Thanks,
Steve
^ permalink raw reply
* Re: [RFC v3 1/4] fs: Add generic file system event notifications
From: Beata Michalska @ 2015-06-24 15:31 UTC (permalink / raw)
To: Dmitry Monakhov
Cc: linux-kernel, linux-fsdevel, linux-api, greg, jack, tytso,
adilger.kernel, hughd, lczerner, hch, linux-ext4, linux-mm,
kyungmin.park, kmpark
In-Reply-To: <87oak5ebmx.fsf@openvz.org>
On 06/24/2015 10:47 AM, Dmitry Monakhov wrote:
> Beata Michalska <b.michalska@samsung.com> writes:
>
>> Introduce configurable generic interface for file
>> system-wide event notifications, to provide file
>> systems with a common way of reporting any potential
>> issues as they emerge.
>>
>> The notifications are to be issued through generic
>> netlink interface by newly introduced multicast group.
>>
>> Threshold notifications have been included, allowing
>> triggering an event whenever the amount of free space drops
>> below a certain level - or levels to be more precise as two
>> of them are being supported: the lower and the upper range.
>> The notifications work both ways: once the threshold level
>> has been reached, an event shall be generated whenever
>> the number of available blocks goes up again re-activating
>> the threshold.
>>
>> The interface has been exposed through a vfs. Once mounted,
>> it serves as an entry point for the set-up where one can
>> register for particular file system events.
>>
>> Signed-off-by: Beata Michalska <b.michalska@samsung.com>
>> ---
>> Documentation/filesystems/events.txt | 232 ++++++++++
>> fs/Kconfig | 2 +
>> fs/Makefile | 1 +
>> fs/events/Kconfig | 7 +
>> fs/events/Makefile | 5 +
>> fs/events/fs_event.c | 809 ++++++++++++++++++++++++++++++++++
>> fs/events/fs_event.h | 22 +
>> fs/events/fs_event_netlink.c | 104 +++++
>> fs/namespace.c | 1 +
>> include/linux/fs.h | 6 +-
>> include/linux/fs_event.h | 72 +++
>> include/uapi/linux/Kbuild | 1 +
>> include/uapi/linux/fs_event.h | 58 +++
>> 13 files changed, 1319 insertions(+), 1 deletion(-)
>> create mode 100644 Documentation/filesystems/events.txt
>> create mode 100644 fs/events/Kconfig
>> create mode 100644 fs/events/Makefile
>> create mode 100644 fs/events/fs_event.c
>> create mode 100644 fs/events/fs_event.h
>> create mode 100644 fs/events/fs_event_netlink.c
>> create mode 100644 include/linux/fs_event.h
>> create mode 100644 include/uapi/linux/fs_event.h
>>
>> diff --git a/Documentation/filesystems/events.txt b/Documentation/filesystems/events.txt
>> new file mode 100644
>> index 0000000..c2e6227
>> --- /dev/null
>> +++ b/Documentation/filesystems/events.txt
>> @@ -0,0 +1,232 @@
>> +
>> + Generic file system event notification interface
>> +
>> +Document created 23 April 2015 by Beata Michalska <b.michalska@samsung.com>
>> +
>> +1. The reason behind:
>> +=====================
>> +
>> +There are many corner cases when things might get messy with the filesystems.
>> +And it is not always obvious what and when went wrong. Sometimes you might
>> +get some subtle hints that there is something going on - but by the time
>> +you realise it, it might be too late as you are already out-of-space
>> +or the filesystem has been remounted as read-only (i.e.). The generic
>> +interface for the filesystem events fills the gap by providing a rather
>> +easy way of real-time notifications triggered whenever something interesting
>> +happens, allowing filesystems to report events in a common way, as they occur.
>> +
>> +2. How does it work:
>> +====================
>> +
>> +The interface itself has been exposed as fstrace-type Virtual File System,
>> +primarily to ease the process of setting up the configuration for the
>> +notifications. So for starters, it needs to get mounted (obviously):
>> +
>> + mount -t fstrace none /sys/fs/events
>> +
>> +This will unveil the single fstrace filesystem entry - the 'config' file,
>> +through which the notification are being set-up.
>> +
>> +Activating notifications for particular filesystem is as straightforward
>> +as writing into the 'config' file. Note that by default all events, despite
>> +the actual filesystem type, are being disregarded.
>> +
>> +Synopsis of config:
>> +------------------
>> +
>> + MOUNT EVENT_TYPE [L1] [L2]
>> +
>> + MOUNT : the filesystem's mount point
>> + EVENT_TYPE : event types - currently two of them are being supported:
>> +
>> + * generic events ("G") covering most common warnings
>> + and errors that might be reported by any filesystem;
>> + this option does not take any arguments;
>> +
>> + * threshold notifications ("T") - events sent whenever
>> + the amount of available space drops below certain level;
>> + it is possible to specify two threshold levels though
>> + only one is required to properly setup the notifications;
>> + as those refer to the number of available blocks, the lower
>> + level [L1] needs to be higher than the upper one [L2]
>> +
>> +Sample request could look like the following:
>> +
>> + echo /sample/mount/point G T 710000 500000 > /sys/fs/events/config
>> +
>> +Multiple request might be specified provided they are separated with semicolon.
>> +
>> +The configuration itself might be modified at any time. One can add/remove
>> +particular event types for given fielsystem, modify the threshold levels,
>> +and remove single or all entries from the 'config' file.
>> +
>> + - Adding new event type:
>> +
>> + $ echo MOUNT EVENT_TYPE > /sys/fs/events/config
>> +
>> +(Note that is is enough to provide the event type to be enabled without
>> +the already set ones.)
>> +
>> + - Removing event type:
>> +
>> + $ echo '!MOUNT EVENT_TYPE' > /sys/fs/events/config
>> +
>> + - Updating threshold limits:
>> +
>> + $ echo MOUNT T L1 L2 > /sys/fs/events/config
>> +
>> + - Removing single entry:
>> +
>> + $ echo '!MOUNT' > /sys/fs/events/config
>> +
>> + - Removing all entries:
>> +
>> + $ echo > /sys/fs/events/config
>> +
>> +Reading the file will list all registered entries with their current set-up
>> +along with some additional info like the filesystem type and the backing device
>> +name if available.
>> +
>> +Final, though a very important note on the configuration: when and if the
>> +actual events are being triggered falls way beyond the scope of the generic
>> +filesystem events interface. It is up to a particular filesystem
>> +implementation which events are to be supported - if any at all. So if
>> +given filesystem does not support the event notifications, an attempt to
>> +enable those through 'config' file will fail.
>> +
>> +
>> +3. The generic netlink interface support:
>> +=========================================
>> +
>> +Whenever an event notification is triggered (by given filesystem) the current
>> +configuration is being validated to decide whether a userpsace notification
>> +should be launched. If there has been no request (in a mean of 'config' file
>> +entry) for given event, one will be silently disregarded. If, on the other
>> +hand, someone is 'watching' given filesystem for specific events, a generic
>> +netlink message will be sent. A dedicated multicast group has been provided
>> +solely for this purpose so in order to receive such notifications, one should
>> +subscribe to this new multicast group. As for now only the init network
>> +namespace is being supported.
>> +
>> +3.1 Message format
>> +
>> +The FS_NL_C_EVENT shall be stored within the generic netlink message header
>> +as the command field. The message payload will provide more detailed info:
>> +the backing device major and minor numbers, the event code and the id of
>> +the process which action led to the event occurrence. In case of threshold
>> +notifications, the current number of available blocks will be included
>> +in the payload as well.
>> +
>> +
>> + 0 1 2 3
>> + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
>> + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>> + | NETLINK MESSAGE HEADER |
>> + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>> + | GENERIC NETLINK MESSAGE HEADER |
>> + | (with FS_NL_C_EVENT as genlmsghdr cdm field) |
>> + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>> + | Optional user specific message header |
>> + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>> + | GENERIC MESSAGE PAYLOAD: |
>> + +---------------------------------------------------------------+
>> + | FS_NL_A_EVENT_ID (NLA_U32) |
>> + +---------------------------------------------------------------+
>> + | FS_NL_A_DEV_MAJOR (NLA_U32) |
>> + +---------------------------------------------------------------+
>> + | FS_NL_A_DEV_MINOR (NLA_U32) |
>
...
>> +
>> +static int create_common_msg(struct sk_buff *skb, void *data)
>> +{
>> + struct fs_trace_entry *en = (struct fs_trace_entry *)data;
>> + struct super_block *sb = en->sb;
>> +
>> + if (nla_put_u32(skb, FS_NL_A_DEV_MAJOR, MAJOR(sb->s_dev))
>> + || nla_put_u32(skb, FS_NL_A_DEV_MINOR, MINOR(sb->s_dev)))
>> + return -EINVAL;
> What about diskless(nfs,cifs,etc) filesystem? btrfs also has no
> valid sb->s_dev
Those are using the anon ids, generated by get_anon_bdev
(through set_anon_super). This id will be visible in
/proc/self/mountinfo or through stat. i.e:
30 22 0:21 / /root/fake_fs/btrfs rw,realtime - btrfs /dev/loop4 rw,nospace_cache
Best Regards
Beata
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [PATCH v2] st: convert DRIVER_ATTR macros to DRIVER_ATTR_RO
From: Greg KH <gregkh@linuxfoundation.org> (gregkh@linuxfoundation.org) @ 2015-06-24 15:10 UTC (permalink / raw)
To: Seymour, Shane M
Cc: linux-scsi@vger.kernel.org, linux-api@vger.kernel.org,
Kai.Makisara@kolumbus.fi
In-Reply-To: <DDB9C85B850785449757F9914A034FCB3F8E9E02@G4W3219.americas.hpqcorp.net>
On Wed, Jun 24, 2015 at 06:54:35AM +0000, Seymour, Shane M wrote:
>
> Convert DRIVER_ATTR macros to DRIVER_ATTR_RO requested by
> Greg KH. Also switched to using scnprintf instead of snprintf
> per Documentation/filesystems/sysfs.txt.
>
> Suggested-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Signed-off-by: Shane Seymour <shane.seymour@hp.com>
> ---
> This patch was implemented on top of the previous patch to
> convert to using driver attr groups.
>
> Changes from v1:
> - switched to scnprintf from sprintf after feedback from Sergey
> Senozhatsky.
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
^ permalink raw reply
* Re: [PATCH] st: convert DRIVER_ATTR macros to DRIVER_ATTR_RO
From: Greg KH <gregkh@linuxfoundation.org> (gregkh@linuxfoundation.org) @ 2015-06-24 15:10 UTC (permalink / raw)
To: Sergey Senozhatsky
Cc: Seymour, Shane M, linux-scsi@vger.kernel.org,
linux-api@vger.kernel.org, Kai.Makisara@kolumbus.fi
In-Reply-To: <20150624062557.GA10808@swordfish>
On Wed, Jun 24, 2015 at 03:25:57PM +0900, Sergey Senozhatsky wrote:
> On (06/24/15 06:10), Seymour, Shane M wrote:
> [..]
> >
> > /* The sysfs driver interface. Read-only at the moment */
> > -static ssize_t st_try_direct_io_show(struct device_driver *ddp, char *buf)
> > +static ssize_t try_direct_io_show(struct device_driver *ddp, char *buf)
> > {
> > - return snprintf(buf, PAGE_SIZE, "%d\n", try_direct_io);
> > + return sprintf(buf, "%d\n", try_direct_io);
> > }
>
> a nitpick,
>
> per Documentation/filesystems/sysfs.txt
>
> :
> : - show() should always use scnprintf().
> :
That should be rewritten to say, "don't use snprintf(), but scnprintf(),
if you want to. Otherwise sprintf() should be fine as you obviously are
only returning a single value to userspace"
Or something like that.
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH RFC] vhost: add ioctl to query nregions upper limit
From: Michael S. Tsirkin @ 2015-06-24 15:08 UTC (permalink / raw)
To: Igor Mammedov
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Paolo Bonzini,
kvm-u79uwXL29TY76Z2rM5mHXA,
virtualization-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
netdev-u79uwXL29TY76Z2rM5mHXA, linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20150624165229.4f8bf82b-XNjAa/bfCnL1wF9wiOj0lkEOCMrvLtNR@public.gmane.org>
On Wed, Jun 24, 2015 at 04:52:29PM +0200, Igor Mammedov wrote:
> On Wed, 24 Jun 2015 16:17:46 +0200
> "Michael S. Tsirkin" <mst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
>
> > On Wed, Jun 24, 2015 at 04:07:27PM +0200, Igor Mammedov wrote:
> > > On Wed, 24 Jun 2015 15:49:27 +0200
> > > "Michael S. Tsirkin" <mst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> > >
> > > > Userspace currently simply tries to give vhost as many regions
> > > > as it happens to have, but you only have the mem table
> > > > when you have initialized a large part of VM, so graceful
> > > > failure is very hard to support.
> > > >
> > > > The result is that userspace tends to fail catastrophically.
> > > >
> > > > Instead, add a new ioctl so userspace can find out how much kernel
> > > > supports, up front. This returns a positive value that we commit to.
> > > >
> > > > Also, document our contract with legacy userspace: when running on an
> > > > old kernel, you get -1 and you can assume at least 64 slots. Since 0
> > > > value's left unused, let's make that mean that the current userspace
> > > > behaviour (trial and error) is required, just in case we want it back.
> > > >
> > > > Signed-off-by: Michael S. Tsirkin <mst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> > > > Cc: Igor Mammedov <imammedo-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> > > > Cc: Paolo Bonzini <pbonzini-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> > > > ---
> > > > include/uapi/linux/vhost.h | 17 ++++++++++++++++-
> > > > drivers/vhost/vhost.c | 5 +++++
> > > > 2 files changed, 21 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/include/uapi/linux/vhost.h b/include/uapi/linux/vhost.h
> > > > index ab373191..f71fa6d 100644
> > > > --- a/include/uapi/linux/vhost.h
> > > > +++ b/include/uapi/linux/vhost.h
> > > > @@ -80,7 +80,7 @@ struct vhost_memory {
> > > > * Allows subsequent call to VHOST_OWNER_SET to succeed. */
> > > > #define VHOST_RESET_OWNER _IO(VHOST_VIRTIO, 0x02)
> > > >
> > > > -/* Set up/modify memory layout */
> > > > +/* Set up/modify memory layout: see also VHOST_GET_MEM_MAX_NREGIONS below. */
> > > > #define VHOST_SET_MEM_TABLE _IOW(VHOST_VIRTIO, 0x03, struct vhost_memory)
> > > >
> > > > /* Write logging setup. */
> > > > @@ -127,6 +127,21 @@ struct vhost_memory {
> > > > /* Set eventfd to signal an error */
> > > > #define VHOST_SET_VRING_ERR _IOW(VHOST_VIRTIO, 0x22, struct vhost_vring_file)
> > > >
> > > > +/* Query upper limit on nregions in VHOST_SET_MEM_TABLE arguments.
> > > > + * Returns:
> > > > + * 0 < value <= MAX_INT - gives the upper limit, higher values will fail
> > > > + * 0 - there's no static limit: try and see if it works
> > > > + * -1 - on failure
> > > > + */
> > > > +#define VHOST_GET_MEM_MAX_NREGIONS _IO(VHOST_VIRTIO, 0x23)
> > > > +
> > > > +/* Returned by VHOST_GET_MEM_MAX_NREGIONS to mean there's no static limit:
> > > > + * try and it'll work if you are lucky. */
> > > > +#define VHOST_MEM_MAX_NREGIONS_NONE 0
> > > is it needed? we always have a limit,
> > > or don't have IOCTL => -1 => old try and see way
> > >
> > > > +/* We support at least as many nregions in VHOST_SET_MEM_TABLE:
> > > > + * for use on legacy kernels without VHOST_GET_MEM_MAX_NREGIONS support. */
> > > > +#define VHOST_MEM_MAX_NREGIONS_DEFAULT 64
> > > ^^^ not used below,
> > > if it's for legacy then perhaps s/DEFAULT/LEGACY/
> >
> > The assumption was that userspace detecting old kernels will just use 64,
> > this means we do want a flag to get the old way.
> >
> > OTOH if you won't think it's useful, let me know.
> this header will be synced into QEMU's tree so that we could use this define there,
> isn't it? IMHO then _LEGACY is more exact description of macro.
>
> As for 0 return value, -1 is just fine for detecting old kernels (i.e. try and see if it works), so 0 looks unnecessary but it doesn't in any way hurt either.
> For me limit or -1 is enough to try fix userspace.
OK.
Do you want to try now before I do v2?
> >
> > > > +
> > > > /* VHOST_NET specific defines */
> > > >
> > > > /* Attach virtio net ring to a raw socket, or tap device.
> > > > diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> > > > index 9e8e004..3b68f9d 100644
> > > > --- a/drivers/vhost/vhost.c
> > > > +++ b/drivers/vhost/vhost.c
> > > > @@ -917,6 +917,11 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp)
> > > > long r;
> > > > int i, fd;
> > > >
> > > > + if (ioctl == VHOST_GET_MEM_MAX_NREGIONS) {
> > > > + r = VHOST_MEMORY_MAX_NREGIONS;
> > > > + goto done;
> > > > + }
> > > > +
> > > > /* If you are not the owner, you can become one */
> > > > if (ioctl == VHOST_SET_OWNER) {
> > > > r = vhost_dev_set_owner(d);
> > --
> > To unsubscribe from this list: send the line "unsubscribe kvm" in
> > the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] st: convert DRIVER_ATTR macros to DRIVER_ATTR_RO
From: Greg KH <gregkh@linuxfoundation.org> (gregkh@linuxfoundation.org) @ 2015-06-24 15:08 UTC (permalink / raw)
To: Sergey Senozhatsky
Cc: Seymour, Shane M, linux-scsi@vger.kernel.org,
linux-api@vger.kernel.org, Kai.Makisara@kolumbus.fi
In-Reply-To: <20150624062557.GA10808@swordfish>
On Wed, Jun 24, 2015 at 03:25:57PM +0900, Sergey Senozhatsky wrote:
> On (06/24/15 06:10), Seymour, Shane M wrote:
> [..]
> >
> > /* The sysfs driver interface. Read-only at the moment */
> > -static ssize_t st_try_direct_io_show(struct device_driver *ddp, char *buf)
> > +static ssize_t try_direct_io_show(struct device_driver *ddp, char *buf)
> > {
> > - return snprintf(buf, PAGE_SIZE, "%d\n", try_direct_io);
> > + return sprintf(buf, "%d\n", try_direct_io);
> > }
>
> a nitpick,
>
> per Documentation/filesystems/sysfs.txt
>
> :
> : - show() should always use scnprintf().
> :
Don't believe everything you read, this change is just fine.
But, you are doing something here that you did not say you were doing in
the changelog, so for that reason, the patch should be redone.
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH RFC] vhost: add ioctl to query nregions upper limit
From: Igor Mammedov @ 2015-06-24 14:52 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: kvm, linux-api, linux-kernel, virtualization, netdev,
Paolo Bonzini
In-Reply-To: <20150624161606-mutt-send-email-mst@redhat.com>
On Wed, 24 Jun 2015 16:17:46 +0200
"Michael S. Tsirkin" <mst@redhat.com> wrote:
> On Wed, Jun 24, 2015 at 04:07:27PM +0200, Igor Mammedov wrote:
> > On Wed, 24 Jun 2015 15:49:27 +0200
> > "Michael S. Tsirkin" <mst@redhat.com> wrote:
> >
> > > Userspace currently simply tries to give vhost as many regions
> > > as it happens to have, but you only have the mem table
> > > when you have initialized a large part of VM, so graceful
> > > failure is very hard to support.
> > >
> > > The result is that userspace tends to fail catastrophically.
> > >
> > > Instead, add a new ioctl so userspace can find out how much kernel
> > > supports, up front. This returns a positive value that we commit to.
> > >
> > > Also, document our contract with legacy userspace: when running on an
> > > old kernel, you get -1 and you can assume at least 64 slots. Since 0
> > > value's left unused, let's make that mean that the current userspace
> > > behaviour (trial and error) is required, just in case we want it back.
> > >
> > > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> > > Cc: Igor Mammedov <imammedo@redhat.com>
> > > Cc: Paolo Bonzini <pbonzini@redhat.com>
> > > ---
> > > include/uapi/linux/vhost.h | 17 ++++++++++++++++-
> > > drivers/vhost/vhost.c | 5 +++++
> > > 2 files changed, 21 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/include/uapi/linux/vhost.h b/include/uapi/linux/vhost.h
> > > index ab373191..f71fa6d 100644
> > > --- a/include/uapi/linux/vhost.h
> > > +++ b/include/uapi/linux/vhost.h
> > > @@ -80,7 +80,7 @@ struct vhost_memory {
> > > * Allows subsequent call to VHOST_OWNER_SET to succeed. */
> > > #define VHOST_RESET_OWNER _IO(VHOST_VIRTIO, 0x02)
> > >
> > > -/* Set up/modify memory layout */
> > > +/* Set up/modify memory layout: see also VHOST_GET_MEM_MAX_NREGIONS below. */
> > > #define VHOST_SET_MEM_TABLE _IOW(VHOST_VIRTIO, 0x03, struct vhost_memory)
> > >
> > > /* Write logging setup. */
> > > @@ -127,6 +127,21 @@ struct vhost_memory {
> > > /* Set eventfd to signal an error */
> > > #define VHOST_SET_VRING_ERR _IOW(VHOST_VIRTIO, 0x22, struct vhost_vring_file)
> > >
> > > +/* Query upper limit on nregions in VHOST_SET_MEM_TABLE arguments.
> > > + * Returns:
> > > + * 0 < value <= MAX_INT - gives the upper limit, higher values will fail
> > > + * 0 - there's no static limit: try and see if it works
> > > + * -1 - on failure
> > > + */
> > > +#define VHOST_GET_MEM_MAX_NREGIONS _IO(VHOST_VIRTIO, 0x23)
> > > +
> > > +/* Returned by VHOST_GET_MEM_MAX_NREGIONS to mean there's no static limit:
> > > + * try and it'll work if you are lucky. */
> > > +#define VHOST_MEM_MAX_NREGIONS_NONE 0
> > is it needed? we always have a limit,
> > or don't have IOCTL => -1 => old try and see way
> >
> > > +/* We support at least as many nregions in VHOST_SET_MEM_TABLE:
> > > + * for use on legacy kernels without VHOST_GET_MEM_MAX_NREGIONS support. */
> > > +#define VHOST_MEM_MAX_NREGIONS_DEFAULT 64
> > ^^^ not used below,
> > if it's for legacy then perhaps s/DEFAULT/LEGACY/
>
> The assumption was that userspace detecting old kernels will just use 64,
> this means we do want a flag to get the old way.
>
> OTOH if you won't think it's useful, let me know.
this header will be synced into QEMU's tree so that we could use this define there,
isn't it? IMHO then _LEGACY is more exact description of macro.
As for 0 return value, -1 is just fine for detecting old kernels (i.e. try and see if it works), so 0 looks unnecessary but it doesn't in any way hurt either.
For me limit or -1 is enough to try fix userspace.
>
> > > +
> > > /* VHOST_NET specific defines */
> > >
> > > /* Attach virtio net ring to a raw socket, or tap device.
> > > diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> > > index 9e8e004..3b68f9d 100644
> > > --- a/drivers/vhost/vhost.c
> > > +++ b/drivers/vhost/vhost.c
> > > @@ -917,6 +917,11 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp)
> > > long r;
> > > int i, fd;
> > >
> > > + if (ioctl == VHOST_GET_MEM_MAX_NREGIONS) {
> > > + r = VHOST_MEMORY_MAX_NREGIONS;
> > > + goto done;
> > > + }
> > > +
> > > /* If you are not the owner, you can become one */
> > > if (ioctl == VHOST_SET_OWNER) {
> > > r = vhost_dev_set_owner(d);
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH RFC] vhost: add ioctl to query nregions upper limit
From: Michael S. Tsirkin @ 2015-06-24 14:17 UTC (permalink / raw)
To: Igor Mammedov
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Paolo Bonzini,
kvm-u79uwXL29TY76Z2rM5mHXA,
virtualization-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
netdev-u79uwXL29TY76Z2rM5mHXA, linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20150624160727.2e0f542f-XNjAa/bfCnL1wF9wiOj0lkEOCMrvLtNR@public.gmane.org>
On Wed, Jun 24, 2015 at 04:07:27PM +0200, Igor Mammedov wrote:
> On Wed, 24 Jun 2015 15:49:27 +0200
> "Michael S. Tsirkin" <mst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
>
> > Userspace currently simply tries to give vhost as many regions
> > as it happens to have, but you only have the mem table
> > when you have initialized a large part of VM, so graceful
> > failure is very hard to support.
> >
> > The result is that userspace tends to fail catastrophically.
> >
> > Instead, add a new ioctl so userspace can find out how much kernel
> > supports, up front. This returns a positive value that we commit to.
> >
> > Also, document our contract with legacy userspace: when running on an
> > old kernel, you get -1 and you can assume at least 64 slots. Since 0
> > value's left unused, let's make that mean that the current userspace
> > behaviour (trial and error) is required, just in case we want it back.
> >
> > Signed-off-by: Michael S. Tsirkin <mst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> > Cc: Igor Mammedov <imammedo-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> > Cc: Paolo Bonzini <pbonzini-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> > ---
> > include/uapi/linux/vhost.h | 17 ++++++++++++++++-
> > drivers/vhost/vhost.c | 5 +++++
> > 2 files changed, 21 insertions(+), 1 deletion(-)
> >
> > diff --git a/include/uapi/linux/vhost.h b/include/uapi/linux/vhost.h
> > index ab373191..f71fa6d 100644
> > --- a/include/uapi/linux/vhost.h
> > +++ b/include/uapi/linux/vhost.h
> > @@ -80,7 +80,7 @@ struct vhost_memory {
> > * Allows subsequent call to VHOST_OWNER_SET to succeed. */
> > #define VHOST_RESET_OWNER _IO(VHOST_VIRTIO, 0x02)
> >
> > -/* Set up/modify memory layout */
> > +/* Set up/modify memory layout: see also VHOST_GET_MEM_MAX_NREGIONS below. */
> > #define VHOST_SET_MEM_TABLE _IOW(VHOST_VIRTIO, 0x03, struct vhost_memory)
> >
> > /* Write logging setup. */
> > @@ -127,6 +127,21 @@ struct vhost_memory {
> > /* Set eventfd to signal an error */
> > #define VHOST_SET_VRING_ERR _IOW(VHOST_VIRTIO, 0x22, struct vhost_vring_file)
> >
> > +/* Query upper limit on nregions in VHOST_SET_MEM_TABLE arguments.
> > + * Returns:
> > + * 0 < value <= MAX_INT - gives the upper limit, higher values will fail
> > + * 0 - there's no static limit: try and see if it works
> > + * -1 - on failure
> > + */
> > +#define VHOST_GET_MEM_MAX_NREGIONS _IO(VHOST_VIRTIO, 0x23)
> > +
> > +/* Returned by VHOST_GET_MEM_MAX_NREGIONS to mean there's no static limit:
> > + * try and it'll work if you are lucky. */
> > +#define VHOST_MEM_MAX_NREGIONS_NONE 0
> is it needed? we always have a limit,
> or don't have IOCTL => -1 => old try and see way
>
> > +/* We support at least as many nregions in VHOST_SET_MEM_TABLE:
> > + * for use on legacy kernels without VHOST_GET_MEM_MAX_NREGIONS support. */
> > +#define VHOST_MEM_MAX_NREGIONS_DEFAULT 64
> ^^^ not used below,
> if it's for legacy then perhaps s/DEFAULT/LEGACY/
The assumption was that userspace detecting old kernels will just use 64,
this means we do want a flag to get the old way.
OTOH if you won't think it's useful, let me know.
> > +
> > /* VHOST_NET specific defines */
> >
> > /* Attach virtio net ring to a raw socket, or tap device.
> > diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> > index 9e8e004..3b68f9d 100644
> > --- a/drivers/vhost/vhost.c
> > +++ b/drivers/vhost/vhost.c
> > @@ -917,6 +917,11 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp)
> > long r;
> > int i, fd;
> >
> > + if (ioctl == VHOST_GET_MEM_MAX_NREGIONS) {
> > + r = VHOST_MEMORY_MAX_NREGIONS;
> > + goto done;
> > + }
> > +
> > /* If you are not the owner, you can become one */
> > if (ioctl == VHOST_SET_OWNER) {
> > r = vhost_dev_set_owner(d);
^ permalink raw reply
* Re: [PATCH RFC] vhost: add ioctl to query nregions upper limit
From: Igor Mammedov @ 2015-06-24 14:07 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Paolo Bonzini,
kvm-u79uwXL29TY76Z2rM5mHXA,
virtualization-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
netdev-u79uwXL29TY76Z2rM5mHXA, linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1435153753-2686-1-git-send-email-mst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
On Wed, 24 Jun 2015 15:49:27 +0200
"Michael S. Tsirkin" <mst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> Userspace currently simply tries to give vhost as many regions
> as it happens to have, but you only have the mem table
> when you have initialized a large part of VM, so graceful
> failure is very hard to support.
>
> The result is that userspace tends to fail catastrophically.
>
> Instead, add a new ioctl so userspace can find out how much kernel
> supports, up front. This returns a positive value that we commit to.
>
> Also, document our contract with legacy userspace: when running on an
> old kernel, you get -1 and you can assume at least 64 slots. Since 0
> value's left unused, let's make that mean that the current userspace
> behaviour (trial and error) is required, just in case we want it back.
>
> Signed-off-by: Michael S. Tsirkin <mst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> Cc: Igor Mammedov <imammedo-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> Cc: Paolo Bonzini <pbonzini-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---
> include/uapi/linux/vhost.h | 17 ++++++++++++++++-
> drivers/vhost/vhost.c | 5 +++++
> 2 files changed, 21 insertions(+), 1 deletion(-)
>
> diff --git a/include/uapi/linux/vhost.h b/include/uapi/linux/vhost.h
> index ab373191..f71fa6d 100644
> --- a/include/uapi/linux/vhost.h
> +++ b/include/uapi/linux/vhost.h
> @@ -80,7 +80,7 @@ struct vhost_memory {
> * Allows subsequent call to VHOST_OWNER_SET to succeed. */
> #define VHOST_RESET_OWNER _IO(VHOST_VIRTIO, 0x02)
>
> -/* Set up/modify memory layout */
> +/* Set up/modify memory layout: see also VHOST_GET_MEM_MAX_NREGIONS below. */
> #define VHOST_SET_MEM_TABLE _IOW(VHOST_VIRTIO, 0x03, struct vhost_memory)
>
> /* Write logging setup. */
> @@ -127,6 +127,21 @@ struct vhost_memory {
> /* Set eventfd to signal an error */
> #define VHOST_SET_VRING_ERR _IOW(VHOST_VIRTIO, 0x22, struct vhost_vring_file)
>
> +/* Query upper limit on nregions in VHOST_SET_MEM_TABLE arguments.
> + * Returns:
> + * 0 < value <= MAX_INT - gives the upper limit, higher values will fail
> + * 0 - there's no static limit: try and see if it works
> + * -1 - on failure
> + */
> +#define VHOST_GET_MEM_MAX_NREGIONS _IO(VHOST_VIRTIO, 0x23)
> +
> +/* Returned by VHOST_GET_MEM_MAX_NREGIONS to mean there's no static limit:
> + * try and it'll work if you are lucky. */
> +#define VHOST_MEM_MAX_NREGIONS_NONE 0
is it needed? we always have a limit,
or don't have IOCTL => -1 => old try and see way
> +/* We support at least as many nregions in VHOST_SET_MEM_TABLE:
> + * for use on legacy kernels without VHOST_GET_MEM_MAX_NREGIONS support. */
> +#define VHOST_MEM_MAX_NREGIONS_DEFAULT 64
^^^ not used below,
if it's for legacy then perhaps s/DEFAULT/LEGACY/
> +
> /* VHOST_NET specific defines */
>
> /* Attach virtio net ring to a raw socket, or tap device.
> diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> index 9e8e004..3b68f9d 100644
> --- a/drivers/vhost/vhost.c
> +++ b/drivers/vhost/vhost.c
> @@ -917,6 +917,11 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp)
> long r;
> int i, fd;
>
> + if (ioctl == VHOST_GET_MEM_MAX_NREGIONS) {
> + r = VHOST_MEMORY_MAX_NREGIONS;
> + goto done;
> + }
> +
> /* If you are not the owner, you can become one */
> if (ioctl == VHOST_SET_OWNER) {
> r = vhost_dev_set_owner(d);
^ permalink raw reply
* [PATCH RFC] vhost: add ioctl to query nregions upper limit
From: Michael S. Tsirkin @ 2015-06-24 13:49 UTC (permalink / raw)
To: linux-kernel
Cc: Igor Mammedov, Paolo Bonzini, kvm, virtualization, netdev,
linux-api
Userspace currently simply tries to give vhost as many regions
as it happens to have, but you only have the mem table
when you have initialized a large part of VM, so graceful
failure is very hard to support.
The result is that userspace tends to fail catastrophically.
Instead, add a new ioctl so userspace can find out how much kernel
supports, up front. This returns a positive value that we commit to.
Also, document our contract with legacy userspace: when running on an
old kernel, you get -1 and you can assume at least 64 slots. Since 0
value's left unused, let's make that mean that the current userspace
behaviour (trial and error) is required, just in case we want it back.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
---
include/uapi/linux/vhost.h | 17 ++++++++++++++++-
drivers/vhost/vhost.c | 5 +++++
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/vhost.h b/include/uapi/linux/vhost.h
index ab373191..f71fa6d 100644
--- a/include/uapi/linux/vhost.h
+++ b/include/uapi/linux/vhost.h
@@ -80,7 +80,7 @@ struct vhost_memory {
* Allows subsequent call to VHOST_OWNER_SET to succeed. */
#define VHOST_RESET_OWNER _IO(VHOST_VIRTIO, 0x02)
-/* Set up/modify memory layout */
+/* Set up/modify memory layout: see also VHOST_GET_MEM_MAX_NREGIONS below. */
#define VHOST_SET_MEM_TABLE _IOW(VHOST_VIRTIO, 0x03, struct vhost_memory)
/* Write logging setup. */
@@ -127,6 +127,21 @@ struct vhost_memory {
/* Set eventfd to signal an error */
#define VHOST_SET_VRING_ERR _IOW(VHOST_VIRTIO, 0x22, struct vhost_vring_file)
+/* Query upper limit on nregions in VHOST_SET_MEM_TABLE arguments.
+ * Returns:
+ * 0 < value <= MAX_INT - gives the upper limit, higher values will fail
+ * 0 - there's no static limit: try and see if it works
+ * -1 - on failure
+ */
+#define VHOST_GET_MEM_MAX_NREGIONS _IO(VHOST_VIRTIO, 0x23)
+
+/* Returned by VHOST_GET_MEM_MAX_NREGIONS to mean there's no static limit:
+ * try and it'll work if you are lucky. */
+#define VHOST_MEM_MAX_NREGIONS_NONE 0
+/* We support at least as many nregions in VHOST_SET_MEM_TABLE:
+ * for use on legacy kernels without VHOST_GET_MEM_MAX_NREGIONS support. */
+#define VHOST_MEM_MAX_NREGIONS_DEFAULT 64
+
/* VHOST_NET specific defines */
/* Attach virtio net ring to a raw socket, or tap device.
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 9e8e004..3b68f9d 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -917,6 +917,11 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp)
long r;
int i, fd;
+ if (ioctl == VHOST_GET_MEM_MAX_NREGIONS) {
+ r = VHOST_MEMORY_MAX_NREGIONS;
+ goto done;
+ }
+
/* If you are not the owner, you can become one */
if (ioctl == VHOST_SET_OWNER) {
r = vhost_dev_set_owner(d);
--
MST
^ permalink raw reply related
* [PATCH v6 4/5] block: loop: prepare for supporing direct IO
From: Ming Lei @ 2015-06-24 13:07 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Dave Kleikamp
Cc: Jens Axboe, Zach Brown, Christoph Hellwig, Maxim Patlasov,
Andrew Morton, Alexander Viro, Tejun Heo, Dave Chinner, Ming Lei,
linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1435151266-13819-1-git-send-email-ming.lei-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
This patches provides one interface for enabling direct IO
from user space:
- userspace(such as losetup) can pass 'file' which is
opened/fcntl as O_DIRECT
Also __loop_update_dio() is introduced to check if direct I/O
can be used on current loop setting.
The last big change is to introduce LO_FLAGS_DIRECT_IO flag
for userspace to know if direct IO is used to access backing
file.
Cc: linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Signed-off-by: Ming Lei <ming.lei-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
---
drivers/block/loop.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/block/loop.h | 1 +
include/uapi/linux/loop.h | 1 +
3 files changed, 58 insertions(+)
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 555b895..599d668 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -421,6 +421,51 @@ struct switch_request {
struct completion wait;
};
+static void __loop_update_dio(struct loop_device *lo, bool dio)
+{
+ struct file *file = lo->lo_backing_file;
+ struct inode *inode = file->f_mapping->host;
+ bool use_dio;
+
+ /*
+ * loop block's logical block size is 512, now
+ * we support direct I/O only if the backing
+ * block devices' minimize I/O size is 512 and
+ * the offset is aligned with 512.
+ */
+ if (dio) {
+ if (inode->i_sb->s_bdev &&
+ bdev_io_min(inode->i_sb->s_bdev) == 512 &&
+ !(lo->lo_offset & 511))
+ use_dio = true;
+ else
+ use_dio = false;
+ } else {
+ use_dio = false;
+ }
+
+ if (lo->use_dio == use_dio)
+ return;
+
+ /* flush dirty pages before changing direct IO */
+ vfs_fsync(file, 0);
+
+ /*
+ * The flag of LO_FLAGS_DIRECT_IO is handled similarly with
+ * LO_FLAGS_READ_ONLY, both are set from kernel, and losetup
+ * will get updated by ioctl(LOOP_GET_STATUS)
+ */
+ blk_mq_freeze_queue(lo->lo_queue);
+ lo->use_dio = use_dio;
+ lo->lo_flags |= use_dio ? LO_FLAGS_DIRECT_IO : 0;
+ blk_mq_unfreeze_queue(lo->lo_queue);
+}
+
+static inline void loop_update_dio(struct loop_device *lo)
+{
+ __loop_update_dio(lo, io_is_direct(lo->lo_backing_file));
+}
+
/*
* Do the actual switch; called from the BIO completion routine
*/
@@ -441,6 +486,7 @@ static void do_loop_switch(struct loop_device *lo, struct switch_request *p)
mapping->host->i_bdev->bd_block_size : PAGE_SIZE;
lo->old_gfp_mask = mapping_gfp_mask(mapping);
mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
+ loop_update_dio(lo);
}
/*
@@ -627,11 +673,19 @@ static ssize_t loop_attr_partscan_show(struct loop_device *lo, char *buf)
return sprintf(buf, "%s\n", partscan ? "1" : "0");
}
+static ssize_t loop_attr_dio_show(struct loop_device *lo, char *buf)
+{
+ int dio = (lo->lo_flags & LO_FLAGS_DIRECT_IO);
+
+ return sprintf(buf, "%s\n", dio ? "1" : "0");
+}
+
LOOP_ATTR_RO(backing_file);
LOOP_ATTR_RO(offset);
LOOP_ATTR_RO(sizelimit);
LOOP_ATTR_RO(autoclear);
LOOP_ATTR_RO(partscan);
+LOOP_ATTR_RO(dio);
static struct attribute *loop_attrs[] = {
&loop_attr_backing_file.attr,
@@ -639,6 +693,7 @@ static struct attribute *loop_attrs[] = {
&loop_attr_sizelimit.attr,
&loop_attr_autoclear.attr,
&loop_attr_partscan.attr,
+ &loop_attr_dio.attr,
NULL,
};
@@ -783,6 +838,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync)
blk_queue_flush(lo->lo_queue, REQ_FLUSH);
+ loop_update_dio(lo);
set_capacity(lo->lo_disk, size);
bd_set_size(bdev, size << 9);
loop_sysfs_init(lo);
diff --git a/drivers/block/loop.h b/drivers/block/loop.h
index b6c7d21..d1de221 100644
--- a/drivers/block/loop.h
+++ b/drivers/block/loop.h
@@ -58,6 +58,7 @@ struct loop_device {
struct mutex lo_ctl_mutex;
struct kthread_worker worker;
struct task_struct *worker_task;
+ bool use_dio;
struct request_queue *lo_queue;
struct blk_mq_tag_set tag_set;
diff --git a/include/uapi/linux/loop.h b/include/uapi/linux/loop.h
index e0cecd2..949851c 100644
--- a/include/uapi/linux/loop.h
+++ b/include/uapi/linux/loop.h
@@ -21,6 +21,7 @@ enum {
LO_FLAGS_READ_ONLY = 1,
LO_FLAGS_AUTOCLEAR = 4,
LO_FLAGS_PARTSCAN = 8,
+ LO_FLAGS_DIRECT_IO = 16,
};
#include <asm/posix_types.h> /* for __kernel_old_dev_t */
--
1.9.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox