Linux userland API discussions
 help / color / mirror / Atom feed
* Re: [PATCH v6 6/8] virtio: add explicit big-endian support to memory accessors
From: Cornelia Huck @ 2015-04-27  9:14 UTC (permalink / raw)
  To: Greg Kurz
  Cc: Rusty Russell, Michael S. Tsirkin, Thomas Huth,
	kvm-u79uwXL29TY76Z2rM5mHXA, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	virtualization-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
In-Reply-To: <20150424122521.19156.65586.stgit-GiB8zCg7hOfDOqzlkpFKJg@public.gmane.org>

On Fri, 24 Apr 2015 14:26:24 +0200
Greg Kurz <gkurz-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org> wrote:

> The current memory accessors logic is:
> - little endian if little_endian
> - native endian (i.e. no byteswap) if !little_endian
> 
> If we want to fully support cross-endian vhost, we also need to be
> able to convert to big endian.
> 
> Instead of changing the little_endian argument to some 3-value enum, this
> patch changes the logic to:
> - little endian if little_endian
> - big endian if !little_endian
> 
> The native endian case is handled by all users with a trivial helper. This
> patch doesn't change any functionality, nor it does add overhead.
> 
> Signed-off-by: Greg Kurz <gkurz-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
> ---
> 
> Changes since v5:
> - changed endian checking helpers as suggested by Thomas (use || and line
>   breaker)
> 
>  drivers/net/macvtap.c            |    3 ++-
>  drivers/net/tun.c                |    3 ++-
>  drivers/vhost/vhost.h            |    3 ++-
>  include/linux/virtio_byteorder.h |   24 ++++++++++++++----------
>  include/linux/virtio_config.h    |    3 ++-
>  include/linux/vringh.h           |    3 ++-
>  6 files changed, 24 insertions(+), 15 deletions(-)
> 

Reviewed-by: Cornelia Huck <cornelia.huck-tA70FqPdS9bQT0dZR+AlfA@public.gmane.org>

^ permalink raw reply

* Re: [PATCH v6 7/8] vhost: cross-endian support for legacy devices
From: Cornelia Huck @ 2015-04-27  9:17 UTC (permalink / raw)
  To: Greg Kurz
  Cc: Rusty Russell, Michael S. Tsirkin, Thomas Huth, kvm, linux-api,
	linux-kernel, virtualization
In-Reply-To: <20150424122632.19156.88058.stgit@bahia.local>

On Fri, 24 Apr 2015 14:27:24 +0200
Greg Kurz <gkurz@linux.vnet.ibm.com> wrote:

> This patch brings cross-endian support to vhost when used to implement
> legacy virtio devices. Since it is a relatively rare situation, the
> feature availability is controlled by a kernel config option (not set
> by default).
> 
> The vq->is_le boolean field is added to cache the endianness to be
> used for ring accesses. It defaults to native endian, as expected
> by legacy virtio devices. When the ring gets active, we force little
> endian if the device is modern. When the ring is deactivated, we
> revert to the native endian default.
> 
> If cross-endian was compiled in, a vq->user_be boolean field is added
> so that userspace may request a specific endianness. This field is
> used to override the default when activating the ring of a legacy
> device. It has no effect on modern devices.
> 
> Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
> ---
> 
> Changes since v5:
> - fixed description in Kconfig
> - fixed error description in uapi header
> - dropped useless semi-colon in the vhost_vq_reset_user_be() stub
> 
>  drivers/vhost/Kconfig      |   15 ++++++++
>  drivers/vhost/vhost.c      |   85 +++++++++++++++++++++++++++++++++++++++++++-
>  drivers/vhost/vhost.h      |   11 +++++-
>  include/uapi/linux/vhost.h |   14 +++++++
>  4 files changed, 122 insertions(+), 3 deletions(-)
> 
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>

^ permalink raw reply

* [RFC v2 0/4] fs: Add generic file system event notifications
From: Beata Michalska @ 2015-04-27 11:51 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-api-u79uwXL29TY76Z2rM5mHXA
  Cc: jack-AlSwsSmVLrQ, tytso-3s7WtUTddSA,
	adilger.kernel-m1MBpc4rdrD3fQ9qLvQP4Q,
	hughd-hpIqsD4AKlfQT0dZR+AlfA, lczerner-H+wXaHxf7aLQT0dZR+AlfA,
	hch-wEGCiKHe2LqWVfeAwA7xHQ, linux-ext4-u79uwXL29TY76Z2rM5mHXA,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	kmpark-wEGCiKHe2LqWVfeAwA7xHQ

Hi All,

This series is a follow-up of the RFC patchset for generic filesystem
events interface [1]. As there have been some rather significant changes
to the synchronization method being used, more extensive testing (stress
testing) has been performed (thus the delay).

Changes from v1:
	- Improved synchronization: switched to RCU accompanied with
	  ref counting mechanism
	- Limiting scope of supported event types along with default
	  event codes
	- Slightly modified configuration (event types followed by arguments
	  where required)
	- Updated documentation
	- Unified naming for netlink attributes
	- Updated netlink message format to include dev minor:major numbers
	  despite the filesystem type
	- Switched to single cmd id for messages
	- Removed the per-config-entry ids

---
[1] https://lkml.org/lkml/2015/4/15/46
---


Beata Michalska (4):
  fs: Add generic file system event notifications
  ext4: Add helper function to mark group as corrupted
  ext4: Add support for generic FS events
  shmem: Add support for generic FS events

 Documentation/filesystems/events.txt |  231 ++++++++++
 fs/Makefile                          |    1 +
 fs/events/Makefile                   |    6 +
 fs/events/fs_event.c                 |  770 ++++++++++++++++++++++++++++++++++
 fs/events/fs_event.h                 |   25 ++
 fs/events/fs_event_netlink.c         |   99 +++++
 fs/ext4/balloc.c                     |   25 +-
 fs/ext4/ext4.h                       |   10 +
 fs/ext4/ialloc.c                     |    5 +-
 fs/ext4/inode.c                      |    2 +-
 fs/ext4/mballoc.c                    |   17 +-
 fs/ext4/resize.c                     |    1 +
 fs/ext4/super.c                      |   39 ++
 fs/namespace.c                       |    1 +
 include/linux/fs.h                   |    6 +-
 include/linux/fs_event.h             |   58 +++
 include/uapi/linux/fs_event.h        |   54 +++
 include/uapi/linux/genetlink.h       |    1 +
 mm/shmem.c                           |   33 +-
 net/netlink/genetlink.c              |    7 +-
 20 files changed, 1357 insertions(+), 34 deletions(-)
 create mode 100644 Documentation/filesystems/events.txt
 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

-- 
1.7.9.5

^ permalink raw reply

* [RFC v2 1/4] fs: Add generic file system event notifications
From: Beata Michalska @ 2015-04-27 11:51 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-api
  Cc: jack, tytso, adilger.kernel, hughd, lczerner, hch, linux-ext4,
	linux-mm, kyungmin.park, kmpark
In-Reply-To: <1430135504-24334-1-git-send-email-b.michalska@samsung.com>

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 |  231 ++++++++++
 fs/Makefile                          |    1 +
 fs/events/Makefile                   |    6 +
 fs/events/fs_event.c                 |  770 ++++++++++++++++++++++++++++++++++
 fs/events/fs_event.h                 |   25 ++
 fs/events/fs_event_netlink.c         |   99 +++++
 fs/namespace.c                       |    1 +
 include/linux/fs.h                   |    6 +-
 include/linux/fs_event.h             |   58 +++
 include/uapi/linux/fs_event.h        |   54 +++
 include/uapi/linux/genetlink.h       |    1 +
 net/netlink/genetlink.c              |    7 +-
 12 files changed, 1257 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/filesystems/events.txt
 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..df0b0e2
--- /dev/null
+++ b/Documentation/filesystems/events.txt
@@ -0,0 +1,231 @@
+
+	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.
+
+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) 			|
+	+---------------------------------------------------------------+
+	|  		  FS_NL_A_CAUSED_ID (NLA_U32)			|
+	+---------------------------------------------------------------+
+	|  		    FS_NL_A_DATA (NLA_U64)			|
+	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+The above figure is based on:
+ http://www.linuxfoundation.org/collaborate/workgroups/networking/generic_netlink_howto#Message_Format
+
+
+4. API Reference:
+=================
+
+ 4.1 Generic file system event interface data & operations
+
+ #include <linux/fs_event.h>
+
+ struct fs_trace_info {
+	void	__rcu	*e_priv		 /* READ ONLY */
+	unsigned int 	events_cap_mask; /* Supported notifications */
+	const struct fs_trace_operations *ops;
+ };
+
+ struct fs_trace_operations {
+	void (*query)(struct super_block *, u64 *);
+ };
+
+ In order to get the fireworks and stuff, each filesystem needs to setup
+ the events_cap_mask field of the fs_trace_info structure, which has been
+ embedded within the super_block structure. This should reflect the type of
+ events the filesystem wants to support. In case of threshold notifications,
+ apart from setting the FS_EVENT_THRESH flag, the 'query' callback should
+ be provided as this enables the events interface to get the up-to-date
+ state of the number of available blocks whenever those notifications are
+ being requested.
+
+ The 'e_priv' field of the fs_trace_info structure should be completely ignored
+ as it's for INTERNAL USE ONLY. So don't even think of messing with it, if you
+ do not want to get yourself into some real trouble. If still, you are tempted
+ to do so - feel free, it's gonna be pure fun. Consider yourself warned.
+
+
+ 4.2 Event notification:
+
+ #include <linux/fs_event.h>
+ void fs_event_notify(struct super_block *sb, unsigned int event_id);
+
+ Notify the generic FS event interface of an occurring event.
+ This shall be used by any file system that wishes to inform any potential
+ listeners/watchers of a particular event.
+ - sb:         the filesystem's super block
+ - event_id:   an event identifier
+
+ 4.3 Threshold notifications:
+
+ #include <linux/fs_event.h>
+ void fs_event_alloc_space(struct super_block *sb, u64 ncount);
+ void fs_event_free_space(struct super_block *sb, u64 ncount);
+
+ Each filesystme supporting the threshold notifications should call
+ fs_event_alloc_space/fs_event_free_space respectively whenever the
+ amount of available blocks changes.
+ - sb:     the filesystem's super block
+ - ncount: number of blocks being acquired/released
+
+ Note that to properly handle the threshold notifications the fs events
+ interface needs to be kept up to date by the filesystems. Each should
+ register fs_trace_operations to enable querying the current number of
+ available blocks.
+
+ 4.4 Sending message through generic netlink interface
+
+ #include <linux/fs_event.h>
+
+ int fs_netlink_send_event(size_t size, unsigned int event_id,
+	int (*compose_msg)(struct sk_buff *skb, void *data), void *cbdata);
+
+ Although the fs event interface is fully responsible for sending the messages
+ over the netlink, filesystems might use the FS_EVENT multicast group to send
+ their own custom messages.
+ - size:        the size of the message payload
+ - event_id:    the event identifier
+ - compose_msg: a callback responsible for filling-in the message payload
+ - cbdata:      message custom data
+
+ Calling fs_netlink_send_event will result in a message being sent by
+ the FS_EVENT multicast group. Note that the body of the message should be
+ prepared (set-up )by the caller - through compose_msg callback. The message's
+ sk_buff will be allocated on behalf of the caller (thus the size parameter).
+ The compose_msg should only fill the payload with proper data. Unless
+ the event id is specified as FS_EVENT_NONE, it's value shall be added
+ to the payload prior to calling the compose_msg.
+
+
diff --git a/fs/Makefile b/fs/Makefile
index a88ac48..798021d 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -126,3 +126,4 @@ obj-y				+= exofs/ # Multiple modules
 obj-$(CONFIG_CEPH_FS)		+= ceph/
 obj-$(CONFIG_PSTORE)		+= pstore/
 obj-$(CONFIG_EFIVAR_FS)		+= efivarfs/
+obj-y				+= events/
diff --git a/fs/events/Makefile b/fs/events/Makefile
new file mode 100644
index 0000000..58d1454
--- /dev/null
+++ b/fs/events/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the Linux Generic File System Event Interface
+#
+
+obj-y := fs_event.o
+obj-$(CONFIG_NET) += fs_event_netlink.o
diff --git a/fs/events/fs_event.c b/fs/events/fs_event.c
new file mode 100644
index 0000000..ea6afdd
--- /dev/null
+++ b/fs/events/fs_event.c
@@ -0,0 +1,770 @@
+/*
+ * Generic File System Evens Interface
+ *
+ * Copyright(c) 2015 Samsung Electronics. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ *
+ * 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/fs.h>
+#include <linux/hashtable.h>
+#include <linux/module.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/parser.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/rcupdate.h>
+#include <net/genetlink.h>
+#include "../mount.h"
+#include "fs_event.h"
+
+static LIST_HEAD(fs_trace_list);
+static DEFINE_SPINLOCK(fs_trace_lock);
+
+static struct kmem_cache *fs_trace_cachep __read_mostly;
+
+static atomic_t stray_traces = ATOMIC_INIT(0);
+static DECLARE_WAIT_QUEUE_HEAD(trace_wq);
+/*
+ * Threshold notification state bits.
+ * Note the reverse as this refers to the number
+ * of available blocks.
+ */
+#define THRESH_LR_BELOW		0x0001 /* Falling below the lower range */
+#define THRESH_LR_BEYOND	0x0002
+#define THRESH_UR_BELOW		0x0004
+#define THRESH_UR_BEYOND	0x0008 /* Going beyond the upper range */
+
+#define THRESH_LR_ON	(THRESH_LR_BELOW | THRESH_LR_BEYOND)
+#define THRESH_UR_ON	(THRESH_UR_BELOW | THRESH_UR_BEYOND)
+
+#define FS_TRACE_ADD	0x100000
+
+struct fs_trace_entry {
+	atomic_t	 count;
+	atomic_t	 active;
+	struct super_block *sb;
+	unsigned int	 notify;
+	struct path	 mnt_path;
+	struct list_head node;
+
+	struct fs_event_thresh {
+		u64		 avail_space;
+		u64		 lrange;
+		u64		 urange;
+		unsigned int	 state;
+	}		 th;
+	struct rcu_head	 rcu_head;
+	spinlock_t	 lock;
+};
+
+static const match_table_t fs_etypes = {
+	{ FS_EVENT_GENERIC, "G"   },
+	{ FS_EVENT_THRESH,  "T"   },
+	{ 0, NULL },
+};
+
+static __always_inline int fs_trace_query_data(struct super_block *sb,
+				       struct fs_trace_entry *en)
+{
+	if (sb->s_etrace.ops && sb->s_etrace.ops->query) {
+		sb->s_etrace.ops->query(sb, &en->th.avail_space);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static inline void fs_trace_entry_list_del(struct fs_trace_entry *en)
+{
+
+	lockdep_assert_held(&fs_trace_lock);
+
+	if (!atomic_add_unless(&en->active, -1, 0))
+		return;
+	/*
+	 * At this point the trace entry is being marked as inactive
+	 * so no new references will be allowed.
+	 */
+	list_del(&en->node);
+	atomic_inc(&stray_traces);
+}
+
+static inline void fs_trace_entry_free(struct fs_trace_entry *en)
+{
+	kmem_cache_free(fs_trace_cachep, en);
+}
+
+static void fs_destroy_trace_entry(struct rcu_head *rcu_head)
+{
+	struct fs_trace_entry *en = container_of(rcu_head,
+					struct fs_trace_entry, rcu_head);
+
+	WARN_ON(atomic_read(&en->active));
+	fs_trace_entry_free(en);
+	atomic_dec(&stray_traces);
+}
+
+static inline void fs_release_trace_entry(struct fs_trace_entry *en)
+{
+	struct super_block *sb = en->sb;
+
+	rcu_assign_pointer(sb->s_etrace.e_priv, NULL);
+	call_rcu(&en->rcu_head, fs_destroy_trace_entry);
+}
+
+static inline void fs_trace_entry_put(struct fs_trace_entry *en)
+{
+	if (en && atomic_dec_and_test(&en->count))
+		fs_release_trace_entry(en);
+}
+
+static inline
+struct fs_trace_entry *fs_trace_entry_get(struct fs_trace_entry *en)
+{
+	if (en) {
+		if (!atomic_inc_not_zero(&en->count))
+			return NULL;
+		/* Don't allow referencing inactive object */
+		if (!atomic_read(&en->active)) {
+			fs_trace_entry_put(en);
+			return NULL;
+		}
+	}
+	return en;
+}
+
+static struct fs_trace_entry *fetch_trace_entry(struct super_block *sb)
+{
+	struct fs_trace_entry *en;
+
+	if (!sb)
+		return NULL;
+
+	rcu_read_lock();
+	en = rcu_dereference(sb->s_etrace.e_priv);
+	en = fs_trace_entry_get(en);
+	rcu_read_unlock();
+
+	return en;
+}
+
+static int fs_remove_trace_entry(struct super_block *sb)
+{
+	struct fs_trace_entry *en;
+
+	en = fetch_trace_entry(sb);
+	if (!en)
+		return -EINVAL;
+
+	spin_lock(&fs_trace_lock);
+	/*
+	 * The trace entry might have already been removed
+	 * from the list of active traces with the proper
+	 * ref drop, though it was still in use handling
+	 * one of the fs events. This means that the object
+	 * has been already scheduled for being released.
+	 */
+	if (atomic_read(&en->active)) {
+		fs_trace_entry_list_del(en);
+		fs_trace_entry_put(en);
+	}
+	spin_unlock(&fs_trace_lock);
+	fs_trace_entry_put(en);
+	return 0;
+}
+
+static void fs_remove_all_traces(void)
+{
+	struct fs_trace_entry *en, *guard;
+
+	spin_lock(&fs_trace_lock);
+	list_for_each_entry_safe(en, guard, &fs_trace_list, node) {
+		fs_trace_entry_list_del(en);
+		fs_trace_entry_put(en);
+	}
+	spin_unlock(&fs_trace_lock);
+}
+
+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;
+
+	if (nla_put_u64(skb, FS_NL_A_CAUSED_ID, pid_nr(task_pid(current))))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int create_thresh_msg(struct sk_buff *skb, void *data)
+{
+	struct fs_trace_entry *en = (struct fs_trace_entry *)data;
+	int ret;
+
+	ret = create_common_msg(skb, data);
+	if (!ret)
+		ret = nla_put_u64(skb, FS_NL_A_DATA, en->th.avail_space);
+	return ret;
+}
+
+static void fs_event_send(struct fs_trace_entry *en, unsigned int event_id)
+{
+	size_t size = nla_total_size(sizeof(u32)) * 2 +
+		      nla_total_size(sizeof(u64));
+
+	fs_netlink_send_event(size, event_id, create_common_msg, en);
+}
+
+static void fs_event_send_thresh(struct fs_trace_entry *en,
+				  unsigned int event_id)
+{
+	size_t size = nla_total_size(sizeof(u32)) * 2 +
+		      nla_total_size(sizeof(u64)) * 2;
+
+	fs_netlink_send_event(size, event_id, create_thresh_msg, en);
+}
+
+void fs_event_notify(struct super_block *sb, unsigned int event_id)
+{
+	struct fs_trace_entry *en;
+
+	en = fetch_trace_entry(sb);
+	if (!en)
+		return;
+
+	spin_lock(&en->lock);
+	if (en->notify & FS_EVENT_GENERIC)
+		fs_event_send(en, event_id);
+	spin_unlock(&en->lock);
+	fs_trace_entry_put(en);
+}
+EXPORT_SYMBOL(fs_event_notify);
+
+void fs_event_alloc_space(struct super_block *sb, u64 ncount)
+{
+	struct fs_trace_entry *en;
+	s64 count;
+
+	en = fetch_trace_entry(sb);
+	if (!en)
+		return;
+
+	spin_lock(&en->lock);
+
+	if (!(en->notify & FS_EVENT_THRESH))
+		goto leave;
+	/* we shouldn't drop below 0 here,
+	 * unless there is a sync issue somewhere (?)
+	 */
+	count = en->th.avail_space - ncount;
+	en->th.avail_space = count < 0 ? 0 : count;
+
+	if (en->th.avail_space > en->th.lrange)
+		/* Not 'even' close - leave */
+		goto leave;
+
+	if (en->th.avail_space > en->th.urange) {
+		/* Close enough - the lower range has been reached */
+		if (!(en->th.state & THRESH_LR_BEYOND)) {
+			/* Send notification */
+			fs_event_send_thresh(en, FS_THR_LRBELOW);
+			en->th.state &= ~THRESH_LR_BELOW;
+			en->th.state |= THRESH_LR_BEYOND;
+		}
+		goto leave;
+	}
+	if (!(en->th.state & THRESH_UR_BEYOND)) {
+		fs_event_send_thresh(en, FS_THR_URBELOW);
+		en->th.state &=  ~THRESH_UR_BELOW;
+		en->th.state |= THRESH_UR_BEYOND;
+	}
+
+leave:
+	spin_unlock(&en->lock);
+	fs_trace_entry_put(en);
+}
+EXPORT_SYMBOL(fs_event_alloc_space);
+
+void fs_event_free_space(struct super_block *sb, u64 ncount)
+{
+	struct fs_trace_entry *en;
+
+	en = fetch_trace_entry(sb);
+	if (!en)
+		return;
+
+	spin_lock(&en->lock);
+
+	if (!(en->notify & FS_EVENT_THRESH))
+		goto leave;
+
+	en->th.avail_space += ncount;
+
+	if (en->th.avail_space > en->th.lrange) {
+		if (!(en->th.state & THRESH_LR_BELOW)
+		&& en->th.state & THRESH_LR_BEYOND) {
+			/* Send notification */
+			fs_event_send_thresh(en, FS_THR_LRABOVE);
+			en->th.state &= ~THRESH_LR_BEYOND;
+			en->th.state |= THRESH_LR_BELOW;
+			goto leave;
+		}
+	}
+	if (en->th.avail_space > en->th.urange) {
+		if (!(en->th.state & THRESH_UR_BELOW)
+		&& en->th.state & THRESH_UR_BEYOND) {
+			/* Notify */
+			fs_event_send_thresh(en, FS_THR_URABOVE);
+			en->th.state &= ~THRESH_UR_BEYOND;
+			en->th.state |= THRESH_UR_BELOW;
+		}
+	}
+leave:
+	spin_unlock(&en->lock);
+	fs_trace_entry_put(en);
+}
+EXPORT_SYMBOL(fs_event_free_space);
+
+void fs_event_mount_dropped(struct vfsmount *mnt)
+{
+	/*
+	 * This gets tricky here: the mount is dropped but the super
+	 * might not get released at once so there is very small chance
+	 * some notifications will come through.
+	 */
+	fs_remove_trace_entry(mnt->mnt_sb);
+}
+
+static int fs_new_trace_entry(struct path *path, struct fs_event_thresh *thresh,
+				unsigned int nmask)
+{
+	struct fs_trace_entry *en;
+	struct super_block *sb;
+	struct mount *r_mnt;
+
+	en = kmem_cache_zalloc(fs_trace_cachep, GFP_KERNEL);
+	if (unlikely(!en))
+		return -ENOMEM;
+	/*
+	 * Note that no reference is being taken here for the path as it would
+	 * make the umount unnecessarily puzzling (due to an extra 'valid'
+	 * reference for the mnt).
+	 * This is *rather* safe as the notification on mount being dropped
+	 * will get called prior to releasing the super block - so right
+	 * in time to perform appropriate clean-up
+	 */
+	r_mnt = real_mount(path->mnt);
+	en->mnt_path.dentry = r_mnt->mnt.mnt_root;
+	en->mnt_path.mnt = &r_mnt->mnt;
+
+	sb = path->mnt->mnt_sb;
+	en->sb = sb;
+
+	nmask &= sb->s_etrace.events_cap_mask;
+	if (!nmask)
+		goto leave;
+
+	spin_lock_init(&en->lock);
+	INIT_LIST_HEAD(&en->node);
+
+	en->notify = nmask;
+	memcpy(&en->th, thresh, offsetof(struct fs_event_thresh, state));
+	if (nmask & FS_EVENT_THRESH)
+		fs_trace_query_data(sb, en);
+
+	atomic_set(&en->count, 1);
+
+	if (rcu_access_pointer(sb->s_etrace.e_priv) != NULL) {
+		struct fs_trace_entry *prev_en;
+
+		prev_en = fetch_trace_entry(sb);
+		if (prev_en) {
+			fs_trace_entry_put(prev_en);
+			goto leave;
+		}
+	}
+	atomic_set(&en->active, 1);
+
+	spin_lock(&fs_trace_lock);
+	list_add(&en->node, &fs_trace_list);
+	spin_unlock(&fs_trace_lock);
+
+	rcu_assign_pointer(sb->s_etrace.e_priv, en);
+	synchronize_rcu();
+
+	return 0;
+leave:
+	kmem_cache_free(fs_trace_cachep, en);
+	return -EINVAL;
+}
+
+static int fs_update_trace_entry_locked(struct fs_trace_entry *en,
+				   struct fs_event_thresh *thresh,
+				    unsigned int nmask)
+{
+	int extend = nmask & FS_TRACE_ADD;
+	struct super_block *sb = en->sb;
+
+	nmask &= ~FS_TRACE_ADD;
+	if (!(nmask & sb->s_etrace.events_cap_mask))
+		return -EINVAL;
+
+	if (nmask & FS_EVENT_THRESH) {
+		if (extend) {
+			/* Get the current state */
+			if (!(en->notify & FS_EVENT_THRESH))
+				if (fs_trace_query_data(sb, en))
+					return -EINVAL;
+
+			if (thresh->state & THRESH_LR_ON) {
+				en->th.lrange = thresh->lrange;
+				en->th.state &= ~THRESH_LR_ON;
+			}
+
+			if (thresh->state & THRESH_UR_ON) {
+				en->th.urange = thresh->urange;
+				en->th.state &= ~THRESH_UR_ON;
+			}
+		} else {
+			memset(&en->th, 0, sizeof(en->th));
+		}
+	}
+
+	if (extend)
+		en->notify |= nmask;
+	else
+		en->notify &= ~nmask;
+	return 0;
+}
+
+static int fs_update_trace_entry(struct path *path,
+				  struct fs_event_thresh *thresh,
+				  unsigned int nmask)
+{
+	struct fs_trace_entry *en;
+	int ret;
+
+	en = fetch_trace_entry(path->mnt->mnt_sb);
+	if (!en)
+		return (nmask & FS_TRACE_ADD)
+			?  fs_new_trace_entry(path, thresh, nmask)
+			: -EINVAL;
+
+	spin_lock(&en->lock);
+	ret = fs_update_trace_entry_locked(en, thresh, nmask);
+	spin_unlock(&en->lock);
+
+	fs_trace_entry_put(en);
+	return ret;
+}
+
+static int fs_parse_trace_request(int argc, char **argv)
+{
+	struct fs_event_thresh thresh = {0};
+	struct path path;
+	substring_t args[MAX_OPT_ARGS];
+	unsigned int nmask = FS_TRACE_ADD;
+	int token;
+	char *s;
+	int ret = -EINVAL;
+
+	if (!argc) {
+		fs_remove_all_traces();
+		return 0;
+	}
+
+	s = *(argv);
+	if (*s == '!') {
+		/* Clear the trace entry */
+		nmask &= ~FS_TRACE_ADD;
+		++s;
+	}
+
+	if (kern_path_mountpoint(AT_FDCWD, s, &path, LOOKUP_FOLLOW))
+		return -EINVAL;
+
+	if (!(--argc)) {
+		if (!(nmask & FS_TRACE_ADD))
+			ret = fs_remove_trace_entry(path.mnt->mnt_sb);
+		goto leave;
+	}
+
+repeat:
+	args[0].to = args[0].from = NULL;
+	token = match_token(*(++argv), fs_etypes, args);
+	if (!token && !nmask)
+		goto leave;
+
+	nmask |= token & FS_EVENTS_ALL;
+	--argc;
+	if ((token & FS_EVENT_THRESH)  && (nmask & FS_TRACE_ADD)) {
+		/*
+		 * Get the threshold config data:
+		 * lower range
+		 * upper range
+		 */
+		if (!argc)
+			goto leave;
+
+		ret = kstrtoull(*(++argv), 10, &thresh.lrange);
+		if (ret)
+			goto leave;
+		thresh.state |= THRESH_LR_ON;
+		if ((--argc)) {
+			ret = kstrtoull(*(++argv), 10, &thresh.urange);
+			if (ret)
+				goto leave;
+			thresh.state |= THRESH_UR_ON;
+			--argc;
+		}
+		/* The thresholds are based on number of available blocks */
+		if (thresh.lrange < thresh.urange) {
+			ret = -EINVAL;
+			goto leave;
+		}
+	}
+	if (argc)
+		goto repeat;
+
+	ret = fs_update_trace_entry(&path, &thresh, nmask);
+leave:
+	path_put(&path);
+	return ret;
+}
+
+#define DEFAULT_BUF_SIZE PAGE_SIZE
+
+static ssize_t fs_trace_write(struct file *file, const char __user *buffer,
+				size_t count, loff_t *ppos)
+{
+	char **argv;
+	char *kern_buf, *next, *cfg;
+	size_t size, dcount = 0;
+	int argc;
+
+	if (!count)
+		return 0;
+
+	kern_buf = kmalloc(DEFAULT_BUF_SIZE, GFP_KERNEL);
+	if (!kern_buf)
+		return -ENOMEM;
+
+	while (dcount < count) {
+
+		size = count - dcount;
+		if (size >= DEFAULT_BUF_SIZE)
+			size = DEFAULT_BUF_SIZE - 1;
+		if (copy_from_user(kern_buf, buffer + dcount, size)) {
+			dcount = -EINVAL;
+			goto leave;
+		}
+
+		kern_buf[size] = '\0';
+
+		next = cfg = kern_buf;
+
+		do {
+			next = strchr(cfg, ';');
+			if (next)
+				*next = '\0';
+
+			argv = argv_split(GFP_KERNEL, cfg, &argc);
+			if (!argv) {
+				dcount = -ENOMEM;
+				goto leave;
+			}
+
+			if (fs_parse_trace_request(argc, argv)) {
+				dcount = -EINVAL;
+				argv_free(argv);
+				goto leave;
+			}
+
+			argv_free(argv);
+			if (next)
+				cfg = ++next;
+
+		} while (next);
+		dcount += size;
+	}
+leave:
+	kfree(kern_buf);
+	return dcount;
+}
+
+static void *fs_trace_seq_start(struct seq_file *m, loff_t *pos)
+{
+	spin_lock(&fs_trace_lock);
+	return seq_list_start(&fs_trace_list, *pos);
+}
+
+static void *fs_trace_seq_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	return seq_list_next(v, &fs_trace_list, pos);
+}
+
+static void fs_trace_seq_stop(struct seq_file *m, void *v)
+{
+	spin_unlock(&fs_trace_lock);
+}
+
+static int fs_trace_seq_show(struct seq_file *m, void *v)
+{
+	struct fs_trace_entry *en;
+	struct super_block *sb;
+	struct mount *r_mnt;
+	const struct match_token *match;
+	unsigned int nmask;
+
+	en = list_entry(v, struct fs_trace_entry, node);
+	sb = en->sb;
+
+	seq_path(m, &en->mnt_path, "\t\n\\");
+	seq_putc(m, ' ');
+
+	seq_escape(m, sb->s_type->name, " \t\n\\");
+	if (sb->s_subtype && sb->s_subtype[0]) {
+		seq_putc(m, '.');
+		seq_escape(m, sb->s_subtype, " \t\n\\");
+	}
+
+	seq_putc(m, ' ');
+	if (sb->s_op->show_devname) {
+		sb->s_op->show_devname(m, en->mnt_path.mnt->mnt_root);
+	} else {
+		r_mnt = real_mount(en->mnt_path.mnt);
+		seq_escape(m, r_mnt->mnt_devname ? r_mnt->mnt_devname : "none",
+				" \t\n\\");
+	}
+	seq_puts(m, " (");
+
+	nmask = en->notify;
+	for (match = fs_etypes; match->pattern; ++match) {
+		if (match->token & nmask) {
+			seq_puts(m, match->pattern);
+			nmask &= ~match->token;
+			if (nmask)
+				seq_putc(m, ',');
+		}
+	}
+	seq_printf(m, " %llu %llu", en->th.lrange, en->th.urange);
+	seq_puts(m, ")\n");
+	return 0;
+}
+
+static const struct seq_operations fs_trace_seq_ops = {
+	.start	= fs_trace_seq_start,
+	.next	= fs_trace_seq_next,
+	.stop	= fs_trace_seq_stop,
+	.show	= fs_trace_seq_show,
+};
+
+static int fs_trace_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &fs_trace_seq_ops);
+}
+
+static const struct file_operations fs_trace_fops = {
+	.owner		= THIS_MODULE,
+	.open		= fs_trace_open,
+	.write		= fs_trace_write,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+static int fs_trace_init(void)
+{
+	fs_trace_cachep = KMEM_CACHE(fs_trace_entry, 0);
+	if (!fs_trace_cachep)
+		return -EINVAL;
+	init_waitqueue_head(&trace_wq);
+	return 0;
+}
+
+/* VFS support */
+static int fs_trace_fill_super(struct super_block *sb, void *data, int silen)
+{
+	int ret;
+	static struct tree_descr desc[] = {
+		[2] = {
+			.name	= "config",
+			.ops	= &fs_trace_fops,
+			.mode	= S_IWUSR | S_IRUGO,
+		},
+		{""},
+	};
+
+	ret = simple_fill_super(sb, 0x7246332, desc);
+	return !ret ? fs_trace_init() : ret;
+}
+
+static struct dentry *fs_trace_do_mount(struct file_system_type *fs_type,
+		 int ntype, const char *dev_name, void *data)
+{
+	return mount_single(fs_type, ntype, data, fs_trace_fill_super);
+}
+
+static void fs_trace_kill_super(struct super_block *sb)
+{
+	/*
+	 * The rcu_barrier here will/should make sure all call_rcu
+	 * callbacks are completed - still there might be some active
+	 * trace objects in use, so the callbacks will not be triggered
+	 * for them at all (at this point), which makes calling the
+	 * kmem_cache_destroy unsafe. So we wait until all traces
+	 * are finally released.
+	 */
+	fs_remove_all_traces();
+	rcu_barrier();
+
+	wait_event(trace_wq, !atomic_read(&stray_traces));
+
+	kmem_cache_destroy(fs_trace_cachep);
+	kill_litter_super(sb);
+}
+
+static struct kset	*fs_trace_kset;
+
+static struct file_system_type fs_trace_fstype = {
+	.name		= "fstrace",
+	.mount		= fs_trace_do_mount,
+	.kill_sb	= fs_trace_kill_super,
+};
+
+static void __init fs_trace_vfs_init(void)
+{
+	fs_trace_kset = kset_create_and_add("events", NULL, fs_kobj);
+
+	if (!fs_trace_kset)
+		return;
+
+	if (!register_filesystem(&fs_trace_fstype)) {
+		if (!fs_event_netlink_register())
+			return;
+		unregister_filesystem(&fs_trace_fstype);
+	}
+	kset_unregister(fs_trace_kset);
+}
+
+static int __init fs_trace_evens_init(void)
+{
+	fs_trace_vfs_init();
+	return 0;
+};
+module_init(fs_trace_evens_init);
+
diff --git a/fs/events/fs_event.h b/fs/events/fs_event.h
new file mode 100644
index 0000000..716a2dd
--- /dev/null
+++ b/fs/events/fs_event.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright(c) 2015 Samsung Electronics. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ *
+ * 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 __GENERIC_FS_EVENTS_H
+#define __GENERIC_FS_EVENTS_H
+
+#ifdef CONFIG_NET
+int  fs_event_netlink_register(void);
+#else /* CONFIG_NET */
+static inline int  fs_event_netlink_register(void) { return -ENOSYS; }
+#endif /* CONFIG_NET */
+
+#endif /* __GENERIC_FS_EVENTS_H */
diff --git a/fs/events/fs_event_netlink.c b/fs/events/fs_event_netlink.c
new file mode 100644
index 0000000..b59c6dc
--- /dev/null
+++ b/fs/events/fs_event_netlink.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright(c) 2015 Samsung Electronics. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ *
+ * 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/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <net/netlink.h>
+#include <net/genetlink.h>
+#include "fs_event.h"
+
+static const struct genl_multicast_group fs_event_mcgroups[] = {
+	{ .name = "event", },
+};
+
+static struct genl_family fs_event_family = {
+	.id		= GENL_ID_FS_EVENT,
+	.hdrsize	= 0,
+	.name		= "FS_EVENT",
+	.version	= 1,
+	.maxattr	= FS_NL_A_MAX,
+	.mcgrps		= fs_event_mcgroups,
+	.n_mcgrps	= ARRAY_SIZE(fs_event_mcgroups),
+};
+
+int fs_netlink_send_event(size_t size, unsigned int event_id,
+	int (*compose_msg)(struct sk_buff *skb,  void *data), void *cbdata)
+{
+	static atomic_t seq;
+	struct sk_buff *skb;
+	void *msg_head;
+	int ret = 0;
+
+	if (!size || !compose_msg)
+		return -EINVAL;
+
+	if (event_id != FS_EVENT_NONE)
+		size += nla_total_size(sizeof(u32));
+	size += nla_total_size(sizeof(u64));
+	skb = genlmsg_new(size, GFP_NOWAIT);
+
+	if (!skb) {
+		pr_err("Failed to allocate new FS generic netlink message\n");
+		return -ENOMEM;
+	}
+
+	msg_head = genlmsg_put(skb, 0, atomic_add_return(1, &seq),
+			&fs_event_family, 0, FS_NL_C_EVENT);
+	if (!msg_head)
+		goto cleanup;
+
+	if (event_id != FS_EVENT_NONE)
+		if (nla_put_u32(skb, FS_NL_A_EVENT_ID, event_id))
+			goto cancel;
+
+	ret = compose_msg(skb, cbdata);
+	if (ret)
+		goto cancel;
+
+	genlmsg_end(skb, msg_head);
+	ret = genlmsg_multicast(&fs_event_family, skb, 0, 0, GFP_NOWAIT);
+	if (ret && ret != -ENOBUFS && ret != -ESRCH)
+		goto cleanup;
+
+	return ret;
+cancel:
+	genlmsg_cancel(skb, msg_head);
+cleanup:
+	nlmsg_free(skb);
+	return ret;
+}
+EXPORT_SYMBOL(fs_netlink_send_event);
+
+int fs_event_netlink_register(void)
+{
+	int ret;
+
+	ret = genl_register_family(&fs_event_family);
+	if (ret)
+		pr_err("Failed to register FS netlink interface\n");
+	return ret;
+}
+
+void fs_event_netlink_unregister(void)
+{
+	genl_unregister_family(&fs_event_family);
+}
diff --git a/fs/namespace.c b/fs/namespace.c
index 82ef140..ec6e2ef 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1031,6 +1031,7 @@ static void cleanup_mnt(struct mount *mnt)
 	if (unlikely(mnt->mnt_pins.first))
 		mnt_pin_kill(mnt);
 	fsnotify_vfsmount_delete(&mnt->mnt);
+	fs_event_mount_dropped(&mnt->mnt);
 	dput(mnt->mnt.mnt_root);
 	deactivate_super(mnt->mnt.mnt_sb);
 	mnt_free_id(mnt);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b4d71b5..b7dadd9 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -263,6 +263,10 @@ struct iattr {
  * Includes for diskquotas.
  */
 #include <linux/quota.h>
+/*
+ * Include for Generic File System Events Interface
+ */
+#include <linux/fs_event.h>
 
 /*
  * Maximum number of layers of fs stack.  Needs to be limited to
@@ -1253,7 +1257,7 @@ struct super_block {
 	struct hlist_node	s_instances;
 	unsigned int		s_quota_types;	/* Bitmask of supported quota types */
 	struct quota_info	s_dquot;	/* Diskquota specific options */
-
+	struct fs_trace_info	s_etrace;
 	struct sb_writers	s_writers;
 
 	char s_id[32];				/* Informational name */
diff --git a/include/linux/fs_event.h b/include/linux/fs_event.h
new file mode 100644
index 0000000..aa182ec
--- /dev/null
+++ b/include/linux/fs_event.h
@@ -0,0 +1,58 @@
+/*
+ * Generic File System Events Interface
+ *
+ * Copyright(c) 2015 Samsung Electronics. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ *
+ * 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 _LINUX_GENERIC_FS_EVETS_
+#define _LINUX_GENERIC_FS_EVETS_
+#include <net/netlink.h>
+#include <uapi/linux/fs_event.h>
+
+/*
+ * Currently supported event types
+ */
+#define FS_EVENT_GENERIC 0x001
+#define FS_EVENT_THRESH	 0x002
+
+#define FS_EVENTS_ALL  (FS_EVENT_GENERIC | FS_EVENT_THRESH)
+
+struct fs_trace_operations {
+	void (*query)(struct super_block *, u64 *);
+};
+
+struct fs_trace_info {
+	void	__rcu	*e_priv;		 /* READ ONLY */
+	unsigned int	events_cap_mask; /* Supported notifications */
+	const struct fs_trace_operations *ops;
+};
+
+void fs_event_notify(struct super_block *sb, unsigned int event_id);
+void fs_event_alloc_space(struct super_block *sb, u64 ncount);
+void fs_event_free_space(struct super_block *sb, u64 ncount);
+void fs_event_mount_dropped(struct vfsmount *mnt);
+
+#ifdef CONFIG_NET
+int fs_netlink_send_event(size_t size, unsigned int event_id,
+	int (*compose_msg)(struct sk_buff *skb, void *data), void *cbdata);
+#else /* CONFIG_NET */
+static inline
+int fs_netlink_send_event(size_t size,  unsigned int event_id,
+	int (*compose_msig)(struct sk_buff *skb, void *data), void *cbdata)
+{
+	return -ENOSYS;
+}
+#endif /* CONFIG_NET */
+
+#endif /* _LINUX_GENERIC_FS_EVENTS_ */
+
diff --git a/include/uapi/linux/fs_event.h b/include/uapi/linux/fs_event.h
new file mode 100644
index 0000000..081c39b
--- /dev/null
+++ b/include/uapi/linux/fs_event.h
@@ -0,0 +1,54 @@
+/*
+ * Generic netlink support for Generic File System Events Interface
+ *
+ * Copyright(c) 2015 Samsung Electronics. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ *
+ * 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 _UAPI_LINUX_GENERIC_FS_EVENTS_
+#define _UAPI_LINUX_GENERIC_FS_EVENTS_
+/*
+ * Generic netlink attribute types
+ */
+enum {
+	FS_NL_A_NONE,
+	FS_NL_A_EVENT_ID,
+	FS_NL_A_DEV_MAJOR,
+	FS_NL_A_DEV_MINOR,
+	FS_NL_A_CAUSED_ID,
+	FS_NL_A_DATA,
+	__FS_NL_A_MAX,
+};
+#define FS_NL_A_MAX (__FS_NL_A_MAX - 1)
+/*
+ * Generic netlink commands
+ */
+#define FS_NL_C_EVENT		1
+
+/*
+ * Supported set of FS events
+ */
+enum {
+	FS_EVENT_NONE,
+	FS_WARN_ENOSPC,		/* No space left to reserve data blks */
+	FS_WARN_ENOSPC_META,	/* No space left for metadata */
+	FS_THR_LRBELOW,		/* The threshold lower range has been reached */
+	FS_THR_LRABOVE,		/* The threshold lower range re-activcated*/
+	FS_THR_URBELOW,
+	FS_THR_URABOVE,
+	FS_ERR_REMOUNT_RO,	/* The file system has been remounted as RO */
+	FS_ERR_CORRUPTED	/* Critical error - fs corrupted */
+
+};
+
+#endif /* _UAPI_LINUX_GENERIC_FS_EVENTS_ */
+
diff --git a/include/uapi/linux/genetlink.h b/include/uapi/linux/genetlink.h
index c3363ba..6464129 100644
--- a/include/uapi/linux/genetlink.h
+++ b/include/uapi/linux/genetlink.h
@@ -29,6 +29,7 @@ struct genlmsghdr {
 #define GENL_ID_CTRL		NLMSG_MIN_TYPE
 #define GENL_ID_VFS_DQUOT	(NLMSG_MIN_TYPE + 1)
 #define GENL_ID_PMCRAID		(NLMSG_MIN_TYPE + 2)
+#define GENL_ID_FS_EVENT	(NLMSG_MIN_TYPE + 3)
 
 /**************************************************************************
  * Controller
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 2ed5f96..e8e0bd68 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -82,7 +82,8 @@ static struct list_head family_ht[GENL_FAM_TAB_SIZE];
  */
 static unsigned long mc_group_start = 0x3 | BIT(GENL_ID_CTRL) |
 				      BIT(GENL_ID_VFS_DQUOT) |
-				      BIT(GENL_ID_PMCRAID);
+				      BIT(GENL_ID_PMCRAID) |
+				      BIT(GENL_ID_FS_EVENT);
 static unsigned long *mc_groups = &mc_group_start;
 static unsigned long mc_groups_longs = 1;
 
@@ -146,6 +147,7 @@ static u16 genl_generate_id(void)
 	for (i = 0; i <= GENL_MAX_ID - GENL_MIN_ID; i++) {
 		if (id_gen_idx != GENL_ID_VFS_DQUOT &&
 		    id_gen_idx != GENL_ID_PMCRAID &&
+		    id_gen_idx != GENL_ID_FS_EVENT &&
 		    !genl_family_find_byid(id_gen_idx))
 			return id_gen_idx;
 		if (++id_gen_idx > GENL_MAX_ID)
@@ -249,6 +251,9 @@ static int genl_validate_assign_mc_groups(struct genl_family *family)
 	} else if (family->id == GENL_ID_PMCRAID) {
 		first_id = GENL_ID_PMCRAID;
 		BUG_ON(n_groups != 1);
+	} else if (family->id == GENL_ID_FS_EVENT) {
+		first_id = GENL_ID_FS_EVENT;
+		BUG_ON(n_groups != 1);
 	} else {
 		groups_allocated = true;
 		err = genl_allocate_reserve_groups(n_groups, &first_id);
-- 
1.7.9.5

--
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 related

* [RFC v2 2/4] ext4: Add helper function to mark group as corrupted
From: Beata Michalska @ 2015-04-27 11:51 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-api-u79uwXL29TY76Z2rM5mHXA
  Cc: jack-AlSwsSmVLrQ, tytso-3s7WtUTddSA,
	adilger.kernel-m1MBpc4rdrD3fQ9qLvQP4Q,
	hughd-hpIqsD4AKlfQT0dZR+AlfA, lczerner-H+wXaHxf7aLQT0dZR+AlfA,
	hch-wEGCiKHe2LqWVfeAwA7xHQ, linux-ext4-u79uwXL29TY76Z2rM5mHXA,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	kmpark-wEGCiKHe2LqWVfeAwA7xHQ
In-Reply-To: <1430135504-24334-1-git-send-email-b.michalska-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>

Add ext4_mark_group_corrupted helper function to
simplify the code and to keep the logic in one place.

Signed-off-by: Beata Michalska <b.michalska-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
---
 fs/ext4/balloc.c  |   15 +++------------
 fs/ext4/ext4.h    |    9 +++++++++
 fs/ext4/ialloc.c  |    5 +----
 fs/ext4/mballoc.c |   11 ++---------
 4 files changed, 15 insertions(+), 25 deletions(-)

diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 83a6f49..e95b27a 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -193,10 +193,7 @@ static int ext4_init_block_bitmap(struct super_block *sb,
 	 * essentially implementing a per-group read-only flag. */
 	if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) {
 		grp = ext4_get_group_info(sb, block_group);
-		if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
-			percpu_counter_sub(&sbi->s_freeclusters_counter,
-					   grp->bb_free);
-		set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
+		ext4_mark_group_corrupted(sbi, grp);
 		if (!EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) {
 			int count;
 			count = ext4_free_inodes_count(sb, gdp);
@@ -379,20 +376,14 @@ static void ext4_validate_block_bitmap(struct super_block *sb,
 		ext4_unlock_group(sb, block_group);
 		ext4_error(sb, "bg %u: block %llu: invalid block bitmap",
 			   block_group, blk);
-		if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
-			percpu_counter_sub(&sbi->s_freeclusters_counter,
-					   grp->bb_free);
-		set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
+		ext4_mark_group_corrupted(sbi, grp);
 		return;
 	}
 	if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group,
 			desc, bh))) {
 		ext4_unlock_group(sb, block_group);
 		ext4_error(sb, "bg %u: bad block bitmap checksum", block_group);
-		if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
-			percpu_counter_sub(&sbi->s_freeclusters_counter,
-					   grp->bb_free);
-		set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
+		ext4_mark_group_corrupted(sbi, grp);
 		return;
 	}
 	set_buffer_verified(bh);
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index f63c3d5..163afe2 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2535,6 +2535,15 @@ static inline spinlock_t *ext4_group_lock_ptr(struct super_block *sb,
 	return bgl_lock_ptr(EXT4_SB(sb)->s_blockgroup_lock, group);
 }
 
+static inline
+void ext4_mark_group_corrupted(struct ext4_sb_info *sbi,
+				struct ext4_group_info *grp)
+{
+	if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
+		percpu_counter_sub(&sbi->s_freeclusters_counter, grp->bb_free);
+	set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
+}
+
 /*
  * Returns true if the filesystem is busy enough that attempts to
  * access the block group locks has run into contention.
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index ac644c3..ebe0499 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -79,10 +79,7 @@ static unsigned ext4_init_inode_bitmap(struct super_block *sb,
 	if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) {
 		ext4_error(sb, "Checksum bad for group %u", block_group);
 		grp = ext4_get_group_info(sb, block_group);
-		if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
-			percpu_counter_sub(&sbi->s_freeclusters_counter,
-					   grp->bb_free);
-		set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
+		ext4_mark_group_corrupted(sbi, grp);
 		if (!EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) {
 			int count;
 			count = ext4_free_inodes_count(sb, gdp);
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 8d1e602..24a4b6d 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -760,10 +760,7 @@ void ext4_mb_generate_buddy(struct super_block *sb,
 		 * corrupt and update bb_free using bitmap value
 		 */
 		grp->bb_free = free;
-		if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
-			percpu_counter_sub(&sbi->s_freeclusters_counter,
-					   grp->bb_free);
-		set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
+		ext4_mark_group_corrupted(sbi, grp);
 	}
 	mb_set_largest_free_order(sb, grp);
 
@@ -1448,12 +1445,8 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
 				      "freeing already freed block "
 				      "(bit %u); block bitmap corrupt.",
 				      block);
-		if (!EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info))
-			percpu_counter_sub(&sbi->s_freeclusters_counter,
-					   e4b->bd_info->bb_free);
 		/* Mark the block group as corrupt. */
-		set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT,
-			&e4b->bd_info->bb_state);
+		ext4_mark_group_corrupted(sbi, e4b->bd_info);
 		mb_regenerate_buddy(e4b);
 		goto done;
 	}
-- 
1.7.9.5

^ permalink raw reply related

* [RFC v2 3/4] ext4: Add support for generic FS events
From: Beata Michalska @ 2015-04-27 11:51 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-api
  Cc: jack, tytso, adilger.kernel, hughd, lczerner, hch, linux-ext4,
	linux-mm, kyungmin.park, kmpark
In-Reply-To: <1430135504-24334-1-git-send-email-b.michalska@samsung.com>

Add support for generic FS events including threshold
notifications, ENOSPC and remount as read-only warnings,
along with generic internal warnings/errors.

Signed-off-by: Beata Michalska <b.michalska@samsung.com>
---
 fs/ext4/balloc.c  |   10 ++++++++--
 fs/ext4/ext4.h    |    1 +
 fs/ext4/inode.c   |    2 +-
 fs/ext4/mballoc.c |    6 +++++-
 fs/ext4/resize.c  |    1 +
 fs/ext4/super.c   |   39 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 55 insertions(+), 4 deletions(-)

diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index e95b27a..a48450f 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -569,6 +569,7 @@ int ext4_claim_free_clusters(struct ext4_sb_info *sbi,
 {
 	if (ext4_has_free_clusters(sbi, nclusters, flags)) {
 		percpu_counter_add(&sbi->s_dirtyclusters_counter, nclusters);
+		fs_event_alloc_space(sbi->s_sb, EXT4_C2B(sbi, nclusters));
 		return 0;
 	} else
 		return -ENOSPC;
@@ -590,9 +591,10 @@ int ext4_should_retry_alloc(struct super_block *sb, int *retries)
 {
 	if (!ext4_has_free_clusters(EXT4_SB(sb), 1, 0) ||
 	    (*retries)++ > 3 ||
-	    !EXT4_SB(sb)->s_journal)
+	    !EXT4_SB(sb)->s_journal) {
+		fs_event_notify(sb, FS_WARN_ENOSPC);
 		return 0;
-
+	}
 	jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id);
 
 	return jbd2_journal_force_commit_nested(EXT4_SB(sb)->s_journal);
@@ -637,6 +639,10 @@ ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
 		dquot_alloc_block_nofail(inode,
 				EXT4_C2B(EXT4_SB(inode->i_sb), ar.len));
 	}
+
+	if (*errp == -ENOSPC)
+		fs_event_notify(inode->i_sb, FS_WARN_ENOSPC_META);
+
 	return ret;
 }
 
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 163afe2..7d75ff9 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2542,6 +2542,7 @@ void ext4_mark_group_corrupted(struct ext4_sb_info *sbi,
 	if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
 		percpu_counter_sub(&sbi->s_freeclusters_counter, grp->bb_free);
 	set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
+	fs_event_alloc_space(sbi->s_sb, EXT4_C2B(sbi, grp->bb_free));
 }
 
 /*
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 5cb9a21..2a7af0f 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1238,7 +1238,7 @@ static void ext4_da_release_space(struct inode *inode, int to_free)
 	percpu_counter_sub(&sbi->s_dirtyclusters_counter, to_free);
 
 	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
-
+	fs_event_free_space(sbi->s_sb, to_free);
 	dquot_release_reservation_block(inode, EXT4_C2B(sbi, to_free));
 }
 
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 24a4b6d..c2df6f0 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -4511,6 +4511,9 @@ out:
 		kmem_cache_free(ext4_ac_cachep, ac);
 	if (inquota && ar->len < inquota)
 		dquot_free_block(ar->inode, EXT4_C2B(sbi, inquota - ar->len));
+	if (reserv_clstrs && ar->len < reserv_clstrs)
+		fs_event_free_space(sbi->s_sb,
+			EXT4_C2B(sbi, reserv_clstrs - ar->len));
 	if (!ar->len) {
 		if ((ar->flags & EXT4_MB_DELALLOC_RESERVED) == 0)
 			/* release all the reserved blocks if non delalloc */
@@ -4848,7 +4851,7 @@ do_more:
 	if (!(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE))
 		dquot_free_block(inode, EXT4_C2B(sbi, count_clusters));
 	percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters);
-
+	fs_event_free_space(sb, EXT4_C2B(sbi, count_clusters));
 	ext4_mb_unload_buddy(&e4b);
 
 	/* We dirtied the bitmap block */
@@ -4982,6 +4985,7 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
 	ext4_unlock_group(sb, block_group);
 	percpu_counter_add(&sbi->s_freeclusters_counter,
 			   EXT4_NUM_B2C(sbi, blocks_freed));
+	fs_event_free_space(sb, blocks_freed);
 
 	if (sbi->s_log_groups_per_flex) {
 		ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index 8a8ec62..dbf08d6 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -1378,6 +1378,7 @@ static void ext4_update_super(struct super_block *sb,
 			   EXT4_NUM_B2C(sbi, free_blocks));
 	percpu_counter_add(&sbi->s_freeinodes_counter,
 			   EXT4_INODES_PER_GROUP(sb) * flex_gd->count);
+	fs_event_free_space(sb, free_blocks - reserved_blocks);
 
 	ext4_debug("free blocks count %llu",
 		   percpu_counter_read(&sbi->s_freeclusters_counter));
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index e061e66..108b667 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -585,6 +585,8 @@ void __ext4_abort(struct super_block *sb, const char *function,
 		if (EXT4_SB(sb)->s_journal)
 			jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
 		save_error_info(sb, function, line);
+		fs_event_notify(sb, FS_ERR_REMOUNT_RO);
+
 	}
 	if (test_opt(sb, ERRORS_PANIC))
 		panic("EXT4-fs panic from previous error\n");
@@ -1083,6 +1085,12 @@ static const struct quotactl_ops ext4_qctl_operations = {
 };
 #endif
 
+static void ext4_trace_query(struct super_block *sb, u64 *ncount);
+
+static const struct fs_trace_operations ext4_trace_ops = {
+	.query	= ext4_trace_query,
+};
+
 static const struct super_operations ext4_sops = {
 	.alloc_inode	= ext4_alloc_inode,
 	.destroy_inode	= ext4_destroy_inode,
@@ -3398,11 +3406,20 @@ static int ext4_reserve_clusters(struct ext4_sb_info *sbi, ext4_fsblk_t count)
 {
 	ext4_fsblk_t clusters = ext4_blocks_count(sbi->s_es) >>
 				sbi->s_cluster_bits;
+	ext4_fsblk_t current_resv;
 
 	if (count >= clusters)
 		return -EINVAL;
 
+	current_resv = atomic64_read(&sbi->s_resv_clusters);
 	atomic64_set(&sbi->s_resv_clusters, count);
+
+	if (count > current_resv)
+		fs_event_alloc_space(sbi->s_sb,
+			EXT4_C2B(sbi, count - current_resv));
+	else
+		fs_event_free_space(sbi->s_sb,
+			EXT4_C2B(sbi, current_resv - count));
 	return 0;
 }
 
@@ -3966,6 +3983,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 		sb->s_qcop = &ext4_qctl_operations;
 	sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP;
 #endif
+	sb->s_etrace.ops = &ext4_trace_ops;
+	sb->s_etrace.events_cap_mask = FS_EVENTS_ALL;
+
 	memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid));
 
 	INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
@@ -5438,6 +5458,25 @@ out:
 
 #endif
 
+static void ext4_trace_query(struct super_block *sb, u64 *ncount)
+{
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+	struct ext4_super_block *es = sbi->s_es;
+	ext4_fsblk_t rsv_blocks;
+	ext4_fsblk_t nblocks;
+
+	nblocks = percpu_counter_sum_positive(&sbi->s_freeclusters_counter) -
+		percpu_counter_sum_positive(&sbi->s_dirtyclusters_counter);
+	nblocks = EXT4_C2B(sbi, nblocks);
+	rsv_blocks = ext4_r_blocks_count(es) +
+		     EXT4_C2B(sbi, atomic64_read(&sbi->s_resv_clusters));
+	if (nblocks < rsv_blocks)
+		nblocks = 0;
+	else
+		nblocks -= rsv_blocks;
+	*ncount = nblocks;
+}
+
 static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags,
 		       const char *dev_name, void *data)
 {
-- 
1.7.9.5

--
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 related

* [RFC v2 4/4] shmem: Add support for generic FS events
From: Beata Michalska @ 2015-04-27 11:51 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-api
  Cc: jack, tytso, adilger.kernel, hughd, lczerner, hch, linux-ext4,
	linux-mm, kyungmin.park, kmpark
In-Reply-To: <1430135504-24334-1-git-send-email-b.michalska@samsung.com>

Add support for the generic FS events interface
covering threshold notifiactions and the ENOSPC
warning.

Signed-off-by: Beata Michalska <b.michalska@samsung.com>
---
 mm/shmem.c |   33 ++++++++++++++++++++++++++++++---
 1 file changed, 30 insertions(+), 3 deletions(-)

diff --git a/mm/shmem.c b/mm/shmem.c
index cf2d0ca..a044d12 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -201,6 +201,7 @@ static int shmem_reserve_inode(struct super_block *sb)
 		spin_lock(&sbinfo->stat_lock);
 		if (!sbinfo->free_inodes) {
 			spin_unlock(&sbinfo->stat_lock);
+			fs_event_notify(sb, FS_WARN_ENOSPC);
 			return -ENOSPC;
 		}
 		sbinfo->free_inodes--;
@@ -239,8 +240,10 @@ static void shmem_recalc_inode(struct inode *inode)
 	freed = info->alloced - info->swapped - inode->i_mapping->nrpages;
 	if (freed > 0) {
 		struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
-		if (sbinfo->max_blocks)
+		if (sbinfo->max_blocks) {
 			percpu_counter_add(&sbinfo->used_blocks, -freed);
+			fs_event_free_space(inode->i_sb, freed);
+		}
 		info->alloced -= freed;
 		inode->i_blocks -= freed * BLOCKS_PER_PAGE;
 		shmem_unacct_blocks(info->flags, freed);
@@ -1164,6 +1167,7 @@ repeat:
 				goto unacct;
 			}
 			percpu_counter_inc(&sbinfo->used_blocks);
+			fs_event_alloc_space(inode->i_sb, 1);
 		}
 
 		page = shmem_alloc_page(gfp, info, index);
@@ -1245,8 +1249,10 @@ trunc:
 	spin_unlock(&info->lock);
 decused:
 	sbinfo = SHMEM_SB(inode->i_sb);
-	if (sbinfo->max_blocks)
+	if (sbinfo->max_blocks) {
 		percpu_counter_add(&sbinfo->used_blocks, -1);
+		fs_event_free_space(inode->i_sb, 1);
+	}
 unacct:
 	shmem_unacct_blocks(info->flags, 1);
 failed:
@@ -1258,12 +1264,16 @@ unlock:
 		unlock_page(page);
 		page_cache_release(page);
 	}
-	if (error == -ENOSPC && !once++) {
+	if (error == -ENOSPC) {
+		if (!once++) {
 		info = SHMEM_I(inode);
 		spin_lock(&info->lock);
 		shmem_recalc_inode(inode);
 		spin_unlock(&info->lock);
 		goto repeat;
+		} else {
+			fs_event_notify(inode->i_sb, FS_WARN_ENOSPC);
+		}
 	}
 	if (error == -EEXIST)	/* from above or from radix_tree_insert */
 		goto repeat;
@@ -2729,12 +2739,26 @@ static int shmem_encode_fh(struct inode *inode, __u32 *fh, int *len,
 	return 1;
 }
 
+static void shmem_trace_query(struct super_block *sb, u64 *ncount)
+{
+	struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
+
+	if (sbinfo->max_blocks)
+		*ncount = sbinfo->max_blocks -
+			percpu_counter_sum(&sbinfo->used_blocks);
+
+}
+
 static const struct export_operations shmem_export_ops = {
 	.get_parent     = shmem_get_parent,
 	.encode_fh      = shmem_encode_fh,
 	.fh_to_dentry	= shmem_fh_to_dentry,
 };
 
+static const struct fs_trace_operations shmem_trace_ops = {
+	.query	= shmem_trace_query,
+};
+
 static int shmem_parse_options(char *options, struct shmem_sb_info *sbinfo,
 			       bool remount)
 {
@@ -3020,6 +3044,9 @@ int shmem_fill_super(struct super_block *sb, void *data, int silent)
 		sb->s_flags |= MS_NOUSER;
 	}
 	sb->s_export_op = &shmem_export_ops;
+	sb->s_etrace.ops = &shmem_trace_ops;
+	sb->s_etrace.events_cap_mask = FS_EVENTS_ALL;
+
 	sb->s_flags |= MS_NOSEC;
 #else
 	sb->s_flags |= MS_NOUSER;
-- 
1.7.9.5

--
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 related

* Re: [RFC v2 1/4] fs: Add generic file system event notifications
From: Greg KH @ 2015-04-27 14:24 UTC (permalink / raw)
  To: Beata Michalska
  Cc: linux-kernel, linux-fsdevel, linux-api, jack, tytso,
	adilger.kernel, hughd, lczerner, hch, linux-ext4, linux-mm,
	kyungmin.park, kmpark
In-Reply-To: <1430135504-24334-2-git-send-email-b.michalska@samsung.com>

On Mon, Apr 27, 2015 at 01:51:41PM +0200, Beata Michalska wrote:
> 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 |  231 ++++++++++
>  fs/Makefile                          |    1 +
>  fs/events/Makefile                   |    6 +
>  fs/events/fs_event.c                 |  770 ++++++++++++++++++++++++++++++++++
>  fs/events/fs_event.h                 |   25 ++
>  fs/events/fs_event_netlink.c         |   99 +++++
>  fs/namespace.c                       |    1 +
>  include/linux/fs.h                   |    6 +-
>  include/linux/fs_event.h             |   58 +++
>  include/uapi/linux/fs_event.h        |   54 +++
>  include/uapi/linux/genetlink.h       |    1 +
>  net/netlink/genetlink.c              |    7 +-
>  12 files changed, 1257 insertions(+), 2 deletions(-)
>  create mode 100644 Documentation/filesystems/events.txt
>  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

Any reason why you just don't do uevents for the block devices today,
and not create a new type of netlink message and userspace tool required
to read these?

> --- a/fs/Makefile
> +++ b/fs/Makefile
> @@ -126,3 +126,4 @@ obj-y				+= exofs/ # Multiple modules
>  obj-$(CONFIG_CEPH_FS)		+= ceph/
>  obj-$(CONFIG_PSTORE)		+= pstore/
>  obj-$(CONFIG_EFIVAR_FS)		+= efivarfs/
> +obj-y				+= events/

Always?

> diff --git a/fs/events/Makefile b/fs/events/Makefile
> new file mode 100644
> index 0000000..58d1454
> --- /dev/null
> +++ b/fs/events/Makefile
> @@ -0,0 +1,6 @@
> +#
> +# Makefile for the Linux Generic File System Event Interface
> +#
> +
> +obj-y := fs_event.o

Always?  Even if the option is not selected?  Why is everyone forced to
always use this code?  Can't you disable it for the "tiny" systems that
don't need it?

> +struct fs_trace_entry {
> +	atomic_t	 count;

Why not just use a 'struct kref' for your count, which will save a bunch
of open-coding of reference counting, and forcing us to audit your code
to verify you got all the corner cases correct?  :)

> +	atomic_t	 active;
> +	struct super_block *sb;

Are you properly reference counting this pointer?  I didn't see where
that was happening, so I must have missed it.

thanks,

greg k-h

--
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: [RFC] capabilities: Ambient capabilities
From: Christoph Lameter @ 2015-04-27 14:55 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Serge Hallyn, Jarkko Sakkinen, Andrew Lutomirski, Ted Ts'o,
	Andrew Morton, Andrew G. Morgan, Linux API, Mimi Zohar,
	Michael Kerrisk, Austin S Hemmelgarn, linux-security-module,
	Aaron Jones, Serge Hallyn, LKML, Markku Savela, Kees Cook,
	Jonathan Corbet
In-Reply-To: <CALCETrUrFm9n_4xTj4ELkzTSnWHfxQtANqz2wpzU7riTihLDaA@mail.gmail.com>

On Fri, 24 Apr 2015, Andy Lutomirski wrote:

> Also, in my model you can do:
>
> $ sudo capset cap_whatever=eip something
> $ ./something
>
> and the program can make its cap be ambient and run a helper.  In the
> CAP_SETPCAP model, that doesn't work.

Dont see too much difference in setting caps and CAP_SETPCAP on
"./something" to allow it to set the ambient caps.

^ permalink raw reply

* [RFC PATCH 0/3] iio: export mounting matrix
From: Octavian Purdila @ 2015-04-27 15:01 UTC (permalink / raw)
  To: jic23-DgEjT+Ai2ygdnm+yROfE0A
  Cc: lars-Qo5EllUWu/uELgA04lAiVw, pmeerw-jW+XmwGofnusTnJN9+BGXg,
	robert.moore-ral2JQCrhuEAvxtiuMwx3w,
	rafael.j.wysocki-ral2JQCrhuEAvxtiuMwx3w,
	lenb-DgEjT+Ai2ygdnm+yROfE0A, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA, Octavian Purdila

This is a RFC patch series that exports information about the way the
sensors are connected to the system so that userspace can correct
readings.

It is inspired by the way MPU6050 exports this information via the
in_{gyro,accel,magn}_matrix sysfs entries.

Octavian Purdila (3):
  iio: export mounting matrix information
  ACPICA: Add _PLD front and back panel constants
  iio: derive the mounting matrix from ACPI _PLD objects

 Documentation/ABI/testing/sysfs-bus-iio | 11 ++++
 drivers/iio/industrialio-core.c         | 93 +++++++++++++++++++++++++++++++++
 include/acpi/acbuffer.h                 |  5 ++
 include/linux/iio/iio.h                 | 55 +++++++++++++++++++
 4 files changed, 164 insertions(+)

-- 
1.9.1

^ permalink raw reply

* [RFC PATCH 1/3] iio: export mounting matrix information
From: Octavian Purdila @ 2015-04-27 15:01 UTC (permalink / raw)
  To: jic23
  Cc: lars, pmeerw, robert.moore, rafael.j.wysocki, lenb, linux-api,
	linux-kernel, linux-iio, linux-acpi, Octavian Purdila
In-Reply-To: <1430146908-27919-1-git-send-email-octavian.purdila@intel.com>

Export a new sysfs attribute that describes the placement of the
sensor on the device in the form of a mounting matrix so that
userspace can do the required correction to get accurate data:

corrected X = MM[0] * X + MM[1] Y + MM[2] * Z
corrected Y = MM[3] * X + MM[4] Y + MM[5] * Z
corrected Z = MM[6] * X + MM[7] Y + MM[8] * Z

This information is read from the device properties of the parent of
the IIO device.

Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
 Documentation/ABI/testing/sysfs-bus-iio | 11 +++++++++
 drivers/iio/industrialio-core.c         | 42 +++++++++++++++++++++++++++++++++
 include/linux/iio/iio.h                 |  9 +++++++
 3 files changed, 62 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
index 866b4ec..d36476e 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -1375,3 +1375,14 @@ Description:
 		The emissivity ratio of the surface in the field of view of the
 		contactless temperature sensor.  Emissivity varies from 0 to 1,
 		with 1 being the emissivity of a black body.
+
+What:		/sys/bus/iio/devices/iio:deviceX/mounting_matrix
+KernelVersion:	4.2
+Contact:	linux-iio@vger.kernel.org
+Description:
+		A list of 9 floating point values that describes the
+		transformation needed to account for the way the sensor has been
+		placed on the PCB:
+		corrected X = MM[0] * X + MM[1] Y + MM[2] * Z
+		corrected Y = MM[3] * X + MM[4] Y + MM[5] * Z
+		corrected Z = MM[6] * X + MM[7] Y + MM[8] * Z
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 7c98bc1..9000c53 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -871,6 +871,45 @@ static ssize_t iio_show_dev_name(struct device *dev,
 
 static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL);
 
+static bool iio_get_mounting_matrix(struct iio_dev *indio_dev)
+{
+	int i, err;
+
+	err = device_property_read_u32_array(&indio_dev->dev, "mounting-matrix",
+					     indio_dev->mounting_matrix, 9);
+	if (!err) {
+		int *mm = indio_dev->mounting_matrix;
+
+		for (i = IIO_MM_SIZE - 2; i > 0; i -= 2) {
+			mm[i] = mm[i / 2];
+			mm[i + 1] = 0;
+		}
+
+		return true;
+	}
+
+	return false;
+}
+
+static ssize_t iio_show_mounting_matrix(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	char *tmp = buf;
+	int i;
+
+	for (i = 0; i < IIO_MM_SIZE; i += 2) {
+		tmp += iio_format_value(tmp, IIO_VAL_INT_PLUS_MICRO, 2,
+					&indio_dev->mounting_matrix[i]);
+		if (((i + 2) / 2) % 3)
+			tmp[-1] = ' ';
+	}
+	return tmp - buf;
+}
+
+static DEVICE_ATTR(mounting_matrix, S_IRUGO, iio_show_mounting_matrix, NULL);
+
 static int iio_device_register_sysfs(struct iio_dev *indio_dev)
 {
 	int i, ret = 0, attrcount, attrn, attrcount_orig = 0;
@@ -920,6 +959,9 @@ static int iio_device_register_sysfs(struct iio_dev *indio_dev)
 		indio_dev->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr;
 	if (indio_dev->name)
 		indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr;
+	if (iio_get_mounting_matrix(indio_dev))
+		indio_dev->chan_attr_group.attrs[attrn++] =
+			&dev_attr_mounting_matrix.attr;
 
 	indio_dev->groups[indio_dev->groupcounter++] =
 		&indio_dev->chan_attr_group;
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index b1e46ae..c1fa852 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -434,6 +434,8 @@ struct iio_buffer_setup_ops {
 				   const unsigned long *scan_mask);
 };
 
+#define IIO_MM_SIZE		18
+
 /**
  * struct iio_dev - industrial I/O device
  * @id:			[INTERN] used to identify device internally
@@ -469,6 +471,12 @@ struct iio_buffer_setup_ops {
  * @groups:		[INTERN] attribute groups
  * @groupcounter:	[INTERN] index of next attribute group
  * @flags:		[INTERN] file ops related flags including busy flag.
+ * @mounting_matrix:	[INTERN] the mounting matrix is a series of 9
+ *			IIO_VAL_INT_PLUS_MICRO pairs that describes the
+ *			transformation needed to account for the way the sensor
+ *			has been placed on the PCB. See the mounting_matrix
+ *			entry in Documentation/ABI/testing/sysfs-bus-iio about
+ *			details of the transformation operations.
  * @debugfs_dentry:	[INTERN] device specific debugfs dentry.
  * @cached_reg_addr:	[INTERN] cached register address for debugfs reads.
  */
@@ -509,6 +517,7 @@ struct iio_dev {
 	int				groupcounter;
 
 	unsigned long			flags;
+	int				mounting_matrix[IIO_MM_SIZE];
 #if defined(CONFIG_DEBUG_FS)
 	struct dentry			*debugfs_dentry;
 	unsigned			cached_reg_addr;
-- 
1.9.1


^ permalink raw reply related

* [RFC PATCH 2/3] ACPICA: Add _PLD front and back panel constants
From: Octavian Purdila @ 2015-04-27 15:01 UTC (permalink / raw)
  To: jic23-DgEjT+Ai2ygdnm+yROfE0A
  Cc: lars-Qo5EllUWu/uELgA04lAiVw, pmeerw-jW+XmwGofnusTnJN9+BGXg,
	robert.moore-ral2JQCrhuEAvxtiuMwx3w,
	rafael.j.wysocki-ral2JQCrhuEAvxtiuMwx3w,
	lenb-DgEjT+Ai2ygdnm+yROfE0A, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA, Octavian Purdila
In-Reply-To: <1430146908-27919-1-git-send-email-octavian.purdila-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

Signed-off-by: Octavian Purdila <octavian.purdila-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 include/acpi/acbuffer.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/acpi/acbuffer.h b/include/acpi/acbuffer.h
index 6b040f4..2be0270 100644
--- a/include/acpi/acbuffer.h
+++ b/include/acpi/acbuffer.h
@@ -139,6 +139,11 @@ struct acpi_pld_info {
 	u16 horizontal_offset;
 };
 
+enum {
+	ACPI_PLD_PANEL_FRONT = 4,
+	ACPI_PLD_PANEL_BACK
+};
+
 /*
  * Macros to:
  *     1) Convert a _PLD buffer to internal struct acpi_pld_info format - ACPI_PLD_GET*
-- 
1.9.1

^ permalink raw reply related

* [RFC PATCH 3/3] iio: derive the mounting matrix from ACPI _PLD objects
From: Octavian Purdila @ 2015-04-27 15:01 UTC (permalink / raw)
  To: jic23-DgEjT+Ai2ygdnm+yROfE0A
  Cc: lars-Qo5EllUWu/uELgA04lAiVw, pmeerw-jW+XmwGofnusTnJN9+BGXg,
	robert.moore-ral2JQCrhuEAvxtiuMwx3w,
	rafael.j.wysocki-ral2JQCrhuEAvxtiuMwx3w,
	lenb-DgEjT+Ai2ygdnm+yROfE0A, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA, Octavian Purdila
In-Reply-To: <1430146908-27919-1-git-send-email-octavian.purdila-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

This patch derives the mounting matrix for a particular IIO device
based ont the ACPI _PLD information. Note that if mounting matrix is
defined in the device properties it overrieds the _PLD information.

Signed-off-by: Octavian Purdila <octavian.purdila-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/iio/industrialio-core.c | 51 +++++++++++++++++++++++++++++++++++++++++
 include/linux/iio/iio.h         | 46 +++++++++++++++++++++++++++++++++++++
 2 files changed, 97 insertions(+)

diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 9000c53..90ee58a 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -31,6 +31,7 @@
 #include <linux/iio/sysfs.h>
 #include <linux/iio/events.h>
 #include <linux/iio/buffer.h>
+#include <linux/acpi.h>
 
 /* IDA to assign each registered device a unique id */
 static DEFINE_IDA(iio_ida);
@@ -871,6 +872,53 @@ static ssize_t iio_show_dev_name(struct device *dev,
 
 static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL);
 
+#if IS_ENABLED(CONFIG_ACPI)
+static bool iio_get_mounting_matrix_acpi(struct iio_dev *indio_dev)
+{
+	acpi_handle h = ACPI_HANDLE(indio_dev->dev.parent);
+	struct acpi_pld_info *info;
+
+	if (ACPI_SUCCESS(acpi_get_physical_device_location(h, &info))) {
+		IIO_MM_SET(indio_dev->mounting_matrix, X, X, 1, 0);
+		IIO_MM_SET(indio_dev->mounting_matrix, Y, Y, 1, 0);
+		IIO_MM_SET(indio_dev->mounting_matrix, Z, Z, 1, 0);
+
+		/* Chip placed on the back panel ; negate x and z */
+		if (info->panel == ACPI_PLD_PANEL_BACK) {
+			IIO_MM_MUL(indio_dev->mounting_matrix, X, X, -1, 0);
+			IIO_MM_MUL(indio_dev->mounting_matrix, Z, Z, -1, 0);
+		}
+
+		switch (info->rotation) {
+		case 2:
+			/* 90 deg clockwise: negate y then swap x,y */
+			IIO_MM_MUL(indio_dev->mounting_matrix, Y, Y, -1, 0);
+			IIO_MM_SWAP(indio_dev->mounting_matrix, X, Y);
+			break;
+		case 4:
+			/* Upside down: negate x and y */
+			IIO_MM_MUL(indio_dev->mounting_matrix, X, X, -1, 0);
+			IIO_MM_MUL(indio_dev->mounting_matrix, Y, Y, -1, 0);
+			break;
+		case 6:
+			/* 90 deg counter clockwise: negate x then swap x,y */
+			IIO_MM_MUL(indio_dev->mounting_matrix, X, X, -1, 0);
+			IIO_MM_SWAP(indio_dev->mounting_matrix, X, Y);
+			break;
+		}
+
+		return true;
+	}
+
+	return false;
+}
+#else
+static bool iio_get_mounting_matrix_acpi(struct iio_dev *indio_dev)
+{
+	return false;
+}
+#endif
+
 static bool iio_get_mounting_matrix(struct iio_dev *indio_dev)
 {
 	int i, err;
@@ -888,6 +936,9 @@ static bool iio_get_mounting_matrix(struct iio_dev *indio_dev)
 		return true;
 	}
 
+	if (ACPI_HANDLE(indio_dev->dev.parent))
+		return iio_get_mounting_matrix_acpi(indio_dev);
+
 	return false;
 }
 
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index c1fa852..feb7813 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -436,6 +436,52 @@ struct iio_buffer_setup_ops {
 
 #define IIO_MM_SIZE		18
 
+enum {
+	IIO_MM_XX0,
+	IIO_MM_XX1,
+	IIO_MM_XY0,
+	IIO_MM_XY1,
+	IIO_MM_XZ0,
+	IIO_MM_XZ1,
+	IIO_MM_YX0,
+	IIO_MM_YX1,
+	IIO_MM_YY0,
+	IIO_MM_YY1,
+	IIO_MM_YZ0,
+	IIO_MM_YZ1,
+	IIO_MM_ZX0,
+	IIO_MM_ZX1,
+	IIO_MM_ZY0,
+	IIO_MM_ZY1,
+	IIO_MM_ZZ0,
+	IIO_MM_ZZ1,
+};
+
+#define IIO_MM_SET(mm, a, b, val0, val1)	\
+	do {					\
+		mm[IIO_MM_##a##b##0] = val0;	\
+		mm[IIO_MM_##a##b##1] = val1;	\
+	} while (0)				\
+
+#define IIO_MM_MUL(mm, a, b, val0, val1)	\
+	do {					\
+		mm[IIO_MM_##a##b##0] *= val0;	\
+		mm[IIO_MM_##a##b##0] *= val1;	\
+	} while (0)				\
+
+#define IIO_MM_SWAP(mm, x, y)					\
+	do {							\
+		int tmp;					\
+								\
+		tmp = mm[IIO_MM_##x##x##0];			\
+		mm[IIO_MM_##x##x##0] = mm[IIO_MM_##y##y##0];	\
+		mm[IIO_MM_##y##y##0] = tmp;			\
+								\
+		tmp = mm[IIO_MM_##x##x##1];			\
+		mm[IIO_MM_##x##x##1] = mm[IIO_MM_##y##y##1];	\
+		mm[IIO_MM_##y##y##1] = tmp;			\
+	} while (0)						\
+
 /**
  * struct iio_dev - industrial I/O device
  * @id:			[INTERN] used to identify device internally
-- 
1.9.1

^ permalink raw reply related

* Re: [RFC v2 1/4] fs: Add generic file system event notifications
From: Beata Michalska @ 2015-04-27 15:08 UTC (permalink / raw)
  To: Greg KH
  Cc: linux-kernel, linux-fsdevel, linux-api, jack, tytso,
	adilger.kernel, hughd, lczerner, hch, linux-ext4, linux-mm,
	kyungmin.park, kmpark
In-Reply-To: <20150427142421.GB21942@kroah.com>

On 04/27/2015 04:24 PM, Greg KH wrote:
> On Mon, Apr 27, 2015 at 01:51:41PM +0200, Beata Michalska wrote:
>> 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 |  231 ++++++++++
>>  fs/Makefile                          |    1 +
>>  fs/events/Makefile                   |    6 +
>>  fs/events/fs_event.c                 |  770 ++++++++++++++++++++++++++++++++++
>>  fs/events/fs_event.h                 |   25 ++
>>  fs/events/fs_event_netlink.c         |   99 +++++
>>  fs/namespace.c                       |    1 +
>>  include/linux/fs.h                   |    6 +-
>>  include/linux/fs_event.h             |   58 +++
>>  include/uapi/linux/fs_event.h        |   54 +++
>>  include/uapi/linux/genetlink.h       |    1 +
>>  net/netlink/genetlink.c              |    7 +-
>>  12 files changed, 1257 insertions(+), 2 deletions(-)
>>  create mode 100644 Documentation/filesystems/events.txt
>>  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
> 
> Any reason why you just don't do uevents for the block devices today,
> and not create a new type of netlink message and userspace tool required
> to read these?

The idea here is to have support for filesystems with no backing device as well.
Parsing the message with libnl is really simple and requires few lines of code
(sample application has been presented in the initial version of this RFC)

> 
>> --- a/fs/Makefile
>> +++ b/fs/Makefile
>> @@ -126,3 +126,4 @@ obj-y				+= exofs/ # Multiple modules
>>  obj-$(CONFIG_CEPH_FS)		+= ceph/
>>  obj-$(CONFIG_PSTORE)		+= pstore/
>>  obj-$(CONFIG_EFIVAR_FS)		+= efivarfs/
>> +obj-y				+= events/
> 
> Always?
> 
>> diff --git a/fs/events/Makefile b/fs/events/Makefile
>> new file mode 100644
>> index 0000000..58d1454
>> --- /dev/null
>> +++ b/fs/events/Makefile
>> @@ -0,0 +1,6 @@
>> +#
>> +# Makefile for the Linux Generic File System Event Interface
>> +#
>> +
>> +obj-y := fs_event.o
> 
> Always?  Even if the option is not selected?  Why is everyone forced to
> always use this code?  Can't you disable it for the "tiny" systems that
> don't need it?
> 

I was considering making it optional and I guess it's worth getting back
to this idea.

>> +struct fs_trace_entry {
>> +	atomic_t	 count;
> 
> Why not just use a 'struct kref' for your count, which will save a bunch
> of open-coding of reference counting, and forcing us to audit your code
> to verify you got all the corner cases correct?  :)
> 
>> +	atomic_t	 active;
>> +	struct super_block *sb;

Not sure if using kref would change much here as the kref would not really
make it easier to verify those corner cases, unfortunately.

> 
> Are you properly reference counting this pointer?  I didn't see where
> that was happening, so I must have missed it.
> 
> thanks,
>

You haven't. And if I haven't missed anything, the sb is being used only
as long as the super is alive. Most of the code operates on sb only if it
was explicitly asked to, through call from filesystem. There is also
a callback notifying of mount being dropped (which proceeds the call to 
kill_super) that invalidates the object that depends on it.
Still, it should be explicitly stated that the sb is being used through
bidding up the s_count counter, though that would require taking the
sb_lock. AFAIK, one can get the reference to super block but for a particular
device. Maybe it would be worth having it more generic (?).


> greg k-h
> 


BR
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: [RFC v2 1/4] fs: Add generic file system event notifications
From: Greg KH @ 2015-04-27 15:37 UTC (permalink / raw)
  To: Beata Michalska
  Cc: linux-kernel, linux-fsdevel, linux-api, jack, tytso,
	adilger.kernel, hughd, lczerner, hch, linux-ext4, linux-mm,
	kyungmin.park, kmpark
In-Reply-To: <553E50EB.3000402@samsung.com>

On Mon, Apr 27, 2015 at 05:08:27PM +0200, Beata Michalska wrote:
> On 04/27/2015 04:24 PM, Greg KH wrote:
> > On Mon, Apr 27, 2015 at 01:51:41PM +0200, Beata Michalska wrote:
> >> 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 |  231 ++++++++++
> >>  fs/Makefile                          |    1 +
> >>  fs/events/Makefile                   |    6 +
> >>  fs/events/fs_event.c                 |  770 ++++++++++++++++++++++++++++++++++
> >>  fs/events/fs_event.h                 |   25 ++
> >>  fs/events/fs_event_netlink.c         |   99 +++++
> >>  fs/namespace.c                       |    1 +
> >>  include/linux/fs.h                   |    6 +-
> >>  include/linux/fs_event.h             |   58 +++
> >>  include/uapi/linux/fs_event.h        |   54 +++
> >>  include/uapi/linux/genetlink.h       |    1 +
> >>  net/netlink/genetlink.c              |    7 +-
> >>  12 files changed, 1257 insertions(+), 2 deletions(-)
> >>  create mode 100644 Documentation/filesystems/events.txt
> >>  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
> > 
> > Any reason why you just don't do uevents for the block devices today,
> > and not create a new type of netlink message and userspace tool required
> > to read these?
> 
> The idea here is to have support for filesystems with no backing device as well.
> Parsing the message with libnl is really simple and requires few lines of code
> (sample application has been presented in the initial version of this RFC)

I'm not saying it's not "simple" to parse, just that now you are doing
something that requires a different tool.  If you have a block device,
you should be able to emit uevents for it, you don't need a backing
device, we handle virtual filesystems in /sys/block/ just fine :)

People already have tools that listen to libudev for system monitoring
and management, why require them to hook up to yet-another-library?  And
what is going to provide the ability for multiple userspace tools to
listen to these netlink messages in case you have more than one program
that wants to watch for these things (i.e. multiple desktop filesystem
monitoring tools, system-health checkers, etc.)?

> >> --- a/fs/Makefile
> >> +++ b/fs/Makefile
> >> @@ -126,3 +126,4 @@ obj-y				+= exofs/ # Multiple modules
> >>  obj-$(CONFIG_CEPH_FS)		+= ceph/
> >>  obj-$(CONFIG_PSTORE)		+= pstore/
> >>  obj-$(CONFIG_EFIVAR_FS)		+= efivarfs/
> >> +obj-y				+= events/
> > 
> > Always?
> > 
> >> diff --git a/fs/events/Makefile b/fs/events/Makefile
> >> new file mode 100644
> >> index 0000000..58d1454
> >> --- /dev/null
> >> +++ b/fs/events/Makefile
> >> @@ -0,0 +1,6 @@
> >> +#
> >> +# Makefile for the Linux Generic File System Event Interface
> >> +#
> >> +
> >> +obj-y := fs_event.o
> > 
> > Always?  Even if the option is not selected?  Why is everyone forced to
> > always use this code?  Can't you disable it for the "tiny" systems that
> > don't need it?
> > 
> 
> I was considering making it optional and I guess it's worth getting back
> to this idea.

The "linux-tiny" people will appreciate that :)

> >> +struct fs_trace_entry {
> >> +	atomic_t	 count;
> > 
> > Why not just use a 'struct kref' for your count, which will save a bunch
> > of open-coding of reference counting, and forcing us to audit your code
> > to verify you got all the corner cases correct?  :)
> > 
> >> +	atomic_t	 active;
> >> +	struct super_block *sb;
> 
> Not sure if using kref would change much here as the kref would not really
> make it easier to verify those corner cases, unfortunately.

Why not, that's the goal of a kref.  Yes, you already did the hard work,
but now you require everyone else to also do the hard work of trying to
audit your code.  That's why we have common functions/data structures in
the kernel, to make long-term maintenance easier.

Please switch to make it so that we "know" you are doing this correctly.

> > Are you properly reference counting this pointer?  I didn't see where
> > that was happening, so I must have missed it.
> > 
> > thanks,
> >
> 
> You haven't. And if I haven't missed anything, the sb is being used only
> as long as the super is alive.

How do you know that? :)

> Most of the code operates on sb only if it
> was explicitly asked to, through call from filesystem. There is also
> a callback notifying of mount being dropped (which proceeds the call to 
> kill_super) that invalidates the object that depends on it.
> Still, it should be explicitly stated that the sb is being used through
> bidding up the s_count counter, though that would require taking the
> sb_lock. AFAIK, one can get the reference to super block but for a particular
> device. Maybe it would be worth having it more generic (?).

Why not just grab a reference to the sb when you save the pointer, and
release it when you are done with it?  That should handle the lifecycle
properly.  It's always a very bad idea to have a pointer to a reference
counted object without actually grabbing the reference, as you have no
idea what is happening with it behind your back.

thanks,

greg k-h

--
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: [RFC PATCH 3/3] iio: derive the mounting matrix from ACPI _PLD objects
From: Kuppuswamy Sathyanarayanan @ 2015-04-27 15:42 UTC (permalink / raw)
  Cc: jic23, lars, pmeerw, robert.moore, rafael.j.wysocki, lenb,
	linux-api, linux-kernel, linux-iio, linux-acpi, Octavian Purdila
In-Reply-To: <1430146908-27919-4-git-send-email-octavian.purdila@intel.com>

Since Acpi framework already exports this info to user space, Why not do
this derivation in user space code ? Why do we need new ABI, if the same
can be derived from existing one.

> This patch derives the mounting matrix for a particular IIO device
> based ont the ACPI _PLD information. Note that if mounting matrix is
> defined in the device properties it overrieds the _PLD information.
>
> Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
> ---
>  drivers/iio/industrialio-core.c | 51
> +++++++++++++++++++++++++++++++++++++++++
>  include/linux/iio/iio.h         | 46
> +++++++++++++++++++++++++++++++++++++
>  2 files changed, 97 insertions(+)
>
> diff --git a/drivers/iio/industrialio-core.c
> b/drivers/iio/industrialio-core.c
> index 9000c53..90ee58a 100644
> --- a/drivers/iio/industrialio-core.c
> +++ b/drivers/iio/industrialio-core.c
> @@ -31,6 +31,7 @@
>  #include <linux/iio/sysfs.h>
>  #include <linux/iio/events.h>
>  #include <linux/iio/buffer.h>
> +#include <linux/acpi.h>
>
>  /* IDA to assign each registered device a unique id */
>  static DEFINE_IDA(iio_ida);
> @@ -871,6 +872,53 @@ static ssize_t iio_show_dev_name(struct device *dev,
>
>  static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL);
>
> +#if IS_ENABLED(CONFIG_ACPI)
> +static bool iio_get_mounting_matrix_acpi(struct iio_dev *indio_dev)
> +{
> +	acpi_handle h = ACPI_HANDLE(indio_dev->dev.parent);
> +	struct acpi_pld_info *info;
> +
> +	if (ACPI_SUCCESS(acpi_get_physical_device_location(h, &info))) {
> +		IIO_MM_SET(indio_dev->mounting_matrix, X, X, 1, 0);
> +		IIO_MM_SET(indio_dev->mounting_matrix, Y, Y, 1, 0);
> +		IIO_MM_SET(indio_dev->mounting_matrix, Z, Z, 1, 0);
> +
> +		/* Chip placed on the back panel ; negate x and z */
> +		if (info->panel == ACPI_PLD_PANEL_BACK) {
> +			IIO_MM_MUL(indio_dev->mounting_matrix, X, X, -1, 0);
> +			IIO_MM_MUL(indio_dev->mounting_matrix, Z, Z, -1, 0);
> +		}
> +
> +		switch (info->rotation) {
> +		case 2:
> +			/* 90 deg clockwise: negate y then swap x,y */
> +			IIO_MM_MUL(indio_dev->mounting_matrix, Y, Y, -1, 0);
> +			IIO_MM_SWAP(indio_dev->mounting_matrix, X, Y);
> +			break;
> +		case 4:
> +			/* Upside down: negate x and y */
> +			IIO_MM_MUL(indio_dev->mounting_matrix, X, X, -1, 0);
> +			IIO_MM_MUL(indio_dev->mounting_matrix, Y, Y, -1, 0);
> +			break;
> +		case 6:
> +			/* 90 deg counter clockwise: negate x then swap x,y */
> +			IIO_MM_MUL(indio_dev->mounting_matrix, X, X, -1, 0);
> +			IIO_MM_SWAP(indio_dev->mounting_matrix, X, Y);
> +			break;
> +		}
> +
> +		return true;
> +	}
> +
> +	return false;
> +}
> +#else
> +static bool iio_get_mounting_matrix_acpi(struct iio_dev *indio_dev)
> +{
> +	return false;
> +}
> +#endif
> +
>  static bool iio_get_mounting_matrix(struct iio_dev *indio_dev)
>  {
>  	int i, err;
> @@ -888,6 +936,9 @@ static bool iio_get_mounting_matrix(struct iio_dev
> *indio_dev)
>  		return true;
>  	}
>
> +	if (ACPI_HANDLE(indio_dev->dev.parent))
> +		return iio_get_mounting_matrix_acpi(indio_dev);
> +
>  	return false;
>  }
>
> diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
> index c1fa852..feb7813 100644
> --- a/include/linux/iio/iio.h
> +++ b/include/linux/iio/iio.h
> @@ -436,6 +436,52 @@ struct iio_buffer_setup_ops {
>
>  #define IIO_MM_SIZE		18
>
> +enum {
> +	IIO_MM_XX0,
> +	IIO_MM_XX1,
> +	IIO_MM_XY0,
> +	IIO_MM_XY1,
> +	IIO_MM_XZ0,
> +	IIO_MM_XZ1,
> +	IIO_MM_YX0,
> +	IIO_MM_YX1,
> +	IIO_MM_YY0,
> +	IIO_MM_YY1,
> +	IIO_MM_YZ0,
> +	IIO_MM_YZ1,
> +	IIO_MM_ZX0,
> +	IIO_MM_ZX1,
> +	IIO_MM_ZY0,
> +	IIO_MM_ZY1,
> +	IIO_MM_ZZ0,
> +	IIO_MM_ZZ1,
> +};
> +
> +#define IIO_MM_SET(mm, a, b, val0, val1)	\
> +	do {					\
> +		mm[IIO_MM_##a##b##0] = val0;	\
> +		mm[IIO_MM_##a##b##1] = val1;	\
> +	} while (0)				\
> +
> +#define IIO_MM_MUL(mm, a, b, val0, val1)	\
> +	do {					\
> +		mm[IIO_MM_##a##b##0] *= val0;	\
> +		mm[IIO_MM_##a##b##0] *= val1;	\
> +	} while (0)				\
> +
> +#define IIO_MM_SWAP(mm, x, y)					\
> +	do {							\
> +		int tmp;					\
> +								\
> +		tmp = mm[IIO_MM_##x##x##0];			\
> +		mm[IIO_MM_##x##x##0] = mm[IIO_MM_##y##y##0];	\
> +		mm[IIO_MM_##y##y##0] = tmp;			\
> +								\
> +		tmp = mm[IIO_MM_##x##x##1];			\
> +		mm[IIO_MM_##x##x##1] = mm[IIO_MM_##y##y##1];	\
> +		mm[IIO_MM_##y##y##1] = tmp;			\
> +	} while (0)						\
> +
>  /**
>   * struct iio_dev - industrial I/O device
>   * @id:			[INTERN] used to identify device internally
> --
> 1.9.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Sathyanarayanan Kuppuswamy

^ permalink raw reply

* Re: [PATCH 01/11] coresight-etm4x: Adding CoreSight ETM4x driver
From: Mathieu Poirier @ 2015-04-27 15:48 UTC (permalink / raw)
  To: Ivan T. Ivanov
  Cc: Greg KH,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Kaixu Xia,
	Chunyan Zhang
In-Reply-To: <1429890108.5211.8.camel-NEYub+7Iv8PQT0dZR+AlfA@public.gmane.org>

On 24 April 2015 at 09:41, Ivan T. Ivanov <iivanov-NEYub+7Iv8PQT0dZR+AlfA@public.gmane.org> wrote:
>
> On Wed, 2015-04-22 at 16:40 -0600, Mathieu Poirier wrote:
>>
>
>> +static struct amba_id etm4_ids[] = {
>> +       {       /* ETM 4.0 - Hi6220 board */
>> +               .id     = 0x0003b95d,
>> +               .mask   = 0x0003ffff,
>> +               .data   = "ETM 4.0",
>> +       },
>> +       {       /* ETM 4.0 - Juno board */
>> +               .id     = 0x000bb95e,
>> +               .mask   = 0x000bffff,
>
> Mask looks suspicious.

Can you please expand the "suspicious" part ?

>
> Regards,
> Ivan
>
>

^ permalink raw reply

* Re: [PATCH 01/11] coresight-etm4x: Adding CoreSight ETM4x driver
From: Mathieu Poirier @ 2015-04-27 15:51 UTC (permalink / raw)
  To: Ivan T. Ivanov
  Cc: Greg KH, linux-arm-kernel@lists.infradead.org, linux-api,
	linux-kernel@vger.kernel.org, Kaixu Xia, Chunyan Zhang
In-Reply-To: <1429887923.5211.6.camel@mm-sol.com>

On 24 April 2015 at 09:05, Ivan T. Ivanov <iivanov@mm-sol.com> wrote:
>
> On Wed, 2015-04-22 at 16:40 -0600, Mathieu Poirier wrote:
>> From: Pratik Patel <pratikp@codeaurora.org>
>>
>> This driver manages the CoreSight ETMv4 (Embedded Trace Macrocell) IP block
>> to support HW assisted tracing on ARMv7 and ARMv8 architectures.
>>
>> Signed-off-by: Pratik Patel <pratikp@codeaurora.org>
>> Signed-off-by: Kaixu Xia <xiakaixu@huawei.com>
>> Signed-off-by: Mathieu Poirier poirier@linaro.org>
>
> <snip>
>
>>
>
>> +       pm_runtime_put(&adev->dev);
>> +
>> +       desc->type = CORESIGHT_DEV_TYPE_SOURCE;
>> +       desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
>> +       desc->ops = &etm4_cs_ops;
>> +       desc->pdata = pdata;
>> +       desc->dev = dev;
>> +       desc->groups = coresight_etmv4_groups;
>> +       drvdata->csdev = coresight_register(desc);
>> +       if (IS_ERR(drvdata->csdev)) {
>> +               ret = PTR_ERR(drvdata->csdev);
>> +               goto err_arch_supported;
>
> double runtime put.

Good catch - thanks.

>
>> +       }
>> +
>> +       dev_info(dev, "%s initialized\n", (char *)id->data);
>> +
>> +       if (boot_enable) {
>> +               coresight_enable(drvdata->csdev);
>> +               drvdata->boot_enable = true;
>> +       }
>> +
>> +       return 0;
>> +
>> +err_arch_supported:
>> +       pm_runtime_put(&adev->dev);
>> +       if (--etm4_count == 0)
>> +               unregister_hotcpu_notifier(&etm4_cpu_notifier);
>> +       return ret;
>> +}
>
> Regards,
> Ivan

^ permalink raw reply

* Re: [RFC PATCH 3/3] iio: derive the mounting matrix from ACPI _PLD objects
From: Octavian Purdila @ 2015-04-27 15:54 UTC (permalink / raw)
  To: sathyanarayanan.kuppuswamy-VuQAYsv1563Yd54FQh9/CA
  Cc: Jonathan Cameron, Lars-Peter Clausen, Peter Meerwald,
	Robert Moore, Rafael J Wysocki, lenb-DgEjT+Ai2ygdnm+yROfE0A,
	linux-api-u79uwXL29TY76Z2rM5mHXA, lkml,
	linux-iio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <64714.10.254.87.235.1430149342.squirrel-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>

On Mon, Apr 27, 2015 at 6:42 PM, Kuppuswamy Sathyanarayanan
<sathyanarayanan.kuppuswamy-VuQAYsv1563Yd54FQh9/CA@public.gmane.org> wrote:
> Since Acpi framework already exports this info to user space, Why not do
> this derivation in user space code ? Why do we need new ABI, if the same
> can be derived from existing one.
>

The ABI was added in the previous patch so that we can present the
sensor orientation information to userspace even in the case of device
tree.

The purpose of this patch is to provide a consistent ABI to userspace,
i.e. to avoid doing one thing in the ACPI case and another thing in
the case of device tree.

^ permalink raw reply

* Re: [PATCH v3 4/4] Documentation: ABI: /sys/firmware/devicetree/overlays
From: Pantelis Antoniou @ 2015-04-27 17:51 UTC (permalink / raw)
  To: Greg KH
  Cc: Rob Herring, Grant Likely, Andrew Morton, Matt Porter, Koen Kooi,
	Guenter Roeck, devicetree-u79uwXL29TY76Z2rM5mHXA,
	Linux Kernel Mailing List, linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20150424203121.GB14970-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>

Hi Greg,

> On Apr 24, 2015, at 23:31 , Greg KH <greg-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org> wrote:
> 
> On Fri, Apr 24, 2015 at 12:45:44PM +0300, Pantelis Antoniou wrote:
>> Documentation ABI entry for overlays sysfs entries.
>> 
>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
>> ---
>> .../ABI/testing/sysfs-firmware-devicetree-overlays | 23 ++++++++++++++++++++++
>> 1 file changed, 23 insertions(+)
>> create mode 100644 Documentation/ABI/testing/sysfs-firmware-devicetree-overlays
>> 
>> diff --git a/Documentation/ABI/testing/sysfs-firmware-devicetree-overlays b/Documentation/ABI/testing/sysfs-firmware-devicetree-overlays
>> new file mode 100644
>> index 0000000..6b81f1c
>> --- /dev/null
>> +++ b/Documentation/ABI/testing/sysfs-firmware-devicetree-overlays
>> @@ -0,0 +1,23 @@
>> +What:		/sys/firmware/devicetree/overlays/
>> +Date:		March 2015
>> +Contact:	Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
>> +Description:
>> +		This directory contains the applied device tree overlays of
>> +		the running system, as directories of the overlay id.
> 
> "as"?
> 
>> +
>> +		enable: The master enable switch, by default is 1, and when
>> +		        set to 0 it cannot be re-enabled for security reasons.
> 
> What are those reasons?
> 

There’s a whole subthread with Grant & Kees going over security concerns.

http://comments.gmane.org/gmane.linux.drivers.devicetree/101871

> thanks,
> 
> greg k-h

Regards

— Pantelis

> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" 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 v3 4/4] Documentation: ABI: /sys/firmware/devicetree/overlays
From: Greg KH @ 2015-04-27 18:11 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Rob Herring, Grant Likely, Andrew Morton, Matt Porter, Koen Kooi,
	Guenter Roeck, devicetree-u79uwXL29TY76Z2rM5mHXA,
	Linux Kernel Mailing List, linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <C49CC7F9-C877-4590-AA63-F45D2D8E8CDC-wVdstyuyKrO8r51toPun2/C9HSW9iNxf@public.gmane.org>

On Mon, Apr 27, 2015 at 08:51:20PM +0300, Pantelis Antoniou wrote:
> Hi Greg,
> 
> > On Apr 24, 2015, at 23:31 , Greg KH <greg-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org> wrote:
> > 
> > On Fri, Apr 24, 2015 at 12:45:44PM +0300, Pantelis Antoniou wrote:
> >> Documentation ABI entry for overlays sysfs entries.
> >> 
> >> Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
> >> ---
> >> .../ABI/testing/sysfs-firmware-devicetree-overlays | 23 ++++++++++++++++++++++
> >> 1 file changed, 23 insertions(+)
> >> create mode 100644 Documentation/ABI/testing/sysfs-firmware-devicetree-overlays
> >> 
> >> diff --git a/Documentation/ABI/testing/sysfs-firmware-devicetree-overlays b/Documentation/ABI/testing/sysfs-firmware-devicetree-overlays
> >> new file mode 100644
> >> index 0000000..6b81f1c
> >> --- /dev/null
> >> +++ b/Documentation/ABI/testing/sysfs-firmware-devicetree-overlays
> >> @@ -0,0 +1,23 @@
> >> +What:		/sys/firmware/devicetree/overlays/
> >> +Date:		March 2015
> >> +Contact:	Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
> >> +Description:
> >> +		This directory contains the applied device tree overlays of
> >> +		the running system, as directories of the overlay id.
> > 
> > "as"?
> > 
> >> +
> >> +		enable: The master enable switch, by default is 1, and when
> >> +		        set to 0 it cannot be re-enabled for security reasons.
> > 
> > What are those reasons?
> > 
> 
> There’s a whole subthread with Grant & Kees going over security concerns.
> 
> http://comments.gmane.org/gmane.linux.drivers.devicetree/101871

Great, document it here please, so that others know this :)

thanks,

greg k-h

^ permalink raw reply

* Re: [PATCH v3 2/4] of: overlay: global sysfs enable attribute
From: Pantelis Antoniou @ 2015-04-27 18:13 UTC (permalink / raw)
  To: Greg KH
  Cc: Rob Herring, Grant Likely, Andrew Morton, Matt Porter, Koen Kooi,
	Guenter Roeck, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20150424202922.GA14970-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>

Hi Greg,

> On Apr 24, 2015, at 23:29 , Greg KH <greg-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org> wrote:
> 
> On Fri, Apr 24, 2015 at 12:45:42PM +0300, Pantelis Antoniou wrote:
>> A throw once master enable switch to protect against any
>> further overlay applications if the administrator desires so.
>> 
>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
>> ---
>> drivers/of/overlay.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
>> 1 file changed, 44 insertions(+), 1 deletion(-)
>> 
>> diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
>> index f17f5ef..c335809 100644
>> --- a/drivers/of/overlay.c
>> +++ b/drivers/of/overlay.c
>> @@ -21,6 +21,7 @@
>> #include <linux/err.h>
>> #include <linux/idr.h>
>> #include <linux/sysfs.h>
>> +#include <linux/atomic.h>
>> 
>> #include "of_private.h"
>> 
>> @@ -55,8 +56,12 @@ struct of_overlay {
>> 	struct kobject kobj;
>> };
>> 
>> +/* master enable switch; once set to 0 can't be re-enabled */
>> +static atomic_t ov_enable = ATOMIC_INIT(1);
>> +
>> static int of_overlay_apply_one(struct of_overlay *ov,
>> 		struct device_node *target, const struct device_node *overlay);
>> +static int overlay_removal_is_ok(struct of_overlay *ov);
>> 
>> static int of_overlay_apply_single_property(struct of_overlay *ov,
>> 		struct device_node *target, struct property *prop)
>> @@ -339,6 +344,37 @@ void of_overlay_release(struct kobject *kobj)
>> 	kfree(ov);
>> }
>> 
>> +static ssize_t enable_show(struct kobject *kobj,
>> +		struct kobj_attribute *attr, char *buf)
>> +{
>> +	return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&ov_enable));
>> +}
>> +
>> +static ssize_t enable_store(struct kobject *kobj,
>> +		struct kobj_attribute *attr, const char *buf, size_t count)
>> +{
>> +	int ret;
>> +	long new_enable;
>> +
>> +	ret = kstrtol(buf, 10, &new_enable);
>> +	if (ret != 0)
>> +		return ret;
>> +	if ((unsigned long)new_enable > 1)
>> +		return -EINVAL;
>> +	/* if we've disabled it, no going back */
>> +	if (atomic_read(&ov_enable) == 0)
>> +		return -EPERM;
>> +	atomic_set(&ov_enable, (int)new_enable);
>> +	return count;
>> +}
>> +
>> +static struct kobj_attribute enable_attr = __ATTR_RW(enable);
>> +
>> +static const struct attribute *overlay_global_attrs[] = {
>> +	&enable_attr.attr,
>> +	NULL
>> +};
> 
> Why not make this an attribute group and then attach it to the kobj_type
> to create the files in a race-free manner?
> 

Err, these are the global attributes. They are attached to the
parent of the overlay objects which is a kset object itself.

There’s no way which I can attach the attribute to it as far
as I can tell.

>> +
>> static struct kobj_type of_overlay_ktype = {
>> 	.release = of_overlay_release,
>> };
>> @@ -360,6 +396,10 @@ int of_overlay_create(struct device_node *tree)
>> 	struct of_overlay *ov;
>> 	int err, id;
>> 
>> +	/* administratively disabled */
>> +	if (!atomic_read(&ov_enable))
>> +		return -EPERM;
>> +
>> 	/* allocate the overlay structure */
>> 	ov = kzalloc(sizeof(*ov), GFP_KERNEL);
>> 	if (ov == NULL)
>> @@ -596,5 +636,8 @@ int of_overlay_init(void)
>> 	if (!ov_kset)
>> 		return -ENOMEM;
>> 
>> -	return 0;
>> +	rc = sysfs_create_files(&ov_kset->kobj, overlay_global_attrs);
>> +	WARN(rc, "%s: error adding global attributes\n", __func__);
> 
> What can a user do with this warning message?  If nothing, then don't
> print it out, right?
> 
> You are creating sysfs files _after_ the kobject has been announced to
> userspace, causing nasty race conditions.  Please don't do that.
> 

This is at overlay_init() time, which is way way before userspace ever
has a chance to start. If there’s a different way to attach a attribute
group to a kset object I’d like to find out how :)

> thanks,
> 
> greg k-h

Regards

— Pantelis--
To unsubscribe from this list: send the line "unsubscribe devicetree" 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 v3 2/4] of: overlay: global sysfs enable attribute
From: Pantelis Antoniou @ 2015-04-27 18:25 UTC (permalink / raw)
  To: Greg KH
  Cc: Rob Herring, Grant Likely, Andrew Morton, Matt Porter, Koen Kooi,
	Guenter Roeck, devicetree, Linux Kernel Mailing List, linux-api
In-Reply-To: <20150424203619.GC14970@kroah.com>

Hi Greg,

> On Apr 24, 2015, at 23:36 , Greg KH <greg@kroah.com> wrote:
> 
> On Fri, Apr 24, 2015 at 12:45:42PM +0300, Pantelis Antoniou wrote:
>> A throw once master enable switch to protect against any
>> further overlay applications if the administrator desires so.
>> 
>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
>> ---
>> drivers/of/overlay.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
>> 1 file changed, 44 insertions(+), 1 deletion(-)
>> 
>> diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
>> index f17f5ef..c335809 100644
>> --- a/drivers/of/overlay.c
>> +++ b/drivers/of/overlay.c
>> @@ -21,6 +21,7 @@
>> #include <linux/err.h>
>> #include <linux/idr.h>
>> #include <linux/sysfs.h>
>> +#include <linux/atomic.h>
>> 
>> #include "of_private.h"
>> 
>> @@ -55,8 +56,12 @@ struct of_overlay {
>> 	struct kobject kobj;
>> };
>> 
>> +/* master enable switch; once set to 0 can't be re-enabled */
>> +static atomic_t ov_enable = ATOMIC_INIT(1);
>> +
>> static int of_overlay_apply_one(struct of_overlay *ov,
>> 		struct device_node *target, const struct device_node *overlay);
>> +static int overlay_removal_is_ok(struct of_overlay *ov);
>> 
>> static int of_overlay_apply_single_property(struct of_overlay *ov,
>> 		struct device_node *target, struct property *prop)
>> @@ -339,6 +344,37 @@ void of_overlay_release(struct kobject *kobj)
>> 	kfree(ov);
>> }
>> 
>> +static ssize_t enable_show(struct kobject *kobj,
>> +		struct kobj_attribute *attr, char *buf)
>> +{
>> +	return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&ov_enable));
>> +}
>> +
>> +static ssize_t enable_store(struct kobject *kobj,
>> +		struct kobj_attribute *attr, const char *buf, size_t count)
>> +{
>> +	int ret;
>> +	long new_enable;
>> +
>> +	ret = kstrtol(buf, 10, &new_enable);
> 
> strtobool()?

OK

Regards

— Pantelis

^ permalink raw reply

* Re: [PATCH v3 2/4] of: overlay: global sysfs enable attribute
From: Greg KH @ 2015-04-27 18:39 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Rob Herring, Grant Likely, Andrew Morton, Matt Porter, Koen Kooi,
	Guenter Roeck, devicetree, linux-kernel, linux-api
In-Reply-To: <355B6AF0-7F58-4BE4-BEE6-A77246D40652@konsulko.com>

On Mon, Apr 27, 2015 at 09:13:56PM +0300, Pantelis Antoniou wrote:
> Hi Greg,
> 
> > On Apr 24, 2015, at 23:29 , Greg KH <greg@kroah.com> wrote:
> > 
> > On Fri, Apr 24, 2015 at 12:45:42PM +0300, Pantelis Antoniou wrote:
> >> A throw once master enable switch to protect against any
> >> further overlay applications if the administrator desires so.
> >> 
> >> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> >> ---
> >> drivers/of/overlay.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
> >> 1 file changed, 44 insertions(+), 1 deletion(-)
> >> 
> >> diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
> >> index f17f5ef..c335809 100644
> >> --- a/drivers/of/overlay.c
> >> +++ b/drivers/of/overlay.c
> >> @@ -21,6 +21,7 @@
> >> #include <linux/err.h>
> >> #include <linux/idr.h>
> >> #include <linux/sysfs.h>
> >> +#include <linux/atomic.h>
> >> 
> >> #include "of_private.h"
> >> 
> >> @@ -55,8 +56,12 @@ struct of_overlay {
> >> 	struct kobject kobj;
> >> };
> >> 
> >> +/* master enable switch; once set to 0 can't be re-enabled */
> >> +static atomic_t ov_enable = ATOMIC_INIT(1);
> >> +
> >> static int of_overlay_apply_one(struct of_overlay *ov,
> >> 		struct device_node *target, const struct device_node *overlay);
> >> +static int overlay_removal_is_ok(struct of_overlay *ov);
> >> 
> >> static int of_overlay_apply_single_property(struct of_overlay *ov,
> >> 		struct device_node *target, struct property *prop)
> >> @@ -339,6 +344,37 @@ void of_overlay_release(struct kobject *kobj)
> >> 	kfree(ov);
> >> }
> >> 
> >> +static ssize_t enable_show(struct kobject *kobj,
> >> +		struct kobj_attribute *attr, char *buf)
> >> +{
> >> +	return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&ov_enable));
> >> +}
> >> +
> >> +static ssize_t enable_store(struct kobject *kobj,
> >> +		struct kobj_attribute *attr, const char *buf, size_t count)
> >> +{
> >> +	int ret;
> >> +	long new_enable;
> >> +
> >> +	ret = kstrtol(buf, 10, &new_enable);
> >> +	if (ret != 0)
> >> +		return ret;
> >> +	if ((unsigned long)new_enable > 1)
> >> +		return -EINVAL;
> >> +	/* if we've disabled it, no going back */
> >> +	if (atomic_read(&ov_enable) == 0)
> >> +		return -EPERM;
> >> +	atomic_set(&ov_enable, (int)new_enable);
> >> +	return count;
> >> +}
> >> +
> >> +static struct kobj_attribute enable_attr = __ATTR_RW(enable);
> >> +
> >> +static const struct attribute *overlay_global_attrs[] = {
> >> +	&enable_attr.attr,
> >> +	NULL
> >> +};
> > 
> > Why not make this an attribute group and then attach it to the kobj_type
> > to create the files in a race-free manner?
> > 
> 
> Err, these are the global attributes. They are attached to the
> parent of the overlay objects which is a kset object itself.

Ick, no, never attach attributes to a kobject that you don't create
yourself, otherwise it's a race that you lost.

> >> +
> >> static struct kobj_type of_overlay_ktype = {
> >> 	.release = of_overlay_release,
> >> };
> >> @@ -360,6 +396,10 @@ int of_overlay_create(struct device_node *tree)
> >> 	struct of_overlay *ov;
> >> 	int err, id;
> >> 
> >> +	/* administratively disabled */
> >> +	if (!atomic_read(&ov_enable))
> >> +		return -EPERM;
> >> +
> >> 	/* allocate the overlay structure */
> >> 	ov = kzalloc(sizeof(*ov), GFP_KERNEL);
> >> 	if (ov == NULL)
> >> @@ -596,5 +636,8 @@ int of_overlay_init(void)
> >> 	if (!ov_kset)
> >> 		return -ENOMEM;
> >> 
> >> -	return 0;
> >> +	rc = sysfs_create_files(&ov_kset->kobj, overlay_global_attrs);
> >> +	WARN(rc, "%s: error adding global attributes\n", __func__);
> > 
> > What can a user do with this warning message?  If nothing, then don't
> > print it out, right?
> > 
> > You are creating sysfs files _after_ the kobject has been announced to
> > userspace, causing nasty race conditions.  Please don't do that.
> > 
> 
> This is at overlay_init() time, which is way way before userspace ever
> has a chance to start. If there’s a different way to attach a attribute
> group to a kset object I’d like to find out how :)

You can't load this as a module?  Where exactly in sysfs is this
kobject, and who creates it?

thanks,

greg k-h

^ permalink raw reply

* Re: [PATCH v3 2/4] of: overlay: global sysfs enable attribute
From: Pantelis Antoniou @ 2015-04-27 18:43 UTC (permalink / raw)
  To: Greg KH
  Cc: Rob Herring, Grant Likely, Andrew Morton, Matt Porter, Koen Kooi,
	Guenter Roeck, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20150427183915.GA29312-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>

Hi Greg,

> On Apr 27, 2015, at 21:39 , Greg KH <greg-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org> wrote:
> 
> On Mon, Apr 27, 2015 at 09:13:56PM +0300, Pantelis Antoniou wrote:
>> Hi Greg,
>> 
>>> On Apr 24, 2015, at 23:29 , Greg KH <greg-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org> wrote:
>>> 
>>> On Fri, Apr 24, 2015 at 12:45:42PM +0300, Pantelis Antoniou wrote:
>>>> A throw once master enable switch to protect against any
>>>> further overlay applications if the administrator desires so.
>>>> 
>>>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
>>>> ---
>>>> drivers/of/overlay.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
>>>> 1 file changed, 44 insertions(+), 1 deletion(-)
>>>> 
>>>> diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
>>>> index f17f5ef..c335809 100644
>>>> --- a/drivers/of/overlay.c
>>>> +++ b/drivers/of/overlay.c
>>>> @@ -21,6 +21,7 @@
>>>> #include <linux/err.h>
>>>> #include <linux/idr.h>
>>>> #include <linux/sysfs.h>
>>>> +#include <linux/atomic.h>
>>>> 
>>>> #include "of_private.h"
>>>> 
>>>> @@ -55,8 +56,12 @@ struct of_overlay {
>>>> 	struct kobject kobj;
>>>> };
>>>> 
>>>> +/* master enable switch; once set to 0 can't be re-enabled */
>>>> +static atomic_t ov_enable = ATOMIC_INIT(1);
>>>> +
>>>> static int of_overlay_apply_one(struct of_overlay *ov,
>>>> 		struct device_node *target, const struct device_node *overlay);
>>>> +static int overlay_removal_is_ok(struct of_overlay *ov);
>>>> 
>>>> static int of_overlay_apply_single_property(struct of_overlay *ov,
>>>> 		struct device_node *target, struct property *prop)
>>>> @@ -339,6 +344,37 @@ void of_overlay_release(struct kobject *kobj)
>>>> 	kfree(ov);
>>>> }
>>>> 
>>>> +static ssize_t enable_show(struct kobject *kobj,
>>>> +		struct kobj_attribute *attr, char *buf)
>>>> +{
>>>> +	return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&ov_enable));
>>>> +}
>>>> +
>>>> +static ssize_t enable_store(struct kobject *kobj,
>>>> +		struct kobj_attribute *attr, const char *buf, size_t count)
>>>> +{
>>>> +	int ret;
>>>> +	long new_enable;
>>>> +
>>>> +	ret = kstrtol(buf, 10, &new_enable);
>>>> +	if (ret != 0)
>>>> +		return ret;
>>>> +	if ((unsigned long)new_enable > 1)
>>>> +		return -EINVAL;
>>>> +	/* if we've disabled it, no going back */
>>>> +	if (atomic_read(&ov_enable) == 0)
>>>> +		return -EPERM;
>>>> +	atomic_set(&ov_enable, (int)new_enable);
>>>> +	return count;
>>>> +}
>>>> +
>>>> +static struct kobj_attribute enable_attr = __ATTR_RW(enable);
>>>> +
>>>> +static const struct attribute *overlay_global_attrs[] = {
>>>> +	&enable_attr.attr,
>>>> +	NULL
>>>> +};
>>> 
>>> Why not make this an attribute group and then attach it to the kobj_type
>>> to create the files in a race-free manner?
>>> 
>> 
>> Err, these are the global attributes. They are attached to the
>> parent of the overlay objects which is a kset object itself.
> 
> Ick, no, never attach attributes to a kobject that you don't create
> yourself, otherwise it's a race that you lost.
> 

Err, it is created by me. It’s a kset by the following call:

> ov_kset = kset_create_and_add("overlays", NULL, &of_kset->kobj);
> 

What is the problem with this?

>>>> +
>>>> static struct kobj_type of_overlay_ktype = {
>>>> 	.release = of_overlay_release,
>>>> };
>>>> @@ -360,6 +396,10 @@ int of_overlay_create(struct device_node *tree)
>>>> 	struct of_overlay *ov;
>>>> 	int err, id;
>>>> 
>>>> +	/* administratively disabled */
>>>> +	if (!atomic_read(&ov_enable))
>>>> +		return -EPERM;
>>>> +
>>>> 	/* allocate the overlay structure */
>>>> 	ov = kzalloc(sizeof(*ov), GFP_KERNEL);
>>>> 	if (ov == NULL)
>>>> @@ -596,5 +636,8 @@ int of_overlay_init(void)
>>>> 	if (!ov_kset)
>>>> 		return -ENOMEM;
>>>> 
>>>> -	return 0;
>>>> +	rc = sysfs_create_files(&ov_kset->kobj, overlay_global_attrs);
>>>> +	WARN(rc, "%s: error adding global attributes\n", __func__);
>>> 
>>> What can a user do with this warning message?  If nothing, then don't
>>> print it out, right?
>>> 
>>> You are creating sysfs files _after_ the kobject has been announced to
>>> userspace, causing nasty race conditions.  Please don't do that.
>>> 
>> 
>> This is at overlay_init() time, which is way way before userspace ever
>> has a chance to start. If there’s a different way to attach a attribute
>> group to a kset object I’d like to find out how :)
> 
> You can't load this as a module?  Where exactly in sysfs is this
> kobject, and who creates it?
> 

No, there’s no way to load this as a module, it’s in /sys/firmware/devicetree

And it’s created by the call to kset_create_and_add()

> thanks,
> 
> greg k-h

Regards

— Pantelis

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox