diff options
author | Tzafrir Cohen <tzafrir.cohen@xorcom.com> | 2011-02-20 23:13:20 +0000 |
---|---|---|
committer | Tzafrir Cohen <tzafrir.cohen@xorcom.com> | 2011-02-20 23:13:20 +0000 |
commit | 3ccb4aeee7852c9bf85bebf355419cb51abc36ad (patch) | |
tree | c4f6ba9aec3cb51328547510bc8e55c141f9252b /drivers/dahdi/dahdi-base.c | |
parent | 8bb318ace88f1038fdc952d4c8af7010c2c4d195 (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.c | 159 |
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 |