Netdev List
 help / color / mirror / Atom feed
* [PATCH] can: switch to seq_file
From: Alexey Dobriyan @ 2009-08-28 19:57 UTC (permalink / raw)
  To: urs.thuermann, oliver.hartkopp; +Cc: netdev

create_proc_read_entry() is going to be removed soon.

Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---

 net/can/bcm.c  |   85 +++++++----------
 net/can/proc.c |  281 ++++++++++++++++++++++++++-------------------------------
 2 files changed, 167 insertions(+), 199 deletions(-)

--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -46,6 +46,7 @@
 #include <linux/hrtimer.h>
 #include <linux/list.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/uio.h>
 #include <linux/net.h>
 #include <linux/netdevice.h>
@@ -146,23 +147,18 @@ static char *bcm_proc_getifname(int ifindex)
 	return "???";
 }
 
-static int bcm_read_proc(char *page, char **start, off_t off,
-			 int count, int *eof, void *data)
+static int bcm_proc_show(struct seq_file *m, void *v)
 {
-	int len = 0;
-	struct sock *sk = (struct sock *)data;
+	struct sock *sk = (struct sock *)m->private;
 	struct bcm_sock *bo = bcm_sk(sk);
 	struct bcm_op *op;
 
-	len += snprintf(page + len, PAGE_SIZE - len, ">>> socket %p",
-			sk->sk_socket);
-	len += snprintf(page + len, PAGE_SIZE - len, " / sk %p", sk);
-	len += snprintf(page + len, PAGE_SIZE - len, " / bo %p", bo);
-	len += snprintf(page + len, PAGE_SIZE - len, " / dropped %lu",
-			bo->dropped_usr_msgs);
-	len += snprintf(page + len, PAGE_SIZE - len, " / bound %s",
-			bcm_proc_getifname(bo->ifindex));
-	len += snprintf(page + len, PAGE_SIZE - len, " <<<\n");
+	seq_printf(m, ">>> socket %p", sk->sk_socket);
+	seq_printf(m, " / sk %p", sk);
+	seq_printf(m, " / bo %p", bo);
+	seq_printf(m, " / dropped %lu", bo->dropped_usr_msgs);
+	seq_printf(m, " / bound %s", bcm_proc_getifname(bo->ifindex));
+	seq_printf(m, " <<<\n");
 
 	list_for_each_entry(op, &bo->rx_ops, list) {
 
@@ -172,71 +168,62 @@ static int bcm_read_proc(char *page, char **start, off_t off,
 		if (!op->frames_abs)
 			continue;
 
-		len += snprintf(page + len, PAGE_SIZE - len,
-				"rx_op: %03X %-5s ",
+		seq_printf(m, "rx_op: %03X %-5s ",
 				op->can_id, bcm_proc_getifname(op->ifindex));
-		len += snprintf(page + len, PAGE_SIZE - len, "[%d]%c ",
-				op->nframes,
+		seq_printf(m, "[%d]%c ", op->nframes,
 				(op->flags & RX_CHECK_DLC)?'d':' ');
 		if (op->kt_ival1.tv64)
-			len += snprintf(page + len, PAGE_SIZE - len,
-					"timeo=%lld ",
+			seq_printf(m, "timeo=%lld ",
 					(long long)
 					ktime_to_us(op->kt_ival1));
 
 		if (op->kt_ival2.tv64)
-			len += snprintf(page + len, PAGE_SIZE - len,
-					"thr=%lld ",
+			seq_printf(m, "thr=%lld ",
 					(long long)
 					ktime_to_us(op->kt_ival2));
 
-		len += snprintf(page + len, PAGE_SIZE - len,
-				"# recv %ld (%ld) => reduction: ",
+		seq_printf(m, "# recv %ld (%ld) => reduction: ",
 				op->frames_filtered, op->frames_abs);
 
 		reduction = 100 - (op->frames_filtered * 100) / op->frames_abs;
 
-		len += snprintf(page + len, PAGE_SIZE - len, "%s%ld%%\n",
+		seq_printf(m, "%s%ld%%\n",
 				(reduction == 100)?"near ":"", reduction);
-
-		if (len > PAGE_SIZE - 200) {
-			/* mark output cut off */
-			len += snprintf(page + len, PAGE_SIZE - len, "(..)\n");
-			break;
-		}
 	}
 
 	list_for_each_entry(op, &bo->tx_ops, list) {
 
-		len += snprintf(page + len, PAGE_SIZE - len,
-				"tx_op: %03X %s [%d] ",
+		seq_printf(m, "tx_op: %03X %s [%d] ",
 				op->can_id, bcm_proc_getifname(op->ifindex),
 				op->nframes);
 
 		if (op->kt_ival1.tv64)
-			len += snprintf(page + len, PAGE_SIZE - len, "t1=%lld ",
+			seq_printf(m, "t1=%lld ",
 					(long long) ktime_to_us(op->kt_ival1));
 
 		if (op->kt_ival2.tv64)
-			len += snprintf(page + len, PAGE_SIZE - len, "t2=%lld ",
+			seq_printf(m, "t2=%lld ",
 					(long long) ktime_to_us(op->kt_ival2));
 
-		len += snprintf(page + len, PAGE_SIZE - len, "# sent %ld\n",
-				op->frames_abs);
-
-		if (len > PAGE_SIZE - 100) {
-			/* mark output cut off */
-			len += snprintf(page + len, PAGE_SIZE - len, "(..)\n");
-			break;
-		}
+		seq_printf(m, "# sent %ld\n", op->frames_abs);
 	}
+	seq_putc(m, '\n');
+	return 0;
+}
 
-	len += snprintf(page + len, PAGE_SIZE - len, "\n");
-
-	*eof = 1;
-	return len;
+static int bcm_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, bcm_proc_show, PDE(inode)->data);
 }
 
+static const struct file_operations bcm_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= bcm_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 /*
  * bcm_can_tx - send the (next) CAN frame to the appropriate CAN interface
  *              of the given bcm tx op
@@ -1515,9 +1502,9 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len,
 	if (proc_dir) {
 		/* unique socket address as filename */
 		sprintf(bo->procname, "%p", sock);
-		bo->bcm_proc_read = create_proc_read_entry(bo->procname, 0644,
-							   proc_dir,
-							   bcm_read_proc, sk);
+		bo->bcm_proc_read = proc_create_data(bo->procname, 0644,
+						     proc_dir,
+						     &bcm_proc_fops, sk);
 	}
 
 	return 0;
--- a/net/can/proc.c
+++ b/net/can/proc.c
@@ -196,8 +196,8 @@ void can_stat_update(unsigned long data)
  *
  */
 
-static int can_print_rcvlist(char *page, int len, struct hlist_head *rx_list,
-			     struct net_device *dev)
+static void can_print_rcvlist(struct seq_file *m, struct hlist_head *rx_list,
+			      struct net_device *dev)
 {
 	struct receiver *r;
 	struct hlist_node *n;
@@ -208,199 +208,188 @@ static int can_print_rcvlist(char *page, int len, struct hlist_head *rx_list,
 			"   %-5s  %08X  %08x  %08x  %08x  %8ld  %s\n" :
 			"   %-5s     %03X    %08x  %08lx  %08lx  %8ld  %s\n";
 
-		len += snprintf(page + len, PAGE_SIZE - len, fmt,
-				DNAME(dev), r->can_id, r->mask,
+		seq_printf(m, fmt, DNAME(dev), r->can_id, r->mask,
 				(unsigned long)r->func, (unsigned long)r->data,
 				r->matches, r->ident);
-
-		/* does a typical line fit into the current buffer? */
-
-		/* 100 Bytes before end of buffer */
-		if (len > PAGE_SIZE - 100) {
-			/* mark output cut off */
-			len += snprintf(page + len, PAGE_SIZE - len,
-					"   (..)\n");
-			break;
-		}
 	}
 	rcu_read_unlock();
-
-	return len;
 }
 
-static int can_print_recv_banner(char *page, int len)
+static void can_print_recv_banner(struct seq_file *m)
 {
 	/*
 	 *                  can1.  00000000  00000000  00000000
 	 *                 .......          0  tp20
 	 */
-	len += snprintf(page + len, PAGE_SIZE - len,
-			"  device   can_id   can_mask  function"
+	seq_puts(m, "  device   can_id   can_mask  function"
 			"  userdata   matches  ident\n");
-
-	return len;
 }
 
-static int can_proc_read_stats(char *page, char **start, off_t off,
-			       int count, int *eof, void *data)
+static int can_stats_proc_show(struct seq_file *m, void *v)
 {
-	int len = 0;
+	seq_putc(m, '\n');
+	seq_printf(m, " %8ld transmitted frames (TXF)\n", can_stats.tx_frames);
+	seq_printf(m, " %8ld received frames (RXF)\n", can_stats.rx_frames);
+	seq_printf(m, " %8ld matched frames (RXMF)\n", can_stats.matches);
 
-	len += snprintf(page + len, PAGE_SIZE - len, "\n");
-	len += snprintf(page + len, PAGE_SIZE - len,
-			" %8ld transmitted frames (TXF)\n",
-			can_stats.tx_frames);
-	len += snprintf(page + len, PAGE_SIZE - len,
-			" %8ld received frames (RXF)\n", can_stats.rx_frames);
-	len += snprintf(page + len, PAGE_SIZE - len,
-			" %8ld matched frames (RXMF)\n", can_stats.matches);
-
-	len += snprintf(page + len, PAGE_SIZE - len, "\n");
+	seq_putc(m, '\n');
 
 	if (can_stattimer.function == can_stat_update) {
-		len += snprintf(page + len, PAGE_SIZE - len,
-				" %8ld %% total match ratio (RXMR)\n",
+		seq_printf(m, " %8ld %% total match ratio (RXMR)\n",
 				can_stats.total_rx_match_ratio);
 
-		len += snprintf(page + len, PAGE_SIZE - len,
-				" %8ld frames/s total tx rate (TXR)\n",
+		seq_printf(m, " %8ld frames/s total tx rate (TXR)\n",
 				can_stats.total_tx_rate);
-		len += snprintf(page + len, PAGE_SIZE - len,
-				" %8ld frames/s total rx rate (RXR)\n",
+		seq_printf(m, " %8ld frames/s total rx rate (RXR)\n",
 				can_stats.total_rx_rate);
 
-		len += snprintf(page + len, PAGE_SIZE - len, "\n");
+		seq_putc(m, '\n');
 
-		len += snprintf(page + len, PAGE_SIZE - len,
-				" %8ld %% current match ratio (CRXMR)\n",
+		seq_printf(m, " %8ld %% current match ratio (CRXMR)\n",
 				can_stats.current_rx_match_ratio);
 
-		len += snprintf(page + len, PAGE_SIZE - len,
-				" %8ld frames/s current tx rate (CTXR)\n",
+		seq_printf(m, " %8ld frames/s current tx rate (CTXR)\n",
 				can_stats.current_tx_rate);
-		len += snprintf(page + len, PAGE_SIZE - len,
-				" %8ld frames/s current rx rate (CRXR)\n",
+		seq_printf(m, " %8ld frames/s current rx rate (CRXR)\n",
 				can_stats.current_rx_rate);
 
-		len += snprintf(page + len, PAGE_SIZE - len, "\n");
+		seq_putc(m, '\n');
 
-		len += snprintf(page + len, PAGE_SIZE - len,
-				" %8ld %% max match ratio (MRXMR)\n",
+		seq_printf(m, " %8ld %% max match ratio (MRXMR)\n",
 				can_stats.max_rx_match_ratio);
 
-		len += snprintf(page + len, PAGE_SIZE - len,
-				" %8ld frames/s max tx rate (MTXR)\n",
+		seq_printf(m, " %8ld frames/s max tx rate (MTXR)\n",
 				can_stats.max_tx_rate);
-		len += snprintf(page + len, PAGE_SIZE - len,
-				" %8ld frames/s max rx rate (MRXR)\n",
+		seq_printf(m, " %8ld frames/s max rx rate (MRXR)\n",
 				can_stats.max_rx_rate);
 
-		len += snprintf(page + len, PAGE_SIZE - len, "\n");
+		seq_putc(m, '\n');
 	}
 
-	len += snprintf(page + len, PAGE_SIZE - len,
-			" %8ld current receive list entries (CRCV)\n",
+	seq_printf(m, " %8ld current receive list entries (CRCV)\n",
 			can_pstats.rcv_entries);
-	len += snprintf(page + len, PAGE_SIZE - len,
-			" %8ld maximum receive list entries (MRCV)\n",
+	seq_printf(m, " %8ld maximum receive list entries (MRCV)\n",
 			can_pstats.rcv_entries_max);
 
 	if (can_pstats.stats_reset)
-		len += snprintf(page + len, PAGE_SIZE - len,
-				"\n %8ld statistic resets (STR)\n",
+		seq_printf(m, "\n %8ld statistic resets (STR)\n",
 				can_pstats.stats_reset);
 
 	if (can_pstats.user_reset)
-		len += snprintf(page + len, PAGE_SIZE - len,
-				" %8ld user statistic resets (USTR)\n",
+		seq_printf(m, " %8ld user statistic resets (USTR)\n",
 				can_pstats.user_reset);
 
-	len += snprintf(page + len, PAGE_SIZE - len, "\n");
-
-	*eof = 1;
-	return len;
+	seq_putc(m, '\n');
+	return 0;
 }
 
-static int can_proc_read_reset_stats(char *page, char **start, off_t off,
-				     int count, int *eof, void *data)
+static int can_stats_proc_open(struct inode *inode, struct file *file)
 {
-	int len = 0;
+	return single_open(file, can_stats_proc_show, NULL);
+}
+
+static const struct file_operations can_stats_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= can_stats_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
 
+static int can_reset_stats_proc_show(struct seq_file *m, void *v)
+{
 	user_reset = 1;
 
 	if (can_stattimer.function == can_stat_update) {
-		len += snprintf(page + len, PAGE_SIZE - len,
-				"Scheduled statistic reset #%ld.\n",
+		seq_printf(m, "Scheduled statistic reset #%ld.\n",
 				can_pstats.stats_reset + 1);
 
 	} else {
 		if (can_stats.jiffies_init != jiffies)
 			can_init_stats();
 
-		len += snprintf(page + len, PAGE_SIZE - len,
-				"Performed statistic reset #%ld.\n",
+		seq_printf(m, "Performed statistic reset #%ld.\n",
 				can_pstats.stats_reset);
 	}
+	return 0;
+}
 
-	*eof = 1;
-	return len;
+static int can_reset_stats_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, can_reset_stats_proc_show, NULL);
 }
 
-static int can_proc_read_version(char *page, char **start, off_t off,
-				 int count, int *eof, void *data)
+static const struct file_operations can_reset_stats_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= can_reset_stats_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int can_version_proc_show(struct seq_file *m, void *v)
 {
-	int len = 0;
+	seq_printf(m, "%s\n", CAN_VERSION_STRING);
+	return 0;
+}
 
-	len += snprintf(page + len, PAGE_SIZE - len, "%s\n",
-			CAN_VERSION_STRING);
-	*eof = 1;
-	return len;
+static int can_version_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, can_version_proc_show, NULL);
 }
 
-static int can_proc_read_rcvlist(char *page, char **start, off_t off,
-				 int count, int *eof, void *data)
+static const struct file_operations can_version_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= can_version_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int can_rcvlist_proc_show(struct seq_file *m, void *v)
 {
 	/* double cast to prevent GCC warning */
-	int idx = (int)(long)data;
-	int len = 0;
+	int idx = (int)(long)m->private;
 	struct dev_rcv_lists *d;
 	struct hlist_node *n;
 
-	len += snprintf(page + len, PAGE_SIZE - len,
-			"\nreceive list '%s':\n", rx_list_name[idx]);
+	seq_printf(m, "\nreceive list '%s':\n", rx_list_name[idx]);
 
 	rcu_read_lock();
 	hlist_for_each_entry_rcu(d, n, &can_rx_dev_list, list) {
 
 		if (!hlist_empty(&d->rx[idx])) {
-			len = can_print_recv_banner(page, len);
-			len = can_print_rcvlist(page, len, &d->rx[idx], d->dev);
+			can_print_recv_banner(m);
+			can_print_rcvlist(m, &d->rx[idx], d->dev);
 		} else
-			len += snprintf(page + len, PAGE_SIZE - len,
-					"  (%s: no entry)\n", DNAME(d->dev));
-
-		/* exit on end of buffer? */
-		if (len > PAGE_SIZE - 100)
-			break;
+			seq_printf(m, "  (%s: no entry)\n", DNAME(d->dev));
 	}
 	rcu_read_unlock();
 
-	len += snprintf(page + len, PAGE_SIZE - len, "\n");
+	seq_putc(m, '\n');
+	return 0;
+}
 
-	*eof = 1;
-	return len;
+static int can_rcvlist_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, can_rcvlist_proc_show, PDE(inode)->data);
 }
 
-static int can_proc_read_rcvlist_sff(char *page, char **start, off_t off,
-				     int count, int *eof, void *data)
+static const struct file_operations can_rcvlist_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= can_rcvlist_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int can_rcvlist_sff_proc_show(struct seq_file *m, void *v)
 {
-	int len = 0;
 	struct dev_rcv_lists *d;
 	struct hlist_node *n;
 
 	/* RX_SFF */
-	len += snprintf(page + len, PAGE_SIZE - len,
-			"\nreceive list 'rx_sff':\n");
+	seq_puts(m, "\nreceive list 'rx_sff':\n");
 
 	rcu_read_lock();
 	hlist_for_each_entry_rcu(d, n, &can_rx_dev_list, list) {
@@ -413,46 +402,38 @@ static int can_proc_read_rcvlist_sff(char *page, char **start, off_t off,
 			}
 
 		if (!all_empty) {
-			len = can_print_recv_banner(page, len);
+			can_print_recv_banner(m);
 			for (i = 0; i < 0x800; i++) {
-				if (!hlist_empty(&d->rx_sff[i]) &&
-				    len < PAGE_SIZE - 100)
-					len = can_print_rcvlist(page, len,
-								&d->rx_sff[i],
-								d->dev);
+				if (!hlist_empty(&d->rx_sff[i]))
+					can_print_rcvlist(m, &d->rx_sff[i],
+							  d->dev);
 			}
 		} else
-			len += snprintf(page + len, PAGE_SIZE - len,
-					"  (%s: no entry)\n", DNAME(d->dev));
-
-		/* exit on end of buffer? */
-		if (len > PAGE_SIZE - 100)
-			break;
+			seq_printf(m, "  (%s: no entry)\n", DNAME(d->dev));
 	}
 	rcu_read_unlock();
 
-	len += snprintf(page + len, PAGE_SIZE - len, "\n");
+	seq_putc(m, '\n');
+	return 0;
+}
 
-	*eof = 1;
-	return len;
+static int can_rcvlist_sff_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, can_rcvlist_sff_proc_show, NULL);
 }
 
+static const struct file_operations can_rcvlist_sff_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= can_rcvlist_sff_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 /*
  * proc utility functions
  */
 
-static struct proc_dir_entry *can_create_proc_readentry(const char *name,
-							mode_t mode,
-							read_proc_t *read_proc,
-							void *data)
-{
-	if (can_dir)
-		return create_proc_read_entry(name, mode, can_dir, read_proc,
-					      data);
-	else
-		return NULL;
-}
-
 static void can_remove_proc_readentry(const char *name)
 {
 	if (can_dir)
@@ -474,24 +455,24 @@ void can_init_proc(void)
 	}
 
 	/* own procfs entries from the AF_CAN core */
-	pde_version     = can_create_proc_readentry(CAN_PROC_VERSION, 0644,
-					can_proc_read_version, NULL);
-	pde_stats       = can_create_proc_readentry(CAN_PROC_STATS, 0644,
-					can_proc_read_stats, NULL);
-	pde_reset_stats = can_create_proc_readentry(CAN_PROC_RESET_STATS, 0644,
-					can_proc_read_reset_stats, NULL);
-	pde_rcvlist_err = can_create_proc_readentry(CAN_PROC_RCVLIST_ERR, 0644,
-					can_proc_read_rcvlist, (void *)RX_ERR);
-	pde_rcvlist_all = can_create_proc_readentry(CAN_PROC_RCVLIST_ALL, 0644,
-					can_proc_read_rcvlist, (void *)RX_ALL);
-	pde_rcvlist_fil = can_create_proc_readentry(CAN_PROC_RCVLIST_FIL, 0644,
-					can_proc_read_rcvlist, (void *)RX_FIL);
-	pde_rcvlist_inv = can_create_proc_readentry(CAN_PROC_RCVLIST_INV, 0644,
-					can_proc_read_rcvlist, (void *)RX_INV);
-	pde_rcvlist_eff = can_create_proc_readentry(CAN_PROC_RCVLIST_EFF, 0644,
-					can_proc_read_rcvlist, (void *)RX_EFF);
-	pde_rcvlist_sff = can_create_proc_readentry(CAN_PROC_RCVLIST_SFF, 0644,
-					can_proc_read_rcvlist_sff, NULL);
+	pde_version     = proc_create(CAN_PROC_VERSION, 0644, can_dir,
+				      &can_version_proc_fops);
+	pde_stats       = proc_create(CAN_PROC_STATS, 0644, can_dir,
+				      &can_stats_proc_fops);
+	pde_reset_stats = proc_create(CAN_PROC_RESET_STATS, 0644, can_dir,
+				      &can_reset_stats_proc_fops);
+	pde_rcvlist_err = proc_create_data(CAN_PROC_RCVLIST_ERR, 0644, can_dir,
+					   &can_rcvlist_proc_fops, (void *)RX_ERR);
+	pde_rcvlist_all = proc_create_data(CAN_PROC_RCVLIST_ALL, 0644, can_dir,
+					   &can_rcvlist_proc_fops, (void *)RX_ALL);
+	pde_rcvlist_fil = proc_create_data(CAN_PROC_RCVLIST_FIL, 0644, can_dir,
+					   &can_rcvlist_proc_fops, (void *)RX_FIL);
+	pde_rcvlist_inv = proc_create_data(CAN_PROC_RCVLIST_INV, 0644, can_dir,
+					   &can_rcvlist_proc_fops, (void *)RX_INV);
+	pde_rcvlist_eff = proc_create_data(CAN_PROC_RCVLIST_EFF, 0644, can_dir,
+					   &can_rcvlist_proc_fops, (void *)RX_EFF);
+	pde_rcvlist_sff = proc_create(CAN_PROC_RCVLIST_SFF, 0644, can_dir,
+				      &can_rcvlist_sff_proc_fops);
 }
 
 /*

^ permalink raw reply

* Re: [PATCH 2/2]: pkt_sched: Convert CBQ to tasklet_hrtimer.
From: Thomas Gleixner @ 2009-08-28 19:51 UTC (permalink / raw)
  To: David Miller; +Cc: eric.dumazet, netdev
In-Reply-To: <20090828.123035.192913179.davem@davemloft.net>

On Fri, 28 Aug 2009, David Miller wrote:

> From: Eric Dumazet <eric.dumazet@gmail.com>
> Date: Fri, 28 Aug 2009 17:54:53 +0200
> 
> > I now have these dmesg warnings when playing with cbq
> > 
> > # tc qdisc del dev eth3 root
> > # tc qdisc add dev eth3 root handle 1: est 1sec 8sec cbq avpkt 1000 rate 1000Mbit bandwidth 1000Mbit
> > # tc qdisc del dev eth3 root
> > 
> > [12786.458485] Attempt to kill tasklet from interrupt
> > [12786.458522] Attempt to kill tasklet from interrupt
> > [12786.465261] Attempt to kill tasklet from interrupt
> > [12786.465286] Attempt to kill tasklet from interrupt
> > 
> > probably becauce cbq_reset() being called from interrupt context ?
> 
> Grumble... I guess the tasklet_hrtimer infrastructure is less
> of a direct plugin replacement for plain hrtimers than I thought.
> 
> Anyone have any ideas about how to deal with stuff like this?

Hmm. Is it sufficient to cancel just the timer and let an eventually
scheduled tasklet deal with the cleanup ?

Thanks,

	tglx


^ permalink raw reply

* [PATCH] pktgen: use proc_create_data()
From: Alexey Dobriyan @ 2009-08-28 19:47 UTC (permalink / raw)
  To: davem; +Cc: netdev

It looks like after rename device proc entry is unusable,
because of no ->read_proc or ->proc_fops.

And create_proc_entry() is deprecated.

Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---

 net/core/pktgen.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -1873,8 +1873,10 @@ static void pktgen_change_name(struct net_device *dev)
 
 			remove_proc_entry(pkt_dev->entry->name, pg_proc_dir);
 
-			pkt_dev->entry = create_proc_entry(dev->name, 0600,
-							   pg_proc_dir);
+			pkt_dev->entry = proc_create_data(dev->name, 0600,
+							  pg_proc_dir,
+							  &pktgen_if_fops,
+							  pkt_dev);
 			if (!pkt_dev->entry)
 				printk(KERN_ERR "pktgen: can't move proc "
 				       " entry for '%s'\n", dev->name);

^ permalink raw reply

* Re: [PATCH 2/2]: pkt_sched: Convert CBQ to tasklet_hrtimer.
From: David Miller @ 2009-08-28 19:30 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev, tglx
In-Reply-To: <4A97FDCD.10208@gmail.com>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Fri, 28 Aug 2009 17:54:53 +0200

> I now have these dmesg warnings when playing with cbq
> 
> # tc qdisc del dev eth3 root
> # tc qdisc add dev eth3 root handle 1: est 1sec 8sec cbq avpkt 1000 rate 1000Mbit bandwidth 1000Mbit
> # tc qdisc del dev eth3 root
> 
> [12786.458485] Attempt to kill tasklet from interrupt
> [12786.458522] Attempt to kill tasklet from interrupt
> [12786.465261] Attempt to kill tasklet from interrupt
> [12786.465286] Attempt to kill tasklet from interrupt
> 
> probably becauce cbq_reset() being called from interrupt context ?

Grumble... I guess the tasklet_hrtimer infrastructure is less
of a direct plugin replacement for plain hrtimers than I thought.

Anyone have any ideas about how to deal with stuff like this?

^ permalink raw reply

* Re: [linux-pm] power draw depending on PHY speed
From: Ben Hutchings @ 2009-08-28 19:29 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Leisner, Martin, linux-pm, martyleisner, NetDEV list
In-Reply-To: <200908282103.59159.rjw@sisk.pl>

On Fri, 2009-08-28 at 21:03 +0200, Rafael J. Wysocki wrote:
> On Friday 28 August 2009, Leisner, Martin wrote:
> > While doing some current probe measurements (i.e. to measure the effects
> > of NAP and frequency scaling with a freescale processor) I noticed some
> > very
> > significant differents if we ran on 100Mbit of 1000Mbit ethernet.
> > 
> > The hardware guys like at their data sheets and agreed.
> > 
> > Does anyone "drop ethernet speed" to save power?
> > (when a system is idle, is isn't necessary to run 1G ethernet).
> 
> I don't know, really.  This is a netdev question IMO (CC added).

Doing this through the existing autonegotiation mechanism is a bad idea,
because it requires bringing the link down, possibly for a few seconds.
There is a standard on the way (802.3az, aka Energy-Efficient Ethernet
or EEE) which will allow for speed renegotiation without dropping the
link.

> > When a system has WOL capability, what speed does it run at when the
> > system is sleeping?
> 
> That's a very good question.  I bet that depends on the NIC in question, at
> least I'm not sure if any spec regulates it.

I'm not aware of a spec, but generally a 1G or 10G multi-speed PHY will
not advertise speeds higher than 100 Mbit/s when sleeping.

Ben.

-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply

* Re: UDP multicast packet loss not reported if TX ring overrun?
From: David Miller @ 2009-08-28 19:26 UTC (permalink / raw)
  To: cl; +Cc: eric.dumazet, sri, dlstevens, netdev, niv
In-Reply-To: <alpine.DEB.1.10.0908281211150.7317@gentwo.org>

From: Christoph Lameter <cl@linux-foundation.org>
Date: Fri, 28 Aug 2009 12:15:39 -0400 (EDT)

> Because you need drop statistics on a device to figure out when you may
> want to increase the TX buffers for a device. If a packet was dropped
> because of a lack of TX buffers then we need to know.

Christoph, the qdisc layer is there and is where the drops occur, and
you therefore have to be aware of it.

I'm not accepting changes like the patch you propose here, it's not
the correct thing to do.

The device never saw the packet, it never dropped it.

The qdisc saw it, the qdisc dropped it, and therefore that's where we
account for it.

^ permalink raw reply

* Re: UDP multicast packet loss not reported if TX ring overrun?
From: David Miller @ 2009-08-28 19:24 UTC (permalink / raw)
  To: cl; +Cc: sri, dlstevens, eric.dumazet, netdev, niv
In-Reply-To: <alpine.DEB.1.10.0908280948320.3747@gentwo.org>

From: Christoph Lameter <cl@linux-foundation.org>
Date: Fri, 28 Aug 2009 09:53:40 -0400 (EDT)

> Seems though that the qdisc drop count does not flow into the tx_dropped
> counter for the interface.

And it should not.

The qdisc drops the packet due to flow control, not the hardware
device.

Device drops are for things like transmission errors on the wire.

If you start incrementing tx_dropped here, people won't be able
to tell they have a deteriorating cable or bad switch or similar.

^ permalink raw reply

* pull request: wireless-2.6 2009-08-28
From: John W. Linville @ 2009-08-28 19:10 UTC (permalink / raw)
  To: davem; +Cc: linux-wireless, netdev, linux-kernel

Dave,

One more late-breaker for 2.6.31...

This patch is rather large for this stage of the cycle, but it
corrects a regression disussed recently on LKML, documented in bug
14016 at bugzilla.kernel.org.  This jist of it is that the ipw2200
firmware loading routine was using an order 6 memory allocation that was
failing with newer allocators under some circumstances.

Please let me know if there are problems!

Thanks,

John

---

Individual patch is available here:

	http://www.kernel.org/pub/linux/kernel/people/linville/wireless-2.6/

---

The following changes since commit 8ff499e43c537648399fca8ba39d24c0768b3fab:
  Dongdong Deng (1):
        smc91x: let smc91x work well under netpoll

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git master

Zhu Yi (1):
      ipw2200: firmware DMA loading rework

 drivers/net/wireless/ipw2x00/ipw2200.c |  120 ++++++++++++++++++--------------
 1 files changed, 67 insertions(+), 53 deletions(-)

diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index 6dcac73..f593fbb 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -2874,45 +2874,27 @@ static int ipw_fw_dma_add_command_block(struct ipw_priv *priv,
 	return 0;
 }
 
-static int ipw_fw_dma_add_buffer(struct ipw_priv *priv,
-				 u32 src_phys, u32 dest_address, u32 length)
+static int ipw_fw_dma_add_buffer(struct ipw_priv *priv, dma_addr_t *src_address,
+				 int nr, u32 dest_address, u32 len)
 {
-	u32 bytes_left = length;
-	u32 src_offset = 0;
-	u32 dest_offset = 0;
-	int status = 0;
+	int ret, i;
+	u32 size;
+
 	IPW_DEBUG_FW(">> \n");
-	IPW_DEBUG_FW_INFO("src_phys=0x%x dest_address=0x%x length=0x%x\n",
-			  src_phys, dest_address, length);
-	while (bytes_left > CB_MAX_LENGTH) {
-		status = ipw_fw_dma_add_command_block(priv,
-						      src_phys + src_offset,
-						      dest_address +
-						      dest_offset,
-						      CB_MAX_LENGTH, 0, 0);
-		if (status) {
+	IPW_DEBUG_FW_INFO("nr=%d dest_address=0x%x len=0x%x\n",
+			  nr, dest_address, len);
+
+	for (i = 0; i < nr; i++) {
+		size = min_t(u32, len - i * CB_MAX_LENGTH, CB_MAX_LENGTH);
+		ret = ipw_fw_dma_add_command_block(priv, src_address[i],
+						   dest_address +
+						   i * CB_MAX_LENGTH, size,
+						   0, 0);
+		if (ret) {
 			IPW_DEBUG_FW_INFO(": Failed\n");
 			return -1;
 		} else
 			IPW_DEBUG_FW_INFO(": Added new cb\n");
-
-		src_offset += CB_MAX_LENGTH;
-		dest_offset += CB_MAX_LENGTH;
-		bytes_left -= CB_MAX_LENGTH;
-	}
-
-	/* add the buffer tail */
-	if (bytes_left > 0) {
-		status =
-		    ipw_fw_dma_add_command_block(priv, src_phys + src_offset,
-						 dest_address + dest_offset,
-						 bytes_left, 0, 0);
-		if (status) {
-			IPW_DEBUG_FW_INFO(": Failed on the buffer tail\n");
-			return -1;
-		} else
-			IPW_DEBUG_FW_INFO
-			    (": Adding new cb - the buffer tail\n");
 	}
 
 	IPW_DEBUG_FW("<< \n");
@@ -3160,59 +3142,91 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len)
 
 static int ipw_load_firmware(struct ipw_priv *priv, u8 * data, size_t len)
 {
-	int rc = -1;
+	int ret = -1;
 	int offset = 0;
 	struct fw_chunk *chunk;
-	dma_addr_t shared_phys;
-	u8 *shared_virt;
+	int total_nr = 0;
+	int i;
+	struct pci_pool *pool;
+	u32 *virts[CB_NUMBER_OF_ELEMENTS_SMALL];
+	dma_addr_t phys[CB_NUMBER_OF_ELEMENTS_SMALL];
 
 	IPW_DEBUG_TRACE("<< : \n");
-	shared_virt = pci_alloc_consistent(priv->pci_dev, len, &shared_phys);
 
-	if (!shared_virt)
+	pool = pci_pool_create("ipw2200", priv->pci_dev, CB_MAX_LENGTH, 0, 0);
+	if (!pool) {
+		IPW_ERROR("pci_pool_create failed\n");
 		return -ENOMEM;
-
-	memmove(shared_virt, data, len);
+	}
 
 	/* Start the Dma */
-	rc = ipw_fw_dma_enable(priv);
+	ret = ipw_fw_dma_enable(priv);
 
 	/* the DMA is already ready this would be a bug. */
 	BUG_ON(priv->sram_desc.last_cb_index > 0);
 
 	do {
+		u32 chunk_len;
+		u8 *start;
+		int size;
+		int nr = 0;
+
 		chunk = (struct fw_chunk *)(data + offset);
 		offset += sizeof(struct fw_chunk);
+		chunk_len = le32_to_cpu(chunk->length);
+		start = data + offset;
+
+		nr = (chunk_len + CB_MAX_LENGTH - 1) / CB_MAX_LENGTH;
+		for (i = 0; i < nr; i++) {
+			virts[total_nr] = pci_pool_alloc(pool, GFP_KERNEL,
+							 &phys[total_nr]);
+			if (!virts[total_nr]) {
+				ret = -ENOMEM;
+				goto out;
+			}
+			size = min_t(u32, chunk_len - i * CB_MAX_LENGTH,
+				     CB_MAX_LENGTH);
+			memcpy(virts[total_nr], start, size);
+			start += size;
+			total_nr++;
+			/* We don't support fw chunk larger than 64*8K */
+			BUG_ON(total_nr > CB_NUMBER_OF_ELEMENTS_SMALL);
+		}
+
 		/* build DMA packet and queue up for sending */
 		/* dma to chunk->address, the chunk->length bytes from data +
 		 * offeset*/
 		/* Dma loading */
-		rc = ipw_fw_dma_add_buffer(priv, shared_phys + offset,
-					   le32_to_cpu(chunk->address),
-					   le32_to_cpu(chunk->length));
-		if (rc) {
+		ret = ipw_fw_dma_add_buffer(priv, &phys[total_nr - nr],
+					    nr, le32_to_cpu(chunk->address),
+					    chunk_len);
+		if (ret) {
 			IPW_DEBUG_INFO("dmaAddBuffer Failed\n");
 			goto out;
 		}
 
-		offset += le32_to_cpu(chunk->length);
+		offset += chunk_len;
 	} while (offset < len);
 
 	/* Run the DMA and wait for the answer */
-	rc = ipw_fw_dma_kick(priv);
-	if (rc) {
+	ret = ipw_fw_dma_kick(priv);
+	if (ret) {
 		IPW_ERROR("dmaKick Failed\n");
 		goto out;
 	}
 
-	rc = ipw_fw_dma_wait(priv);
-	if (rc) {
+	ret = ipw_fw_dma_wait(priv);
+	if (ret) {
 		IPW_ERROR("dmaWaitSync Failed\n");
 		goto out;
 	}
-      out:
-	pci_free_consistent(priv->pci_dev, len, shared_virt, shared_phys);
-	return rc;
+ out:
+	for (i = 0; i < total_nr; i++)
+		pci_pool_free(pool, virts[i], phys[i]);
+
+	pci_pool_destroy(pool);
+
+	return ret;
 }
 
 /* stop nic */
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply related

* pull request: wireless-next-2.6 2009-08-28
From: John W. Linville @ 2009-08-28 19:11 UTC (permalink / raw)
  To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
  Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA

Dave,

Another huge batch of updates/changes/etc intended for 2.6.32...  This
includes the usual driver updates and miscellaneous fixes, etc.
Highlights in this batch include more LP-PHY support for b43 and the
completion of the cfg80211 API conversion for rndis_wlan.

Please let me know if there are problems!

Thanks,

John

---

Individual patches are available here:

	http://www.kernel.org/pub/linux/kernel/people/linville/wireless-next-2.6/

---

The following changes since commit 7c6a3ed5bd61ec981c8a0d0111cfd435adf3f2b7:
  Ursula Braun (1):
        qeth: display "undefined" value of sysfs-attribute "layer2"

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6.git master

Abhijeet Kolekar (1):
      iwlwifi: fix remove key error

Arnd Hannemann (2):
      mac80211: Remove unnused throughput field from minstrel_rate.
      mac80211: Fix output of minstrels rc_stats

Bob Copeland (4):
      ath5k: clean up filter flags setting
      ath5k: use the skb->cb directly for RX status
      ath5k: add hardware CCMP encyption support
      ath5k: clarify srev comparison for CCMP check

Christian Lamparter (1):
      p54: fix broadcast buffering in AP mode

Dan Williams (1):
      libertas: clean up and clarify get_common_rates

Daniel C Halperin (2):
      iwlwifi: clear rate control flags on non-HT packet
      iwlwifi: set HT flags in ieee80211_rx_status for received packets

Gábor Stefanik (8):
      iwlwifi: Make injection of non-broadcast frames work again
      b43: LP-PHY: Fix a few typos in the RC calibration code
      b43: LP-PHY: Fix and simplify Qdiv roundup
      b43: Fix and update LP-PHY code
      ssb: Implement PMU LDO control and use it in b43
      b43: LP-PHY: Revert to the original PHY register write routine
      b43: Enable LP-PHY support by default and remove Kconfig warning
      b43: Implement antenna diversity support for LP-PHY

Herton Ronaldo Krzesinski (2):
      rtl8187: fix circular locking (rtl8187_stop/rtl8187_work)
      rtl8187: Implement rfkill support

Ivo van Doorn (1):
      rt2x00: Cleanup rt2x00mac_bss_info_changed()

Jaswinder Singh Rajput (1):
      PRISM54: fix compilation warning

Javier Cardona (2):
      mac80211: Update mesh config IE to 11s draft 3.02
      ath9k: Add support FIF_OTHER_BSS filtering mode.

Joerg Albert (2):
      ar9170: cleanup of bss_info_changed and beacon config
      ar9170: remove unnecessary call to ar9170_set_beacon_timers

Johannes Berg (8):
      mac80211: fix configure_filter invocation after stop
      cfg80211: check lost scans later, fix bug
      cfg80211: make spurious warnings less likely, configurable
      cfg80211: clean up properly on interface type change
      mac80211: remove tasklet enable/disable
      mac80211: fix RX skb leaks
      mac80211: fix scan cancel on ifdown
      iwlwifi: fix ICT irq table endianness

John W. Linville (3):
      libipw: switch from ieee80211_* to libipw_* naming policy
      mac80211: remove ieee80211_rx namespace hack
      libipw: initiate cfg80211 API conversion

Jouni Malinen (1):
      mac80211: Check pending scan request after having processed mgd work

Jussi Kivilinna (20):
      rndis_wlan: fix broken logic in add_wep_key()
      rndis_wlan: set cipher suites for cfg80211
      rndis_wlan: ignore OID_802_11_ADD_KEY triggered media connect indications
      rndis_wlan: get bssid scan list before new scan
      rndis_wlan: resize bssid list if too small
      rndis_wlan: increase scan timer delay
      rndis_wlan: move link up/down work to separate functions
      rndis_wlan: use is_zero_ether_addr() and is_broadcast_ether_addr()
      rndis_wlan: set ieee80211_ptr->iftype in rndis_change_virtual_intf
      rndis_wlan: enable infrastructure before setting random essid
      rndis_wlan: add cfg80211 connect, disconnect, join_ibss and leave_ibss
      rndis_wlan: add cfg80211 set_channel
      rndis_wlan: add cfg80211 key handling
      rndis_wlan: add cfg80211 get_station
      rndis_wlan: add cfg80211 dump_station
      rndis_wlan: rename wireless stats worker to device poller
      rndis_wlan: remove unneeded SIOCSIWCOMMIT
      rndis_wlan: convert mic failure wireless event to cfg80211
      rndis_wlan: disable IWEVPMKIDCAND wireless event
      rndis_wlan: use cfg80211_wext_handler

Kiran Divekar (1):
      libertas: add NULL check on return value of get_zeroed_page

Lennert Buytenhek (4):
      mwl8k: fix inverted error test in mwl8k_bss_info_changed()
      mwl8k: fix pci dma mapping leak in mwl8k_post_cmd() error path
      mwl8k: missing endian conversion when printing firmware command result
      mwl8k: separate driver and device info reporting during probe

Marcos Chaparro (1):
      ath5k: add led pin configuration for compaq c700 laptop

Marek Vasut (1):
      libertas: Add support for Marvell Libertas CF8305

Pavel Roskin (2):
      ath5k: fix uninitialized value use in ath5k_eeprom_read_turbo_modes()
      ath5k: don't use PCI ID to find the chip revision

Reinette Chatre (2):
      ipw2x00: update contact information
      MAINTAINERS: Update ipw2x00 and iwlwifi entries

Roel Kluin (3):
      libertas: Read buffer overflow
      nl80211: jump to out_err upon unsupported iftype
      ath9k: Fix read buffer overflow

Sujith (6):
      ath9k: Fix chainmask selection during scanning
      ath9k: Reduce the frequency of PA offset calibration
      ath9k: Fix bugs in programming registers during PA CAL
      ath9k: Handle PA cal usage properly
      ath9k: Update INITVALs for AR9285
      ath9k: Wrap DMA dump function with PS wakeup/restore

Vasanthakumar Thiagarajan (8):
      ath9k: Split ath9k_hw_btcoex_enable() into two logical pieces
      ath9k: Move btcoex stuff from hw.[ch] to new btcoex.[ch]
      ath9k: Configure btcoex register during every reset
      ath9k: Move btcoex related data to a separate struct
      ath9k: Determine btcoex scheme type based on chip version
      ath9k: Remove hw capability bit meant for btcoex
      ath9k: Add infrastructure for generic hw timers
      ath9k: Add Bluetooth Coexistence 3-wire support

Wey-Yi Guy (9):
      iwlwifi: set default tx power user limit to minimal
      iwlwifi: do not allow set tx power over channel power limit
      iwlwifi: name changes from "tx_power_channel_lmt" to "tx_power_device_lmt"
      iwlwifi: error checking for setting tx_power in sysfs
      iwlwifi: change IWL6000_UCODE_API_MAX to v4
      iwlwifi: show current tx power
      iwlwifi: remove duplicated define
      iwlwifi: read enhanced tx power info from EEPROM image
      iwlwifi: fix unloading driver while scanning

 MAINTAINERS                                        |   14 +-
 drivers/net/wireless/ath/ar9170/ar9170.h           |    1 +
 drivers/net/wireless/ath/ar9170/mac.c              |   24 +-
 drivers/net/wireless/ath/ar9170/main.c             |   20 +-
 drivers/net/wireless/ath/ath5k/ath5k.h             |    4 +-
 drivers/net/wireless/ath/ath5k/attach.c            |   21 +-
 drivers/net/wireless/ath/ath5k/base.c              |  121 +-
 drivers/net/wireless/ath/ath5k/eeprom.c            |   29 +-
 drivers/net/wireless/ath/ath5k/led.c               |    2 +
 drivers/net/wireless/ath/ath9k/Makefile            |    3 +-
 drivers/net/wireless/ath/ath9k/ath9k.h             |    5 +
 drivers/net/wireless/ath/ath9k/btcoex.c            |  319 +++++
 drivers/net/wireless/ath/ath9k/btcoex.h            |   98 ++
 drivers/net/wireless/ath/ath9k/calib.c             |   35 +-
 drivers/net/wireless/ath/ath9k/calib.h             |    7 +
 drivers/net/wireless/ath/ath9k/debug.c             |    4 +
 drivers/net/wireless/ath/ath9k/debug.h             |    2 +
 drivers/net/wireless/ath/ath9k/eeprom.c            |   16 +-
 drivers/net/wireless/ath/ath9k/hw.c                |  239 +++-
 drivers/net/wireless/ath/ath9k/hw.h                |   58 +-
 drivers/net/wireless/ath/ath9k/initvals.h          |   10 +-
 drivers/net/wireless/ath/ath9k/main.c              |   40 +-
 drivers/net/wireless/ath/ath9k/recv.c              |    7 +-
 drivers/net/wireless/ath/ath9k/reg.h               |   64 +-
 drivers/net/wireless/ath/ath9k/xmit.c              |    9 +-
 drivers/net/wireless/b43/Kconfig                   |    4 +-
 drivers/net/wireless/b43/main.c                    |    3 +-
 drivers/net/wireless/b43/phy_a.c                   |    2 +-
 drivers/net/wireless/b43/phy_common.c              |   27 +-
 drivers/net/wireless/b43/phy_common.h              |   13 +-
 drivers/net/wireless/b43/phy_g.c                   |    2 +-
 drivers/net/wireless/b43/phy_lp.c                  |  129 +-
 drivers/net/wireless/b43/phy_lp.h                  |    3 +
 drivers/net/wireless/b43/tables_lpphy.c            |   79 +-
 drivers/net/wireless/ipw2x00/ipw2100.c             |  206 ++--
 drivers/net/wireless/ipw2x00/ipw2100.h             |   16 +-
 drivers/net/wireless/ipw2x00/ipw2200.c             | 1043 ++++++++-------
 drivers/net/wireless/ipw2x00/ipw2200.h             |   16 +-
 .../net/wireless/ipw2x00/{ieee80211.h => libipw.h} |  666 +++++-----
 drivers/net/wireless/ipw2x00/libipw_geo.c          |   82 +-
 drivers/net/wireless/ipw2x00/libipw_module.c       |  124 ++-
 drivers/net/wireless/ipw2x00/libipw_rx.c           |  403 +++---
 drivers/net/wireless/ipw2x00/libipw_tx.c           |   70 +-
 drivers/net/wireless/ipw2x00/libipw_wx.c           |   94 +-
 drivers/net/wireless/iwlwifi/iwl-6000.c            |    5 +-
 drivers/net/wireless/iwlwifi/iwl-agn-rs.c          |    1 +
 drivers/net/wireless/iwlwifi/iwl-agn.c             |   15 +-
 drivers/net/wireless/iwlwifi/iwl-commands.h        |   19 +-
 drivers/net/wireless/iwlwifi/iwl-core.c            |   55 +-
 drivers/net/wireless/iwlwifi/iwl-debug.h           |    1 +
 drivers/net/wireless/iwlwifi/iwl-debugfs.c         |   54 +
 drivers/net/wireless/iwlwifi/iwl-dev.h             |    4 +-
 drivers/net/wireless/iwlwifi/iwl-eeprom.c          |  252 ++++
 drivers/net/wireless/iwlwifi/iwl-eeprom.h          |   80 ++-
 drivers/net/wireless/iwlwifi/iwl-rx.c              |   10 +
 drivers/net/wireless/iwlwifi/iwl-scan.c            |    3 +-
 drivers/net/wireless/iwlwifi/iwl-sta.c             |    2 +-
 drivers/net/wireless/iwlwifi/iwl-tx.c              |   10 +-
 drivers/net/wireless/iwlwifi/iwl3945-base.c        |    9 +-
 drivers/net/wireless/libertas/assoc.c              |   57 +-
 drivers/net/wireless/libertas/debugfs.c            |   28 +
 drivers/net/wireless/libertas/if_cs.c              |   39 +-
 drivers/net/wireless/mwl8k.c                       |   30 +-
 drivers/net/wireless/p54/txrx.c                    |    3 +
 drivers/net/wireless/prism54/islpci_eth.c          |    4 +-
 drivers/net/wireless/rndis_wlan.c                  | 1411 +++++++++-----------
 drivers/net/wireless/rt2x00/rt2x00mac.c            |    8 -
 drivers/net/wireless/rtl818x/Makefile              |    2 +-
 drivers/net/wireless/rtl818x/rtl8187.h             |    1 +
 drivers/net/wireless/rtl818x/rtl8187_dev.c         |   31 +-
 drivers/net/wireless/rtl818x/rtl8187_leds.c        |    4 +-
 drivers/net/wireless/rtl818x/rtl8187_rfkill.c      |   63 +
 drivers/net/wireless/rtl818x/rtl8187_rfkill.h      |    8 +
 drivers/net/wireless/rtl818x/rtl818x.h             |    5 +-
 drivers/ssb/driver_chipcommon_pmu.c                |   94 ++
 include/linux/ieee80211.h                          |    2 +-
 include/linux/ssb/ssb_driver_chipcommon.h          |   10 +
 include/net/iw_handler.h                           |    6 +-
 include/net/mac80211.h                             |   11 +-
 net/mac80211/driver-ops.h                          |   14 +-
 net/mac80211/ieee80211_i.h                         |    8 +
 net/mac80211/iface.c                               |   41 +-
 net/mac80211/main.c                                |    2 -
 net/mac80211/mesh.c                                |   49 +-
 net/mac80211/mlme.c                                |   28 +-
 net/mac80211/pm.c                                  |   13 +-
 net/mac80211/rc80211_minstrel.h                    |    1 -
 net/mac80211/rc80211_minstrel_debugfs.c            |    2 +-
 net/mac80211/rx.c                                  |   39 +-
 net/mac80211/scan.c                                |    9 +-
 net/mac80211/util.c                                |   10 +
 net/wireless/Kconfig                               |   17 +
 net/wireless/core.c                                |   58 +-
 net/wireless/core.h                                |   17 +-
 net/wireless/ibss.c                                |    4 +-
 net/wireless/nl80211.c                             |   18 +-
 net/wireless/scan.c                                |   21 +-
 net/wireless/sme.c                                 |   12 +-
 net/wireless/util.c                                |  108 ++
 net/wireless/wext-compat.c                         |   16 +-
 100 files changed, 4299 insertions(+), 2659 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath9k/btcoex.c
 create mode 100644 drivers/net/wireless/ath/ath9k/btcoex.h
 rename drivers/net/wireless/ipw2x00/{ieee80211.h => libipw.h} (54%)
 create mode 100644 drivers/net/wireless/rtl818x/rtl8187_rfkill.c
 create mode 100644 drivers/net/wireless/rtl818x/rtl8187_rfkill.h

Omnibus patch available here:

	http://www.kernel.org/pub/linux/kernel/people/linville/wireless-next-2.6-2009-08-20.patch.bz2

-- 
John W. Linville		Someday the world will need a hero, and you
linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org			might be all we have.  Be ready.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" 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: [linux-pm] power draw depending on PHY speed
From: Rafael J. Wysocki @ 2009-08-28 19:03 UTC (permalink / raw)
  To: Leisner, Martin; +Cc: linux-pm, martyleisner, NetDEV list
In-Reply-To: <76FA3B279DD9DA48896E2B40494495720368E449@USA7061MS02.na.xerox.net>

On Friday 28 August 2009, Leisner, Martin wrote:
> While doing some current probe measurements (i.e. to measure the effects
> of NAP and frequency scaling with a freescale processor) I noticed some
> very
> significant differents if we ran on 100Mbit of 1000Mbit ethernet.
> 
> The hardware guys like at their data sheets and agreed.
> 
> Does anyone "drop ethernet speed" to save power?
> (when a system is idle, is isn't necessary to run 1G ethernet).

I don't know, really.  This is a netdev question IMO (CC added).

> When a system has WOL capability, what speed does it run at when the
> system is sleeping?

That's a very good question.  I bet that depends on the NIC in question, at
least I'm not sure if any spec regulates it.

Thanks,
Rafael

^ permalink raw reply

* [PATCH 9/9] fanotify: send events to userspace over socket reads
From: Eric Paris @ 2009-08-28 18:56 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, netdev; +Cc: davem, viro, alan, hch
In-Reply-To: <20090828185542.8014.22791.stgit@paris.rdu.redhat.com>

fanotify sends event notification to userspace when userspace reads from the
fanotify socket. This patch implements the operations that happen at read
time.  These include opening the file descriptor to the original object and
then filling the userspace buffer.  The fd should be pollable to indicate when
it has data present and it should return how much data it has to send when the
FIONREAD ioctl is checked.

Signed-off-by: Eric Paris <eparis@redhat.com>
---

 fs/notify/fanotify/af_fanotify.c |  230 ++++++++++++++++++++++++++++++++++++++
 fs/notify/fanotify/fanotify.h    |    5 +
 include/linux/fanotify.h         |   22 ++++
 3 files changed, 255 insertions(+), 2 deletions(-)

diff --git a/fs/notify/fanotify/af_fanotify.c b/fs/notify/fanotify/af_fanotify.c
index ac6aee1..cefd108 100644
--- a/fs/notify/fanotify/af_fanotify.c
+++ b/fs/notify/fanotify/af_fanotify.c
@@ -2,6 +2,7 @@
 #include <linux/fdtable.h>
 #include <linux/file.h>
 #include <linux/fsnotify_backend.h>
+#include <linux/ima.h> /* ima_path_check */
 #include <linux/init.h>
 #include <linux/kernel.h> /* UINT_MAX */
 #include <linux/mount.h> /* mntget() */
@@ -16,6 +17,8 @@
 #include "fanotify.h"
 #include "af_fanotify.h"
 
+#include <asm/ioctls.h>
+
 static const struct proto_ops fanotify_proto_ops;
 static struct kmem_cache *fanotify_mark_cache __read_mostly;
 
@@ -114,6 +117,36 @@ static int fan_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
 	return 0;
 }
 
+static int fan_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+	struct fanotify_sock *fan_sock;
+	struct fsnotify_group *group;
+	struct fsnotify_event_holder *holder;
+	void __user *p;
+	int ret = -ENOTTY;
+	size_t send_len = 0;
+
+	if (sock->state != SS_CONNECTED)
+		return -EBADF;
+
+	fan_sock = fan_sk(sock->sk);
+	group = fan_sock->group;
+
+	p = (void __user *) arg;
+
+	switch (cmd) {
+	case FIONREAD:
+		mutex_lock(&group->notification_mutex);
+		list_for_each_entry(holder, &group->notification_list, event_list)
+			send_len += FAN_EVENT_METADATA_LEN;
+		mutex_unlock(&group->notification_mutex);
+		ret = put_user(send_len, (int __user *) p);
+		break;
+	}
+
+	return ret;
+}
+
 static void fanotify_free_mark(struct fsnotify_mark_entry *entry)
 {
 	kmem_cache_free(fanotify_mark_cache, entry);
@@ -278,6 +311,199 @@ static int fan_setsockopt(struct socket *sock, int level, int optname,
 	return ret;
 }
 
+/*
+ * Get an fsnotify notification event if one exists and is small
+ * enough to fit in "count". Return an error pointer if the count
+ * is not large enough.
+ *
+ * Called with the group->notification_mutex held.
+ */
+static struct fsnotify_event *get_one_event(struct fsnotify_group *group,
+					    size_t count)
+{
+	BUG_ON(!mutex_is_locked(&group->notification_mutex));
+
+	if (fsnotify_notify_queue_is_empty(group))
+		return NULL;
+
+	if (FAN_EVENT_METADATA_LEN > count)
+		return ERR_PTR(-EINVAL);
+
+	/* held the notification_mutex the whole time, so this is the
+	 * same event we peeked above */
+	return fsnotify_remove_notify_event(group);
+}
+
+static int create_and_fill_fd(struct fsnotify_group *group,
+			      struct fanotify_event_metadata *metadata,
+			      struct fsnotify_event *event)
+{
+	int client_fd, err;
+	struct dentry *dentry;
+	struct vfsmount *mnt;
+	struct file *new_file;
+
+	client_fd = get_unused_fd();
+	if (client_fd < 0)
+		return client_fd;
+
+	if (event->data_type != FSNOTIFY_EVENT_PATH) {
+		WARN_ON(1);
+		put_unused_fd(client_fd);
+		return -EINVAL;
+	}
+
+	/*
+	 * we need a new file handle for the userspace program so it can read even if it was
+	 * originally opened O_WRONLY.
+	 */
+	dentry = dget(event->path.dentry);
+	mnt = mntget(event->path.mnt);
+	/* it's possible this event was an overflow event.  in that case dentry and mnt
+	 * are NULL;  That's fine, just don't call dentry open */
+	if (dentry && mnt) {
+		err = ima_path_check(&event->path, MAY_READ, IMA_COUNT_UPDATE);
+		if (err)
+			new_file = ERR_PTR(err);
+		else {
+			current->flags |= PF_NONOTIFY;
+			new_file = dentry_open(dentry, mnt, O_RDONLY | O_LARGEFILE,
+					       current_cred());
+			current->flags &= ~PF_NONOTIFY;
+		}
+	} else
+		new_file = ERR_PTR(-EOVERFLOW);
+	if (IS_ERR(new_file)) {
+		/*
+		 * we still send an event even if we can't open the file.  this
+		 * can happen when say tasks are gone and we try to open their
+		 * /proc entries or we try to open a WRONLY file like in sysfs
+		 * we just send the errno to userspace since there isn't much
+		 * else we can do.
+		 */
+		put_unused_fd(client_fd);
+		client_fd = PTR_ERR(new_file);
+	} else {
+		new_file->f_mode |= FMODE_NONOTIFY;
+		fd_install(client_fd, new_file);
+	}
+
+	metadata->fd = client_fd;
+
+	return 0;
+}
+
+static ssize_t fill_event_metadata(struct fsnotify_group *group,
+				   struct fanotify_event_metadata *metadata,
+				   struct fsnotify_event *event)
+{
+	pr_debug("%s: \n", __func__);
+
+	metadata->event_len = FAN_EVENT_METADATA_LEN;
+	metadata->mask = fanotify_outgoing_mask(event->mask);
+
+	return create_and_fill_fd(group, metadata, event);
+
+}
+
+static ssize_t copy_event_to_iov(struct fsnotify_group *group,
+				 struct fsnotify_event *event,
+				 struct iovec *iov)
+{
+	struct fanotify_event_metadata fanotify_event_metadata;
+	int ret;
+
+	pr_debug("%s: \n", __func__);
+
+	ret = fill_event_metadata(group, &fanotify_event_metadata, event);
+	if (ret)
+		return ret;
+
+	/* send the main event */
+	ret = memcpy_toiovec(iov, (unsigned char *)&fanotify_event_metadata,
+			     FAN_EVENT_METADATA_LEN);
+	if (ret < 0)
+		return ret;
+
+	return FAN_EVENT_METADATA_LEN;
+}
+
+static ssize_t fan_recv_events(struct fsnotify_group *group, struct msghdr *msg,
+				int count, int nonblock)
+{
+	struct fsnotify_event *event;
+	int ret, len_sent = 0;
+	DEFINE_WAIT(wait);
+
+	pr_debug("%s: \n", __func__);
+
+	while (1) {
+		prepare_to_wait(&group->notification_waitq, &wait, TASK_INTERRUPTIBLE);
+
+		mutex_lock(&group->notification_mutex);
+		event = get_one_event(group, count);
+		mutex_unlock(&group->notification_mutex);
+
+		if (event) {
+			ret = PTR_ERR(event);
+			if (IS_ERR(event))
+				break;
+
+			ret = copy_event_to_iov(group, event, msg->msg_iov);
+			fsnotify_put_event(event);
+			if (ret < 0)
+				break;
+			len_sent += ret;
+			count -= ret;
+			continue;
+		}
+
+		ret = -EAGAIN;
+		if (nonblock)
+			break;
+		ret = -EINTR;
+		if (signal_pending(current))
+			break;
+
+		if (len_sent)
+			break;
+
+		schedule();
+	}
+
+	finish_wait(&group->notification_waitq, &wait);
+	if (len_sent && ret != -EFAULT)
+		ret = len_sent;
+	return ret;
+}
+
+static int fan_recvmsg(struct kiocb *iocb, struct socket *sock,
+		       struct msghdr *msg, size_t size, int flags)
+{
+	struct fanotify_sock *fan_sock;
+	struct fsnotify_group *group;
+	int nonblock;
+
+	pr_debug("%s: \n", __func__);
+
+	if (sock->state != SS_CONNECTED)
+		return -EBADF;
+
+	if (size < FAN_EVENT_METADATA_LEN)
+		return -ENOMEM;
+
+	fan_sock = fan_sk(sock->sk);
+	group = fan_sock->group;
+
+	/* hey, nonblock no matter how they ask */
+	nonblock = !!(sock->file->f_flags & O_NONBLOCK);
+	nonblock |= !!(flags & MSG_DONTWAIT);
+
+	size = fan_recv_events(group, msg, size, nonblock);
+
+	return size;
+}
+
 static const struct net_proto_family fanotify_family_ops = {
 	.family		=	PF_FANOTIFY,
 	.create		=	fan_sock_create,
@@ -294,13 +520,13 @@ static const struct proto_ops fanotify_proto_ops = {
 	.accept =	sock_no_accept,
 	.getname =	sock_no_getname,
 	.poll =		sock_no_poll,
-	.ioctl =	sock_no_ioctl,
+	.ioctl =	fan_ioctl,
 	.listen =	sock_no_listen,
 	.shutdown =	sock_no_shutdown,
 	.setsockopt =	fan_setsockopt,
 	.getsockopt =	sock_no_getsockopt,
 	.sendmsg =	sock_no_sendmsg,
-	.recvmsg =	sock_no_recvmsg,
+	.recvmsg =	fan_recvmsg,
 	.mmap =		sock_no_mmap,
 	.sendpage =	sock_no_sendpage,
 };
diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
index 6c7bf06..4a5c785 100644
--- a/fs/notify/fanotify/fanotify.h
+++ b/fs/notify/fanotify/fanotify.h
@@ -12,3 +12,8 @@ static inline bool fanotify_is_mask_valid(__u32 mask)
 		return false;
 	return true;
 }
+
+static inline __u32 fanotify_outgoing_mask(__u32 mask)
+{
+	return mask & FAN_ALL_OUTGOING_EVENTS;
+}
diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h
index db96dd8..f44a668 100644
--- a/include/linux/fanotify.h
+++ b/include/linux/fanotify.h
@@ -35,6 +35,10 @@
  */
 #define FAN_ALL_INCOMING_EVENTS	(FAN_ALL_EVENTS |\
 				 FAN_EVENT_ON_CHILD)
+
+#define FAN_ALL_OUTGOING_EVENTS	(FAN_ALL_EVENTS |\
+				 FAN_Q_OVERFLOW)
+
 #ifndef SOL_FANOTIFY
 #define SOL_FANOTIFY	278
 #endif
@@ -63,6 +67,24 @@ struct fanotify_so_inode_mark {
 #define FANOTIFY_SET_MARK	1
 #define FANOTIFY_REMOVE_MARK	2
 
+struct fanotify_event_metadata {
+	__u32 event_len;
+	__s32 fd;
+	__u32 mask;
+}  __attribute__((packed));
+
+
+/* Helper functions to deal with fanotify_event_metadata buffers */
+#define FAN_EVENT_METADATA_LEN	(sizeof(struct fanotify_event_metadata))
+
+#define FAN_EVENT_NEXT(meta, len) ((len) -= (meta)->event_len, \
+				   (struct fanotify_event_metadata*)(((char *)(meta)) + \
+				   (meta)->event_len))
+
+#define FAN_EVENT_OK(meta, len)	((long)(len) >= (long)FAN_EVENT_METADATA_LEN && \
+				 (long)(meta)->event_len >= (long)FAN_EVENT_METADATA_LEN && \
+				 (long)(meta)->event_len <= (long)(len))
+
 #ifdef __KERNEL__
 
 #endif /* __KERNEL__ */


^ permalink raw reply related

* [PATCH 8/9] fanotify: userspace can add and remove fsnotify inode marks
From: Eric Paris @ 2009-08-28 18:56 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, netdev; +Cc: davem, viro, alan, hch
In-Reply-To: <20090828185542.8014.22791.stgit@paris.rdu.redhat.com>

Using setsockopt a user can add or remove fsnotify marks on inodes.  These
marks are used to determine which events for which inode are to be sent to
userspace.  They are very similar in nature to inotify_add_watch and
inotify_rm_watch.

Signed-off-by: Eric Paris <eparis@redhat.com>
---

 fs/notify/fanotify/af_fanotify.c |  169 ++++++++++++++++++++++++++++++++++++++
 include/linux/fanotify.h         |   10 ++
 2 files changed, 178 insertions(+), 1 deletions(-)

diff --git a/fs/notify/fanotify/af_fanotify.c b/fs/notify/fanotify/af_fanotify.c
index d7bf658..ac6aee1 100644
--- a/fs/notify/fanotify/af_fanotify.c
+++ b/fs/notify/fanotify/af_fanotify.c
@@ -17,6 +17,7 @@
 #include "af_fanotify.h"
 
 static const struct proto_ops fanotify_proto_ops;
+static struct kmem_cache *fanotify_mark_cache __read_mostly;
 
 static struct proto fanotify_proto = {
 	.name     = "FANOTIFY",
@@ -113,6 +114,170 @@ static int fan_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
 	return 0;
 }
 
+static void fanotify_free_mark(struct fsnotify_mark_entry *entry)
+{
+	kmem_cache_free(fanotify_mark_cache, entry);
+}
+
+static int fanotify_remove_inode_mark(struct fsnotify_group *group,
+				      struct fanotify_so_inode_mark *so_inode_mark)
+{
+	struct fsnotify_mark_entry *entry;
+	struct file *file;
+	struct inode *inode;
+	int fput_needed, ret = 0;
+
+	ret = -EBADF;
+	file = fget_light(so_inode_mark->fd, &fput_needed);
+	if (!file)
+		goto out;
+
+	inode = file->f_path.dentry->d_inode;
+
+	spin_lock(&inode->i_lock);
+	entry = fsnotify_find_mark_entry(group, inode);
+	spin_unlock(&inode->i_lock);
+
+	ret = -ENOENT;
+	if (!entry)
+		goto out_fput;
+
+	ret = 0;
+
+	fsnotify_destroy_mark_by_entry(entry);
+
+	/* matches the fsnotify_find_mark_entry() */
+	fsnotify_put_mark(entry);
+
+	fsnotify_recalc_group_mask(group);
+out_fput:
+	fput_light(file, fput_needed);
+out:
+	return ret;
+}
+
+static int fanotify_add_inode_mark(struct fsnotify_group *group,
+				   struct fanotify_so_inode_mark *so_inode_mark)
+{
+	struct fsnotify_mark_entry *entry;
+	struct file *file;
+	struct inode *inode;
+	__u32 old_mask, new_mask;
+	int fput_needed, ret;
+
+	ret = -EINVAL;
+	if (!fanotify_is_mask_valid(so_inode_mark->mask))
+		goto out;
+
+	ret = -EBADF;
+	file = fget_light(so_inode_mark->fd, &fput_needed);
+	if (!file)
+		goto out;
+
+	inode = file->f_path.dentry->d_inode;
+
+	spin_lock(&inode->i_lock);
+	entry = fsnotify_find_mark_entry(group, inode);
+	spin_unlock(&inode->i_lock);
+
+	if (!entry) {
+		struct fsnotify_mark_entry *new_entry;
+
+		ret = -ENOMEM;
+		new_entry = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL);
+		if (!new_entry)
+			goto out_fput;
+
+		fsnotify_init_mark(new_entry, fanotify_free_mark);
+		ret = fsnotify_add_mark(new_entry, group, inode, 0);
+		if (ret) {
+			fanotify_free_mark(new_entry);
+			goto out_fput;
+		}
+
+		entry = new_entry;
+	}
+
+	ret = 0;
+
+	spin_lock(&entry->lock);
+	old_mask = entry->mask;
+	entry->mask |= so_inode_mark->mask;
+	new_mask = entry->mask;
+	spin_unlock(&entry->lock);
+
+	/* we made changes to a mask, update the group mask and the inode mask
+	 * so things happen quickly. */
+	if (old_mask != new_mask) {
+		/* more bits in old than in new? */
+		int dropped = (old_mask & ~new_mask);
+		/* more bits in this entry than the inode's mask? */
+		int do_inode = (new_mask & ~inode->i_fsnotify_mask);
+		/* more bits in this entry than the group? */
+		int do_group = (new_mask & ~group->mask);
+
+		/* update the inode with this new entry */
+		if (dropped || do_inode)
+			fsnotify_recalc_inode_mask(inode);
+
+		/* update the group mask with the new mask */
+		if (dropped || do_group)
+			fsnotify_recalc_group_mask(group);
+	}
+
+	/* match the init or the find.... */
+	fsnotify_put_mark(entry);
+
+out_fput:
+	fput_light(file, fput_needed);
+out:
+	return ret;
+}
+
+static int fan_setsockopt(struct socket *sock, int level, int optname,
+			  char __user *optval, int optlen)
+{
+	struct fanotify_sock *fan_sock;
+	struct fsnotify_group *group;
+	size_t copy_len;
+
+	union {
+		struct fanotify_so_inode_mark inode_mark;
+	} data;
+	int ret = 0;
+
+	if (sock->state != SS_CONNECTED)
+		return -EBADF;
+
+	if (level != SOL_FANOTIFY)
+		return -ENOPROTOOPT;
+
+	fan_sock = fan_sk(sock->sk);
+	group = fan_sock->group;
+
+	copy_len = min(optlen, (int)sizeof(data));
+	ret = copy_from_user(&data, optval, copy_len);
+	if (ret)
+		return ret;
+
+	switch (optname) {
+	case FANOTIFY_SET_MARK:
+	case FANOTIFY_REMOVE_MARK:
+		if (optlen < sizeof(struct fanotify_so_inode_mark))
+			return -ENOMEM;
+
+		if (optname == FANOTIFY_SET_MARK)
+			ret = fanotify_add_inode_mark(group, &data.inode_mark);
+		else if (optname == FANOTIFY_REMOVE_MARK)
+			ret = fanotify_remove_inode_mark(group, &data.inode_mark);
+		break;
+	default:
+		return -ENOPROTOOPT;
+	}
+
+	return ret;
+}
+
 static const struct net_proto_family fanotify_family_ops = {
 	.family		=	PF_FANOTIFY,
 	.create		=	fan_sock_create,
@@ -132,7 +297,7 @@ static const struct proto_ops fanotify_proto_ops = {
 	.ioctl =	sock_no_ioctl,
 	.listen =	sock_no_listen,
 	.shutdown =	sock_no_shutdown,
-	.setsockopt =	sock_no_setsockopt,
+	.setsockopt =	fan_setsockopt,
 	.getsockopt =	sock_no_getsockopt,
 	.sendmsg =	sock_no_sendmsg,
 	.recvmsg =	sock_no_recvmsg,
@@ -142,6 +307,8 @@ static const struct proto_ops fanotify_proto_ops = {
 
 static int __init fanotify_init(void)
 {
+	fanotify_mark_cache = KMEM_CACHE(fsnotify_mark_entry, SLAB_PANIC);
+
 	if (proto_register(&fanotify_proto, 0))
 		panic("unable to register fanotify protocol with network stack\n");
 
diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h
index 31fa74d..db96dd8 100644
--- a/include/linux/fanotify.h
+++ b/include/linux/fanotify.h
@@ -53,6 +53,16 @@ struct fanotify_addr {
 	__u32 unused[16];
 }  __attribute__((packed));
 
+/* struct used for FANOTIFY_SET_MARK */
+struct fanotify_so_inode_mark {
+	__s32 fd;
+	__u32 mask;
+}  __attribute__((packed));
+
+/* fanotify setsockopt optvals */
+#define FANOTIFY_SET_MARK	1
+#define FANOTIFY_REMOVE_MARK	2
+
 #ifdef __KERNEL__
 
 #endif /* __KERNEL__ */


^ permalink raw reply related

* [PATCH 6/9] fanotify: merge notification events with different masks
From: Eric Paris @ 2009-08-28 18:56 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, netdev; +Cc: davem, viro, alan, hch
In-Reply-To: <20090828185542.8014.22791.stgit@paris.rdu.redhat.com>

Instead of just merging fanotify events if they are exactly the same, merge
notification events with different masks.  To do this we have to clone the
old event, update the mask in the new event with the new merged mask, and
put the new event in place of the old event.

Signed-off-by: Eric Paris <eparis@redhat.com>
---

 fs/notify/fanotify/fanotify.c |   24 ++++++++++++++++++------
 1 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index caf34bb..e8e56cb 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -10,8 +10,7 @@
 
 static bool try_merge(struct fsnotify_event *old, struct fsnotify_event *new)
 {
-	if ((old->mask == new->mask) &&
-	    (old->to_tell == new->to_tell) &&
+	if ((old->to_tell == new->to_tell) &&
 	    (old->data_type == new->data_type)) {
 		switch (old->data_type) {
 		case (FSNOTIFY_EVENT_PATH):
@@ -29,15 +28,28 @@ static bool try_merge(struct fsnotify_event *old, struct fsnotify_event *new)
 
 static int fanotify_merge(struct list_head *list, struct fsnotify_event *event)
 {
-	struct fsnotify_event_holder *holder;
+	struct fsnotify_event_holder *test_holder, *prev;
 	struct fsnotify_event *test_event;
+	struct fsnotify_event *new_event;
+	int ret;
 
 	/* and the list better be locked by something too! */
 
-	list_for_each_entry_reverse(holder, list, event_list) {
-		test_event = holder->event;
-		if (try_merge(test_event, event))
+	list_for_each_entry_safe_reverse(test_holder, prev, list, event_list) {
+		test_event = test_holder->event;
+		if (try_merge(test_event, event)) {
+			if (test_event->mask == event->mask)
+				return -EEXIST;
+			new_event = fsnotify_clone_event(test_event);
+			if (!new_event)
+				return 0;
+			new_event->mask = (test_event->mask | event->mask);
+			ret = fsnotify_replace_event(test_holder, new_event);
+			fsnotify_put_event(new_event); /* matches the ref from clone */
+			if (ret)
+				return ret;
 			return -EEXIST;
+		}
 	}
 
 	return 0;


^ permalink raw reply related

* [PATCH 7/9] fanotify: userspace socket
From: Eric Paris @ 2009-08-28 18:56 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, netdev; +Cc: davem, viro, alan, hch
In-Reply-To: <20090828185542.8014.22791.stgit@paris.rdu.redhat.com>

This patch implements an userspace interface for the fanotify notification
system.  An fanotify socket is created in userspace and is 'bound' to an
address.  That bind call actually creates the new fanotify listener much like
inotify_init() creates an inotify instance.

Requests for notification of events on certain fs objects is done using a
setsockopt() call.  (not implemented in this patch)  This setsockopt() call is
largely analogous to inotify_add_watch()

Events are retrieved from the kernel calling read on the bound socket.
This interface is designed to be forward looking as the kernel/userspace
interaction can be changed simply by implementing a new getsockopt option.

Macros are provided much like the netlink macros in order to allow of the
messages from the kernel to userspace to change in length in the future while
maintaining backwards compatibility.

This patch only implements the socket registration and the bind call.  The
getsockopt() calls and data read call are implemented in later patches.

Signed-off-by: Eric Paris <eparis@redhat.com>
---

 fs/notify/fanotify/Makefile      |    2 -
 fs/notify/fanotify/af_fanotify.c |  152 ++++++++++++++++++++++++++++++++++++++
 fs/notify/fanotify/af_fanotify.h |   21 +++++
 fs/notify/fanotify/fanotify.h    |    2 +
 include/linux/fanotify.h         |   19 +++++
 5 files changed, 195 insertions(+), 1 deletions(-)
 create mode 100644 fs/notify/fanotify/af_fanotify.c
 create mode 100644 fs/notify/fanotify/af_fanotify.h

diff --git a/fs/notify/fanotify/Makefile b/fs/notify/fanotify/Makefile
index e7d39c0..1196005 100644
--- a/fs/notify/fanotify/Makefile
+++ b/fs/notify/fanotify/Makefile
@@ -1 +1 @@
-obj-$(CONFIG_FANOTIFY)		+= fanotify.o
+obj-$(CONFIG_FANOTIFY)		+= fanotify.o af_fanotify.o
diff --git a/fs/notify/fanotify/af_fanotify.c b/fs/notify/fanotify/af_fanotify.c
new file mode 100644
index 0000000..d7bf658
--- /dev/null
+++ b/fs/notify/fanotify/af_fanotify.c
@@ -0,0 +1,152 @@
+#include <linux/errno.h>
+#include <linux/fdtable.h>
+#include <linux/file.h>
+#include <linux/fsnotify_backend.h>
+#include <linux/init.h>
+#include <linux/kernel.h> /* UINT_MAX */
+#include <linux/mount.h> /* mntget() */
+#include <linux/net.h>
+#include <linux/skbuff.h>
+#include <linux/socket.h>
+#include <linux/types.h>
+
+#include <net/net_namespace.h>
+#include <net/sock.h>
+
+#include "fanotify.h"
+#include "af_fanotify.h"
+
+static const struct proto_ops fanotify_proto_ops;
+
+static struct proto fanotify_proto = {
+	.name     = "FANOTIFY",
+	.owner    = THIS_MODULE,
+	.obj_size = sizeof(struct fanotify_sock),
+};
+
+static int fan_sock_create(struct net *net, struct socket *sock, int protocol)
+{
+	struct sock *sk;
+	struct fanotify_sock *fan_sock;
+
+	/* FIXME maybe a new LSM hook? */
+	if (!capable(CAP_NET_RAW))
+		return -EPERM;
+
+	if (protocol != 0)
+		return -ESOCKTNOSUPPORT;
+
+	if (sock->type != SOCK_RAW)
+		return -ESOCKTNOSUPPORT;
+
+	sock->state = SS_UNCONNECTED;
+
+	sk = sk_alloc(net, PF_FANOTIFY, GFP_KERNEL, &fanotify_proto);
+	if (sk == NULL)
+		return -ENOBUFS;
+
+	sock->ops = &fanotify_proto_ops;
+
+	sock_init_data(sock, sk);
+
+	sk->sk_family = PF_FANOTIFY;
+	sk_refcnt_debug_inc(sk);
+
+	fan_sock = fan_sk(sk);
+	fan_sock->group = NULL;
+
+	return 0;
+}
+
+static int fan_release(struct socket *sock)
+{
+	struct sock *sk;
+	struct fanotify_sock *fan_sock;
+
+	sk = sock->sk;
+	if (!sk)
+		return 0;
+
+	fan_sock = fan_sk(sk);
+
+	if (sock->state == SS_CONNECTED) {
+		sock->state = SS_UNCONNECTED;
+		fsnotify_put_group(fan_sock->group);
+	}
+
+	fan_sock->group = NULL;
+
+	sock_orphan(sk);
+	sock->sk = NULL;
+
+	sk_refcnt_debug_release(sk);
+
+	sock_put(sk);
+
+	return 0;
+}
+
+static int fan_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
+{
+	struct fanotify_addr *fan_addr = (struct fanotify_addr *)addr;
+	struct fanotify_sock *fan_sock;
+
+	if (addr_len != sizeof(struct fanotify_addr))
+		return -EINVAL;
+
+	if (sock->state != SS_UNCONNECTED)
+		return -EINVAL;
+
+	if (!fanotify_is_mask_valid(fan_addr->mask))
+		return -EINVAL;
+
+	fan_sock = fan_sk(sock->sk);
+	fan_sock->group = fsnotify_obtain_group(fan_addr->mask, &fanotify_ops);
+
+	if (IS_ERR(fan_sock->group))
+		return PTR_ERR(fan_sock->group);
+
+	fan_sock->group->max_events = 16383;
+
+	sock->state = SS_CONNECTED;
+
+	return 0;
+}
+
+static const struct net_proto_family fanotify_family_ops = {
+	.family		=	PF_FANOTIFY,
+	.create		=	fan_sock_create,
+	.owner		=	THIS_MODULE,
+};
+
+static const struct proto_ops fanotify_proto_ops = {
+	.family =	PF_FANOTIFY,
+	.owner =	THIS_MODULE,
+	.release =	fan_release,
+	.bind =		fan_bind,
+	.connect =	sock_no_connect,
+	.socketpair =	sock_no_socketpair,
+	.accept =	sock_no_accept,
+	.getname =	sock_no_getname,
+	.poll =		sock_no_poll,
+	.ioctl =	sock_no_ioctl,
+	.listen =	sock_no_listen,
+	.shutdown =	sock_no_shutdown,
+	.setsockopt =	sock_no_setsockopt,
+	.getsockopt =	sock_no_getsockopt,
+	.sendmsg =	sock_no_sendmsg,
+	.recvmsg =	sock_no_recvmsg,
+	.mmap =		sock_no_mmap,
+	.sendpage =	sock_no_sendpage,
+};
+
+static int __init fanotify_init(void)
+{
+	if (proto_register(&fanotify_proto, 0))
+		panic("unable to register fanotify protocol with network stack\n");
+
+	sock_register(&fanotify_family_ops);
+
+	return 0;
+}
+device_initcall(fanotify_init);
diff --git a/fs/notify/fanotify/af_fanotify.h b/fs/notify/fanotify/af_fanotify.h
new file mode 100644
index 0000000..fff0e66
--- /dev/null
+++ b/fs/notify/fanotify/af_fanotify.h
@@ -0,0 +1,21 @@
+#ifndef _LINUX_AF_FANOTIFY_H
+#define _LINUX_AF_FANOTIFY_H
+
+#include <linux/fanotify.h>
+#include <net/sock.h>
+
+struct fanotify_sock {
+	struct sock		sock;
+	struct fsnotify_group	*group;
+};
+
+static inline struct fanotify_sock *fan_sk(struct sock *sock)
+{
+	struct fanotify_sock *fan_sock;
+
+	fan_sock = container_of(sock, struct fanotify_sock, sock);
+
+	return fan_sock;
+}
+
+#endif /* _LINUX_AF_NET_H */
diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
index a8785c1..6c7bf06 100644
--- a/fs/notify/fanotify/fanotify.h
+++ b/fs/notify/fanotify/fanotify.h
@@ -4,6 +4,8 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 
+extern const struct fsnotify_ops fanotify_ops;
+
 static inline bool fanotify_is_mask_valid(__u32 mask)
 {
 	if (mask & ~(FAN_ALL_INCOMING_EVENTS))
diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h
index b560f86..31fa74d 100644
--- a/include/linux/fanotify.h
+++ b/include/linux/fanotify.h
@@ -1,6 +1,7 @@
 #ifndef _LINUX_FANOTIFY_H
 #define _LINUX_FANOTIFY_H
 
+#include <linux/socket.h>
 #include <linux/types.h>
 
 /* the following events that user-space can register for */
@@ -34,6 +35,24 @@
  */
 #define FAN_ALL_INCOMING_EVENTS	(FAN_ALL_EVENTS |\
 				 FAN_EVENT_ON_CHILD)
+#ifndef SOL_FANOTIFY
+#define SOL_FANOTIFY	278
+#endif
+
+#ifndef AF_FANOTIFY
+#define AF_FANOTIFY	37
+#define PF_FANOTIFY	AF_FANOTIFY
+#endif
+
+struct fanotify_addr {
+	sa_family_t family;
+	__u32 priority; /* unused */
+	__u32 mask_hi; /* unused */
+	__u32 mask;
+	__u32 f_flags; /* unused */
+	__u32 unused[16];
+}  __attribute__((packed));
+
 #ifdef __KERNEL__
 
 #endif /* __KERNEL__ */

^ permalink raw reply related

* [PATCH 5/9] fanotify:drop notification if they exist in the outgoing queue
From: Eric Paris @ 2009-08-28 18:56 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, netdev; +Cc: davem, viro, alan, hch
In-Reply-To: <20090828185542.8014.22791.stgit@paris.rdu.redhat.com>

fanotify listeners get an open file descriptor to the object in question so
the ordering of operations is not as important as in other notification
systems.  inotify will drop events if the last event in the event FIFO is
the same as the current event.  This patch will drop fanotify events if
they are the same as another event anywhere in the event FIFO.

Signed-off-by: Eric Paris <eparis@redhat.com>
---

 fs/notify/fanotify/fanotify.c |   40 ++++++++++++++++++++++++++++++++++++++--
 1 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 59bc883..caf34bb 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -8,6 +8,40 @@
 
 #include "fanotify.h"
 
+static bool try_merge(struct fsnotify_event *old, struct fsnotify_event *new)
+{
+	if ((old->mask == new->mask) &&
+	    (old->to_tell == new->to_tell) &&
+	    (old->data_type == new->data_type)) {
+		switch (old->data_type) {
+		case (FSNOTIFY_EVENT_PATH):
+			if ((old->path.mnt == new->path.mnt) &&
+			    (old->path.dentry == new->path.dentry))
+				return true;
+		case (FSNOTIFY_EVENT_NONE):
+			return true;
+		default:
+			BUG();
+		};
+	}
+	return false;
+}
+
+static int fanotify_merge(struct list_head *list, struct fsnotify_event *event)
+{
+	struct fsnotify_event_holder *holder;
+	struct fsnotify_event *test_event;
+
+	/* and the list better be locked by something too! */
+
+	list_for_each_entry_reverse(holder, list, event_list) {
+		test_event = holder->event;
+		if (try_merge(test_event, event))
+			return -EEXIST;
+	}
+
+	return 0;
+}
 static int fanotify_handle_event(struct fsnotify_group *group, struct fsnotify_event *event)
 {
 	int ret;
@@ -20,8 +54,10 @@ static int fanotify_handle_event(struct fsnotify_group *group, struct fsnotify_e
 	BUILD_BUG_ON(FAN_EVENT_ON_CHILD != FS_EVENT_ON_CHILD);
 	BUILD_BUG_ON(FAN_Q_OVERFLOW != FS_Q_OVERFLOW);
 
-	ret = fsnotify_add_notify_event(group, event, NULL, NULL);
-
+	ret = fsnotify_add_notify_event(group, event, NULL, fanotify_merge);
+	/* -EEXIST means this event was merged with another, not that it was an error */
+	if (ret == -EEXIST)
+		ret = 0;
 	return ret;
 }
 


^ permalink raw reply related

* [PATCH 4/9] fanotify: fscking all notification system
From: Eric Paris @ 2009-08-28 18:56 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, netdev; +Cc: davem, viro, alan, hch
In-Reply-To: <20090828185542.8014.22791.stgit@paris.rdu.redhat.com>

fanotify is a novel file notification system which bases notification on
giving userspace both an event type (open, close, read, write) and an open
file descriptor to the object in question.  This should address a number of
races and problems with other notification systems like inotify and dnotify
and should allow the future implementation of blocking or access controlled
notification.  These are useful for on access scanners or hierachical storage
management schemes.

This patch just implements the basics of the fsnotify functions.

Signed-off-by: Eric Paris <eparis@redhat.com>
---

 fs/notify/Kconfig             |    1 
 fs/notify/Makefile            |    1 
 fs/notify/fanotify/Kconfig    |   11 +++++
 fs/notify/fanotify/Makefile   |    1 
 fs/notify/fanotify/fanotify.c |   90 +++++++++++++++++++++++++++++++++++++++++
 fs/notify/fanotify/fanotify.h |   12 +++++
 include/linux/Kbuild          |    1 
 include/linux/fanotify.h      |   40 ++++++++++++++++++
 8 files changed, 157 insertions(+), 0 deletions(-)
 create mode 100644 fs/notify/fanotify/Kconfig
 create mode 100644 fs/notify/fanotify/Makefile
 create mode 100644 fs/notify/fanotify/fanotify.c
 create mode 100644 fs/notify/fanotify/fanotify.h
 create mode 100644 include/linux/fanotify.h

diff --git a/fs/notify/Kconfig b/fs/notify/Kconfig
index dffbb09..22c629e 100644
--- a/fs/notify/Kconfig
+++ b/fs/notify/Kconfig
@@ -3,3 +3,4 @@ config FSNOTIFY
 
 source "fs/notify/dnotify/Kconfig"
 source "fs/notify/inotify/Kconfig"
+source "fs/notify/fanotify/Kconfig"
diff --git a/fs/notify/Makefile b/fs/notify/Makefile
index 0922cc8..396a387 100644
--- a/fs/notify/Makefile
+++ b/fs/notify/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_FSNOTIFY)		+= fsnotify.o notification.o group.o inode_mark.o
 
 obj-y			+= dnotify/
 obj-y			+= inotify/
+obj-y			+= fanotify/
diff --git a/fs/notify/fanotify/Kconfig b/fs/notify/fanotify/Kconfig
new file mode 100644
index 0000000..70631ed
--- /dev/null
+++ b/fs/notify/fanotify/Kconfig
@@ -0,0 +1,11 @@
+config FANOTIFY
+	bool "Filesystem wide access notification"
+	select FSNOTIFY
+	default y
+	---help---
+	   Say Y here to enable fanotify suport.  fanotify is a system wide
+	   file access notification interface.  Events are read from from a
+	   socket and in doing so an fd is created in the reading process
+	   which points to the same data as the one on which the event occured.
+
+	   If unsure, say Y.
diff --git a/fs/notify/fanotify/Makefile b/fs/notify/fanotify/Makefile
new file mode 100644
index 0000000..e7d39c0
--- /dev/null
+++ b/fs/notify/fanotify/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_FANOTIFY)		+= fanotify.o
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
new file mode 100644
index 0000000..59bc883
--- /dev/null
+++ b/fs/notify/fanotify/fanotify.c
@@ -0,0 +1,90 @@
+#include <linux/fdtable.h>
+#include <linux/fsnotify_backend.h>
+#include <linux/init.h>
+#include <linux/kernel.h> /* UINT_MAX */
+#include <linux/net.h> /* struct socket */
+#include <linux/sched.h> /* task_struct */
+#include <linux/types.h>
+
+#include "fanotify.h"
+
+static int fanotify_handle_event(struct fsnotify_group *group, struct fsnotify_event *event)
+{
+	int ret;
+
+	BUILD_BUG_ON(FAN_ACCESS != FS_ACCESS);
+	BUILD_BUG_ON(FAN_MODIFY != FS_MODIFY);
+	BUILD_BUG_ON(FAN_CLOSE_NOWRITE != FS_CLOSE_NOWRITE);
+	BUILD_BUG_ON(FAN_CLOSE_WRITE != FS_CLOSE_WRITE);
+	BUILD_BUG_ON(FAN_OPEN != FS_OPEN);
+	BUILD_BUG_ON(FAN_EVENT_ON_CHILD != FS_EVENT_ON_CHILD);
+	BUILD_BUG_ON(FAN_Q_OVERFLOW != FS_Q_OVERFLOW);
+
+	ret = fsnotify_add_notify_event(group, event, NULL, NULL);
+
+	return ret;
+}
+
+static bool fanotify_should_send_event(struct fsnotify_group *group, struct inode *inode,
+				       __u32 mask, void *data, int data_type)
+{
+	struct fsnotify_mark_entry *entry;
+	bool send;
+
+	/* if we are in an open operation do not send events to fanotify */
+	if (current->flags & PF_NONOTIFY)
+		return false;
+
+	/* sorry, fanotify only gives a damn about files and dirs */
+	if (!S_ISREG(inode->i_mode) &&
+	    !S_ISDIR(inode->i_mode))
+		return false;
+
+	/* if we don't have enough info to send an event to userspace say no */
+	if ((data_type != FSNOTIFY_EVENT_FILE) &&
+	    (data_type != FSNOTIFY_EVENT_PATH))
+		return false;
+
+	/* if this file was opened by fanotify don't send events about it */
+	if (data_type == FSNOTIFY_EVENT_FILE) {
+		struct file *file;
+
+		file = (struct file *)data;
+		if (file->f_mode & FMODE_NONOTIFY)
+			return false;
+	}
+
+	spin_lock(&inode->i_lock);
+	entry = fsnotify_find_mark_entry(group, inode);
+	spin_unlock(&inode->i_lock);
+	if (!entry)
+		return false;
+
+	/* if the event is for a child and this inode doesn't care about
+	 * events on the child, don't send it! */
+	if ((mask & FS_EVENT_ON_CHILD) &&
+	    !(entry->mask & FS_EVENT_ON_CHILD))
+		send = false;
+	else {
+		if (!(entry->mask & FS_EVENT_ON_CHILD) &&
+		    (mask & FS_EVENT_ON_CHILD))
+			send = false;
+		else {
+			mask = (mask & ~FS_EVENT_ON_CHILD);
+			send = (entry->mask & mask);
+		}
+	}
+
+	/* find took a reference */
+	fsnotify_put_mark(entry);
+
+	return send;
+}
+
+const struct fsnotify_ops fanotify_ops = {
+	.handle_event = fanotify_handle_event,
+	.should_send_event = fanotify_should_send_event,
+	.free_group_priv = NULL,
+	.free_event_priv = NULL,
+	.freeing_mark = NULL,
+};
diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
new file mode 100644
index 0000000..a8785c1
--- /dev/null
+++ b/fs/notify/fanotify/fanotify.h
@@ -0,0 +1,12 @@
+#include <linux/fanotify.h>
+#include <linux/fsnotify_backend.h>
+#include <linux/net.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+static inline bool fanotify_is_mask_valid(__u32 mask)
+{
+	if (mask & ~(FAN_ALL_INCOMING_EVENTS))
+		return false;
+	return true;
+}
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index e7d84ff..b298c0e 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -206,6 +206,7 @@ unifdef-y += ethtool.h
 unifdef-y += eventpoll.h
 unifdef-y += signalfd.h
 unifdef-y += ext2_fs.h
+unifdef-y += fanotify.h
 unifdef-y += fb.h
 unifdef-y += fcntl.h
 unifdef-y += filter.h
diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h
new file mode 100644
index 0000000..b560f86
--- /dev/null
+++ b/include/linux/fanotify.h
@@ -0,0 +1,40 @@
+#ifndef _LINUX_FANOTIFY_H
+#define _LINUX_FANOTIFY_H
+
+#include <linux/types.h>
+
+/* the following events that user-space can register for */
+#define FAN_ACCESS		0x00000001	/* File was accessed */
+#define FAN_MODIFY		0x00000002	/* File was modified */
+#define FAN_CLOSE_WRITE		0x00000008	/* Unwrittable file closed */
+#define FAN_CLOSE_NOWRITE	0x00000010	/* Writtable file closed */
+#define FAN_OPEN		0x00000020	/* File was opened */
+
+#define FAN_EVENT_ON_CHILD	0x08000000	/* interested in child events */
+
+/* FIXME currently Q's have no limit.... */
+#define FAN_Q_OVERFLOW		0x00004000	/* Event queued overflowed */
+
+/* helper events */
+#define FAN_CLOSE		(FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE) /* close */
+
+/*
+ * All of the events - we build the list by hand so that we can add flags in
+ * the future and not break backward compatibility.  Apps will get only the
+ * events that they originally wanted.  Be sure to add new events here!
+ */
+#define FAN_ALL_EVENTS (FAN_ACCESS |\
+			FAN_MODIFY |\
+			FAN_CLOSE |\
+			FAN_OPEN)
+
+/*
+ * All legal FAN bits userspace can request (although possibly not all
+ * at the same time.
+ */
+#define FAN_ALL_INCOMING_EVENTS	(FAN_ALL_EVENTS |\
+				 FAN_EVENT_ON_CHILD)
+#ifdef __KERNEL__
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_FANOTIFY_H */

^ permalink raw reply related

* [PATCH 3/9] networking/fanotify: declare fanotify socket numbers
From: Eric Paris @ 2009-08-28 18:55 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, netdev; +Cc: davem, viro, alan, hch
In-Reply-To: <20090828185542.8014.22791.stgit@paris.rdu.redhat.com>

fanotify's user interface uses a custom socket (it doesn't use netlink
since work must be done in the context of the receive side of the socket)

This patch simply defines the fanotify socket number declarations.  The
actual implementation of the socket is in a later patch.

Signed-off-by: Eric Paris <eparis@redhat.com>
---

 include/linux/socket.h |    5 ++++-
 net/core/sock.c        |    6 +++---
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/include/linux/socket.h b/include/linux/socket.h
index 3b461df..e03f47b 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -195,7 +195,8 @@ struct ucred {
 #define AF_ISDN		34	/* mISDN sockets 		*/
 #define AF_PHONET	35	/* Phonet sockets		*/
 #define AF_IEEE802154	36	/* IEEE802154 sockets		*/
-#define AF_MAX		37	/* For now.. */
+#define AF_FANOTIFY	37	/* fscking all access sockets	*/
+#define AF_MAX		38	/* For now.. */
 
 /* Protocol families, same as address families. */
 #define PF_UNSPEC	AF_UNSPEC
@@ -235,6 +236,7 @@ struct ucred {
 #define PF_ISDN		AF_ISDN
 #define PF_PHONET	AF_PHONET
 #define PF_IEEE802154	AF_IEEE802154
+#define PF_FANOTIFY	AF_FANOTIFY
 #define PF_MAX		AF_MAX
 
 /* Maximum queue length specifiable by listen.  */
@@ -306,6 +308,7 @@ struct ucred {
 #define SOL_PNPIPE	275
 #define SOL_RDS		276
 #define SOL_IUCV	277
+#define SOL_FANOTIFY	278
 
 /* IPX options */
 #define IPX_TYPE	1
diff --git a/net/core/sock.c b/net/core/sock.c
index 3ac34ea..1259525 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -155,7 +155,7 @@ static const char *const af_family_key_strings[AF_MAX+1] = {
   "sk_lock-27"       , "sk_lock-28"          , "sk_lock-AF_CAN"      ,
   "sk_lock-AF_TIPC"  , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV"        ,
   "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN"     , "sk_lock-AF_PHONET"   ,
-  "sk_lock-AF_IEEE802154",
+  "sk_lock-AF_IEEE802154", "sk_lock-AF_FANOTIFY",
   "sk_lock-AF_MAX"
 };
 static const char *const af_family_slock_key_strings[AF_MAX+1] = {
@@ -171,7 +171,7 @@ static const char *const af_family_slock_key_strings[AF_MAX+1] = {
   "slock-27"       , "slock-28"          , "slock-AF_CAN"      ,
   "slock-AF_TIPC"  , "slock-AF_BLUETOOTH", "slock-AF_IUCV"     ,
   "slock-AF_RXRPC" , "slock-AF_ISDN"     , "slock-AF_PHONET"   ,
-  "slock-AF_IEEE802154",
+  "slock-AF_IEEE802154", "slock=AF_FANOTIFY",
   "slock-AF_MAX"
 };
 static const char *const af_family_clock_key_strings[AF_MAX+1] = {
@@ -187,7 +187,7 @@ static const char *const af_family_clock_key_strings[AF_MAX+1] = {
   "clock-27"       , "clock-28"          , "clock-AF_CAN"      ,
   "clock-AF_TIPC"  , "clock-AF_BLUETOOTH", "clock-AF_IUCV"     ,
   "clock-AF_RXRPC" , "clock-AF_ISDN"     , "clock-AF_PHONET"   ,
-  "clock-AF_IEEE802154",
+  "clock-AF_IEEE802154", "clock-AF_FANOTIFY",
   "clock-AF_MAX"
 };
 

^ permalink raw reply related

* [PATCH 2/9] vfs: introduce FMODE_NONOTIFY
From: Eric Paris @ 2009-08-28 18:55 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, netdev; +Cc: davem, viro, alan, hch
In-Reply-To: <20090828185542.8014.22791.stgit@paris.rdu.redhat.com>

This is a new f_mode which can only be set by the kernel.  It indicates
that the fd was opened by fanotify and should not cause future fanotify
events.  This is needed to prevent fanotify livelock.  An example of
obvious livelock is from fanotify close events.

Process A closes file1
This creates a close event for file1.
fanotify opens file1 for Listener X
Listener X deals with the event and closes its fd for file1.
This creates a close event for file1.
fanotify opens file1 for Listener X
Listener X deals with the event and closes its fd for file1.
This creates a close event for file1.
fanotify opens file1 for Listener X
Listener X deals with the event and closes its fd for file1.
notice a pattern?

The fix is to add the FMODE_NONOTIFY bit to the open filp done by the kernel
for fanotify.  Thus when that file is used it will not generate future
events.

This patch simply defines the bit.

Signed-off-by: Eric Paris <eparis@redhat.com>
---

 include/linux/fs.h |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/include/linux/fs.h b/include/linux/fs.h
index 6e3a32d..c3d7b8b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -87,6 +87,9 @@ struct inodes_stat_t {
  */
 #define FMODE_NOCMTIME		((__force fmode_t)2048)
 
+/* File was opened by fanotify and shouldn't generate fanotify events */
+#define FMODE_NONOTIFY		((__force fmode_t)4096)
+
 /*
  * The below are the various read and write types that we support. Some of
  * them include behavioral modifiers that send information down to the

^ permalink raw reply related

* [PATCH 1/9] task_struct: add PF_NONOTIFY for fanotify to use
From: Eric Paris @ 2009-08-28 18:55 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, netdev; +Cc: davem, viro, alan, hch

Since fanotify opens file descriptors inside the kernel for it's listeners
it needs a way to make sure that 2 fanotify listeners, both which listen to
open events do not continuously see each others open events (and get into a
livelock reporting on each other's activity).  This fix is to create a new
tast_struct flags called PF_NONOTIFY.  If this flag is set in a task no
fanotify events will be generated for that task.   fanotify will set the
flag before and open call and will clear it immediately after.

Signed-off-by: Eric Paris <eparis@redhat.com>
---

 include/linux/sched.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/include/linux/sched.h b/include/linux/sched.h
index b88872f..3c1ce66 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1695,6 +1695,7 @@ extern cputime_t task_gtime(struct task_struct *p);
 #define PF_EXITING	0x00000004	/* getting shut down */
 #define PF_EXITPIDONE	0x00000008	/* pi exit done on shut down */
 #define PF_VCPU		0x00000010	/* I'm a virtual CPU */
+#define PF_NONOTIFY	0x00000020	/* In fanotify open operation */
 #define PF_FORKNOEXEC	0x00000040	/* forked but didn't exec */
 #define PF_MCE_PROCESS  0x00000080      /* process policy on mce errors */
 #define PF_SUPERPRIV	0x00000100	/* used super-user privileges */


^ permalink raw reply related

* Re: 100Mbit ethernet performance on embedded devices
From: Mark Brown @ 2009-08-28 17:35 UTC (permalink / raw)
  To: Johannes Stezenbach; +Cc: Jamie Lokier, linux-embedded, netdev
In-Reply-To: <20090828144138.GB7375@sig21.net>

On Fri, Aug 28, 2009 at 04:41:38PM +0200, Johannes Stezenbach wrote:
> On Thu, Aug 20, 2009 at 02:56:49PM +0200, Johannes Stezenbach wrote:

> > which came with the 2.6.20 kernel.  The delay between irq ->
> > netif_rx_schedule() -> NET_RX_SOFTIRQ ->  ->poll()  doesn't seem
> > to be long enough.  But of course my understanding of NAPI is
> > very limited, probably I missed something...

> It would've been nice to get a comment on this.  Yeah I know,
> old kernel, non-mainline driver...

> On this platform NAPI seems to be a win when receiving small packets,
> but not for a single max-bandwidth TCP stream.  The folks at
> stlinux.com seem to be using a dedicated hw timer to delay
> the NAPI poll() calls:
> http://www.stlinux.com/drupal/kernel/network/stmmac-optimizations

> This of course adds some latency to the packet processing,
> however in the single TCP stream case this wouldn't matter.

Does your actual system have any appreciable CPU loading?  If so that
will normally have the same effect as inserting a delay in the RX path.
Some of the numbers will often look worse with NAPI when the system is
lightly loaded (though not normally throughput).

^ permalink raw reply

* [PATCH net-next-2.6] ip: Report qdisc packet drops
From: Eric Dumazet @ 2009-08-28 17:26 UTC (permalink / raw)
  To: Christoph Lameter
  Cc: Sridhar Samudrala, David Stevens, David S. Miller, netdev, niv,
	Michael Kerrisk
In-Reply-To: <alpine.DEB.1.10.0908281211150.7317@gentwo.org>

Christoph Lameter a écrit :
> On Fri, 28 Aug 2009, Eric Dumazet wrote:
>> Only change you want is eventually to account for the UDP drop (SndbufErrors).
> 
> That is only a counter at the UDP layer. That one does not allow you to
> identify which NIC it was nor which application caused it.

We dont have per-application SNMP counters, so application is responsible
to get proper syscall return check logic / accounting if necessary.

NIC level, just forget it, it makes no sense.

> 
> But its already a big improvement to see TX drops at all. Could we get
> your latest patch merged soon?

I officially submit it, but David have to take it or reject it :)

Thanks

[PATCH] ip: Report qdisc packet drops

Christoph Lameter pointed out that packet drops at qdisc level where not
accounted in SNMP counters. Only if application sets IP_RECVERR, drops
are reported to user and SNMP counters updated.

IP_RECVERR is used to enable extended reliable error message passing.
In case of tx drops at qdisc level, no error packet will be generated.
It seems un-necessary to hide the qdisc drops for non IP_RECVERR enabled
sockets (as probably most sockets are)

By removing the check of IP_RECVERR enabled sockets in ip_push_pending_frames()/
raw_send_hdrinc() / ip6_push_pending_frames() / rawv6_send_hdrinc(),
we can properly update IPSTATS_MIB_OUTDISCARDS, and in case of UDP, update
UDP_MIB_SNDBUFERRORS SNMP counters.

Application send() syscalls, instead of returning an OK status (thus lying),
will return -ENOBUFS error.

Note : send() manual page explicitly says for -ENOBUFS error :

 "The output queue for a network interface was full.
  This generally indicates that the interface has stopped sending,
  but may be caused by transient congestion.
  (Normally, this does not occur in Linux. Packets are just silently
  dropped when a device queue overflows.) "

This was not true for IP_RECVERR enabled sockets for < 2.6.32 linuxes,
and starting from linux 2.6.32, last part wont be true at all.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Christoph Lameter <cl@linux-foundation.org>
---
 net/ipv4/ip_output.c  |    2 +-
 net/ipv4/raw.c        |    2 +-
 net/ipv6/ip6_output.c |    2 +-
 net/ipv6/raw.c        |    2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 7d08210..afae0cb 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1302,7 +1302,7 @@ int ip_push_pending_frames(struct sock *sk)
 	err = ip_local_out(skb);
 	if (err) {
 		if (err > 0)
-			err = inet->recverr ? net_xmit_errno(err) : 0;
+			err = net_xmit_errno(err);
 		if (err)
 			goto error;
 	}
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 2979f14..80ff607 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -375,7 +375,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length,
 	err = NF_HOOK(PF_INET, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
 		      dst_output);
 	if (err > 0)
-		err = inet->recverr ? net_xmit_errno(err) : 0;
+		err = net_xmit_errno(err);
 	if (err)
 		goto error;
 out:
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 6ad5aad..537e8cf 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1511,7 +1511,7 @@ int ip6_push_pending_frames(struct sock *sk)
 	err = ip6_local_out(skb);
 	if (err) {
 		if (err > 0)
-			err = np->recverr ? net_xmit_errno(err) : 0;
+			err = net_xmit_errno(err);
 		if (err)
 			goto error;
 	}
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 5068410..1f7ee61 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -642,7 +642,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
 		      dst_output);
 	if (err > 0)
-		err = np->recverr ? net_xmit_errno(err) : 0;
+		err = net_xmit_errno(err);
 	if (err)
 		goto error;
 out:

^ permalink raw reply related

* Re: UDP multicast packet loss not reported if TX ring overrun?
From: Christoph Lameter @ 2009-08-28 16:15 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Sridhar Samudrala, David Stevens, David S. Miller, netdev, niv
In-Reply-To: <4A97F2B4.7030900@gmail.com>

On Fri, 28 Aug 2009, Eric Dumazet wrote:

> "tc -s qdisc show" only displays queue info for tx packets.

Duh. The packet counters and bytes are way out of whack and do not reflect
what was actually sent. This must be some other qdisc.

> >  	sch->qstats.drops++;
> >
> > +	/* device queue statistics */
> > +	sch->dev_queue->tx_dropped++;
> > +
> >  	return NET_XMIT_DROP;
> >  }
>
> locking problem here, tx_dropped can be changed by another cpu.

Who cares. It just was for debugging.

> As David Stevens pointed out, device was not ever called at all when your packet(s) was/were lost.
> Why should we account a non existent drop at device level ?

Because you need drop statistics on a device to figure out when you may
want to increase the TX buffers for a device. If a packet was dropped
because of a lack of TX buffers then we need to know.

> When a process wants a new memory page and hits its own limit, do you want to increment a system global
> counter saying 'memory allocation failed' ?

When a process allocates and locks all of memory then you get an OOM.

> Only change you want is eventually to account for the UDP drop (SndbufErrors).

That is only a counter at the UDP layer. That one does not allow you to
identify which NIC it was nor which application caused it.

But its already a big improvement to see TX drops at all. Could we get
your latest patch merged soon?




^ permalink raw reply

* Re: [PATCH 08/14] pktgen: reorganize transmit loop
From: Ben Greear @ 2009-08-28 16:01 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: David Miller, Robert Olsson, netdev, Thomas Gleixner
In-Reply-To: <20090827224902.49f80920@nehalam>

On 08/27/2009 10:49 PM, Stephen Hemminger wrote:
> On Thu, 27 Aug 2009 20:52:32 -0700
> Ben Greear<greearb@candelatech.com>  wrote:
>
>> +		default: /* Drivers are not supposed to return other
>> values! */
>> +			if (net_ratelimit())
>> +				pr_info("pktgen: %s xmit error:
>> %d\n",
>> +					odev->name, ret);
>>   			pkt_dev->errors++;
>>
>> I believe this is faulty.  Things like vlans can send pkts to qdiscs
>> of the underlying device and those can return other values.
>>
>> Patric McHardy put in some patches recently to achieve this in a more
>> uniform manner:
>>
>> http://patchwork.ozlabs.org/patch/28340/
>>
>> Thanks,
>> Ben
>>
>
> Since pktgen has its own way of generating vlan tags, it
> makes no sense to use it on top of 8021q vlan driver.

Maybe someone wants to test their virtual device driver using pktgen?

Or generate traffic with lots of different vlan IDs & associated
IP, mac-addresses, etc?

Same issue applies to mac-vlans and possibly other virtual devices.

Thanks,
Ben

-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


^ permalink raw reply

* Re: [PATCH 2/2]: pkt_sched: Convert CBQ to tasklet_hrtimer.
From: Eric Dumazet @ 2009-08-28 15:54 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, tglx
In-Reply-To: <20090821.170333.153413841.davem@davemloft.net>

David Miller a écrit :
> This code expects to run in softirq context, and bare hrtimers
> run in hw IRQ context.
> 
> Signed-off-by: David S. Miller <davem@davemloft.net>

...

>  	sch->flags &= ~TCQ_F_THROTTLED;
> @@ -1214,7 +1216,7 @@ cbq_reset(struct Qdisc* sch)
>  	q->tx_class = NULL;
>  	q->tx_borrowed = NULL;
>  	qdisc_watchdog_cancel(&q->watchdog);
> -	hrtimer_cancel(&q->delay_timer);
> +	tasklet_hrtimer_cancel(&q->delay_timer);
>  	q->toplevel = TC_CBQ_MAXLEVEL;
>  	q->now = psched_get_time();
>  	q->now_rt = q->now;

David

I now have these dmesg warnings when playing with cbq

# tc qdisc del dev eth3 root
# tc qdisc add dev eth3 root handle 1: est 1sec 8sec cbq avpkt 1000 rate 1000Mbit bandwidth 1000Mbit
# tc qdisc del dev eth3 root

[12786.458485] Attempt to kill tasklet from interrupt
[12786.458522] Attempt to kill tasklet from interrupt
[12786.465261] Attempt to kill tasklet from interrupt
[12786.465286] Attempt to kill tasklet from interrupt

probably becauce cbq_reset() being called from interrupt context ?

Thanks

^ permalink raw reply

* Re: [PATCHv5 1/3] mm: export use_mm/unuse_mm to modules
From: Gregory Haskins @ 2009-08-28 15:31 UTC (permalink / raw)
  To: Michael S. Tsirkin, akpm
  Cc: netdev, virtualization, kvm, linux-kernel, mingo, linux-mm, hpa,
	Rusty Russell, s.hetze
In-Reply-To: <20090827160656.GB23722@redhat.com>

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

Michael S. Tsirkin wrote:
> vhost net module wants to do copy to/from user from a kernel thread,
> which needs use_mm (like what fs/aio has).  Move that into mm/ and
> export to modules.


Michael, Andrew,

I am just curious: Is there any technical reason why a kthread cannot
have a long-term use_mm() in effect? (Assuming this makes sense for the
design, of course).  For the cases there we know the kthread will always
service the same context (such as with venettap/vhost, it may make sense
to do a use_mm() at init time and just leave it until the thread exits.
 Will this break anything?

Kind Regards,
-Greg


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 267 bytes --]

^ 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