Skip to content

Commit

Permalink
proc_fops: convert drivers/isdn/ to seq_file
Browse files Browse the repository at this point in the history
Convert code away from ->read_proc/->write_proc interfaces.  Switch to
proc_create()/proc_create_data() which make addition of proc entries
reliable wrt NULL ->proc_fops, NULL ->data and so on.

Problem with ->read_proc et al is described here commit
786d7e1 "Fix rmmod/read/write races in
/proc entries"

[[email protected]: CONFIG_PROC_FS=n build fix]
Signed-off-by: Alexey Dobriyan <[email protected]>
Signed-off-by: Tilman Schmidt <[email protected]>
Signed-off-by: Karsten Keil <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Alexey Dobriyan authored and davem330 committed Jan 14, 2010
1 parent 508e14b commit 9a58a80
Show file tree
Hide file tree
Showing 21 changed files with 411 additions and 458 deletions.
9 changes: 5 additions & 4 deletions Documentation/isdn/INTERFACE.CAPI
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,11 @@ char *(*procinfo)(struct capi_ctr *ctrlr)
pointer to a callback function returning the entry for the device in
the CAPI controller info table, /proc/capi/controller

read_proc_t *ctr_read_proc
pointer to the read_proc callback function for the device's proc file
system entry, /proc/capi/controllers/<n>; will be called with a
pointer to the device's capi_ctr structure as the last (data) argument
const struct file_operations *proc_fops
pointers to callback functions for the device's proc file
system entry, /proc/capi/controllers/<n>; pointer to the device's
capi_ctr structure is available from struct proc_dir_entry::data
which is available from struct inode.

Note: Callback functions except send_message() are never called in interrupt
context.
Expand Down
99 changes: 35 additions & 64 deletions drivers/isdn/capi/capi.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
#include <linux/skbuff.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/poll.h>
#include <linux/capi.h>
#include <linux/kernelcapi.h>
Expand Down Expand Up @@ -1407,114 +1408,84 @@ static void capinc_tty_exit(void)
* /proc/capi/capi20:
* minor applid nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt
*/
static int proc_capidev_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
static int capi20_proc_show(struct seq_file *m, void *v)
{
struct capidev *cdev;
struct list_head *l;
int len = 0;

read_lock(&capidev_list_lock);
list_for_each(l, &capidev_list) {
cdev = list_entry(l, struct capidev, list);
len += sprintf(page+len, "0 %d %lu %lu %lu %lu\n",
seq_printf(m, "0 %d %lu %lu %lu %lu\n",
cdev->ap.applid,
cdev->ap.nrecvctlpkt,
cdev->ap.nrecvdatapkt,
cdev->ap.nsentctlpkt,
cdev->ap.nsentdatapkt);
if (len <= off) {
off -= len;
len = 0;
} else {
if (len-off > count)
goto endloop;
}
}

endloop:
read_unlock(&capidev_list_lock);
if (len < count)
*eof = 1;
if (len > count) len = count;
if (len < 0) len = 0;
return len;
return 0;
}

static int capi20_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, capi20_proc_show, NULL);
}

static const struct file_operations capi20_proc_fops = {
.owner = THIS_MODULE,
.open = capi20_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};

/*
* /proc/capi/capi20ncci:
* applid ncci
*/
static int proc_capincci_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
static int capi20ncci_proc_show(struct seq_file *m, void *v)
{
struct capidev *cdev;
struct capincci *np;
struct list_head *l;
int len = 0;

read_lock(&capidev_list_lock);
list_for_each(l, &capidev_list) {
cdev = list_entry(l, struct capidev, list);
for (np=cdev->nccis; np; np = np->next) {
len += sprintf(page+len, "%d 0x%x\n",
seq_printf(m, "%d 0x%x\n",
cdev->ap.applid,
np->ncci);
if (len <= off) {
off -= len;
len = 0;
} else {
if (len-off > count)
goto endloop;
}
}
}
endloop:
read_unlock(&capidev_list_lock);
*start = page+off;
if (len < count)
*eof = 1;
if (len>count) len = count;
if (len<0) len = 0;
return len;
return 0;
}

static struct procfsentries {
char *name;
mode_t mode;
int (*read_proc)(char *page, char **start, off_t off,
int count, int *eof, void *data);
struct proc_dir_entry *procent;
} procfsentries[] = {
/* { "capi", S_IFDIR, 0 }, */
{ "capi/capi20", 0 , proc_capidev_read_proc },
{ "capi/capi20ncci", 0 , proc_capincci_read_proc },
static int capi20ncci_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, capi20ncci_proc_show, NULL);
}

static const struct file_operations capi20ncci_proc_fops = {
.owner = THIS_MODULE,
.open = capi20ncci_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};

static void __init proc_init(void)
{
int nelem = ARRAY_SIZE(procfsentries);
int i;

for (i=0; i < nelem; i++) {
struct procfsentries *p = procfsentries + i;
p->procent = create_proc_entry(p->name, p->mode, NULL);
if (p->procent) p->procent->read_proc = p->read_proc;
}
proc_create("capi/capi20", 0, NULL, &capi20_proc_fops);
proc_create("capi/capi20ncci", 0, NULL, &capi20ncci_proc_fops);
}

static void __exit proc_exit(void)
{
int nelem = ARRAY_SIZE(procfsentries);
int i;

for (i=nelem-1; i >= 0; i--) {
struct procfsentries *p = procfsentries + i;
if (p->procent) {
remove_proc_entry(p->name, NULL);
p->procent = NULL;
}
}
remove_proc_entry("capi/capi20", NULL);
remove_proc_entry("capi/capi20ncci", NULL);
}

/* -------- init function and module interface ---------------------- */
Expand Down
55 changes: 17 additions & 38 deletions drivers/isdn/capi/capidrv.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <linux/isdn.h>
#include <linux/isdnif.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/capi.h>
#include <linux/kernelcapi.h>
#include <linux/ctype.h>
Expand Down Expand Up @@ -2229,59 +2230,37 @@ static void lower_callback(unsigned int cmd, u32 contr, void *data)
* /proc/capi/capidrv:
* nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt
*/
static int proc_capidrv_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
static int capidrv_proc_show(struct seq_file *m, void *v)
{
int len = 0;

len += sprintf(page+len, "%lu %lu %lu %lu\n",
seq_printf(m, "%lu %lu %lu %lu\n",
global.ap.nrecvctlpkt,
global.ap.nrecvdatapkt,
global.ap.nsentctlpkt,
global.ap.nsentdatapkt);
if (off+count >= len)
*eof = 1;
if (len < off)
return 0;
*start = page + off;
return ((count < len-off) ? count : len-off);
return 0;
}

static int capidrv_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, capidrv_proc_show, NULL);
}

static struct procfsentries {
char *name;
mode_t mode;
int (*read_proc)(char *page, char **start, off_t off,
int count, int *eof, void *data);
struct proc_dir_entry *procent;
} procfsentries[] = {
/* { "capi", S_IFDIR, 0 }, */
{ "capi/capidrv", 0 , proc_capidrv_read_proc },
static const struct file_operations capidrv_proc_fops = {
.owner = THIS_MODULE,
.open = capidrv_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};

static void __init proc_init(void)
{
int nelem = ARRAY_SIZE(procfsentries);
int i;

for (i=0; i < nelem; i++) {
struct procfsentries *p = procfsentries + i;
p->procent = create_proc_entry(p->name, p->mode, NULL);
if (p->procent) p->procent->read_proc = p->read_proc;
}
proc_create("capi/capidrv", 0, NULL, &capidrv_proc_fops);
}

static void __exit proc_exit(void)
{
int nelem = ARRAY_SIZE(procfsentries);
int i;

for (i=nelem-1; i >= 0; i--) {
struct procfsentries *p = procfsentries + i;
if (p->procent) {
remove_proc_entry(p->name, NULL);
p->procent = NULL;
}
}
remove_proc_entry("capi/capidrv", NULL);
}

static int __init capidrv_init(void)
Expand Down
8 changes: 1 addition & 7 deletions drivers/isdn/capi/kcapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -490,13 +490,7 @@ attach_capi_ctr(struct capi_ctr *card)
card->traceflag = showcapimsgs;

sprintf(card->procfn, "capi/controllers/%d", card->cnr);
card->procent = create_proc_entry(card->procfn, 0, NULL);
if (card->procent) {
card->procent->read_proc =
(int (*)(char *,char **,off_t,int,int *,void *))
card->ctr_read_proc;
card->procent->data = card;
}
card->procent = proc_create_data(card->procfn, 0, NULL, card->proc_fops, card);

ncards++;
printk(KERN_NOTICE "kcapi: Controller [%03d]: %s attached\n",
Expand Down
Loading

0 comments on commit 9a58a80

Please sign in to comment.