public inbox for linux-xfs@vger.kernel.org
 help / color / mirror / Atom feed
* generating uevents by xfs
@ 2009-04-28 16:18 Krzysztof Błaszkowski
  2009-04-29 12:50 ` Andi Kleen
  0 siblings, 1 reply; 3+ messages in thread
From: Krzysztof Błaszkowski @ 2009-04-28 16:18 UTC (permalink / raw)
  To: xfs

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

Hello,

once upon i was asked to think about such facility for notifying userspace 
when some mount point is nearly full at some level let's say e.g. 90% 
(threshold should be configurable).

here is a solution designed by me and i would like to see comments on this 
idea and solution.

i verified these patches with 2.6.27.19 (SuSE) but there are also patches for 
2.6.28.4 and 2.6.29.2 but i haven't given a try to latest two kernels.

to use it one may need to pick right *-1- patch and the *-2 patch.


Krzysztof Blaszkowski

[-- Attachment #2: xfs-sysfs-1-26292.diff --]
[-- Type: text/x-diff, Size: 2825 bytes --]

diff --git a/xfs/Makefile b/xfs/Makefile
index c3dc491..b0a1330 100644
--- a/xfs/Makefile
+++ b/xfs/Makefile
@@ -88,7 +88,8 @@ xfs-y				+= xfs_alloc.o \
 				   xfs_vnodeops.o \
 				   xfs_rw.o \
 				   xfs_dmops.o \
-				   xfs_qmops.o
+				   xfs_qmops.o \
+				   xfs_sysfs.o
 
 xfs-$(CONFIG_XFS_TRACE)		+= xfs_btree_trace.o \
 				   xfs_dir2_trace.o
diff --git a/xfs/linux-2.6/xfs_super.c b/xfs/linux-2.6/xfs_super.c
index 32ae502..99ac6ed 100644
--- a/xfs/linux-2.6/xfs_super.c
+++ b/xfs/linux-2.6/xfs_super.c
@@ -1082,6 +1082,9 @@ xfs_fs_put_super(
 	xfs_close_devices(mp);
 	xfs_qmops_put(mp);
 	xfs_dmops_put(mp);
+#ifdef CONFIG_SYSFS
+	xfs_event_release(mp);
+#endif
 	xfs_free_fsname(mp);
 	kfree(mp);
 }
@@ -1509,6 +1512,9 @@ xfs_fs_fill_super(
 
 	kfree(mtpt);
 
+#ifdef CONFIG_SYSFS
+	xfs_event_alloc(mp);
+#endif
 	xfs_itrace_exit(XFS_I(sb->s_root->d_inode));
 	return 0;
 
@@ -1873,6 +1879,10 @@ init_xfs_fs(void)
 	error = register_filesystem(&xfs_fs_type);
 	if (error)
 		goto out_sysctl_unregister;
+
+#ifdef CONFIG_SYSFS
+	xfs_sysfs_init();
+#endif	
 	return 0;
 
  out_sysctl_unregister:
@@ -1906,6 +1916,9 @@ exit_xfs_fs(void)
 	xfs_free_trace_bufs();
 	xfs_destroy_zones();
 	ktrace_uninit();
+#ifdef CONFIG_SYSFS
+	xfs_sysfs_done();
+#endif	
 }
 
 module_init(init_xfs_fs);
diff --git a/xfs/xfs_mount.c b/xfs/xfs_mount.c
index 3530025..c19fc17 100644
--- a/xfs/xfs_mount.c
+++ b/xfs/xfs_mount.c
@@ -2413,3 +2413,25 @@ balance_counter:
 }
 
 #endif
+
+
+__uint64_t xfs_icsb_get_fdblocks_lazy(xfs_mount_t *mp)
+{
+        __uint64_t fdblocks = 0;
+#ifdef HAVE_PERCPU_SB
+        xfs_icsb_cnts_t *cntp;
+        int i;
+
+        for_each_online_cpu(i) {
+                cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
+                fdblocks += cntp->icsb_fdblocks;
+        }
+
+        if (xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS))
+                fdblocks = mp->m_sb.sb_fdblocks;
+#else
+        fdblocks = mp->m_sb.sb_fdblocks;
+#endif
+        return fdblocks - XFS_ALLOC_SET_ASIDE(mp);
+}
+
diff --git a/xfs/xfs_mount.h b/xfs/xfs_mount.h
index f5e9937..45ef4cb 100644
--- a/xfs/xfs_mount.h
+++ b/xfs/xfs_mount.h
@@ -329,6 +329,9 @@ typedef struct xfs_mount {
 	wait_queue_head_t	m_wait_single_sync_task;
 	__int64_t		m_update_flags;	/* sb flags we need to update
 						   on the next remount,rw */
+#ifdef CONFIG_SYSFS
+	void *event_onlow;
+#endif
 } xfs_mount_t;
 
 /*
@@ -528,6 +531,13 @@ extern void	xfs_qmops_put(struct xfs_mount *);
 
 extern struct xfs_dmops xfs_dmcore_xfs;
 
+#ifdef CONFIG_SYSFS
+extern void xfs_sysfs_init(void);
+extern void xfs_sysfs_done(void);
+extern int xfs_event_alloc(struct xfs_mount *mnt);
+extern int xfs_event_release(struct xfs_mount *mnt);
+#endif
+
 #endif	/* __KERNEL__ */
 
 extern void	xfs_mod_sb(struct xfs_trans *, __int64_t);

[-- Attachment #3: xfs-sysfs-1-26284.diff --]
[-- Type: text/x-diff, Size: 2802 bytes --]

diff --git a/xfs/Makefile b/xfs/Makefile
index 737c9a4..1df5f4e 100644
--- a/xfs/Makefile
+++ b/xfs/Makefile
@@ -89,7 +89,8 @@ xfs-y				+= xfs_alloc.o \
 				   xfs_vnodeops.o \
 				   xfs_rw.o \
 				   xfs_dmops.o \
-				   xfs_qmops.o
+				   xfs_qmops.o \
+				   xfs_sysfs.o
 
 xfs-$(CONFIG_XFS_TRACE)		+= xfs_dir2_trace.o
 
diff --git a/xfs/linux-2.6/xfs_super.c b/xfs/linux-2.6/xfs_super.c
index 37ebe36..7cc0b6b 100644
--- a/xfs/linux-2.6/xfs_super.c
+++ b/xfs/linux-2.6/xfs_super.c
@@ -1152,6 +1152,9 @@ xfs_fs_put_super(
 	xfs_close_devices(mp);
 	xfs_qmops_put(mp);
 	xfs_dmops_put(mp);
+#ifdef CONFIG_SYSFS
+	xfs_event_release(mp);
+#endif
 	xfs_free_fsname(mp);
 	kfree(mp);
 }
@@ -1783,6 +1786,9 @@ xfs_fs_fill_super(
 	xfs_itrace_exit(XFS_I(sb->s_root->d_inode));
 
 	kfree(args);
+#ifdef CONFIG_SYSFS
+	xfs_event_alloc(mp);
+#endif
 	return 0;
 
  out_filestream_unmount:
@@ -2142,6 +2148,10 @@ init_xfs_fs(void)
 	error = register_filesystem(&xfs_fs_type);
 	if (error)
 		goto out_sysctl_unregister;
+
+#ifdef CONFIG_SYSFS
+	xfs_sysfs_init();
+#endif	
 	return 0;
 
  out_sysctl_unregister:
@@ -2175,6 +2185,9 @@ exit_xfs_fs(void)
 	xfs_free_trace_bufs();
 	xfs_destroy_zones();
 	ktrace_uninit();
+#ifdef CONFIG_SYSFS
+	xfs_sysfs_done();
+#endif	
 }
 
 module_init(init_xfs_fs);
diff --git a/xfs/xfs_mount.c b/xfs/xfs_mount.c
index 15f5dd2..47e8202 100644
--- a/xfs/xfs_mount.c
+++ b/xfs/xfs_mount.c
@@ -2442,3 +2442,25 @@ balance_counter:
 }
 
 #endif
+
+
+__uint64_t xfs_icsb_get_fdblocks_lazy(xfs_mount_t *mp)
+{
+        __uint64_t fdblocks = 0;
+#ifdef HAVE_PERCPU_SB
+        xfs_icsb_cnts_t *cntp;
+        int i;
+
+        for_each_online_cpu(i) {
+                cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
+                fdblocks += cntp->icsb_fdblocks;
+        }
+
+        if (xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS))
+                fdblocks = mp->m_sb.sb_fdblocks;
+#else
+        fdblocks = mp->m_sb.sb_fdblocks;
+#endif
+        return fdblocks - XFS_ALLOC_SET_ASIDE(mp);
+}
+
diff --git a/xfs/xfs_mount.h b/xfs/xfs_mount.h
index f3c1024..9a98c44 100644
--- a/xfs/xfs_mount.h
+++ b/xfs/xfs_mount.h
@@ -341,6 +341,9 @@ typedef struct xfs_mount {
 	spinlock_t		m_sync_lock;	/* work item list lock */
 	int			m_sync_seq;	/* sync thread generation no. */
 	wait_queue_head_t	m_wait_single_sync_task;
+#ifdef CONFIG_SYSFS
+	void *event_onlow;
+#endif
 } xfs_mount_t;
 
 /*
@@ -539,6 +542,13 @@ extern void	xfs_qmops_put(struct xfs_mou
 
 extern struct xfs_dmops xfs_dmcore_xfs;
 
+#ifdef CONFIG_SYSFS
+extern void xfs_sysfs_init(void);
+extern void xfs_sysfs_done(void);
+extern int xfs_event_alloc(struct xfs_mount *mnt);
+extern int xfs_event_release(struct xfs_mount *mnt);
+#endif
+
 #endif	/* __KERNEL__ */
 
 #endif	/* __XFS_MOUNT_H__ */

[-- Attachment #4: xfs-sysfs-1-262719.diff --]
[-- Type: text/x-diff, Size: 2794 bytes --]

diff --git a/xfs/Makefile b/xfs/Makefile
index ba17121..904372b 100644
--- a/xfs/Makefile
+++ b/xfs/Makefile
@@ -91,7 +91,8 @@ xfs-y				+= xfs_alloc.o \
 				   xfs_vnodeops.o \
 				   xfs_rw.o \
 				   xfs_dmops.o \
-				   xfs_qmops.o
+				   xfs_qmops.o \
+				   xfs_sysfs.o
 
 xfs-$(CONFIG_XFS_TRACE)		+= xfs_dir2_trace.o
 
diff --git a/xfs/linux-2.6/xfs_super.c b/xfs/linux-2.6/xfs_super.c
index 9eaddb4..57f2558 100644
--- a/xfs/linux-2.6/xfs_super.c
+++ b/xfs/linux-2.6/xfs_super.c
@@ -1152,6 +1152,9 @@ xfs_fs_put_super(
 	xfs_close_devices(mp);
 	xfs_qmops_put(mp);
 	xfs_dmops_put(mp);
+#ifdef CONFIG_SYSFS
+	xfs_event_release(mp);
+#endif
 	xfs_free_fsname(mp);
 	kfree(mp);
 }
@@ -1783,6 +1786,9 @@ xfs_fs_fill_super(
 	xfs_itrace_exit(XFS_I(sb->s_root->d_inode));
 
 	kfree(args);
+#ifdef CONFIG_SYSFS
+	xfs_event_alloc(mp);
+#endif
 	return 0;
 
  out_filestream_unmount:
@@ -2151,6 +2157,10 @@ init_xfs_fs(void)
 	error = register_filesystem(&xfs_fs_type);
 	if (error)
 		goto out_sysctl_unregister;
+
+#ifdef CONFIG_SYSFS
+	xfs_sysfs_init();
+#endif	
 	return 0;
 
  out_sysctl_unregister:
@@ -2184,6 +2194,9 @@ exit_xfs_fs(void)
 	xfs_free_trace_bufs();
 	xfs_destroy_zones();
 	ktrace_uninit();
+#ifdef CONFIG_SYSFS
+	xfs_sysfs_done();
+#endif	
 }
 
 module_init(init_xfs_fs);
diff --git a/xfs/xfs_mount.c b/xfs/xfs_mount.c
index a4503f5..2854b00 100644
--- a/xfs/xfs_mount.c
+++ b/xfs/xfs_mount.c
@@ -2441,3 +2441,25 @@ balance_counter:
 }
 
 #endif
+
+
+__uint64_t xfs_icsb_get_fdblocks_lazy(xfs_mount_t *mp)
+{
+        __uint64_t fdblocks = 0;
+#ifdef HAVE_PERCPU_SB
+        xfs_icsb_cnts_t *cntp;
+        int i;
+
+        for_each_online_cpu(i) {
+                cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
+                fdblocks += cntp->icsb_fdblocks;
+        }
+
+        if (xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS))
+                fdblocks = mp->m_sb.sb_fdblocks;
+#else
+        fdblocks = mp->m_sb.sb_fdblocks;
+#endif
+        return fdblocks - XFS_ALLOC_SET_ASIDE(mp);
+}
+
diff --git a/xfs/xfs_mount.h b/xfs/xfs_mount.h
index b6b8be8..a7c17fe 100644
--- a/xfs/xfs_mount.h
+++ b/xfs/xfs_mount.h
@@ -342,6 +342,9 @@ typedef struct xfs_mount {
 	int			m_sync_seq;	/* sync thread generation no. */
 	wait_queue_head_t	m_wait_single_sync_task;
 	struct vfsmount         *m_vfsmount;
+#ifdef CONFIG_SYSFS
+	void *event_onlow;
+#endif
 } xfs_mount_t;
 
 /*
@@ -540,6 +543,13 @@ extern void	xfs_qmops_put(struct xfs_mount *);
 
 extern struct xfs_dmops xfs_dmcore_xfs;
 
+#ifdef CONFIG_SYSFS
+extern void xfs_sysfs_init(void);
+extern void xfs_sysfs_done(void);
+extern int xfs_event_alloc(struct xfs_mount *mnt);
+extern int xfs_event_release(struct xfs_mount *mnt);
+#endif
+
 #endif	/* __KERNEL__ */
 
 #endif	/* __XFS_MOUNT_H__ */

[-- Attachment #5: xfs-sysfs-2.diff --]
[-- Type: text/x-diff, Size: 9399 bytes --]

diff --git a/xfs/xfs_sysfs.c b/xfs/xfs_sysfs.c
new file mode 100644
index 0000000..cbb0ed2
--- /dev/null
+++ b/xfs/xfs_sysfs.c
@@ -0,0 +1,339 @@
+/*
+ * A sysfs interface for triggering events like "Nearly Out Of Space"
+ * Krzysztof Blaszkowski <kb@sysmikro.com.pl> 2009
+ *
+ *
+ * each mounted block device will be associted with a directory under
+ *   /sys/fs/xfs-oos/ where there is a file "trigger" which sets
+ * a free space trigger point and if crossed over then there will be raised
+ * an uevent like this:
+ *   UEVENT[1240929288.150050] change   /fs/xfs-oos/dm-18 (xfs-oos)
+ *   ACTION=change
+ *   DEVPATH=/fs/xfs-oos/dm-18
+ *   SUBSYSTEM=xfs-oos
+ *   XFSDEV=dm-18
+ *   XFSLEFT=191111168
+ *
+ * syntax:
+ * echo "1G" > /sys/fs/xfs-oos/ the_block_device_name /trigger
+ * echo "400M" > /sys/fs/xfs-oos/ some_other_bdev /trigger
+ * echo "20000000" > /sys/fs/xfs-oos/ yet_another_bdev /trigger
+ *
+ * the module polls each mount point every fixed time (5 sec)
+ * and if necessary raises events. it utilizes hysteresis loop of 1/8 
+ * of trigger value to avoid sending excessive events on small change.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#ifdef CONFIG_SYSFS
+
+#include <linux/kobject.h>
+#include <linux/string.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+
+#include "xfs.h"
+#include "xfs_fs.h"
+#include "xfs_types.h"
+#include "xfs_bit.h"
+#include "xfs_log.h"
+#include "xfs_inum.h"
+#include "xfs_trans.h"
+#include "xfs_sb.h"
+#include "xfs_ag.h"
+#include "xfs_dir2.h"
+#include "xfs_dmapi.h"
+#include "xfs_mount.h"
+
+
+static struct xfs_event_ctrl {
+	struct kset *kset;
+	struct timer_list poll;
+	int poll_interval;
+	spinlock_t kset_lock;
+	/* because kset is acessed in different contextes then 
+	 kobject locking (kset->lock) is not appropriate this time */
+} xfs_event_ctrl;
+
+
+
+struct xfs_event_s {
+	struct kobject kobj;
+	__uint64_t trigger;
+	__uint64_t left_bytes;
+	struct xfs_mount *mp;
+	int triggered:1;
+	int fire_event:1;
+};
+
+struct xfs_event_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct xfs_event_s *, struct xfs_event_attribute *, char *);
+	ssize_t (*store)(struct xfs_event_s *, struct xfs_event_attribute *, const char *, ssize_t);
+};
+
+
+static ssize_t xfs_event_kobj_attr_show(struct kobject *_kobj,
+			     struct attribute *a,
+			     char *buf)
+{
+	struct xfs_event_attribute *attribute = container_of(a, struct xfs_event_attribute, attr);
+	struct xfs_event_s *event = container_of(_kobj, struct xfs_event_s, kobj);
+
+	if (!attribute->show)
+		return -EIO;
+
+	return attribute->show(event, attribute, buf);
+}
+
+static ssize_t xfs_event_kobj_attr_store(struct kobject *_kobj,
+			      struct attribute *a,
+			      const char *buf, size_t len)
+{
+	struct xfs_event_attribute *attribute = container_of(a, struct xfs_event_attribute, attr);
+	struct xfs_event_s *event = container_of(_kobj, struct xfs_event_s, kobj);
+
+	if (!attribute->store)
+		return -EIO;
+
+	return attribute->store(event, attribute, buf, len);
+}
+
+static void xfs_event_kobj_release(struct kobject *_kobj)
+{
+	struct xfs_event_s *event = container_of(_kobj, struct xfs_event_s, kobj);
+	kfree(event);
+}
+
+
+static const struct sysfs_ops xfs_event_sysfs_ops = {
+	.show = xfs_event_kobj_attr_show,
+	.store = xfs_event_kobj_attr_store,
+};
+
+static const struct attribute *xfs_events_attrs[];
+static const struct kobj_type xfs_event_ktype = {
+	.sysfs_ops = (void *)&xfs_event_sysfs_ops,
+	.release = xfs_event_kobj_release,
+	.default_attrs = (void *)xfs_events_attrs,
+};
+
+
+
+
+
+static ssize_t xfs_trigger_get(struct xfs_event_s *event,
+				struct xfs_event_attribute *obj_attr,
+				char *buf)
+{
+	__uint64_t bs = event->mp->m_sb.sb_blocksize;
+	
+	return sprintf(buf, "%lld %lld %c", event->trigger * bs, event->left_bytes, event->triggered ? '1' : '0');
+}
+
+static ssize_t xfs_trigger_set(struct xfs_event_s *event,
+				struct xfs_event_attribute *obj_attr,
+				const char *buf, ssize_t count)
+{
+	int rc;
+	char unit;
+	
+	spin_lock_bh(&xfs_event_ctrl.kset_lock);
+	rc = sscanf(buf, "%lld%c", &event->trigger, &unit);
+	if (rc == 2) {
+		switch(unit) {
+			case 'T':
+			case 't':
+				event->trigger <<= 10;
+			case 'G':
+			case 'g':
+				event->trigger <<= 10;
+			case 'M':
+			case 'm':
+				event->trigger <<= 20;
+		}
+	}
+	event->trigger /= event->mp->m_sb.sb_blocksize;
+	spin_unlock_bh(&xfs_event_ctrl.kset_lock);
+	return count;
+}
+
+
+static const struct xfs_event_attribute xfs_event_trigger = 
+	__ATTR(trigger, S_IFREG | S_IRUGO | S_IWUSR,
+	xfs_trigger_get,
+	xfs_trigger_set);
+
+static const struct attribute *xfs_events_attrs[] = {
+	&xfs_event_trigger.attr,
+	NULL
+}; 
+
+
+extern __uint64_t xfs_icsb_get_fdblocks_lazy(xfs_mount_t *mp);
+
+static void xfs_event_fdblocks_poll(unsigned long arg)
+{
+	struct xfs_event_ctrl *ctrl = (struct xfs_event_ctrl *)arg;
+	struct kset *kset = ctrl->kset;
+	struct kobject *k, *tmp;
+	
+	struct list_head events_to_fire;
+	
+	INIT_LIST_HEAD(&events_to_fire);
+	mod_timer(&ctrl->poll, jiffies + ctrl->poll_interval);
+	spin_lock_bh(&ctrl->kset_lock);
+	/* no need to use kset->lock */
+	list_for_each_entry_safe(k, tmp, &kset->list, entry) {
+		struct xfs_event_s *event = container_of(k, struct xfs_event_s, kobj);
+		__uint64_t space_left = xfs_icsb_get_fdblocks_lazy(event->mp);
+
+		if (space_left < event->trigger && !event->triggered) {
+			event->triggered = 1;
+			kobject_get(&event->kobj);
+			event->left_bytes = space_left * event->mp->m_sb.sb_blocksize;
+			list_del(&event->kobj.entry);
+			list_add(&event->kobj.entry, &events_to_fire);
+		}
+
+		if (space_left > (event->trigger + (event->trigger >> 3)) 
+			&& event->triggered) {
+			event->triggered = 0;
+		}
+	
+	}
+	spin_unlock_bh(&ctrl->kset_lock);
+	
+	if (!list_empty(&events_to_fire)) {
+		char buffer[256];
+		char *envp[3];
+	
+		envp[0] = buffer;
+		envp[2] = NULL;
+		list_for_each_entry(k, &events_to_fire, entry) {
+			struct xfs_event_s *event = container_of(k, struct xfs_event_s, kobj);
+			
+			envp[1] = envp[0] + snprintf(envp[0], 250, "XFSDEV=%s", k->name) + 1;
+			snprintf(envp[1], 250 - (envp[1] - envp[0]), "XFSLEFT=%lld", event->left_bytes);
+
+//			printk("%s:%d firing [%s] [%s] [%s]\n", __FUNCTION__, __LINE__, k->name, envp[0], envp[1]);
+			kobject_uevent_env(k, KOBJ_CHANGE, envp);
+		}
+
+		spin_lock_bh(&ctrl->kset_lock);
+		list_for_each_entry_safe(k, tmp, &events_to_fire, entry) {
+			struct xfs_event_s *event = container_of(k, struct xfs_event_s, kobj);
+
+			list_del(&event->kobj.entry);
+			list_add(&event->kobj.entry, &kset->list);
+			kobject_put(&event->kobj);
+		}
+		spin_unlock_bh(&ctrl->kset_lock);
+	}
+}
+
+
+/* api */
+
+void xfs_sysfs_init(void)
+{
+	memset(&xfs_event_ctrl, 0, sizeof(struct xfs_event_ctrl));
+
+	xfs_event_ctrl.poll_interval = HZ * 5;
+	xfs_event_ctrl.kset = kset_create_and_add("xfs-oos", NULL, fs_kobj);
+	spin_lock_init(&xfs_event_ctrl.kset_lock);
+	if (!xfs_event_ctrl.kset) {
+		cmn_err(CE_ALERT, "kset_create failed");
+		return;
+	}
+}
+
+void xfs_sysfs_done(void)
+{
+	if (xfs_event_ctrl.kset) {
+		BUG_ON(!list_empty(&xfs_event_ctrl.kset->list));
+		kset_unregister(xfs_event_ctrl.kset);
+		xfs_event_ctrl.kset = NULL;
+	}
+}
+
+/* stuff for xfs_fs_fill_super, xfs_fs_put_super */
+
+int xfs_event_alloc(struct xfs_mount *mnt)
+{
+	struct xfs_event_s * ev;
+	int rc = -1;
+	int empty;
+	
+	if (!xfs_event_ctrl.kset)
+		return rc;
+
+	ev = kzalloc(sizeof(struct xfs_event_s), GFP_KERNEL);
+
+	spin_lock_bh(&xfs_event_ctrl.kset_lock);
+	empty = list_empty(&xfs_event_ctrl.kset->list);
+	
+	if (ev) {
+		ev->kobj.kset = xfs_event_ctrl.kset;
+		ev->mp = mnt;
+		
+		rc = kobject_init_and_add(&ev->kobj, (void *)&xfs_event_ktype, NULL, "%s", mnt->m_fsname);
+		if (!rc) {
+			mnt->event_onlow = ev;
+			kobject_uevent(&ev->kobj, KOBJ_ADD);
+		} else {
+			kobject_put(&ev->kobj); // ev will be freed too.
+		}
+	}
+	spin_unlock_bh(&xfs_event_ctrl.kset_lock);
+	
+	if (empty) {
+		init_timer(&xfs_event_ctrl.poll);
+		xfs_event_ctrl.poll.function = xfs_event_fdblocks_poll;
+		xfs_event_ctrl.poll.data = (unsigned long)&xfs_event_ctrl;
+		xfs_event_ctrl.poll.expires = jiffies + xfs_event_ctrl.poll_interval;
+		add_timer(&xfs_event_ctrl.poll);
+	}
+
+	return rc;
+}
+
+int xfs_event_release(struct xfs_mount *mnt)
+{
+	struct xfs_event_s * ev = (struct xfs_event_s *)mnt->event_onlow;
+	int empty;
+
+	if (!xfs_event_ctrl.kset)
+		return -1;
+
+	spin_lock_bh(&xfs_event_ctrl.kset_lock);
+	if (ev)
+		kobject_put(&ev->kobj);
+
+	empty = list_empty(&xfs_event_ctrl.kset->list);
+	spin_unlock_bh(&xfs_event_ctrl.kset_lock);
+
+	if (empty) {
+		del_timer_sync(&xfs_event_ctrl.poll);
+	}
+	
+	return 0;
+}
+
+#endif
+

[-- Attachment #6: Type: text/plain, Size: 121 bytes --]

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: generating uevents by xfs
  2009-04-28 16:18 generating uevents by xfs Krzysztof Błaszkowski
@ 2009-04-29 12:50 ` Andi Kleen
  2009-04-29 13:12   ` Krzysztof Błaszkowski
  0 siblings, 1 reply; 3+ messages in thread
From: Andi Kleen @ 2009-04-29 12:50 UTC (permalink / raw)
  To: Krzysztof Bâaszkowski; +Cc: xfs

Krzysztof Bâaszkowski <kb@sysmikro.com.pl> writes:

> Hello,
>
> once upon i was asked to think about such facility for notifying userspace 
> when some mount point is nearly full at some level let's say e.g. 90% 
> (threshold should be configurable).
>
> here is a solution designed by me and i would like to see comments on this 
> idea and solution.

It doesn't seem to be very useful to poll in kernel for this. When you're
in kernel you could just hook into the respective functions that handle
disk allocation directly. Polling can be as well done in user space only,
so it doesn't make too much sense to put polling code into the kernel.

-Andi


-- 
ak@linux.intel.com -- Speaking for myself only.

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: generating uevents by xfs
  2009-04-29 12:50 ` Andi Kleen
@ 2009-04-29 13:12   ` Krzysztof Błaszkowski
  0 siblings, 0 replies; 3+ messages in thread
From: Krzysztof Błaszkowski @ 2009-04-29 13:12 UTC (permalink / raw)
  To: Andi Kleen; +Cc: xfs

On Wednesday 29 April 2009 14:50, Andi Kleen wrote:
> Krzysztof Bâaszkowski <kb@sysmikro.com.pl> writes:
> > Hello,
> >
> > once upon i was asked to think about such facility for notifying
> > userspace when some mount point is nearly full at some level let's say
> > e.g. 90% (threshold should be configurable).
> >
> > here is a solution designed by me and i would like to see comments on
> > this idea and solution.
>
> It doesn't seem to be very useful to poll in kernel for this. When you're
> in kernel you could just hook into the respective functions that handle
> disk allocation directly.

i reckon yes and no both. "no" because i wanted a solution which will have 
almost no impact on performance. if the speed wasn't an important concern 
then why would one take care about per cpu counters like fdblocks ?


> Polling can be as well done in user space only, 
> so it doesn't make too much sense to put polling code into the kernel.

yes i think too, that's maybe a bit too huge thing looking at benefits it 
brings but consider bash instance consuming 1.5M (at least) and other things 
spawned periodically, 
do they have more sense ? i don't think so and this is the solution which 
voids all hassle with userspace polling because it uses unified notification 
system and this can be good starting point for notification system for other 
purposes i haven't think of yet but maybe someone has a new idea regarding 
this.

are these reasons good to (complete and) merge this stuff ?

I found that the xfs-sysfs-2 requires small rework around event_alloc() and 
event_release() because of very rare (but possible) race with timer function 
which drops lock (i decided to drop lock because i think kobject_uevent may 
be synchronous in the case of deprecated /sbin/hotplug and i'm not sure also 
how long it takes for udevd)

i think that there is no point to update patch as long as we will not sort out 
if the whole idea is really worth to implement.

Thanks for reply.

Krzysztof Blaszkowski

>
> -Andi

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2009-04-29 13:12 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-04-28 16:18 generating uevents by xfs Krzysztof Błaszkowski
2009-04-29 12:50 ` Andi Kleen
2009-04-29 13:12   ` Krzysztof Błaszkowski

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