* [PATCH] Convert ipvs to use seq_file.
@ 2003-09-15 21:39 Stephen Hemminger
2003-09-15 22:56 ` Roberto Nibali
0 siblings, 1 reply; 5+ messages in thread
From: Stephen Hemminger @ 2003-09-15 21:39 UTC (permalink / raw)
To: David S. Miller; +Cc: lvs-users, netdev
Convert IPVS (for 2.6.0-test5) to use seq_file for the /proc interface.
Got rid of gratuitous 64 column trailing blank padding.
P.s: how come there is no MAINTAINER listed for IPVS?
diff -urNp -X dontdiff linux-2.5/net/ipv4/ipvs/ip_vs_app.c linux-2.5-net/net/ipv4/ipvs/ip_vs_app.c
--- linux-2.5/net/ipv4/ipvs/ip_vs_app.c 2003-09-15 09:57:15.000000000 -0700
+++ linux-2.5-net/net/ipv4/ipvs/ip_vs_app.c 2003-09-15 10:30:18.000000000 -0700
@@ -35,6 +35,7 @@
#include <asm/system.h>
#include <linux/stat.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <net/ip_vs.h>
@@ -480,55 +481,104 @@ int ip_vs_app_pkt_in(struct ip_vs_conn *
}
+#ifdef CONFIG_PROC_FS
/*
* /proc/net/ip_vs_app entry function
*/
-static int
-ip_vs_app_getinfo(char *buffer, char **start, off_t offset, int length)
+#define SEQ_START_TOKEN ((void *)1)
+
+static struct ip_vs_app *ip_vs_app_idx(loff_t pos)
{
- off_t pos=0;
- int len=0;
- char temp[64];
- struct ip_vs_app *app, *inc;
+ loff_t off = 0;
struct list_head *e, *i;
- pos = 64;
- if (pos > offset) {
- len += sprintf(buffer+len, "%-63s\n",
- "prot port usecnt name");
+ list_for_each(e, &ip_vs_app_list) {
+ struct ip_vs_app *app
+ = list_entry(e, struct ip_vs_app, a_list);
+ list_for_each (i, &app->incs_list) {
+ if (off == pos)
+ return list_entry(i, struct ip_vs_app, a_list);
+ ++off;
+ }
}
+ return NULL;
+
+}
+static void *ip_vs_app_seq_start(struct seq_file *seq, loff_t *pos)
+{
down(&__ip_vs_app_mutex);
- list_for_each (e, &ip_vs_app_list) {
+
+ return *pos ? ip_vs_app_idx(*pos - 1) : SEQ_START_TOKEN;
+}
+
+static void *ip_vs_app_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ struct ip_vs_app *inc, *app;
+ struct list_head *i, *e;
+
+ ++*pos;
+ if (v == SEQ_START_TOKEN)
+ return ip_vs_app_idx(0);
+
+ inc = v;
+ app = inc->app;
+
+ if ((i = inc->a_list.next) != &app->incs_list)
+ return list_entry(i, struct ip_vs_app, a_list);
+
+ /* go on to next application */
+ for (e = app->a_list.next; e != &ip_vs_app_list; e = e->next) {
app = list_entry(e, struct ip_vs_app, a_list);
list_for_each (i, &app->incs_list) {
- inc = list_entry(i, struct ip_vs_app, a_list);
-
- pos += 64;
- if (pos <= offset)
- continue;
- sprintf(temp, "%-3s %-7u %-6d %-17s",
- ip_vs_proto_name(inc->protocol),
- ntohs(inc->port),
- atomic_read(&inc->usecnt),
- inc->name);
- len += sprintf(buffer+len, "%-63s\n", temp);
- if (pos >= offset+length)
- goto done;
+ return list_entry(i, struct ip_vs_app, a_list);
}
}
- done:
+ return NULL;
+}
+
+static void ip_vs_app_seq_stop(struct seq_file *seq, void *v)
+{
up(&__ip_vs_app_mutex);
+}
- *start = buffer+len-(pos-offset); /* Start of wanted data */
- len = pos-offset;
- if (len > length)
- len = length;
- if (len < 0)
- len = 0;
- return len;
+static int ip_vs_app_seq_show(struct seq_file *seq, void *v)
+{
+ if (v == SEQ_START_TOKEN)
+ seq_puts(seq, "prot port usecnt name\n");
+ else {
+ const struct ip_vs_app *inc = v;
+
+ seq_printf(seq, "%-3s %-7u %-6d %-17s\n",
+ ip_vs_proto_name(inc->protocol),
+ ntohs(inc->port),
+ atomic_read(&inc->usecnt),
+ inc->name);
+ }
+ return 0;
}
+static struct seq_operations ip_vs_app_seq_ops = {
+ .start = ip_vs_app_seq_start,
+ .next = ip_vs_app_seq_next,
+ .stop = ip_vs_app_seq_stop,
+ .show = ip_vs_app_seq_show,
+};
+
+static int ip_vs_app_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &ip_vs_app_seq_ops);
+}
+
+static struct file_operations ip_vs_app_fops = {
+ .owner = THIS_MODULE,
+ .open = ip_vs_app_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+#endif
+
/*
* Replace a segment of data with a new segment
@@ -577,7 +627,7 @@ int ip_vs_skb_replace(struct sk_buff *sk
int ip_vs_app_init(void)
{
/* we will replace it with proc_net_ipvs_create() soon */
- proc_net_create("ip_vs_app", 0, ip_vs_app_getinfo);
+ proc_net_fops_create("ip_vs_app", 0, &ip_vs_app_fops);
return 0;
}
diff -urNp -X dontdiff linux-2.5/net/ipv4/ipvs/ip_vs_conn.c linux-2.5-net/net/ipv4/ipvs/ip_vs_conn.c
--- linux-2.5/net/ipv4/ipvs/ip_vs_conn.c 2003-09-15 09:57:15.000000000 -0700
+++ linux-2.5-net/net/ipv4/ipvs/ip_vs_conn.c 2003-09-15 10:27:45.000000000 -0700
@@ -30,6 +30,7 @@
#include <linux/compiler.h>
#include <linux/vmalloc.h>
#include <linux/proc_fs.h> /* for proc_net_* */
+#include <linux/seq_file.h>
#include <linux/jhash.h>
#include <linux/random.h>
@@ -188,14 +189,13 @@ static inline struct ip_vs_conn *__ip_vs
{
unsigned hash;
struct ip_vs_conn *cp;
- struct list_head *l,*e;
+ struct list_head *e;
hash = ip_vs_conn_hashkey(protocol, s_addr, s_port);
- l = &ip_vs_conn_tab[hash];
ct_read_lock(hash);
- for (e=l->next; e!=l; e=e->next) {
+ list_for_each(e, &ip_vs_conn_tab[hash]) {
cp = list_entry(e, struct ip_vs_conn, c_list);
if (s_addr==cp->caddr && s_port==cp->cport &&
d_port==cp->vport && d_addr==cp->vaddr &&
@@ -242,17 +242,16 @@ struct ip_vs_conn *ip_vs_conn_out_get
{
unsigned hash;
struct ip_vs_conn *cp, *ret=NULL;
- struct list_head *l,*e;
+ struct list_head *e;
/*
* Check for "full" addressed entries
*/
hash = ip_vs_conn_hashkey(protocol, d_addr, d_port);
- l = &ip_vs_conn_tab[hash];
ct_read_lock(hash);
- for (e=l->next; e!=l; e=e->next) {
+ list_for_each(e, &ip_vs_conn_tab[hash]) {
cp = list_entry(e, struct ip_vs_conn, c_list);
if (d_addr == cp->caddr && d_port == cp->cport &&
s_port == cp->dport && s_addr == cp->daddr &&
@@ -615,61 +614,116 @@ ip_vs_conn_new(int proto, __u32 caddr, _
/*
* /proc/net/ip_vs_conn entries
*/
-static int
-ip_vs_conn_getinfo(char *buffer, char **start, off_t offset, int length)
-{
- off_t pos=0;
- int idx, len=0;
- char temp[70];
- struct ip_vs_conn *cp;
- struct list_head *l, *e;
+#ifdef CONFIG_PROC_FS
- pos = 128;
- if (pos > offset) {
- len += sprintf(buffer+len, "%-127s\n",
- "Pro FromIP FPrt ToIP TPrt DestIP DPrt State Expires");
- }
+#define SEQ_START_TOKEN ((void *)1)
+static void *ip_vs_conn_array(struct seq_file *seq, loff_t pos)
+{
+ struct list_head *e;
+ int idx;
+ loff_t off = 0;
+
for(idx = 0; idx < IP_VS_CONN_TAB_SIZE; idx++) {
- /*
- * Lock is actually only need in next loop
- * we are called from uspace: must stop bh.
- */
ct_read_lock_bh(idx);
+ list_for_each(e, &ip_vs_conn_tab[idx]) {
+ if (off == pos) {
+ seq->private = &ip_vs_conn_tab[idx];
+ return list_entry(e, struct ip_vs_conn, c_list);
+ }
+ ++off;
+ }
+ ct_read_unlock_bh(idx);
+ }
- l = &ip_vs_conn_tab[idx];
- for (e=l->next; e!=l; e=e->next) {
- cp = list_entry(e, struct ip_vs_conn, c_list);
- pos += 128;
- if (pos <= offset)
- continue;
- sprintf(temp,
- "%-3s %08X %04X %08X %04X %08X %04X %-11s %7lu",
+ return NULL;
+}
+
+static void *ip_vs_conn_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ seq->private = NULL;
+ return *pos ? ip_vs_conn_array(seq, *pos - 1) :SEQ_START_TOKEN;
+}
+
+static void *ip_vs_conn_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ struct ip_vs_conn *cp = v;
+ struct list_head *e, *l = seq->private;
+ int idx;
+
+ ++*pos;
+ if (v == SEQ_START_TOKEN)
+ return ip_vs_conn_array(seq, 0);
+
+ /* more on same hash chain? */
+ if ((e = cp->c_list.next) != l)
+ return list_entry(e, struct ip_vs_conn, c_list);
+
+ idx = l - ip_vs_conn_tab;
+ ct_read_unlock_bh(idx);
+
+ while (++idx < IP_VS_CONN_TAB_SIZE) {
+ ct_read_lock_bh(idx);
+ list_for_each(e, &ip_vs_conn_tab[idx]) {
+ seq->private = &ip_vs_conn_tab[idx];
+ return list_entry(e, struct ip_vs_conn, c_list);
+ }
+ ct_read_unlock_bh(idx);
+ }
+ seq->private = NULL;
+ return NULL;
+}
+
+static void ip_vs_conn_seq_stop(struct seq_file *seq, void *v)
+{
+ struct list_head *l = seq->private;
+
+ if (l)
+ ct_read_unlock(l - ip_vs_conn_tab);
+}
+
+static int ip_vs_conn_seq_show(struct seq_file *seq, void *v)
+{
+
+ if (v == SEQ_START_TOKEN)
+ seq_puts(seq,
+ "Pro FromIP FPrt ToIP TPrt DestIP DPrt State Expires\n");
+ else {
+ const struct ip_vs_conn *cp = v;
+
+ seq_printf(seq,
+ "%-3s %08X %04X %08X %04X %08X %04X %-11s %7lu\n",
ip_vs_proto_name(cp->protocol),
ntohl(cp->caddr), ntohs(cp->cport),
ntohl(cp->vaddr), ntohs(cp->vport),
ntohl(cp->daddr), ntohs(cp->dport),
ip_vs_state_name(cp->protocol, cp->state),
(cp->timer.expires-jiffies)/HZ);
- len += sprintf(buffer+len, "%-127s\n", temp);
- if (pos >= offset+length) {
- ct_read_unlock_bh(idx);
- goto done;
- }
- }
- ct_read_unlock_bh(idx);
}
-
- done:
- *start = buffer+len-(pos-offset); /* Start of wanted data */
- len = pos-offset;
- if (len > length)
- len = length;
- if (len < 0)
- len = 0;
- return len;
+ return 0;
}
+static struct seq_operations ip_vs_conn_seq_ops = {
+ .start = ip_vs_conn_seq_start,
+ .next = ip_vs_conn_seq_next,
+ .stop = ip_vs_conn_seq_stop,
+ .show = ip_vs_conn_seq_show,
+};
+
+static int ip_vs_conn_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &ip_vs_conn_seq_ops);
+}
+
+static struct file_operations ip_vs_conn_fops = {
+ .owner = THIS_MODULE,
+ .open = ip_vs_conn_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+#endif
+
/*
* Randomly drop connection entries before running out of memory
@@ -707,7 +761,7 @@ void ip_vs_random_dropentry(void)
{
int idx;
struct ip_vs_conn *cp;
- struct list_head *l,*e;
+ struct list_head *e;
struct ip_vs_conn *ct;
/*
@@ -721,8 +775,7 @@ void ip_vs_random_dropentry(void)
*/
ct_write_lock(hash);
- l = &ip_vs_conn_tab[hash];
- for (e=l->next; e!=l; e=e->next) {
+ list_for_each(e, &ip_vs_conn_tab[hash]) {
cp = list_entry(e, struct ip_vs_conn, c_list);
if (!cp->cport && !(cp->flags & IP_VS_CONN_F_NO_CPORT))
/* connection template */
@@ -775,7 +828,7 @@ static void ip_vs_conn_flush(void)
{
int idx;
struct ip_vs_conn *cp;
- struct list_head *l,*e;
+ struct list_head *e;
struct ip_vs_conn *ct;
flush_again:
@@ -785,8 +838,7 @@ static void ip_vs_conn_flush(void)
*/
ct_write_lock_bh(idx);
- l = &ip_vs_conn_tab[idx];
- for (e=l->next; e!=l; e=e->next) {
+ list_for_each(e, &ip_vs_conn_tab[idx]) {
cp = list_entry(e, struct ip_vs_conn, c_list);
atomic_inc(&cp->refcnt);
ct_write_unlock(idx);
@@ -848,7 +900,7 @@ int ip_vs_conn_init(void)
__ip_vs_conntbl_lock_array[idx].l = RW_LOCK_UNLOCKED;
}
- proc_net_create("ip_vs_conn", 0, ip_vs_conn_getinfo);
+ proc_net_fops_create("ip_vs_conn", 0, &ip_vs_conn_fops);
/* calculate the random value for connection hash */
get_random_bytes(&ip_vs_conn_rnd, sizeof(ip_vs_conn_rnd));
diff -urNp -X dontdiff linux-2.5/net/ipv4/ipvs/ip_vs_ctl.c linux-2.5-net/net/ipv4/ipvs/ip_vs_ctl.c
--- linux-2.5/net/ipv4/ipvs/ip_vs_ctl.c 2003-09-15 09:57:15.000000000 -0700
+++ linux-2.5-net/net/ipv4/ipvs/ip_vs_ctl.c 2003-09-15 12:52:15.000000000 -0700
@@ -31,6 +31,8 @@
#include <linux/proc_fs.h>
#include <linux/timer.h>
#include <linux/swap.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
@@ -1507,207 +1509,253 @@ static struct ip_vs_sysctl_table ipv4_vs
{0}}
};
+#ifdef CONFIG_PROC_FS
+
+struct ip_vs_iter {
+ struct list_head *table;
+ int bucket;
+};
+
+#define SEQ_START_TOKEN ((void *)1)
/*
* Write the contents of the VS rule table to a PROCfs file.
* (It is kept just for backward compatibility)
*/
-static inline char *ip_vs_fwd_name(unsigned flags)
+static inline const char *ip_vs_fwd_name(unsigned flags)
{
- char *fwd;
-
switch (flags & IP_VS_CONN_F_FWD_MASK) {
case IP_VS_CONN_F_LOCALNODE:
- fwd = "Local";
- break;
+ return "Local";
case IP_VS_CONN_F_TUNNEL:
- fwd = "Tunnel";
- break;
+ return "Tunnel";
case IP_VS_CONN_F_DROUTE:
- fwd = "Route";
- break;
+ return "Route";
default:
- fwd = "Masq";
+ return "Masq";
}
- return fwd;
}
-static inline int sprintf_dest(char *str, struct ip_vs_dest *dest)
-{
- return sprintf(str, " -> %08X:%04X %-7s %-6d %-10d %-10d",
- ntohl(dest->addr), ntohs(dest->port),
- ip_vs_fwd_name(atomic_read(&dest->conn_flags)),
- atomic_read(&dest->weight),
- atomic_read(&dest->activeconns),
- atomic_read(&dest->inactconns));
-}
-static int ip_vs_get_info(char *buf, char **start, off_t offset, int length)
+/* Get the Nth entry in the two lists */
+static struct ip_vs_service *ip_vs_info_array(struct seq_file *seq, loff_t pos)
{
- int len=0;
- off_t pos=0;
- char temp[64], temp2[32];
+ struct ip_vs_iter *iter = seq->private;
int idx;
- struct ip_vs_service *svc;
- struct ip_vs_dest *dest;
- struct list_head *l, *e, *p, *q;
-
- /*
- * Note: since the length of the buffer is usually the multiple
- * of 512, it is good to use fixed record of the divisor of 512,
- * so that records won't be truncated at buffer boundary.
- */
- pos = 192;
- if (pos > offset) {
- sprintf(temp,
- "IP Virtual Server version %d.%d.%d (size=%d)",
- NVERSION(IP_VS_VERSION_CODE), IP_VS_CONN_TAB_SIZE);
- len += sprintf(buf+len, "%-63s\n", temp);
- len += sprintf(buf+len, "%-63s\n",
- "Prot LocalAddress:Port Scheduler Flags");
- len += sprintf(buf+len, "%-63s\n",
- " -> RemoteAddress:Port Forward Weight ActiveConn InActConn");
- }
+ struct list_head *e;
- read_lock_bh(&__ip_vs_svc_lock);
-
- /* print the service table hashed by <protocol,addr,port> */
+ /* look in hash by protocol */
for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
- l = &ip_vs_svc_table[idx];
- for (e=l->next; e!=l; e=e->next) {
- svc = list_entry(e, struct ip_vs_service, s_list);
- pos += 64;
- if (pos > offset) {
- if (svc->flags & IP_VS_SVC_F_PERSISTENT)
- sprintf(temp2, "persistent %d %08X",
- svc->timeout,
- ntohl(svc->netmask));
- else
- temp2[0] = '\0';
-
- sprintf(temp, "%s %08X:%04X %s %s",
- ip_vs_proto_name(svc->protocol),
- ntohl(svc->addr),
- ntohs(svc->port),
- svc->scheduler->name, temp2);
- len += sprintf(buf+len, "%-63s\n", temp);
- if (len >= length)
- goto done;
- }
-
- p = &svc->destinations;
- for (q=p->next; q!=p; q=q->next) {
- dest = list_entry(q, struct ip_vs_dest, n_list);
- pos += 64;
- if (pos <= offset)
- continue;
- sprintf_dest(temp, dest);
- len += sprintf(buf+len, "%-63s\n", temp);
- if (len >= length)
- goto done;
+ list_for_each(e, &ip_vs_svc_table[idx]) {
+ if (pos-- == 0){
+ iter->table = ip_vs_svc_table;
+ iter->bucket = idx;
+ return list_entry(e, struct ip_vs_service, s_list);
}
}
}
- /* print the service table hashed by fwmark */
+ /* keep looking in fwmark */
for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
- l = &ip_vs_svc_fwm_table[idx];
- for (e=l->next; e!=l; e=e->next) {
- svc = list_entry(e, struct ip_vs_service, f_list);
- pos += 64;
- if (pos > offset) {
- if (svc->flags & IP_VS_SVC_F_PERSISTENT)
- sprintf(temp2, "persistent %d %08X",
- svc->timeout,
- ntohl(svc->netmask));
- else
- temp2[0] = '\0';
-
- sprintf(temp, "FWM %08X %s %s",
- svc->fwmark,
- svc->scheduler->name, temp2);
- len += sprintf(buf+len, "%-63s\n", temp);
- if (len >= length)
- goto done;
+ list_for_each(e, &ip_vs_svc_fwm_table[idx]) {
+ if (pos-- == 0) {
+ iter->table = ip_vs_svc_fwm_table;
+ iter->bucket = idx;
+ return list_entry(e, struct ip_vs_service, f_list);
}
+ }
+ }
+
+ return NULL;
+}
- p = &svc->destinations;
- for (q=p->next; q!=p; q=q->next) {
- dest = list_entry(q, struct ip_vs_dest, n_list);
- pos += 64;
- if (pos <= offset)
- continue;
- sprintf_dest(temp, dest);
- len += sprintf(buf+len, "%-63s\n", temp);
- if (len >= length)
- goto done;
+static void *ip_vs_info_seq_start(struct seq_file *seq, loff_t *pos)
+{
+
+ read_lock_bh(&__ip_vs_svc_lock);
+ return *pos ? ip_vs_info_array(seq, *pos - 1) : SEQ_START_TOKEN;
+}
+
+
+static void *ip_vs_info_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ struct list_head *e;
+ struct ip_vs_iter *iter;
+ struct ip_vs_service *svc;
+
+ ++*pos;
+ if (v == SEQ_START_TOKEN)
+ return ip_vs_info_array(seq,0);
+
+ svc = v;
+ iter = seq->private;
+
+ if (iter->table == ip_vs_svc_table) {
+ /* next service in table hashed by protocol */
+ if ((e = svc->s_list.next) != &ip_vs_svc_table[iter->bucket])
+ return list_entry(e, struct ip_vs_service, s_list);
+
+
+ while (++iter->bucket < IP_VS_SVC_TAB_SIZE) {
+ list_for_each(e, &ip_vs_svc_table[iter->bucket]) {
+ return list_entry(e, struct ip_vs_service, s_list);
}
}
+
+ iter->table = ip_vs_svc_fwm_table;
+ iter->bucket = -1;
+ goto scan_fwmark;
}
- done:
+ /* next service in hashed by fwmark */
+ if ((e = svc->f_list.next) != &ip_vs_svc_fwm_table[iter->bucket])
+ return list_entry(e, struct ip_vs_service, f_list);
+
+ scan_fwmark:
+ while (++iter->bucket < IP_VS_SVC_TAB_SIZE) {
+ list_for_each(e, &ip_vs_svc_fwm_table[iter->bucket])
+ return list_entry(e, struct ip_vs_service, f_list);
+ }
+
+ return NULL;
+}
+
+static void ip_vs_info_seq_stop(struct seq_file *seq, void *v)
+{
read_unlock_bh(&__ip_vs_svc_lock);
+}
+
+
+static int ip_vs_info_seq_show(struct seq_file *seq, void *v)
+{
+ if (v == SEQ_START_TOKEN) {
+ seq_printf(seq,
+ "IP Virtual Server version %d.%d.%d (size=%d)\n",
+ NVERSION(IP_VS_VERSION_CODE), IP_VS_CONN_TAB_SIZE);
+ seq_puts(seq,
+ "Prot LocalAddress:Port Scheduler Flags\n");
+ seq_puts(seq,
+ " -> RemoteAddress:Port Forward Weight ActiveConn InActConn\n");
+ } else {
+ const struct ip_vs_service *svc = v;
+ const struct ip_vs_iter *iter = seq->private;
+ const struct ip_vs_dest *dest;
+
+ if (iter->table == ip_vs_svc_table)
+ seq_printf(seq, "%s %08X:%04X %s ",
+ ip_vs_proto_name(svc->protocol),
+ ntohl(svc->addr),
+ ntohs(svc->port),
+ svc->scheduler->name);
+ else
+ seq_printf(seq, "FWM %08X %s ",
+ svc->fwmark, svc->scheduler->name);
+
+ if (svc->flags & IP_VS_SVC_F_PERSISTENT)
+ seq_printf(seq, "persistent %d %08X\n",
+ svc->timeout,
+ ntohl(svc->netmask));
+ else
+ seq_putc(seq, '\n');
- *start = buf+len-(pos-offset); /* Start of wanted data */
- len = pos-offset;
- if (len > length)
- len = length;
- if (len < 0)
- len = 0;
- return len;
+ list_for_each_entry(dest, &svc->destinations, n_list) {
+ seq_printf(seq,
+ " -> %08X:%04X %-7s %-6d %-10d %-10d\n",
+ ntohl(dest->addr), ntohs(dest->port),
+ ip_vs_fwd_name(atomic_read(&dest->conn_flags)),
+ atomic_read(&dest->weight),
+ atomic_read(&dest->activeconns),
+ atomic_read(&dest->inactconns));
+ }
+ }
+ return 0;
}
+static struct seq_operations ip_vs_info_seq_ops = {
+ .start = ip_vs_info_seq_start,
+ .next = ip_vs_info_seq_next,
+ .stop = ip_vs_info_seq_stop,
+ .show = ip_vs_info_seq_show,
+};
+
+static int ip_vs_info_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ int rc = -ENOMEM;
+ struct ip_vs_iter *s = kmalloc(sizeof(*s), GFP_KERNEL);
+
+ if (!s)
+ goto out;
+
+ rc = seq_open(file, &ip_vs_info_seq_ops);
+ if (rc)
+ goto out_kfree;
+
+ seq = file->private_data;
+ seq->private = s;
+ memset(s, 0, sizeof(*s));
+out:
+ return rc;
+out_kfree:
+ kfree(s);
+ goto out;
+}
+
+static struct file_operations ip_vs_info_fops = {
+ .owner = THIS_MODULE,
+ .open = ip_vs_info_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release_private,
+};
+
+#endif
struct ip_vs_stats ip_vs_stats;
-static int
-ip_vs_stats_get_info(char *buf, char **start, off_t offset, int length)
+#ifdef CONFIG_PROC_FS
+static int ip_vs_stats_show(struct seq_file *seq, void *v)
{
- int len=0;
- off_t pos=0;
- char temp[64];
-
- pos += 320;
- if (pos > offset) {
- len += sprintf(buf+len, "%-63s\n%-63s\n",
-/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */
- " Total Incoming Outgoing Incoming Outgoing",
- " Conns Packets Packets Bytes Bytes");
-
- spin_lock_bh(&ip_vs_stats.lock);
- sprintf(temp, "%8X %8X %8X %8X%08X %8X%08X",
- ip_vs_stats.conns,
- ip_vs_stats.inpkts,
- ip_vs_stats.outpkts,
- (__u32)(ip_vs_stats.inbytes>>32),
- (__u32)ip_vs_stats.inbytes,
- (__u32)(ip_vs_stats.outbytes>>32),
- (__u32)ip_vs_stats.outbytes);
- len += sprintf(buf+len, "%-62s\n\n", temp);
-
- len += sprintf(buf+len, "%-63s\n",
-/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */
- " Conns/s Pkts/s Pkts/s Bytes/s Bytes/s");
- sprintf(temp, "%8X %8X %8X %16X %16X",
+
+/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */
+ seq_puts(seq,
+ " Total Incoming Outgoing Incoming Outgoing\n");
+ seq_printf(seq,
+ " Conns Packets Packets Bytes Bytes\n");
+
+ spin_lock_bh(&ip_vs_stats.lock);
+ seq_printf(seq, "%8X %8X %8X %16LX %16LX\n\n", ip_vs_stats.conns,
+ ip_vs_stats.inpkts, ip_vs_stats.outpkts,
+ ip_vs_stats.inbytes, ip_vs_stats.outbytes);
+
+/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */
+ seq_puts(seq,
+ " Conns/s Pkts/s Pkts/s Bytes/s Bytes/s\n");
+ seq_printf(seq,"%8X %8X %8X %16X %16X\n",
ip_vs_stats.cps,
ip_vs_stats.inpps,
ip_vs_stats.outpps,
ip_vs_stats.inbps,
ip_vs_stats.outbps);
- len += sprintf(buf+len, "%-63s\n", temp);
+ spin_unlock_bh(&ip_vs_stats.lock);
- spin_unlock_bh(&ip_vs_stats.lock);
- }
+ return 0;
+}
- *start = buf+len-(pos-offset); /* Start of wanted data */
- len = pos-offset;
- if (len > length)
- len = length;
- if (len < 0)
- len = 0;
- return len;
+static int ip_vs_stats_seq_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ip_vs_stats_show, NULL);
}
+static struct file_operations ip_vs_stats_fops = {
+ .owner = THIS_MODULE,
+ .open = ip_vs_stats_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+#endif
/*
* Set timeout values for tcp tcpfin udp in the timeout_table.
@@ -2195,8 +2243,8 @@ int ip_vs_control_init(void)
return ret;
}
- proc_net_create("ip_vs", 0, ip_vs_get_info);
- proc_net_create("ip_vs_stats", 0, ip_vs_stats_get_info);
+ proc_net_fops_create("ip_vs", 0, &ip_vs_info_fops);
+ proc_net_fops_create("ip_vs_stats",0, &ip_vs_stats_fops);
ipv4_vs_table.sysctl_header =
register_sysctl_table(ipv4_vs_table.root_dir, 0);
^ permalink raw reply [flat|nested] 5+ messages in thread
* RE: [PATCH] Convert ipvs to use seq_file.
@ 2003-09-15 21:56 Peter Mueller
2003-09-15 22:01 ` David S. Miller
0 siblings, 1 reply; 5+ messages in thread
From: Peter Mueller @ 2003-09-15 21:56 UTC (permalink / raw)
To: 'LinuxVirtualServer.org users mailing list.',
David S. Miller, 'Stephen Hemminger'
Cc: netdev
Hello Stephen,
> P.s: how come there is no MAINTAINER listed for IPVS?
Wensong Zhang is the maintainer; where did you expect to see a maintainer
listed at? The LVS-developers that seem to be most active are:
Wensong Zhang
Julian Atanasaov
Simon Horman ('Horms')
Alexandre Cassen
Roberto Nibali ('Ratz')
Joseph Mack
AFAIK Redhat takes the LVS-source and patches it up at their end for
Pirahna, so patches should probably not go to RH.
Hope it helps,
Peter
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] Convert ipvs to use seq_file.
2003-09-15 21:56 Peter Mueller
@ 2003-09-15 22:01 ` David S. Miller
0 siblings, 0 replies; 5+ messages in thread
From: David S. Miller @ 2003-09-15 22:01 UTC (permalink / raw)
To: Peter Mueller; +Cc: lvs-users, shemminger, netdev
On Mon, 15 Sep 2003 14:56:59 -0700
Peter Mueller <pmueller@sidestep.com> wrote:
> Hello Stephen,
>
> > P.s: how come there is no MAINTAINER listed for IPVS?
>
> Wensong Zhang is the maintainer; where did you expect to see a maintainer
> listed at?
Where it belongs, in the "linux/MAINTAINERS" file.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] Convert ipvs to use seq_file.
2003-09-15 22:56 ` Roberto Nibali
@ 2003-09-15 22:49 ` David S. Miller
0 siblings, 0 replies; 5+ messages in thread
From: David S. Miller @ 2003-09-15 22:49 UTC (permalink / raw)
To: Roberto Nibali; +Cc: lvs-users, netdev, wensong
On Tue, 16 Sep 2003 00:56:30 +0200
Roberto Nibali <ratz@drugphish.ch> wrote:
> Looks good, but in the end it's of course Wensong's call.
I'll apply Stephen's changes for now, if Wensong doesn't like
them he can make changes when he next sends me IPVS stuff.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] Convert ipvs to use seq_file.
2003-09-15 21:39 [PATCH] Convert ipvs to use seq_file Stephen Hemminger
@ 2003-09-15 22:56 ` Roberto Nibali
2003-09-15 22:49 ` David S. Miller
0 siblings, 1 reply; 5+ messages in thread
From: Roberto Nibali @ 2003-09-15 22:56 UTC (permalink / raw)
To: LinuxVirtualServer.org users mailing list.
Cc: David S. Miller, netdev, wensong
Hi Stephen,
Wow, thanks for doing this!
> Convert IPVS (for 2.6.0-test5) to use seq_file for the /proc interface.
> Got rid of gratuitous 64 column trailing blank padding.
Looks good, but in the end it's of course Wensong's call.
> P.s: how come there is no MAINTAINER listed for IPVS?
You mean something along the lines of:
--- MAINTAINERS 2003-09-08 23:43:22.000000000 +0200
+++ MAINTAINERS.lvs 2003-09-16 00:24:17.000000000 +0200
@@ -1340,6 +1340,14 @@
L: netdev@oss.sgi.com
S: Maintained
+NETWORKING [IPVS]
+P: Wensong Zhang
+M: wensong@linux-vs.org
+M: lvs-users@linuxvirtualserver.org
+W: http://www.linux-vs.org/
+L: lvs-users@linuxvirtualserver.org
+S: Maintained
+
NFS CLIENT
P: Trond Myklebust
M: trond.myklebust@fys.uio.no
> @@ -615,61 +614,116 @@ ip_vs_conn_new(int proto, __u32 caddr, _
> /*
> * /proc/net/ip_vs_conn entries
> */
> -static int
> -ip_vs_conn_getinfo(char *buffer, char **start, off_t offset, int length)
> -{
> - off_t pos=0;
> - int idx, len=0;
> - char temp[70];
> - struct ip_vs_conn *cp;
> - struct list_head *l, *e;
> +#ifdef CONFIG_PROC_FS
>
> - pos = 128;
> - if (pos > offset) {
> - len += sprintf(buffer+len, "%-127s\n",
> - "Pro FromIP FPrt ToIP TPrt DestIP DPrt State Expires");
> - }
> +#define SEQ_START_TOKEN ((void *)1)
>
> +static void *ip_vs_conn_array(struct seq_file *seq, loff_t pos)
> +{
> + struct list_head *e;
> + int idx;
> + loff_t off = 0;
> +
> for(idx = 0; idx < IP_VS_CONN_TAB_SIZE; idx++) {
> - /*
> - * Lock is actually only need in next loop
> - * we are called from uspace: must stop bh.
> - */
> ct_read_lock_bh(idx);
> + list_for_each(e, &ip_vs_conn_tab[idx]) {
> + if (off == pos) {
> + seq->private = &ip_vs_conn_tab[idx];
> + return list_entry(e, struct ip_vs_conn, c_list);
> + }
> + ++off;
> + }
> + ct_read_unlock_bh(idx);
> + }
>
> - l = &ip_vs_conn_tab[idx];
> - for (e=l->next; e!=l; e=e->next) {
> - cp = list_entry(e, struct ip_vs_conn, c_list);
> - pos += 128;
> - if (pos <= offset)
> - continue;
> - sprintf(temp,
> - "%-3s %08X %04X %08X %04X %08X %04X %-11s %7lu",
> + return NULL;
> +}
> +
> +static void *ip_vs_conn_seq_start(struct seq_file *seq, loff_t *pos)
> +{
> + seq->private = NULL;
> + return *pos ? ip_vs_conn_array(seq, *pos - 1) :SEQ_START_TOKEN;
Nitpicking: s/:S/: S/
> -static int
> -ip_vs_stats_get_info(char *buf, char **start, off_t offset, int length)
> +#ifdef CONFIG_PROC_FS
> +static int ip_vs_stats_show(struct seq_file *seq, void *v)
> {
> - int len=0;
> - off_t pos=0;
> - char temp[64];
> -
> - pos += 320;
> - if (pos > offset) {
> - len += sprintf(buf+len, "%-63s\n%-63s\n",
> -/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */
> - " Total Incoming Outgoing Incoming Outgoing",
> - " Conns Packets Packets Bytes Bytes");
> -
> - spin_lock_bh(&ip_vs_stats.lock);
> - sprintf(temp, "%8X %8X %8X %8X%08X %8X%08X",
> - ip_vs_stats.conns,
> - ip_vs_stats.inpkts,
> - ip_vs_stats.outpkts,
> - (__u32)(ip_vs_stats.inbytes>>32),
> - (__u32)ip_vs_stats.inbytes,
> - (__u32)(ip_vs_stats.outbytes>>32),
> - (__u32)ip_vs_stats.outbytes);
> - len += sprintf(buf+len, "%-62s\n\n", temp);
> -
> - len += sprintf(buf+len, "%-63s\n",
> -/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */
> - " Conns/s Pkts/s Pkts/s Bytes/s Bytes/s");
> - sprintf(temp, "%8X %8X %8X %16X %16X",
> +
> +/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */
> + seq_puts(seq,
> + " Total Incoming Outgoing Incoming Outgoing\n");
> + seq_printf(seq,
> + " Conns Packets Packets Bytes Bytes\n");
> +
> + spin_lock_bh(&ip_vs_stats.lock);
> + seq_printf(seq, "%8X %8X %8X %16LX %16LX\n\n", ip_vs_stats.conns,
> + ip_vs_stats.inpkts, ip_vs_stats.outpkts,
> + ip_vs_stats.inbytes, ip_vs_stats.outbytes);
%16LX is maybe better than %8X%08X, I agree ;)
Now we have to wait for Wensong's approval. It certainly looks good to
me. I have no idea what his plans are currently as the CVS version is
not synched with the current bk version of 2.6.x. Also we still seem to
have non-resolved issues with the skb linearisation patches.
Best regards,
Roberto Nibali, ratz
--
echo '[q]sa[ln0=aln256%Pln256/snlbx]sb3135071790101768542287578439snlbxq'|dc
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2003-09-15 22:56 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-09-15 21:39 [PATCH] Convert ipvs to use seq_file Stephen Hemminger
2003-09-15 22:56 ` Roberto Nibali
2003-09-15 22:49 ` David S. Miller
-- strict thread matches above, loose matches on Subject: below --
2003-09-15 21:56 Peter Mueller
2003-09-15 22:01 ` David S. Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).