summaryrefslogtreecommitdiff
path: root/drivers/dahdi/dahdi-base.c
diff options
context:
space:
mode:
authorTzafrir Cohen <tzafrir.cohen@xorcom.com>2011-02-20 23:13:20 +0000
committerTzafrir Cohen <tzafrir.cohen@xorcom.com>2011-02-20 23:13:20 +0000
commit3ccb4aeee7852c9bf85bebf355419cb51abc36ad (patch)
treec4f6ba9aec3cb51328547510bc8e55c141f9252b /drivers/dahdi/dahdi-base.c
parent8bb318ace88f1038fdc952d4c8af7010c2c4d195 (diff)
replace old proc interface by modern seq_file
Switch to using the newer seq_file interface for procfs. Fixes a race when you read the "file" while its size increases (e.g. the span enters an alarm state). Signed-off-by: Oron Peled <oron.peled@xorcom.com> Acked-by: Shaun Ruffell <sruffell@digium.com> Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com> (closes issue #18760) Patches: 0001-DAHDI-linux-trunk-replace-old-proc-interface-by-mode.patch uploaded by tzafrir (license 46) git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9770 a0bf4364-ded3-4de4-8d8a-66a801d63aff
Diffstat (limited to 'drivers/dahdi/dahdi-base.c')
-rw-r--r--drivers/dahdi/dahdi-base.c159
1 files changed, 67 insertions, 92 deletions
diff --git a/drivers/dahdi/dahdi-base.c b/drivers/dahdi/dahdi-base.c
index 01bee57..e7951c0 100644
--- a/drivers/dahdi/dahdi-base.c
+++ b/drivers/dahdi/dahdi-base.c
@@ -39,6 +39,7 @@
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/version.h>
@@ -780,162 +781,135 @@ static int fill_alarm_string(char *buf, int count, int alarms)
return len;
}
-static int dahdi_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
+/*
+ * Sequential proc interface
+ */
+
+static void seq_fill_alarm_string(struct seq_file *sfile, int alarms)
{
- int x, len = 0, real_count;
- long spanno;
- struct dahdi_span *s;
+ char tmp[70];
+ if (fill_alarm_string(tmp, sizeof(tmp), alarms))
+ seq_printf(sfile, "%s", tmp);
+}
- /* In Linux 2.6, page is always PROC_BLOCK_SIZE=(PAGE_SIZE-1024) bytes.
- * 0<count<=PROC_BLOCK_SIZE . count=1 will produce an error in
- * vsnprintf ('head -c 1 /proc/dahdi/1', 'dd bs=1').
- * An ugly hack. Good way: seq_printf (seq_file.c). */
- real_count = count;
- count = PAGE_SIZE-1024;
- spanno = (long)data;
- if (!spanno)
- return 0;
+static int dahdi_seq_show(struct seq_file *sfile, void *v)
+{
+ long spanno = (long)sfile->private;
+ int x;
+ struct dahdi_span *s;
s = span_find_and_get(spanno);
if (!s)
return -ENODEV;
if (s->name)
- len += snprintf(page + len, count - len, "Span %d: %s ",
- s->spanno, s->name);
+ seq_printf(sfile, "Span %d: %s ", s->spanno, s->name);
if (s->desc)
- len += snprintf(page + len, count - len, "\"%s\"",
- s->desc);
+ seq_printf(sfile, "\"%s\"", s->desc);
else
- len += snprintf(page + len, count - len, "\"\"");
+ seq_printf(sfile, "\"\"");
if (s == master)
- len += snprintf(page + len, count - len, " (MASTER)");
+ seq_printf(sfile, " (MASTER)");
if (s->lineconfig) {
/* framing first */
if (s->lineconfig & DAHDI_CONFIG_B8ZS)
- len += snprintf(page + len, count - len, " B8ZS/");
+ seq_printf(sfile, " B8ZS/");
else if (s->lineconfig & DAHDI_CONFIG_AMI)
- len += snprintf(page + len, count - len, " AMI/");
+ seq_printf(sfile, " AMI/");
else if (s->lineconfig & DAHDI_CONFIG_HDB3)
- len += snprintf(page + len, count - len, " HDB3/");
+ seq_printf(sfile, " HDB3/");
/* then coding */
if (s->lineconfig & DAHDI_CONFIG_ESF)
- len += snprintf(page + len, count - len, "ESF");
+ seq_printf(sfile, "ESF");
else if (s->lineconfig & DAHDI_CONFIG_D4)
- len += snprintf(page + len, count - len, "D4");
+ seq_printf(sfile, "D4");
else if (s->lineconfig & DAHDI_CONFIG_CCS)
- len += snprintf(page + len, count - len, "CCS");
+ seq_printf(sfile, "CCS");
/* E1's can enable CRC checking */
if (s->lineconfig & DAHDI_CONFIG_CRC4)
- len += snprintf(page + len, count - len, "/CRC4");
+ seq_printf(sfile, "/CRC4");
}
- len += snprintf(page + len, count - len, " ");
+ seq_printf(sfile, " ");
/* list alarms */
- len += fill_alarm_string(page + len, count - len, s->alarms);
+ seq_fill_alarm_string(sfile, s->alarms);
if (s->syncsrc &&
(s->syncsrc == s->spanno))
- len += snprintf(page + len, count - len, "ClockSource ");
- len += snprintf(page + len, count - len, "\n");
+ seq_printf(sfile, "ClockSource ");
+ seq_printf(sfile, "\n");
if (s->count.bpv)
- len += snprintf(page + len, count - len, "\tBPV count: %d\n",
- s->count.bpv);
+ seq_printf(sfile, "\tBPV count: %d\n", s->count.bpv);
if (s->count.crc4)
- len += snprintf(page + len, count - len,
- "\tCRC4 error count: %d\n",
- s->count.crc4);
+ seq_printf(sfile, "\tCRC4 error count: %d\n", s->count.crc4);
if (s->count.ebit)
- len += snprintf(page + len, count - len,
- "\tE-bit error count: %d\n",
- s->count.ebit);
+ seq_printf(sfile, "\tE-bit error count: %d\n", s->count.ebit);
if (s->count.fas)
- len += snprintf(page + len, count - len,
- "\tFAS error count: %d\n",
- s->count.fas);
+ seq_printf(sfile, "\tFAS error count: %d\n", s->count.fas);
if (s->irqmisses)
- len += snprintf(page + len, count - len,
- "\tIRQ misses: %d\n",
- s->irqmisses);
+ seq_printf(sfile, "\tIRQ misses: %d\n", s->irqmisses);
if (s->timingslips)
- len += snprintf(page + len, count - len,
- "\tTiming slips: %d\n",
- s->timingslips);
- len += snprintf(page + len, count - len, "\n");
+ seq_printf(sfile, "\tTiming slips: %d\n", s->timingslips);
+ seq_printf(sfile, "\n");
for (x = 0; x < s->channels; x++) {
struct dahdi_chan *chan = s->chans[x];
if (chan->name)
- len += snprintf(page + len, count - len,
- "\t%4d %s ", chan->channo, chan->name);
+ seq_printf(sfile, "\t%4d %s ", chan->channo,
+ chan->name);
if (chan->sig) {
if (chan->sig == DAHDI_SIG_SLAVE)
- len += snprintf(page+len, count-len, "%s ",
+ seq_printf(sfile, "%s ",
sigstr(chan->master->sig));
else {
- len += snprintf(page+len, count-len, "%s ",
- sigstr(chan->sig));
+ seq_printf(sfile, "%s ", sigstr(chan->sig));
if (chan->nextslave &&
(chan->master->channo == chan->channo))
- len += snprintf(page+len, count-len,
- "Master ");
+ seq_printf(sfile, "Master ");
}
} else if (!chan->sigcap) {
- len += snprintf(page+len, count-len, "Reserved ");
+ seq_printf(sfile, "Reserved ");
}
if (test_bit(DAHDI_FLAGBIT_OPEN, &chan->flags))
- len += snprintf(page + len, count - len, "(In use) ");
+ seq_printf(sfile, "(In use) ");
#ifdef OPTIMIZE_CHANMUTE
if (chan->chanmute)
- len += snprintf(page+len, count-len, "(no pcm) ");
+ seq_printf(sfile, "(no pcm) ");
#endif
- len += fill_alarm_string(page+len, count-len,
- chan->chan_alarms);
+ seq_fill_alarm_string(sfile, chan->chan_alarms);
if (chan->ec_factory)
- len += snprintf(page+len, count-len, "(EC: %s - %s) ",
+ seq_printf(sfile, "(EC: %s - %s) ",
chan->ec_factory->get_name(chan),
chan->ec_state ? "ACTIVE" : "INACTIVE");
- len += snprintf(page+len, count-len, "\n");
-
- /* If everything printed so far is before beginning
- * of request */
- if (len <= off) {
- off -= len;
- len = 0;
- }
-
- /* stop if we've already generated enough */
- if (len > off + count)
- break;
- /* stop if we're NEAR danger limit. let it be -128 bytes. */
- if (len > count-128)
- break;
- }
- count = real_count;
- /* If everything printed so far is before beginning of request */
- if (len <= off) {
- off = 0;
- len = 0;
+ seq_printf(sfile, "\n");
}
- *start = page + off;
- len -= off; /* un-count any remaining offset */
- *eof = 1;
- if (len > count)
- len = count; /* don't return bytes not asked for */
-
put_span(s);
- return len;
+ return 0;
}
+
+static int dahdi_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, dahdi_seq_show, PDE(inode)->data);
+}
+
+static const struct file_operations dahdi_proc_ops = {
+ .owner = THIS_MODULE,
+ .open = dahdi_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
#endif
static int dahdi_first_empty_alias(void)
@@ -6471,14 +6445,15 @@ static int _dahdi_register(struct dahdi_span *span, int prefmaster)
{
char tempfile[17];
snprintf(tempfile, sizeof(tempfile), "%d", span->spanno);
- span->proc_entry = create_proc_read_entry(tempfile, 0444,
- root_proc_entry, dahdi_proc_read,
- (int *) (long) span->spanno);
+ span->proc_entry = create_proc_entry(tempfile, 0444,
+ root_proc_entry);
if (!span->proc_entry) {
res = -EFAULT;
span_err(span, "Error creating procfs entry\n");
goto cleanup;
}
+ span->proc_entry->data = (void *)(long)span->spanno;
+ span->proc_entry->proc_fops = &dahdi_proc_ops;
}
#endif