Linux userland API discussions
 help / color / mirror / Atom feed
* [PATCH v6 4/5] block: loop: prepare for supporing direct IO
From: Ming Lei @ 2015-06-24 13:07 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Dave Kleikamp
  Cc: Jens Axboe, Zach Brown, Christoph Hellwig, Maxim Patlasov,
	Andrew Morton, Alexander Viro, Tejun Heo, Dave Chinner, Ming Lei,
	linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1435151266-13819-1-git-send-email-ming.lei-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>

This patches provides one interface for enabling direct IO
from user space:

	- userspace(such as losetup) can pass 'file' which is
	opened/fcntl as O_DIRECT

Also __loop_update_dio() is introduced to check if direct I/O
can be used on current loop setting.

The last big change is to introduce LO_FLAGS_DIRECT_IO flag
for userspace to know if direct IO is used to access backing
file.

Cc: linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Signed-off-by: Ming Lei <ming.lei-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
---
 drivers/block/loop.c      | 56 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/block/loop.h      |  1 +
 include/uapi/linux/loop.h |  1 +
 3 files changed, 58 insertions(+)

diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 555b895..599d668 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -421,6 +421,51 @@ struct switch_request {
 	struct completion wait;
 };
 
+static void __loop_update_dio(struct loop_device *lo, bool dio)
+{
+	struct file *file = lo->lo_backing_file;
+	struct inode *inode = file->f_mapping->host;
+	bool use_dio;
+
+	/*
+	 * loop block's logical block size is 512, now
+	 * we support direct I/O only if the backing
+	 * block devices' minimize I/O size is 512 and
+	 * the offset is aligned with 512.
+	 */
+	if (dio) {
+		if (inode->i_sb->s_bdev &&
+			bdev_io_min(inode->i_sb->s_bdev) == 512 &&
+			!(lo->lo_offset & 511))
+			use_dio = true;
+		else
+			use_dio = false;
+	} else {
+		use_dio = false;
+	}
+
+	if (lo->use_dio == use_dio)
+		return;
+
+	/* flush dirty pages before changing direct IO */
+	vfs_fsync(file, 0);
+
+	/*
+	 * The flag of LO_FLAGS_DIRECT_IO is handled similarly with
+	 * LO_FLAGS_READ_ONLY, both are set from kernel, and losetup
+	 * will get updated by ioctl(LOOP_GET_STATUS)
+	 */
+	blk_mq_freeze_queue(lo->lo_queue);
+	lo->use_dio = use_dio;
+	lo->lo_flags |= use_dio ? LO_FLAGS_DIRECT_IO : 0;
+	blk_mq_unfreeze_queue(lo->lo_queue);
+}
+
+static inline void loop_update_dio(struct loop_device *lo)
+{
+	__loop_update_dio(lo, io_is_direct(lo->lo_backing_file));
+}
+
 /*
  * Do the actual switch; called from the BIO completion routine
  */
@@ -441,6 +486,7 @@ static void do_loop_switch(struct loop_device *lo, struct switch_request *p)
 		mapping->host->i_bdev->bd_block_size : PAGE_SIZE;
 	lo->old_gfp_mask = mapping_gfp_mask(mapping);
 	mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
+	loop_update_dio(lo);
 }
 
 /*
@@ -627,11 +673,19 @@ static ssize_t loop_attr_partscan_show(struct loop_device *lo, char *buf)
 	return sprintf(buf, "%s\n", partscan ? "1" : "0");
 }
 
+static ssize_t loop_attr_dio_show(struct loop_device *lo, char *buf)
+{
+	int dio = (lo->lo_flags & LO_FLAGS_DIRECT_IO);
+
+	return sprintf(buf, "%s\n", dio ? "1" : "0");
+}
+
 LOOP_ATTR_RO(backing_file);
 LOOP_ATTR_RO(offset);
 LOOP_ATTR_RO(sizelimit);
 LOOP_ATTR_RO(autoclear);
 LOOP_ATTR_RO(partscan);
+LOOP_ATTR_RO(dio);
 
 static struct attribute *loop_attrs[] = {
 	&loop_attr_backing_file.attr,
@@ -639,6 +693,7 @@ static struct attribute *loop_attrs[] = {
 	&loop_attr_sizelimit.attr,
 	&loop_attr_autoclear.attr,
 	&loop_attr_partscan.attr,
+	&loop_attr_dio.attr,
 	NULL,
 };
 
@@ -783,6 +838,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
 	if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync)
 		blk_queue_flush(lo->lo_queue, REQ_FLUSH);
 
+	loop_update_dio(lo);
 	set_capacity(lo->lo_disk, size);
 	bd_set_size(bdev, size << 9);
 	loop_sysfs_init(lo);
diff --git a/drivers/block/loop.h b/drivers/block/loop.h
index b6c7d21..d1de221 100644
--- a/drivers/block/loop.h
+++ b/drivers/block/loop.h
@@ -58,6 +58,7 @@ struct loop_device {
 	struct mutex		lo_ctl_mutex;
 	struct kthread_worker	worker;
 	struct task_struct	*worker_task;
+	bool			use_dio;
 
 	struct request_queue	*lo_queue;
 	struct blk_mq_tag_set	tag_set;
diff --git a/include/uapi/linux/loop.h b/include/uapi/linux/loop.h
index e0cecd2..949851c 100644
--- a/include/uapi/linux/loop.h
+++ b/include/uapi/linux/loop.h
@@ -21,6 +21,7 @@ enum {
 	LO_FLAGS_READ_ONLY	= 1,
 	LO_FLAGS_AUTOCLEAR	= 4,
 	LO_FLAGS_PARTSCAN	= 8,
+	LO_FLAGS_DIRECT_IO	= 16,
 };
 
 #include <asm/posix_types.h>	/* for __kernel_old_dev_t */
-- 
1.9.1

^ permalink raw reply related

* Re: [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
From: Srinivas Kandagatla @ 2015-06-24 13:03 UTC (permalink / raw)
  To: Stefan Wahren, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Greg Kroah-Hartman, wxt-TNX95d0MmH7DzftRWevZcw,
	linux-api-u79uwXL29TY76Z2rM5mHXA, Kumar Gala, Rob Herring,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ, arnd-r2nGTMty4D4,
	s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	mporter-OWPKS81ov/FWk0Htik3J/w, Maxime Ripard,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mark Brown
In-Reply-To: <558AA2E2.1010606-eS4NqCHxEME@public.gmane.org>



On 24/06/15 13:30, Stefan Wahren wrote:
>> >If the question is just about hexdump, then hexdump itself can read
>> >file from given offset and size.
> yes, this is my question at first. Let me show the difference between
> the current implementation and my expectations as a user.
>
> $ hexdump /sys/class/nvmem/mxs-ocotp/nvmem
>
> Current implementation: dump the complete register range defined in DT
>
Its dumping the range which is specified in the provider regmap. If the 
requirement is to dump only particular range, this has to be made 
explicit while creating regmap, which is to specify the base address to 
start from "First data register" and max_register to be "Last data 
register "- "First data register"

> User expectation: dump only the data from OCOTP block
>
> Let me explain it for i.MX28 OCOTP
>
> 0x8002c000 // Start of OCOTP register block (defined in DT)
>
> 0x8002c020 // First data register
>
> 0x8002c290 // Last data register
>
> 0x8002dfff // End of OCOTP register block (defined in DT)
>
> My knowledge about regmap is limited, but how can i achieve that hexdump
> give me only the data registers? From my understanding this should be
> handled in regmap and not in the read function.

Setup the base and regmap_config correctly in the provider driver before 
calling regmap_init_mmio().

Let me know if you need more details.

--srini

>
> Are my expectations about the raw access wrong?
>
>

^ permalink raw reply

* Re: [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
From: Stefan Wahren @ 2015-06-24 12:30 UTC (permalink / raw)
  To: Srinivas Kandagatla, linux-arm-kernel
  Cc: Greg Kroah-Hartman, wxt, linux-api, Kumar Gala, Rob Herring,
	sboyd, arnd, s.hauer, linux-kernel, linux-arm-msm, mporter,
	Maxime Ripard, pantelis.antoniou, devicetree, Mark Brown
In-Reply-To: <558A7C92.2040102@linaro.org>

Hi Srinivas,

Am 24.06.2015 um 11:46 schrieb Srinivas Kandagatla:
>
>
> On 23/06/15 20:47, Stefan Wahren wrote:
>>> 0001000
>>> >
>> i want to port OCOTP driver for MXS, which hasn't MMIO. From my
>> understanding
> That's cool.
>
>> hexdump would readout the complete register range defined in provider
>> DT node.
>>
>> How can i achieve that hexdump only reads the data area within the
>> register
>> range?
>
> If the question is just about hexdump, then hexdump itself can read
> file from given offset and size.

yes, this is my question at first. Let me show the difference between
the current implementation and my expectations as a user.

$ hexdump /sys/class/nvmem/mxs-ocotp/nvmem

Current implementation: dump the complete register range defined in DT

User expectation: dump only the data from OCOTP block

Let me explain it for i.MX28 OCOTP

0x8002c000 // Start of OCOTP register block (defined in DT)

0x8002c020 // First data register

0x8002c290 // Last data register

0x8002dfff // End of OCOTP register block (defined in DT)

My knowledge about regmap is limited, but how can i achieve that hexdump
give me only the data registers? From my understanding this should be
handled in regmap and not in the read function.

Are my expectations about the raw access wrong?


>
> But I believe the real question is "How can we dump each nvmem cell
> independently"
>
> In one of my replies I mentioned that am planning to add sysfs entries
> under /sys/class/nvmem/<provider>/cells/
>
> ex:
> for qfprom tsens calibration it would look like:
>
> $ hexdump /sys/class/nvmem/qfprom0/cells/tsens_calibration
>
> 0000000 e000 0c00 0c00 0000 0c00
> ...
>
> Is that what you guys are looking for?

That would be nice, too :-)

>
> --srini
>>
>> Stefan

TIA

Stefan

^ permalink raw reply

* [PATCH] mm: fix status code move_pages() returns for zero page
From: Kirill A. Shutemov @ 2015-06-24 10:23 UTC (permalink / raw)
  To: Andrew Morton
  Cc: linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-api-u79uwXL29TY76Z2rM5mHXA, Kirill A. Shutemov,
	Christoph Lameter, Hugh Dickins

Man page for move_pages(2) specifies that status code for zero page is
supposed to be -EFAULT. Currently kernel return -ENOENT in this case.

follow_page() can do it for us, if we would ask for FOLL_DUMP.

Signed-off-by: Kirill A. Shutemov <kirill.shutemov-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Cc: Christoph Lameter <cl-vYTEC60ixJUAvxtiuMwx3w@public.gmane.org>
Cc: Hugh Dickins <hughd-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
---
 mm/migrate.c | 18 ++++++------------
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/mm/migrate.c b/mm/migrate.c
index 236ee25e79d9..d3529d620a5b 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -1222,7 +1222,9 @@ static int do_move_page_to_node_array(struct mm_struct *mm,
 		if (!vma || pp->addr < vma->vm_start || !vma_migratable(vma))
 			goto set_status;
 
-		page = follow_page(vma, pp->addr, FOLL_GET|FOLL_SPLIT);
+		/* FOLL_DUMP to ignore special (like zero) pages */
+		page = follow_page(vma, pp->addr,
+				FOLL_GET | FOLL_SPLIT | FOLL_DUMP);
 
 		err = PTR_ERR(page);
 		if (IS_ERR(page))
@@ -1232,10 +1234,6 @@ static int do_move_page_to_node_array(struct mm_struct *mm,
 		if (!page)
 			goto set_status;
 
-		/* Use PageReserved to check for zero page */
-		if (PageReserved(page))
-			goto put_and_set;
-
 		pp->page = page;
 		err = page_to_nid(page);
 
@@ -1392,18 +1390,14 @@ static void do_pages_stat_array(struct mm_struct *mm, unsigned long nr_pages,
 		if (!vma || addr < vma->vm_start)
 			goto set_status;
 
-		page = follow_page(vma, addr, 0);
+		/* FOLL_DUMP to ignore special (like zero) pages */
+		page = follow_page(vma, addr, FOLL_DUMP);
 
 		err = PTR_ERR(page);
 		if (IS_ERR(page))
 			goto set_status;
 
-		err = -ENOENT;
-		/* Use PageReserved to check for zero page */
-		if (!page || PageReserved(page))
-			goto set_status;
-
-		err = page_to_nid(page);
+		err = page ? page_to_nid(page) : -ENOENT;
 set_status:
 		*status = err;
 
-- 
2.1.4

^ permalink raw reply related

* Re: [PATCH v5 03/11] nvmem: Add a simple NVMEM framework for nvmem providers
From: Srinivas Kandagatla @ 2015-06-24 10:05 UTC (permalink / raw)
  To: Stephen Boyd, linux-arm-kernel
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown, s.hauer,
	Greg Kroah-Hartman, linux-api, linux-kernel, devicetree,
	linux-arm-msm, arnd, pantelis.antoniou, mporter
In-Reply-To: <5589F8C2.3030502@codeaurora.org>



On 24/06/15 01:24, Stephen Boyd wrote:
> Can you assign the attributes to the device_type in the nvmem::struct
> device? I don't see why these attributes need to be part of the class.
>
I will fix this.
>>> >>
>>>> >>>+{
>>>> >>>+    return class_register(&nvmem_class);
>>> >>
>>> >>I thought class was on the way out? Aren't we supposed to use bus types
>>> >>for new stuff?
>> >Do you remember any conversation on the list about this? I could not
>> >find it on web.
>> >
>> >on the other hand, nvmem is not really a bus, making it a bus type
>> >sounds incorrect to me.
>> >
> I found this post on the cpu class that Sudeep tried to introduce[1].
> And there's this post from Kay that alludes to a unification of busses
> and classes[2]. And some other post where Kay says class is dead [3].
Thanks for the links,
Yep, looks like Class is dead, I will change the code to use bus type 
instead.

>
> [1]https://lkml.org/lkml/2014/8/21/191
> [2]https://lwn.net/Articles/471821/
> [3]https://lkml.org/lkml/2010/11/11/17
--srini

^ permalink raw reply

* Re: [PATCH v6 1/9] nvmem: Add a simple NVMEM framework for nvmem providers
From: Srinivas Kandagatla @ 2015-06-24  9:56 UTC (permalink / raw)
  To: Pantelis Antoniou, Joe Perches
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Greg Kroah-Hartman, Maxime Ripard, Rob Herring, Kumar Gala,
	Mark Brown, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ,
	linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, Arnd Bergmann,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ, Matt Porter,
	stefan.wahren-eS4NqCHxEME, wxt-TNX95d0MmH7DzftRWevZcw
In-Reply-To: <7BE8C921-180A-411D-A3C0-5D2A7AE3AB6A-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>



On 23/06/15 10:26, Pantelis Antoniou wrote:
> Hi Joe,
>
>> >On Jun 23, 2015, at 05:52 , Joe Perches<joe-6d6DIl74uiNBDgjK7y7TUQ@public.gmane.org>  wrote:
>> >
>> >On Tue, 2015-06-23 at 00:08 +0100, Srinivas Kandagatla wrote:
>>> >>This patch adds just providers part of the framework just to enable easy
>>> >>review.
>> >[]
>>> >>include/linux/nvmem-provider.h |  54 ++++++
>> >
>> >Unless there are going to be users of nvmem-provider.h
>> >outside of the drivers/nvmem directory, perhaps that
>> >file (and nvmem-consumer.h) should be in drivers/nvmem/
>> >
>> >
> nvmem-consumer.h should be accessible from any driver, no?
>
> And unfortunately nvmem-provider should be accessible too.
> There are already eeprom drivers in the eeprom/misc directory that
> cannot be moved yet to drivers/nvmem (like at24).
>
> They need the provider definitions while they provide both the old
> style interface, and the new NVMEM based one.
>
> When we move them to the drivers/nvmem directory, then yes the
> provider header file should move there.

Yep, that's the plan.

---srini
>
> 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 v6 1/9] nvmem: Add a simple NVMEM framework for nvmem providers
From: Srinivas Kandagatla @ 2015-06-24  9:54 UTC (permalink / raw)
  To: Stefan Wahren, Greg Kroah-Hartman,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: wxt-TNX95d0MmH7DzftRWevZcw, linux-api-u79uwXL29TY76Z2rM5mHXA,
	Kumar Gala, Rob Herring, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	arnd-r2nGTMty4D4, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	mporter-OWPKS81ov/FWk0Htik3J/w, Maxime Ripard,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mark Brown
In-Reply-To: <982684639.251832.1435090259373.JavaMail.open-xchange-0SF9iQWekqLZ78VGacPtK8gmgJlYmuWJ@public.gmane.org>



On 23/06/15 21:10, Stefan Wahren wrote:
> Hi Srinivas,
>
> sorry for the messed up indention.
>
NP,
>> + */
>> +
>> +#include <linux/device.h>
>> +#include <linux/nvmem-provider.h>
>> +#include <linux/export.h>
>> +#include <linux/fs.h>
>> +#include <linux/idr.h>
>> +#include <linux/init.h>
>> +#include <linux/regmap.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/slab.h>
>
> Sorting alphabetically would by nice
>
Good Idea.

>> + [...]
>> +/**
>> + * nvmem_register() - Register a nvmem device for given nvmem_config.
>> + * Also creates an binary entry in /sys/class/nvmem/dev-name/nvmem
>> + *
>> + * @config: nvmem device configuration with which nvmem device is created.
>> + *
>> + * The return value will be an ERR_PTR() on error or a valid pointer
>> + * to nvmem_device.
>> + */
>> +
>> +struct nvmem_device *nvmem_register(struct nvmem_config *config)
>> +{
>> + struct nvmem_device *nvmem;
>> + struct regmap *rm;
>> + int rval;
>> +
>> + if (!config->dev)
>> + return ERR_PTR(-EINVAL);
>> +
>> + rm = dev_get_regmap(config->dev, NULL);
>> + if (!rm) {
>> + dev_err(config->dev, "Regmap not found\n");
>> + return ERR_PTR(-EINVAL);
>> + }
>> +
>> + nvmem = kzalloc(sizeof(*nvmem), GFP_KERNEL);
>> + if (!nvmem)
>> + return ERR_PTR(-ENOMEM);
>> +
>> + nvmem->id = ida_simple_get(&nvmem_ida, 0, 0, GFP_KERNEL);
>> + if (nvmem->id < 0) {
>> + kfree(nvmem);
>> + return ERR_PTR(nvmem->id);
>> + }
>> +
>> + nvmem->regmap = rm;
>> + nvmem->owner = config->owner;
>> + nvmem->stride = regmap_get_reg_stride(rm);
>> + nvmem->word_size = regmap_get_val_bytes(rm);
>> + nvmem->size = regmap_get_max_register(rm) + nvmem->stride;
>> + nvmem->dev.class = &nvmem_class;
>> + nvmem->dev.parent = config->dev;
>> + nvmem->dev.of_node = config->dev->of_node;
>> + dev_set_name(&nvmem->dev, "%s%d",
>> + config->name ? : "nvmem", config->id);
>> +
>> + nvmem->read_only = nvmem->dev.of_node ?
>> + of_property_read_bool(nvmem->dev.of_node,
>> + "read-only") :
>> + config->read_only;
>> +
>> + device_initialize(&nvmem->dev);
>> +
>> + dev_dbg(&nvmem->dev, "Registering nvmem device %s\n",
>> + dev_name(&nvmem->dev));
>> +
>> + rval = device_add(&nvmem->dev);
>> + if (rval) {
>> + ida_simple_remove(&nvmem_ida, nvmem->id);
>> + kfree(nvmem);
>> + return ERR_PTR(rval);
>> + }
>> +
>> + /* update sysfs attributes */
>> + if (nvmem->read_only)
>> + sysfs_update_group(&nvmem->dev.kobj, &nvmem_bin_ro_group);
>> +
>> + if (config->cells)
>> + nvmem_add_cells(nvmem, config);
>
> I think this would be a better place for the debug message from above.
> Additionally we could add the cell count and so on.
I will give it a try.

thanks,
srini
>
> Stefan
>

^ permalink raw reply

* Re: [PATCH v6 2/9] nvmem: Add a simple NVMEM framework for consumers
From: Srinivas Kandagatla @ 2015-06-24  9:53 UTC (permalink / raw)
  To: Stefan Wahren, Greg Kroah-Hartman,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: wxt-TNX95d0MmH7DzftRWevZcw, linux-api-u79uwXL29TY76Z2rM5mHXA,
	Kumar Gala, Rob Herring, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	arnd-r2nGTMty4D4, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	mporter-OWPKS81ov/FWk0Htik3J/w, Maxime Ripard,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mark Brown
In-Reply-To: <272462057.251967.1435090588801.JavaMail.open-xchange-0SF9iQWekqLZ78VGacPtK8gmgJlYmuWJ@public.gmane.org>



On 23/06/15 21:16, Stefan Wahren wrote:
>> +
>> >+struct device;
> Do we need forward declaration of struct device_node too?
>
Yep, Will fix it in next version.
--srini
>> >+/* consumer cookie */
>> >[...]

^ permalink raw reply

* Re: [PATCH v6 3/9] nvmem: Add nvmem_device based consumer apis.
From: Srinivas Kandagatla @ 2015-06-24  9:52 UTC (permalink / raw)
  To: Stefan Wahren, Greg Kroah-Hartman, linux-arm-kernel
  Cc: wxt, linux-api, Kumar Gala, Rob Herring, sboyd, arnd, s.hauer,
	linux-kernel, linux-arm-msm, mporter, Maxime Ripard,
	pantelis.antoniou, devicetree, Mark Brown
In-Reply-To: <1344600420.252283.1435091331020.JavaMail.open-xchange@oxbsltgw00.schlund.de>



On 23/06/15 21:28, Stefan Wahren wrote:
>> >@@ -26,6 +35,21 @@ void devm_nvmem_cell_put(struct device *dev, struct
>> >nvmem_cell *cell);
>> >void *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len);
>> >int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len);
>> >
>> >+/* direct nvmem device read/write interface */
>> >+struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
>> >+struct nvmem_device *devm_nvmem_device_get(struct device *dev,
>> >+ const char *name);
>> >+void nvmem_device_put(struct nvmem_device *nvmem);
>> >+void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem);
>> >+int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
>> >+ size_t bytes, void *buf);
>> >+int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
>> >+ size_t bytes, void *buf);
> Maybe i mixed something but those functions use the datatype unsigned int for
> offset
> and the offset in the structs use datatype int. Looks a little bit inconsistent.
thanks for comments,

I will have a relook at this and see if I can fix it.

thanks,
srini

^ permalink raw reply

* Re: [PATCH v6 4/9] nvmem: Add bindings for simple nvmem framework
From: Srinivas Kandagatla @ 2015-06-24  9:51 UTC (permalink / raw)
  To: Stefan Wahren, Greg Kroah-Hartman,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: wxt-TNX95d0MmH7DzftRWevZcw, linux-api-u79uwXL29TY76Z2rM5mHXA,
	Kumar Gala, Rob Herring, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	arnd-r2nGTMty4D4, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	mporter-OWPKS81ov/FWk0Htik3J/w, Maxime Ripard,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mark Brown
In-Reply-To: <1670081084.252423.1435091735127.JavaMail.open-xchange-0SF9iQWekqLZ78VGacPtK8gmgJlYmuWJ@public.gmane.org>



On 23/06/15 21:35, Stefan Wahren wrote:
>> +Required properties:
>> >+reg: specifies the offset in byte within that storage device, start bit
>> >+ in the byte and the length in bits of the data we care about.
> Is the second parameter really in bits, not bytes?
Thanks for spotting this, I will fix this.

^ permalink raw reply

* Re: [PATCH v6 7/9] nvmem: qfprom: Add bindings for qfprom
From: Srinivas Kandagatla @ 2015-06-24  9:49 UTC (permalink / raw)
  To: Rajendra Nayak, linux-arm-kernel, Greg Kroah-Hartman
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown, s.hauer,
	linux-api, linux-kernel, devicetree, linux-arm-msm, arnd, sboyd,
	pantelis.antoniou, mporter, stefan.wahren, wxt
In-Reply-To: <55892602.2030809@codeaurora.org>



On 23/06/15 10:25, Rajendra Nayak wrote:
> []..
>
>> +Example:
>> +
>> +    qfprom: qfprom@00700000 {
>> +        compatible     = "qcom,qfprom";
>> +        reg        = <0x00700000 0x8000>;
>> +        ...
>> +        /* Data cells */
>> +        tsens_calibration: calib@404 {
>> +            reg = <0x4404 0x10>;
>> +        };
>> +    };
>> +
>> +
>> += Data consumers =
>> +Are device nodes which consume nvmem data cells.
>> +
>> +For example:
>> +
>> +    tsens {
>> +        ...
>> +        nvmem-cell = <&tsens_calibration>;
>
> Shouldn't this be nvmem-cells instead?
>
You are correct, Will fix it in next version.

--srini
>> +        nvmem-cell-names = "calibration";
>> +    };
>>

^ permalink raw reply

* Re: [PATCH v6 8/9] nvmem: sunxi: Move the SID driver to the nvmem framework
From: Srinivas Kandagatla @ 2015-06-24  9:48 UTC (permalink / raw)
  To: Stefan Wahren, Greg Kroah-Hartman, linux-arm-kernel
  Cc: wxt, linux-api, Kumar Gala, Rob Herring, sboyd, arnd, s.hauer,
	linux-kernel, linux-arm-msm, mporter, Maxime Ripard,
	pantelis.antoniou, devicetree, Mark Brown
In-Reply-To: <1335062615.252618.1435092272970.JavaMail.open-xchange@oxbsltgw00.schlund.de>



On 23/06/15 21:44, Stefan Wahren wrote:
>
>> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 23. Juni 2015 um
>> 01:09 geschrieben:
>>
>>
>> From: Maxime Ripard <maxime.ripard@free-electrons.com>
>>
>> Now that we have the nvmem framework, we can consolidate the common
>> driver code. Move the driver to the framework, and hopefully, it will
>> fix the sysfs file creation race.
>> --- /dev/null
>> +++ b/drivers/nvmem/sunxi-sid.c
>> [...]
>> +
>> +static int sunxi_sid_write(void *context, const void *data, size_t count)
>> +{
>> + /* Unimplemented */
>> + return 0;
>> +}
>> +
>
> I think it should be clear that the write operation isn't implemented. It's more
> important to know the function should make
> regmap_init happy.


I totally agree with you.. It was just to make regmap_init happy. Indeed 
I thought of adding this comment, but forgot over the time :-) I will 
fix it.

--srini


> --
> To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply

* Re: [RESEND PATCH V2 1/3] Add mmap flag to request pages are locked after page fault
From: Michal Hocko @ 2015-06-24  9:47 UTC (permalink / raw)
  To: Vlastimil Babka
  Cc: Eric B Munson, Andrew Morton, linux-alpha-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-mips-6z/3iImG2C8G8FEW9MqTrA,
	linux-parisc-u79uwXL29TY76Z2rM5mHXA,
	linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
	sparclinux-u79uwXL29TY76Z2rM5mHXA,
	linux-xtensa-PjhNF2WwrV/0Sa2dR60CXw,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	linux-arch-u79uwXL29TY76Z2rM5mHXA,
	linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <558954DD.4060405-AlSwsSmVLrQ@public.gmane.org>

On Tue 23-06-15 14:45:17, Vlastimil Babka wrote:
> On 06/22/2015 04:18 PM, Eric B Munson wrote:
> >On Mon, 22 Jun 2015, Michal Hocko wrote:
> >
> >>On Fri 19-06-15 12:43:33, Eric B Munson wrote:
[...]
> >>>My thought on detecting was that someone might want to know if they had
> >>>a VMA that was VM_LOCKED but had not been made present becuase of a
> >>>failure in mmap.  We don't have a way today, but adding VM_LOCKONFAULT
> >>>is at least explicit about what is happening which would make detecting
> >>>the VM_LOCKED but not present state easier.
> >>
> >>One could use /proc/<pid>/pagemap to query the residency.
> 
> I think that's all too much complex scenario for a little gain. If someone
> knows that mmap(MAP_LOCKED|MAP_POPULATE) is not perfect, he should either
> mlock() separately from mmap(), or fault the range manually with a for loop.
> Why try to detect if the corner case was hit?

No idea. I have just offered a way to do that. I do not think it is
anyhow useful but who knows... I do agree that the mlock should be used
for the full mlock semantic.

> >>>This assumes that
> >>>MAP_FAULTPOPULATE does not translate to a VMA flag, but it sounds like
> >>>it would have to.
> >>
> >>Yes, it would have to have a VM flag for the vma.
> 
> So with your approach, VM_LOCKED flag is enough, right? The new MAP_ /
> MLOCK_ flags just cause setting VM_LOCKED to not fault the whole vma, but
> otherwise nothing changes.

VM_FAULTPOPULATE would have to be sticky to prevent from other
speculative poppulation of the mapping. I mean, is it OK to have a new
mlock semantic (on fault) which might still populate&lock memory which
hasn't been faulted directly? Who knows what kind of speculative things
we will do in the future and then find out that the semantic of
lock-on-fault is not usable anymore.

[...]

-- 
Michal Hocko
SUSE Labs

^ permalink raw reply

* Re: [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
From: Srinivas Kandagatla @ 2015-06-24  9:46 UTC (permalink / raw)
  To: Stefan Wahren, Greg Kroah-Hartman, linux-arm-kernel
  Cc: wxt, linux-api, Kumar Gala, Rob Herring, sboyd, arnd, s.hauer,
	linux-kernel, linux-arm-msm, mporter, Maxime Ripard,
	pantelis.antoniou, devicetree, Mark Brown
In-Reply-To: <235181230.251177.1435088854197.JavaMail.open-xchange@oxbsltgw00.schlund.de>



On 23/06/15 20:47, Stefan Wahren wrote:
>> 0001000
>> >
> i want to port OCOTP driver for MXS, which hasn't MMIO. From my understanding
That's cool.

> hexdump would readout the complete register range defined in provider DT node.
>
> How can i achieve that hexdump only reads the data area within the register
> range?

If the question is just about hexdump, then hexdump itself can read file 
from given offset and size.

But I believe the real question is "How can we dump each nvmem cell 
independently"

In one of my replies I mentioned that am planning to add sysfs entries 
under /sys/class/nvmem/<provider>/cells/

ex:
for qfprom tsens calibration it would look like:

$ hexdump /sys/class/nvmem/qfprom0/cells/tsens_calibration

0000000 e000 0c00 0c00 0000 0c00
...

Is that what you guys are looking for?

--srini
>
> Stefan

^ permalink raw reply

* Re: [RESEND PATCH V2 1/3] Add mmap flag to request pages are locked after page fault
From: Michal Hocko @ 2015-06-24  8:50 UTC (permalink / raw)
  To: Eric B Munson
  Cc: Andrew Morton, linux-alpha, linux-kernel, linux-mips,
	linux-parisc, linuxppc-dev, sparclinux, linux-xtensa, linux-mm,
	linux-arch, linux-api
In-Reply-To: <20150622141806.GE2329@akamai.com>

On Mon 22-06-15 10:18:06, Eric B Munson wrote:
> On Mon, 22 Jun 2015, Michal Hocko wrote:
> 
> > On Fri 19-06-15 12:43:33, Eric B Munson wrote:
[...]
> > > Are you objecting to the addition of the VMA flag VM_LOCKONFAULT, or the
> > > new MAP_LOCKONFAULT flag (or both)? 
> > 
> > I thought the MAP_FAULTPOPULATE (or any other better name) would
> > directly translate into VM_FAULTPOPULATE and wouldn't be tight to the
> > locked semantic. We already have VM_LOCKED for that. The direct effect
> > of the flag would be to prevent from population other than the direct
> > page fault - including any speculative actions like fault around or
> > read-ahead.
> 
> I like the ability to control other speculative population, but I am not
> sure about overloading it with the VM_LOCKONFAULT case.  Here is my
> concern.  If we are using VM_FAULTPOPULATE | VM_LOCKED to denote
> LOCKONFAULT, how can we tell the difference between someone that wants
> to avoid read-ahead and wants to use mlock()?

Not sure I understand. Something like?
addr = mmap(VM_FAULTPOPULATE) # To prevent speculative mappings into the vma
[...]
mlock(addr, len) # Now I want the full mlock semantic

and the later to have the full mlock semantic and populate the given
area regardless of VM_FAULTPOPULATE being set on the vma? This would
be an interesting question because mlock man page clearly states the
semantic and that is to _always_ populate or fail. So I originally
thought that it would obey VM_FAULTPOPULATE but this needs a more
thinking.

> This might lead to some
> interesting states with mlock() and munlock() that take flags.  For
> instance, using VM_LOCKONFAULT mlock(MLOCK_ONFAULT) followed by
> munlock(MLOCK_LOCKED) leaves the VMAs in the same state with
> VM_LOCKONFAULT set. 

This is really confusing. Let me try to rephrase that. So you have
mlock(addr, len, MLOCK_ONFAULT)
munlock(addr, len, MLOCK_LOCKED)

IIUC you would expect the vma still being MLOCK_ONFAULT, right? Isn't
that behavior strange and unexpected? First of all, munlock has
traditionally dropped the lock on the address range (e.g. what should
happen if you did plain old munlock(addr, len)). But even without
that. You are trying to unlock something that hasn't been locked the
same way. So I would expect -EINVAL at least, if the two modes should be
really represented by different flags.

Or did you mean the both types of lock like:
mlock(addr, len, MLOCK_ONFAULT) | mmap(MAP_LOCKONFAULT)
mlock(addr, len, MLOCK_LOCKED)
munlock(addr, len, MLOCK_LOCKED)

and that should keep MLOCK_ONFAULT?
This sounds even more weird to me because that means that the vma in
question would be locked by two different mechanisms. MLOCK_LOCKED with
the "always populate" semantic would rule out MLOCK_ONFAULT so what
would be the meaning of the other flag then? Also what should regular
munlock(addr, len) without flags unlock? Both?

> If we use VM_FAULTPOPULATE, the same pair of calls
> would clear VM_LOCKED, but leave VM_FAULTPOPULATE.  It may not matter in
> the end, but I am concerned about the subtleties here.

This sounds like the proper behavior to me. munlock should simply always
drop VM_LOCKED and the VM_FAULTPOPULATE can live its separate life.

Btw. could you be more specific about semantic of m{un}lock(addr, len, flags)
you want to propose? The more I think about that the more I am unclear
about it, especially munlock behavior and possible flags.
-- 
Michal Hocko
SUSE Labs

--
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 v3 1/4] fs: Add generic file system event notifications
From: Dmitry Monakhov @ 2015-06-24  8:47 UTC (permalink / raw)
  To: Beata Michalska, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-api-u79uwXL29TY76Z2rM5mHXA
  Cc: greg-U8xfFu+wG4EAvxtiuMwx3w, 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: <1434460173-18427-2-git-send-email-b.michalska-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 47491 bytes --]

Beata Michalska <b.michalska-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> writes:

> Introduce configurable generic interface for file
> system-wide event notifications, to provide file
> systems with a common way of reporting any potential
> issues as they emerge.
>
> The notifications are to be issued through generic
> netlink interface by newly introduced multicast group.
>
> Threshold notifications have been included, allowing
> triggering an event whenever the amount of free space drops
> below a certain level - or levels to be more precise as two
> of them are being supported: the lower and the upper range.
> The notifications work both ways: once the threshold level
> has been reached, an event shall be generated whenever
> the number of available blocks goes up again re-activating
> the threshold.
>
> The interface has been exposed through a vfs. Once mounted,
> it serves as an entry point for the set-up where one can
> register for particular file system events.
>
> Signed-off-by: Beata Michalska <b.michalska-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> ---
>  Documentation/filesystems/events.txt |  232 ++++++++++
>  fs/Kconfig                           |    2 +
>  fs/Makefile                          |    1 +
>  fs/events/Kconfig                    |    7 +
>  fs/events/Makefile                   |    5 +
>  fs/events/fs_event.c                 |  809 ++++++++++++++++++++++++++++++++++
>  fs/events/fs_event.h                 |   22 +
>  fs/events/fs_event_netlink.c         |  104 +++++
>  fs/namespace.c                       |    1 +
>  include/linux/fs.h                   |    6 +-
>  include/linux/fs_event.h             |   72 +++
>  include/uapi/linux/Kbuild            |    1 +
>  include/uapi/linux/fs_event.h        |   58 +++
>  13 files changed, 1319 insertions(+), 1 deletion(-)
>  create mode 100644 Documentation/filesystems/events.txt
>  create mode 100644 fs/events/Kconfig
>  create mode 100644 fs/events/Makefile
>  create mode 100644 fs/events/fs_event.c
>  create mode 100644 fs/events/fs_event.h
>  create mode 100644 fs/events/fs_event_netlink.c
>  create mode 100644 include/linux/fs_event.h
>  create mode 100644 include/uapi/linux/fs_event.h
>
> diff --git a/Documentation/filesystems/events.txt b/Documentation/filesystems/events.txt
> new file mode 100644
> index 0000000..c2e6227
> --- /dev/null
> +++ b/Documentation/filesystems/events.txt
> @@ -0,0 +1,232 @@
> +
> +	Generic file system event notification interface
> +
> +Document created 23 April 2015 by Beata Michalska <b.michalska@samsung.com>
> +
> +1. The reason behind:
> +=====================
> +
> +There are many corner cases when things might get messy with the filesystems.
> +And it is not always obvious what and when went wrong. Sometimes you might
> +get some subtle hints that there is something going on - but by the time
> +you realise it, it might be too late as you are already out-of-space
> +or the filesystem has been remounted as read-only (i.e.). The generic
> +interface for the filesystem events fills the gap by providing a rather
> +easy way of real-time notifications triggered whenever something interesting
> +happens, allowing filesystems to report events in a common way, as they occur.
> +
> +2. How does it work:
> +====================
> +
> +The interface itself has been exposed as fstrace-type Virtual File System,
> +primarily to ease the process of setting up the configuration for the
> +notifications. So for starters, it needs to get mounted (obviously):
> +
> +	mount -t fstrace none /sys/fs/events
> +
> +This will unveil the single fstrace filesystem entry - the 'config' file,
> +through which the notification are being set-up.
> +
> +Activating notifications for particular filesystem is as straightforward
> +as writing into the 'config' file. Note that by default all events, despite
> +the actual filesystem type, are being disregarded.
> +
> +Synopsis of config:
> +------------------
> +
> +	MOUNT EVENT_TYPE [L1] [L2]
> +
> + MOUNT      : the filesystem's mount point
> + EVENT_TYPE : event types - currently two of them are being supported:
> +
> +	      * generic events ("G") covering most common warnings
> +	      and errors that might be reported by any filesystem;
> +	      this option does not take any arguments;
> +
> +	      * threshold notifications ("T") - events sent whenever
> +	      the amount of available space drops below certain level;
> +	      it is possible to specify two threshold levels though
> +	      only one is required to properly setup the notifications;
> +	      as those refer to the number of available blocks, the lower
> +	      level [L1] needs to be higher than the upper one [L2]
> +
> +Sample request could look like the following:
> +
> + echo /sample/mount/point G T 710000 500000 > /sys/fs/events/config
> +
> +Multiple request might be specified provided they are separated with semicolon.
> +
> +The configuration itself might be modified at any time. One can add/remove
> +particular event types for given fielsystem, modify the threshold levels,
> +and remove single or all entries from the 'config' file.
> +
> + - Adding new event type:
> +
> + $ echo MOUNT EVENT_TYPE > /sys/fs/events/config
> +
> +(Note that is is enough to provide the event type to be enabled without
> +the already set ones.)
> +
> + - Removing event type:
> +
> + $ echo '!MOUNT EVENT_TYPE' > /sys/fs/events/config
> +
> + - Updating threshold limits:
> +
> + $ echo MOUNT T L1 L2 > /sys/fs/events/config
> +
> + - Removing single entry:
> +
> + $ echo '!MOUNT' > /sys/fs/events/config
> +
> + - Removing all entries:
> +
> + $ echo > /sys/fs/events/config
> +
> +Reading the file will list all registered entries with their current set-up
> +along with some additional info like the filesystem type and the backing device
> +name if available.
> +
> +Final, though a very important note on the configuration: when and if the
> +actual events are being triggered falls way beyond the scope of the generic
> +filesystem events interface. It is up to a particular filesystem
> +implementation which events are to be supported - if any at all. So if
> +given filesystem does not support the event notifications, an attempt to
> +enable those through 'config' file will fail.
> +
> +
> +3. The generic netlink interface support:
> +=========================================
> +
> +Whenever an event notification is triggered (by given filesystem) the current
> +configuration is being validated to decide whether a userpsace notification
> +should be launched. If there has been no request (in a mean of 'config' file
> +entry) for given event, one will be silently disregarded. If, on the other
> +hand, someone is 'watching' given filesystem for specific events, a generic
> +netlink message will be sent. A dedicated multicast group has been provided
> +solely for this purpose so in order to receive such notifications, one should
> +subscribe to this new multicast group. As for now only the init network
> +namespace is being supported.
> +
> +3.1 Message format
> +
> +The FS_NL_C_EVENT shall be stored within the generic netlink message header
> +as the command field. The message payload will provide more detailed info:
> +the backing device major and minor numbers, the event code and the id of
> +the process which action led to the event occurrence. In case of threshold
> +notifications, the current number of available blocks will be included
> +in the payload as well.
> +
> +
> +	 0                   1                   2                   3
> +	 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
> +	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> +	|	            NETLINK MESSAGE HEADER			|
> +	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> +	| 		GENERIC NETLINK MESSAGE HEADER   		|
> +	| 	   (with FS_NL_C_EVENT as genlmsghdr cdm field)		|
> +	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> +	| 	      Optional user specific message header		|
> +	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> +	|		   GENERIC MESSAGE PAYLOAD:			|
> +	+---------------------------------------------------------------+
> +	| 		  FS_NL_A_EVENT_ID  (NLA_U32)			|
> +	+---------------------------------------------------------------+
> +	|	  	  FS_NL_A_DEV_MAJOR (NLA_U32)			|
> +	+---------------------------------------------------------------+
> +	| 	  	  FS_NL_A_DEV_MINOR (NLA_U32) 			|

> +	+---------------------------------------------------------------+
> +	|  		  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/Kconfig b/fs/Kconfig
> index ec35851..a89e678 100644
> --- a/fs/Kconfig
> +++ b/fs/Kconfig
> @@ -69,6 +69,8 @@ config FILE_LOCKING
>            for filesystems like NFS and for the flock() system
>            call. Disabling this option saves about 11k.
>  
> +source "fs/events/Kconfig"
> +
>  source "fs/notify/Kconfig"
>  
>  source "fs/quota/Kconfig"
> diff --git a/fs/Makefile b/fs/Makefile
> index a88ac48..bcb3048 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-$(CONFIG_FS_EVENTS)		+= events/
> diff --git a/fs/events/Kconfig b/fs/events/Kconfig
> new file mode 100644
> index 0000000..1c60195
> --- /dev/null
> +++ b/fs/events/Kconfig
> @@ -0,0 +1,7 @@
> +# Generic Files System events interface
> +config FS_EVENTS
> +	bool "Generic filesystem events"
> +	select NET
> +	default y
> +	help
> +	  Enable generic filesystem events interface
> diff --git a/fs/events/Makefile b/fs/events/Makefile
> new file mode 100644
> index 0000000..9c98337
> --- /dev/null
> +++ b/fs/events/Makefile
> @@ -0,0 +1,5 @@
> +#
> +# Makefile for the Linux Generic File System Event Interface
> +#
> +
> +obj-y := fs_event.o fs_event_netlink.o
> diff --git a/fs/events/fs_event.c b/fs/events/fs_event.c
> new file mode 100644
> index 0000000..1037311
> --- /dev/null
> +++ b/fs/events/fs_event.c
> @@ -0,0 +1,809 @@
> +/*
> + * 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/module.h>
> +#include <linux/mount.h>
> +#include <linux/namei.h>
> +#include <linux/nsproxy.h>
> +#include <linux/parser.h>
> +#include <linux/seq_file.h>
> +#include <linux/slab.h>
> +#include <linux/rcupdate.h>
> +#include <net/genetlink.h>
> +#include "../pnode.h"
> +#include "fs_event.h"
> +
> +static LIST_HEAD(fs_trace_list);
> +static DEFINE_MUTEX(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 {
> +	struct kref	 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 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_free(struct fs_trace_entry *en)
> +{
> +	kmem_cache_free(fs_trace_cachep, en);
> +}
> +
> +static void fs_destroy_trace_entry(struct kref *en_ref)
> +{
> +	struct fs_trace_entry *en = container_of(en_ref,
> +					 struct fs_trace_entry, count);
> +
> +	/* Last reference has been dropped */
> +	fs_trace_entry_free(en);
> +	atomic_dec(&stray_traces);
> +}
> +
> +static void fs_trace_entry_put(struct fs_trace_entry *en)
> +{
> +	kref_put(&en->count, fs_destroy_trace_entry);
> +}
> +
> +static void fs_release_trace_entry(struct rcu_head *rcu_head)
> +{
> +	struct fs_trace_entry *en = container_of(rcu_head,
> +						 struct fs_trace_entry,
> +						 rcu_head);
> +	/*
> +	 * As opposed to typical reference drop, this one is being
> +	 * called from the rcu callback. This is to make sure all
> +	 * readers have managed to safely grab the reference before
> +	 * the change to rcu pointer is visible to all and before
> +	 * the reference is dropped here.
> +	 */
> +	fs_trace_entry_put(en);
> +}
> +
> +static void fs_drop_trace_entry(struct fs_trace_entry *en)
> +{
> +	struct super_block *sb;
> +
> +	lockdep_assert_held(&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.
> +	 * So leave...
> +	 */
> +
> +	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.
> +	 * Still it might be floating around somewhere
> +	 * so drop the reference when the rcu readers are done.
> +	 */
> +	spin_lock(&en->lock);
> +	list_del(&en->node);
> +	sb = en->sb;
> +	en->sb = NULL;
> +	spin_unlock(&en->lock);
> +
> +	rcu_assign_pointer(sb->s_etrace.e_priv, NULL);
> +	call_rcu(&en->rcu_head, fs_release_trace_entry);
> +	/* It's safe now to drop the reference to the super */
> +	deactivate_super(sb);
> +	atomic_inc(&stray_traces);
> +}
> +
> +static inline
> +struct fs_trace_entry *fs_trace_entry_get(struct fs_trace_entry *en)
> +{
> +	if (en) {
> +		if (!kref_get_unless_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 *fs_trace_entry_get_rcu(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 = fs_trace_entry_get_rcu(sb);
> +	if (!en)
> +		return -EINVAL;
> +
> +	mutex_lock(&fs_trace_lock);
> +	fs_drop_trace_entry(en);
> +	mutex_unlock(&fs_trace_lock);
> +	fs_trace_entry_put(en);
> +	return 0;
> +}
> +
> +static void fs_remove_all_traces(void)
> +{
> +	struct fs_trace_entry *en, *guard;
> +
> +	mutex_lock(&fs_trace_lock);
> +	list_for_each_entry_safe(en, guard, &fs_trace_list, node)
> +		fs_drop_trace_entry(en);
> +	mutex_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;
What about diskless(nfs,cifs,etc) filesystem? btrfs also has no
valid sb->s_dev  
> +
> +	if (nla_put_u64(skb, FS_NL_A_CAUSED_ID, pid_vnr(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 = fs_trace_entry_get_rcu(sb);
> +	if (!en)
> +		return;
> +
> +	spin_lock(&en->lock);
> +	if (atomic_read(&en->active) && (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 = fs_trace_entry_get_rcu(sb);
> +	if (!en)
> +		return;
> +
> +	spin_lock(&en->lock);
> +
> +	if (!atomic_read(&en->active) || !(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 = fs_trace_entry_get_rcu(sb);
> +	if (!en)
> +		return;
> +
> +	spin_lock(&en->lock);
> +
> +	if (!atomic_read(&en->active) || !(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|THRESH_UR_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)
> +{
> +	/*
> +	 * The mount is dropped but the super might not get released
> +	 * at once so there is very small chance some notifications
> +	 * will come through.
> +	 * Note that the mount being dropped here might belong to a different
> +	 * namespace - if this is the case, just ignore it.
> +	 */
> +	struct fs_trace_entry  *en = fs_trace_entry_get_rcu(mnt->mnt_sb);
> +	struct vfsmount *en_mnt;
> +
> +	if (!en || !atomic_read(&en->active))
> +		return;
> +	/*
> +	 * The entry once set, does not change the mountpoint it's being
> +	 * pinned to, so no need to take the lock here.
> +	 */
> +	en_mnt = en->mnt_path.mnt;
> +	if (!(real_mount(mnt)->mnt_ns != (real_mount(en_mnt))->mnt_ns))
> +		fs_remove_trace_entry(mnt->mnt_sb);
> +	fs_trace_entry_put(en);
> +}
> +
> +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 unmount 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;
> +	/*
> +	 * Increase the refcount for sb to mark it's being relied on.
> +	 * Note that the reference to path is taken by the caller, so it
> +	 * is safe to assume there is at least single active reference
> +	 * to super as well.
> +	 */
> +	atomic_inc(&sb->s_active);
> +
> +	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);
> +
> +	kref_init(&en->count);
> +
> +	if (rcu_access_pointer(sb->s_etrace.e_priv) != NULL) {
> +		struct fs_trace_entry *prev_en;
> +
> +		prev_en = fs_trace_entry_get_rcu(sb);
> +		if (prev_en) {
> +			WARN_ON(prev_en);
> +			fs_trace_entry_put(prev_en);
> +			goto leave;
> +		}
> +	}
> +	atomic_set(&en->active, 1);
> +
> +	mutex_lock(&fs_trace_lock);
> +	list_add(&en->node, &fs_trace_list);
> +	mutex_unlock(&fs_trace_lock);
> +
> +	rcu_assign_pointer(sb->s_etrace.e_priv, en);
> +	synchronize_rcu();
> +
> +	return 0;
> +leave:
> +	deactivate_super(sb);
> +	kmem_cache_free(fs_trace_cachep, en);
> +	return -EINVAL;
> +}
> +
> +static int fs_update_trace_entry(struct path *path,
> +				  struct fs_event_thresh *thresh,
> +				  unsigned int nmask)
> +{
> +	struct fs_trace_entry *en;
> +	struct super_block *sb;
> +	int extend = nmask & FS_TRACE_ADD;
> +	int ret = -EINVAL;
> +
> +	en = fs_trace_entry_get_rcu(path->mnt->mnt_sb);
> +	if (!en)
> +		return (extend) ? fs_new_trace_entry(path, thresh, nmask)
> +				: -EINVAL;
> +
> +	if (!atomic_read(&en->active))
> +		return -EINVAL;
> +
> +	nmask &= ~FS_TRACE_ADD;
> +
> +	spin_lock(&en->lock);
> +	sb  = en->sb;
> +	if (!sb || !(nmask & sb->s_etrace.events_cap_mask))
> +		goto leave;
> +
> +	if (nmask & FS_EVENT_THRESH) {
> +		if (extend) {
> +			/* Get the current state */
> +			if (!(en->notify & FS_EVENT_THRESH))
> +				if (fs_trace_query_data(sb, en))
> +					goto leave;
> +
> +			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;
> +	ret = 0;
> +leave:
> +	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)
> +{
> +	mutex_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)
> +{
> +	mutex_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);
> +	/* Do not show the entries outside current mount namespace */
> +	r_mnt = real_mount(en->mnt_path.mnt);
> +	if (r_mnt->mnt_ns != current->nsproxy->mnt_ns) {
> +		if (!__is_local_mountpoint(r_mnt->mnt_mountpoint))
> +			return 0;
> +	}
> +
> +	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 {
> +		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 which can make 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..23f24c8
> --- /dev/null
> +++ b/fs/events/fs_event.h
> @@ -0,0 +1,22 @@
> +/*
> + * 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
> +
> +int  fs_event_netlink_register(void);
> +void fs_event_netlink_unregister(void);
> +
> +#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..0c97eb7
> --- /dev/null
> +++ b/fs/events/fs_event_netlink.c
> @@ -0,0 +1,104 @@
> +/*
> + * 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 = FS_EVENTS_MCAST_GRP_NAME, },
> +};
> +
> +static struct genl_family fs_event_family = {
> +	.id		= GENL_ID_GENERATE,
> +	.name		= FS_EVENTS_FAMILY_NAME,
> +	.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;
> +
> +	/* Skip if there are no listeners */
> +	if (!genl_has_listeners(&fs_event_family, &init_net, 0))
> +		return 0;
> +
> +	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_debug("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..83e22dd
> --- /dev/null
> +++ b/include/linux/fs_event.h
> @@ -0,0 +1,72 @@
> +/*
> + * 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;
> +};
> +
> +#ifdef CONFIG_FS_EVENTS
> +
> +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);
> +
> +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_FS_EVENTS */
> +
> +static inline
> +void fs_event_notify(struct super_block *sb, unsigned int event_id) {};
> +static inline
> +void fs_event_alloc_space(struct super_block *sb, u64 ncount) {};
> +static inline
> +void fs_event_free_space(struct super_block *sb, u64 ncount) {};
> +static inline
> +void fs_event_mount_dropped(struct vfsmount *mnt) {};
> +
> +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_FS_EVENTS */
> +
> +#endif /* _LINUX_GENERIC_FS_EVENTS_ */
> +
> diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
> index 68ceb97..dae0fab 100644
> --- a/include/uapi/linux/Kbuild
> +++ b/include/uapi/linux/Kbuild
> @@ -129,6 +129,7 @@ header-y += firewire-constants.h
>  header-y += flat.h
>  header-y += fou.h
>  header-y += fs.h
> +header-y += fs_event.h
>  header-y += fsl_hypervisor.h
>  header-y += fuse.h
>  header-y += futex.h
> diff --git a/include/uapi/linux/fs_event.h b/include/uapi/linux/fs_event.h
> new file mode 100644
> index 0000000..d8b07da
> --- /dev/null
> +++ b/include/uapi/linux/fs_event.h
> @@ -0,0 +1,58 @@
> +/*
> + * 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_
> +
> +#define FS_EVENTS_FAMILY_NAME	 "fs_event"
> +#define FS_EVENTS_MCAST_GRP_NAME "fs_event_mc_grp"
> +
> +/*
> + * 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_ */
> +
> -- 
> 1.7.9.5
>
> --
> To unsubscribe, send a message with 'unsubscribe linux-mm' in
> the body to majordomo-Bw31MaZKKs0EbZ0PF+XxCw@public.gmane.org  For more info on Linux MM,
> see: http://www.linux-mm.org/ .
> Don't email: <a href=mailto:"dont-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org"> email-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org </a>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 472 bytes --]

^ permalink raw reply

* Re: [PATCH v2] st: convert DRIVER_ATTR macros to DRIVER_ATTR_RO
From: Hannes Reinecke @ 2015-06-24  7:02 UTC (permalink / raw)
  To: Seymour, Shane M,
	linux-scsi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Greg KH <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org> (gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org)
  Cc: linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Kai.Makisara-9Aww8k/80nUxHbG02/KK1g@public.gmane.org
In-Reply-To: <DDB9C85B850785449757F9914A034FCB3F8E9E02-MCKW7lC+H9ISZAcGdq5asR6epYMZPwEe5NbjCUgZEJk@public.gmane.org>

On 06/24/2015 08:54 AM, Seymour, Shane M wrote:
> 
> Convert DRIVER_ATTR macros to DRIVER_ATTR_RO requested by
> Greg KH. Also switched to using scnprintf instead of snprintf
> per Documentation/filesystems/sysfs.txt.
> 
> Suggested-by: Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>
> Signed-off-by: Shane Seymour <shane.seymour-VXdhtT5mjnY@public.gmane.org>
> ---
> This patch was implemented on top of the previous patch to
> convert to using driver attr groups.
> 
> Changes from v1:
> - switched to scnprintf from sprintf after feedback from Sergey
> Senozhatsky.

Reviewed-by: Hannes Reinecke <hare-l3A5Bk7waGM@public.gmane.org>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		               zSeries & Storage
hare-l3A5Bk7waGM@public.gmane.org			               +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)

^ permalink raw reply

* [PATCH v2] st: convert DRIVER_ATTR macros to DRIVER_ATTR_RO
From: Seymour, Shane M @ 2015-06-24  6:54 UTC (permalink / raw)
  To: linux-scsi@vger.kernel.org,
	Greg KH <gregkh@linuxfoundation.org> (gregkh@linuxfoundation.org)
  Cc: linux-api@vger.kernel.org, Kai.Makisara@kolumbus.fi


Convert DRIVER_ATTR macros to DRIVER_ATTR_RO requested by
Greg KH. Also switched to using scnprintf instead of snprintf
per Documentation/filesystems/sysfs.txt.

Suggested-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Shane Seymour <shane.seymour@hp.com>
---
This patch was implemented on top of the previous patch to
convert to using driver attr groups.

Changes from v1:
- switched to scnprintf from sprintf after feedback from Sergey
Senozhatsky.
--- a/drivers/scsi/st.c	2015-06-22 20:38:16.061386739 -0500
+++ b/drivers/scsi/st.c	2015-06-23 19:59:21.302775649 -0500
@@ -4427,29 +4427,29 @@ module_exit(exit_st);
 
 
 /* The sysfs driver interface. Read-only at the moment */
-static ssize_t st_try_direct_io_show(struct device_driver *ddp, char *buf)
+static ssize_t try_direct_io_show(struct device_driver *ddp, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%d\n", try_direct_io);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", try_direct_io);
 }
-static DRIVER_ATTR(try_direct_io, S_IRUGO, st_try_direct_io_show, NULL);
+static DRIVER_ATTR_RO(try_direct_io);
 
-static ssize_t st_fixed_buffer_size_show(struct device_driver *ddp, char *buf)
+static ssize_t fixed_buffer_size_show(struct device_driver *ddp, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%d\n", st_fixed_buffer_size);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", st_fixed_buffer_size);
 }
-static DRIVER_ATTR(fixed_buffer_size, S_IRUGO, st_fixed_buffer_size_show, NULL);
+static DRIVER_ATTR_RO(fixed_buffer_size);
 
-static ssize_t st_max_sg_segs_show(struct device_driver *ddp, char *buf)
+static ssize_t max_sg_segs_show(struct device_driver *ddp, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%d\n", st_max_sg_segs);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", st_max_sg_segs);
 }
-static DRIVER_ATTR(max_sg_segs, S_IRUGO, st_max_sg_segs_show, NULL);
+static DRIVER_ATTR_RO(max_sg_segs);
 
-static ssize_t st_version_show(struct device_driver *ddd, char *buf)
+static ssize_t version_show(struct device_driver *ddd, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "[%s]\n", verstr);
+	return scnprintf(buf, PAGE_SIZE, "[%s]\n", verstr);
 }
-static DRIVER_ATTR(version, S_IRUGO, st_version_show, NULL);
+static DRIVER_ATTR_RO(version);
 
 static struct attribute *st_drv_attrs[] = {
 	&driver_attr_try_direct_io.attr,

^ permalink raw reply

* Re: [PATCH] st: convert DRIVER_ATTR macros to DRIVER_ATTR_RO
From: Sergey Senozhatsky @ 2015-06-24  6:25 UTC (permalink / raw)
  To: Seymour, Shane M
  Cc: linux-scsi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Greg KH <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org> (gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org),
	linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Kai.Makisara-9Aww8k/80nUxHbG02/KK1g@public.gmane.org
In-Reply-To: <DDB9C85B850785449757F9914A034FCB3F8E9DA4-MCKW7lC+H9ISZAcGdq5asR6epYMZPwEe5NbjCUgZEJk@public.gmane.org>

On (06/24/15 06:10), Seymour, Shane M wrote:
[..]
>  
>  /* The sysfs driver interface. Read-only at the moment */
> -static ssize_t st_try_direct_io_show(struct device_driver *ddp, char *buf)
> +static ssize_t try_direct_io_show(struct device_driver *ddp, char *buf)
>  {
> -	return snprintf(buf, PAGE_SIZE, "%d\n", try_direct_io);
> +	return sprintf(buf, "%d\n", try_direct_io);
>  }

a nitpick,

per Documentation/filesystems/sysfs.txt

:
: - show() should always use scnprintf().
:

  -ss

> -static DRIVER_ATTR(try_direct_io, S_IRUGO, st_try_direct_io_show, NULL);
> +static DRIVER_ATTR_RO(try_direct_io);
>  
> -static ssize_t st_fixed_buffer_size_show(struct device_driver *ddp, char *buf)
> +static ssize_t fixed_buffer_size_show(struct device_driver *ddp, char *buf)
>  {
> -	return snprintf(buf, PAGE_SIZE, "%d\n", st_fixed_buffer_size);
> +	return sprintf(buf, "%d\n", st_fixed_buffer_size);
>  }
> -static DRIVER_ATTR(fixed_buffer_size, S_IRUGO, st_fixed_buffer_size_show, NULL);
> +static DRIVER_ATTR_RO(fixed_buffer_size);
>  
> -static ssize_t st_max_sg_segs_show(struct device_driver *ddp, char *buf)
> +static ssize_t max_sg_segs_show(struct device_driver *ddp, char *buf)
>  {
> -	return snprintf(buf, PAGE_SIZE, "%d\n", st_max_sg_segs);
> +	return sprintf(buf, "%d\n", st_max_sg_segs);
>  }
> -static DRIVER_ATTR(max_sg_segs, S_IRUGO, st_max_sg_segs_show, NULL);
> +static DRIVER_ATTR_RO(max_sg_segs);
>  
> -static ssize_t st_version_show(struct device_driver *ddd, char *buf)
> +static ssize_t version_show(struct device_driver *ddd, char *buf)
>  {
> -	return snprintf(buf, PAGE_SIZE, "[%s]\n", verstr);
> +	return sprintf(buf, "[%s]\n", verstr);
>  }
> -static DRIVER_ATTR(version, S_IRUGO, st_version_show, NULL);
> +static DRIVER_ATTR_RO(version);
>  
>  static struct attribute *st_drv_attrs[] = {
>  	&driver_attr_try_direct_io.attr,
> --

^ permalink raw reply

* [PATCH] st: convert DRIVER_ATTR macros to DRIVER_ATTR_RO
From: Seymour, Shane M @ 2015-06-24  6:10 UTC (permalink / raw)
  To: linux-scsi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Greg KH <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org> (gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org)
  Cc: linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Kai.Makisara-9Aww8k/80nUxHbG02/KK1g@public.gmane.org


Convert DRIVER_ATTR macros to DRIVER_ATTR_RO as requested by
Greg KH. Also switched to using sprintf as nothing printed should
exceed PAGE_SIZE - based on feedback from Greg when implementing
show functions for tape stats.

Suggested-by: Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>
Signed-off-by: Shane Seymour <shane.seymour-VXdhtT5mjnY@public.gmane.org>
---
This patch was implemented on top of the previous patch to
convert to using driver attr groups.

Resending with [PATCH] at the front since I forgot to add it.
--- a/drivers/scsi/st.c	2015-06-22 20:38:16.061386739 -0500
+++ b/drivers/scsi/st.c	2015-06-23 17:29:03.547867682 -0500
@@ -4427,29 +4427,29 @@ module_exit(exit_st);
 
 
 /* The sysfs driver interface. Read-only at the moment */
-static ssize_t st_try_direct_io_show(struct device_driver *ddp, char *buf)
+static ssize_t try_direct_io_show(struct device_driver *ddp, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%d\n", try_direct_io);
+	return sprintf(buf, "%d\n", try_direct_io);
 }
-static DRIVER_ATTR(try_direct_io, S_IRUGO, st_try_direct_io_show, NULL);
+static DRIVER_ATTR_RO(try_direct_io);
 
-static ssize_t st_fixed_buffer_size_show(struct device_driver *ddp, char *buf)
+static ssize_t fixed_buffer_size_show(struct device_driver *ddp, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%d\n", st_fixed_buffer_size);
+	return sprintf(buf, "%d\n", st_fixed_buffer_size);
 }
-static DRIVER_ATTR(fixed_buffer_size, S_IRUGO, st_fixed_buffer_size_show, NULL);
+static DRIVER_ATTR_RO(fixed_buffer_size);
 
-static ssize_t st_max_sg_segs_show(struct device_driver *ddp, char *buf)
+static ssize_t max_sg_segs_show(struct device_driver *ddp, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%d\n", st_max_sg_segs);
+	return sprintf(buf, "%d\n", st_max_sg_segs);
 }
-static DRIVER_ATTR(max_sg_segs, S_IRUGO, st_max_sg_segs_show, NULL);
+static DRIVER_ATTR_RO(max_sg_segs);
 
-static ssize_t st_version_show(struct device_driver *ddd, char *buf)
+static ssize_t version_show(struct device_driver *ddd, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "[%s]\n", verstr);
+	return sprintf(buf, "[%s]\n", verstr);
 }
-static DRIVER_ATTR(version, S_IRUGO, st_version_show, NULL);
+static DRIVER_ATTR_RO(version);
 
 static struct attribute *st_drv_attrs[] = {
 	&driver_attr_try_direct_io.attr,
--
To unsubscribe from this list: send the line "unsubscribe linux-api" 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

* st: convert DRIVER_ATTR macros to DRIVER_ATTR_RO
From: Seymour, Shane M @ 2015-06-24  6:02 UTC (permalink / raw)
  To: linux-scsi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Greg KH <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org> (gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org)
  Cc: Kai.Makisara-9Aww8k/80nUxHbG02/KK1g@public.gmane.org,
	linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org


Convert DRIVER_ATTR macros to DRIVER_ATTR_RO as requested by
Greg KH. Also switched to using sprintf as nothing printed should
exceed PAGE_SIZE - based on feedback from Greg when implementing
show functions for tape stats.

Suggested-by: Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>
Signed-off-by: Shane Seymour <shane.seymour-VXdhtT5mjnY@public.gmane.org>
---
This patch was implemented on top of the previous patch to
convert to using driver attr groups.
--- a/drivers/scsi/st.c	2015-06-22 20:38:16.061386739 -0500
+++ b/drivers/scsi/st.c	2015-06-23 17:29:03.547867682 -0500
@@ -4427,29 +4427,29 @@ module_exit(exit_st);
 
 
 /* The sysfs driver interface. Read-only at the moment */
-static ssize_t st_try_direct_io_show(struct device_driver *ddp, char *buf)
+static ssize_t try_direct_io_show(struct device_driver *ddp, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%d\n", try_direct_io);
+	return sprintf(buf, "%d\n", try_direct_io);
 }
-static DRIVER_ATTR(try_direct_io, S_IRUGO, st_try_direct_io_show, NULL);
+static DRIVER_ATTR_RO(try_direct_io);
 
-static ssize_t st_fixed_buffer_size_show(struct device_driver *ddp, char *buf)
+static ssize_t fixed_buffer_size_show(struct device_driver *ddp, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%d\n", st_fixed_buffer_size);
+	return sprintf(buf, "%d\n", st_fixed_buffer_size);
 }
-static DRIVER_ATTR(fixed_buffer_size, S_IRUGO, st_fixed_buffer_size_show, NULL);
+static DRIVER_ATTR_RO(fixed_buffer_size);
 
-static ssize_t st_max_sg_segs_show(struct device_driver *ddp, char *buf)
+static ssize_t max_sg_segs_show(struct device_driver *ddp, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%d\n", st_max_sg_segs);
+	return sprintf(buf, "%d\n", st_max_sg_segs);
 }
-static DRIVER_ATTR(max_sg_segs, S_IRUGO, st_max_sg_segs_show, NULL);
+static DRIVER_ATTR_RO(max_sg_segs);
 
-static ssize_t st_version_show(struct device_driver *ddd, char *buf)
+static ssize_t version_show(struct device_driver *ddd, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "[%s]\n", verstr);
+	return sprintf(buf, "[%s]\n", verstr);
 }
-static DRIVER_ATTR(version, S_IRUGO, st_version_show, NULL);
+static DRIVER_ATTR_RO(version);
 
 static struct attribute *st_drv_attrs[] = {
 	&driver_attr_try_direct_io.attr,

^ permalink raw reply

* Re: [PATCH v6 0/9] Add simple NVMEM Framework via regmap.
From: Sanchayan Maity @ 2015-06-24  5:54 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: Stefan Wahren, Greg Kroah-Hartman, linux-arm-kernel, devicetree,
	arnd, linux-api, s.hauer, sboyd, linux-kernel, pantelis.antoniou,
	Rob Herring, Mark Brown, Kumar Gala, mporter, Maxime Ripard,
	linux-arm-msm, wxt
In-Reply-To: <235181230.251177.1435088854197.JavaMail.open-xchange@oxbsltgw00.schlund.de>

Hello,

On 15-06-23 21:47:34, Stefan Wahren wrote:
> Hi Srinivas,
> 
> > Srinivas Kandagatla <srinivas.kandagatla@linaro.org> hat am 23. Juni 2015 um
> > 01:07 geschrieben:
> >
> >
> > [...]
> >
> > Device Tree:
> >
> > /* Provider */
> > qfprom: qfprom@00700000 {
> > ...
> >
> > /* Data cells */
> > tsens_calibration: calib@404 {
> > reg = <0x404 0x10>;
> > };
> >
> > tsens_calibration_bckp: calib_bckp@504 {
> > reg = <0x504 0x11>;
> > bit-offset = 6;
> > nbits = 128;
> > };
> >
> > pvs_version: pvs-version@6 {
> > reg = <0x6 0x2>
> > bit-offset = 7;
> > nbits = 2;
> > };
> >
> > speed_bin: speed-bin@c{
> > reg = <0xc 0x1>;
> > bit-offset = 2;
> > nbits = 3;
> >
> > };
> > ...
> > };
> >
> > userspace interface: binary file in /sys/class/nvmem/*/nvmem
> >
> > ex:
> > hexdump /sys/class/nvmem/qfprom0/nvmem
> >
> > 0000000 0000 0000 0000 0000 0000 0000 0000 0000
> > *
> > 00000a0 db10 2240 0000 e000 0c00 0c00 0000 0c00
> > 0000000 0000 0000 0000 0000 0000 0000 0000 0000
> > ...
> > *
> > 0001000
> >
> 
> i want to port OCOTP driver for MXS, which hasn't MMIO. From my understanding
> hexdump would readout the complete register range defined in provider DT node.
> 
> How can i achieve that hexdump only reads the data area within the register
> range?

I also had a similar question in my mind.

- Sanchayan.

^ permalink raw reply

* Re: [PATCH] st: convert to using driver attr groups for sysfs
From: Greg KH @ 2015-06-24  2:37 UTC (permalink / raw)
  To: Seymour, Shane M
  Cc: linux-scsi@vger.kernel.org, Kai.Makisara@kolumbus.fi,
	linux-api@vger.kernel.org
In-Reply-To: <DDB9C85B850785449757F9914A034FCB3BFF68D9@G9W0766.americas.hpqcorp.net>

On Tue, Jun 23, 2015 at 08:11:00AM +0000, Seymour, Shane M wrote:
> This patch changes the st driver to use attribute groups so
> driver sysfs files are created automatically. See the
> following for reference:
> 
> http://kroah.com/log/blog/2013/06/26/how-to-create-a-sysfs-file-correctly/
> 
> Signed-off-by: Shane Seymour <shane.seymour@hp.com>

Very nice, thanks for doing this.

Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

> ---
> --- a/drivers/scsi/st.c	2015-06-22 14:20:40.829612661 -0500
> +++ b/drivers/scsi/st.c	2015-06-22 15:49:49.357248393 -0500
> @@ -85,6 +85,7 @@ static int debug_flag;
>  
>  static struct class st_sysfs_class;
>  static const struct attribute_group *st_dev_groups[];
> +static const struct attribute_group *st_drv_groups[];
>  
>  MODULE_AUTHOR("Kai Makisara");
>  MODULE_DESCRIPTION("SCSI tape (st) driver");
> @@ -198,15 +199,13 @@ static int sgl_unmap_user_pages(struct s
>  static int st_probe(struct device *);
>  static int st_remove(struct device *);
>  
> -static int do_create_sysfs_files(void);
> -static void do_remove_sysfs_files(void);
> -
>  static struct scsi_driver st_template = {
>  	.gendrv = {
>  		.name		= "st",
>  		.owner		= THIS_MODULE,
>  		.probe		= st_probe,
>  		.remove		= st_remove,
> +		.groups		= st_drv_groups,
>  	},
>  };
>  
> @@ -4404,14 +4403,8 @@ static int __init init_st(void)
>  	if (err)
>  		goto err_chrdev;
>  
> -	err = do_create_sysfs_files();
> -	if (err)
> -		goto err_scsidrv;
> -
>  	return 0;
>  
> -err_scsidrv:
> -	scsi_unregister_driver(&st_template.gendrv);
>  err_chrdev:
>  	unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
>  				 ST_MAX_TAPE_ENTRIES);
> @@ -4422,7 +4415,6 @@ err_class:
>  
>  static void __exit exit_st(void)
>  {
> -	do_remove_sysfs_files();
>  	scsi_unregister_driver(&st_template.gendrv);
>  	unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
>  				 ST_MAX_TAPE_ENTRIES);
> @@ -4459,44 +4451,14 @@ static ssize_t st_version_show(struct de
>  }
>  static DRIVER_ATTR(version, S_IRUGO, st_version_show, NULL);

For a future patch, you might want to convert these type of declarations
to use DRIVER_ATTR_RO() and friends.

thanks,

greg k-h

^ permalink raw reply

* Re: [PATCH v5 03/11] nvmem: Add a simple NVMEM framework for nvmem providers
From: Stephen Boyd @ 2015-06-24  0:24 UTC (permalink / raw)
  To: Srinivas Kandagatla,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Maxime Ripard, Rob Herring, Kumar Gala, Mark Brown,
	s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ, Greg Kroah-Hartman,
	linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, arnd-r2nGTMty4D4,
	pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w,
	mporter-OWPKS81ov/FWk0Htik3J/w
In-Reply-To: <5582BDAE.5040008-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

On 06/18/2015 05:46 AM, Srinivas Kandagatla wrote:
> Many thanks for review.
>
> On 16/06/15 23:43, Stephen Boyd wrote:
>> On 05/21/2015 09:43 AM, Srinivas Kandagatla wrote:
>>>
>>>> +
>>>> +static int nvmem_add_cells(struct nvmem_device *nvmem,
>>>> +               struct nvmem_config *cfg)
>>>> +{
>>>> +    struct nvmem_cell **cells;
>>>> +    struct nvmem_cell_info *info = cfg->cells;
>>>> +    int i, rval;
>>>> +
>>>> +    cells = kzalloc(sizeof(*cells) * cfg->ncells, GFP_KERNEL);
>>>
>>> kcalloc
> This is temporary array, I did this on intention, to make it easy to
> kfree cells which are found invalid at runtime.

Ok, but how does that change using kcalloc over kzalloc? I must have
missed something.

>
>
>>> + *
>>> + * The return value will be an ERR_PTR() on error or a valid pointer
>>> +    nvmem->dev.of_node = config->dev->of_node;
>>> +    dev_set_name(&nvmem->dev, "%s%d",
>>> +             config->name ? : "nvmem", config->id);
>>
>> It may be better to always name it nvmem%d so that we don't allow the
>> possibility of conflicts.
> We can do that, but I wanted to make the sysfs and dev entries more
> readable than just nvmem0, nvmem1...

Well sysfs is not really for humans. It's for machines. The nvmem
devices could have a name property so that a more human readable string
is present.

>
>>> +
>>> +    device_initialize(&nvmem->dev);
>>> +
>>> +    dev_dbg(&nvmem->dev, "Registering nvmem device %s\n",
>>> +        dev_name(&nvmem->dev));
>>> +
>>> +    rval = device_add(&nvmem->dev);
>>> +    if (rval) {
>>> +        ida_simple_remove(&nvmem_ida, nvmem->id);
>>> +        kfree(nvmem);
>>> +        return ERR_PTR(rval);
>>> +    }
>>> +
>>> +    /* update sysfs attributes */
>>> +    if (nvmem->read_only)
>>> +        sysfs_update_group(&nvmem->dev.kobj, &nvmem_bin_ro_group);
>>
>> It would be nice if this could be done before the device was registered.
>> Perhaps have two device_types, one for read-only and one for read/write?
>
> The attributes are actually coming from the class object, so we have
> no choice to update the attributes before the device is registered.
>
> May it would be more safe to have default as read-only and modify it
> to read/write based on read-only flag?
>
>

Can you assign the attributes to the device_type in the nvmem::struct
device? I don't see why these attributes need to be part of the class.

>>
>>> +{
>>> +    return class_register(&nvmem_class);
>>
>> I thought class was on the way out? Aren't we supposed to use bus types
>> for new stuff?
> Do you remember any conversation on the list about this? I could not
> find it on web.
>
> on the other hand, nvmem is not really a bus, making it a bus type
> sounds incorrect to me.
>

I found this post on the cpu class that Sudeep tried to introduce[1].
And there's this post from Kay that alludes to a unification of busses
and classes[2]. And some other post where Kay says class is dead [3].

[1] https://lkml.org/lkml/2014/8/21/191
[2] https://lwn.net/Articles/471821/
[3] https://lkml.org/lkml/2010/11/11/17

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* Re: [PATCH 10/23] userfaultfd: add new syscall to provide memory externalization
From: Andrea Arcangeli @ 2015-06-23 21:41 UTC (permalink / raw)
  To: Dave Hansen
  Cc: Andrew Morton, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	qemu-devel-qX2TKyscuCcdnm+yROfE0A, kvm-u79uwXL29TY76Z2rM5mHXA,
	linux-api-u79uwXL29TY76Z2rM5mHXA, Pavel Emelyanov,
	Sanidhya Kashyap, zhang.zhanghailiang-hv44wF8Li93QT0dZR+AlfA,
	Linus Torvalds, Kirill A. Shutemov, Andres Lagar-Cavilla,
	Paolo Bonzini, Rik van Riel, Mel Gorman, Andy Lutomirski,
	Hugh Dickins, Peter Feiner, Dr. David Alan Gilbert,
	Johannes Weiner, Huangpeng (Peter)
In-Reply-To: <5589ACC3.3060401-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

Hi Dave,

On Tue, Jun 23, 2015 at 12:00:19PM -0700, Dave Hansen wrote:
> Down in userfaultfd_wake_function(), it looks like you intended for a
> len=0 to mean "wake all".  But the validate_range() that we do from
> userspace has a !len check in it, which keeps us from passing a len=0 in
> from userspace.
> Was that "wake all" for some internal use, or is the check too strict?

It's for internal use or userfaultfd_release that has to wake them all
(after setting ctx->released) if the uffd is closed. It avoids to
enlarge the structure by depending on the invariant that userland
cannot pass len=0.

If we'd accept len=0 from userland as valid, I'd be safer if it does
nothing like in madvise, I doubt we want to expose this non standard
kernel internal behavior to userland.

> I was trying to use the wake ioctl after an madvise() (as opposed to
> filling things in using a userfd copy).

madvise will return 0 if len=0, mremap would return -EINVAL if new_len
is zero, mmap also returns -EINVAL if len is 0, not all MM syscalls
are as permissive as madvise. Can't you pass the same len you pass to
madvise to UFFDIO_WAKE (or just skip the call if the madvise len is
zero)?

Thanks,
Andrea

^ 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