[ALSA] Fix disconnection of proc interface

- Add the linked list to each proc entry to enable a single-shot
  disconnection (unregister)
- Deprecate snd_info_unregister(), use snd_info_free_entry()
- Removed NULL checks of snd_info_free_entry()

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
This commit is contained in:
Takashi Iwai 2006-06-23 14:37:59 +02:00 committed by Jaroslav Kysela
parent 42750b04c5
commit 746d4a02e6
21 changed files with 123 additions and 172 deletions

View File

@ -71,7 +71,6 @@ struct snd_info_entry {
mode_t mode;
long size;
unsigned short content;
unsigned short disconnected: 1;
union {
struct snd_info_entry_text text;
struct snd_info_entry_ops *ops;
@ -83,6 +82,8 @@ struct snd_info_entry {
void (*private_free)(struct snd_info_entry *entry);
struct proc_dir_entry *p;
struct mutex access;
struct list_head children;
struct list_head list;
};
#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS)
@ -122,8 +123,8 @@ int snd_info_restore_text(struct snd_info_entry * entry);
int snd_info_card_create(struct snd_card * card);
int snd_info_card_register(struct snd_card * card);
int snd_info_card_free(struct snd_card * card);
void snd_info_card_disconnect(struct snd_card * card);
int snd_info_register(struct snd_info_entry * entry);
int snd_info_unregister(struct snd_info_entry * entry);
/* for card drivers */
int snd_card_proc_new(struct snd_card *card, const char *name, struct snd_info_entry **entryp);
@ -156,8 +157,8 @@ static inline void snd_info_free_entry(struct snd_info_entry * entry) { ; }
static inline int snd_info_card_create(struct snd_card * card) { return 0; }
static inline int snd_info_card_register(struct snd_card * card) { return 0; }
static inline int snd_info_card_free(struct snd_card * card) { return 0; }
static inline void snd_info_card_disconnect(struct snd_card * card) { }
static inline int snd_info_register(struct snd_info_entry * entry) { return 0; }
static inline int snd_info_unregister(struct snd_info_entry * entry) { return 0; }
static inline int snd_card_proc_new(struct snd_card *card, const char *name,
struct snd_info_entry **entryp) { return -EINVAL; }

View File

@ -497,7 +497,7 @@ static void __init snd_hwdep_proc_init(void)
static void __exit snd_hwdep_proc_done(void)
{
snd_info_unregister(snd_hwdep_proc_entry);
snd_info_free_entry(snd_hwdep_proc_entry);
}
#else /* !CONFIG_PROC_FS */
#define snd_hwdep_proc_init()

View File

@ -78,6 +78,7 @@ struct snd_info_private_data {
static int snd_info_version_init(void);
static int snd_info_version_done(void);
static void snd_info_disconnect(struct snd_info_entry *entry);
/* resize the proc r/w buffer */
@ -304,7 +305,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
mutex_lock(&info_mutex);
p = PDE(inode);
entry = p == NULL ? NULL : (struct snd_info_entry *)p->data;
if (entry == NULL || entry->disconnected) {
if (entry == NULL || ! entry->p) {
mutex_unlock(&info_mutex);
return -ENODEV;
}
@ -586,10 +587,10 @@ int __exit snd_info_done(void)
snd_info_version_done();
if (snd_proc_root) {
#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
snd_info_unregister(snd_seq_root);
snd_info_free_entry(snd_seq_root);
#endif
#ifdef CONFIG_SND_OSSEMUL
snd_info_unregister(snd_oss_root);
snd_info_free_entry(snd_oss_root);
#endif
snd_remove_proc_entry(&proc_root, snd_proc_root);
}
@ -648,17 +649,28 @@ int snd_info_card_register(struct snd_card *card)
* de-register the card proc file
* called from init.c
*/
int snd_info_card_free(struct snd_card *card)
void snd_info_card_disconnect(struct snd_card *card)
{
snd_assert(card != NULL, return -ENXIO);
snd_assert(card != NULL, return);
mutex_lock(&info_mutex);
if (card->proc_root_link) {
snd_remove_proc_entry(snd_proc_root, card->proc_root_link);
card->proc_root_link = NULL;
}
if (card->proc_root) {
snd_info_unregister(card->proc_root);
card->proc_root = NULL;
}
if (card->proc_root)
snd_info_disconnect(card->proc_root);
mutex_unlock(&info_mutex);
}
/*
* release the card proc file resources
* called from init.c
*/
int snd_info_card_free(struct snd_card *card)
{
snd_assert(card != NULL, return -ENXIO);
snd_info_free_entry(card->proc_root);
card->proc_root = NULL;
return 0;
}
@ -767,6 +779,8 @@ static struct snd_info_entry *snd_info_create_entry(const char *name)
entry->mode = S_IFREG | S_IRUGO;
entry->content = SNDRV_INFO_CONTENT_TEXT;
mutex_init(&entry->access);
INIT_LIST_HEAD(&entry->children);
INIT_LIST_HEAD(&entry->list);
return entry;
}
@ -819,6 +833,24 @@ struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card,
EXPORT_SYMBOL(snd_info_create_card_entry);
static void snd_info_disconnect(struct snd_info_entry *entry)
{
struct list_head *p, *n;
struct proc_dir_entry *root;
list_for_each_safe(p, n, &entry->children) {
snd_info_disconnect(list_entry(p, struct snd_info_entry, list));
}
if (! entry->p)
return;
list_del_init(&entry->list);
root = entry->parent == NULL ? snd_proc_root : entry->parent->p;
snd_assert(root, return);
snd_remove_proc_entry(root, entry->p);
entry->p = NULL;
}
static int snd_info_dev_free_entry(struct snd_device *device)
{
struct snd_info_entry *entry = device->device_data;
@ -832,19 +864,6 @@ static int snd_info_dev_register_entry(struct snd_device *device)
return snd_info_register(entry);
}
static int snd_info_dev_disconnect_entry(struct snd_device *device)
{
struct snd_info_entry *entry = device->device_data;
entry->disconnected = 1;
return 0;
}
static int snd_info_dev_unregister_entry(struct snd_device *device)
{
struct snd_info_entry *entry = device->device_data;
return snd_info_unregister(entry);
}
/**
* snd_card_proc_new - create an info entry for the given card
* @card: the card instance
@ -871,8 +890,7 @@ int snd_card_proc_new(struct snd_card *card, const char *name,
static struct snd_device_ops ops = {
.dev_free = snd_info_dev_free_entry,
.dev_register = snd_info_dev_register_entry,
.dev_disconnect = snd_info_dev_disconnect_entry,
.dev_unregister = snd_info_dev_unregister_entry
/* disconnect is done via snd_info_card_disconnect() */
};
struct snd_info_entry *entry;
int err;
@ -901,6 +919,11 @@ void snd_info_free_entry(struct snd_info_entry * entry)
{
if (entry == NULL)
return;
if (entry->p) {
mutex_lock(&info_mutex);
snd_info_disconnect(entry);
mutex_unlock(&info_mutex);
}
kfree(entry->name);
if (entry->private_free)
entry->private_free(entry);
@ -935,38 +958,14 @@ int snd_info_register(struct snd_info_entry * entry)
p->size = entry->size;
p->data = entry;
entry->p = p;
if (entry->parent)
list_add_tail(&entry->list, &entry->parent->children);
mutex_unlock(&info_mutex);
return 0;
}
EXPORT_SYMBOL(snd_info_register);
/**
* snd_info_unregister - de-register the info entry
* @entry: the info entry
*
* De-registers the info entry and releases the instance.
*
* Returns zero if successful, or a negative error code on failure.
*/
int snd_info_unregister(struct snd_info_entry * entry)
{
struct proc_dir_entry *root;
if (! entry)
return 0;
snd_assert(entry->p != NULL, return -ENXIO);
root = entry->parent == NULL ? snd_proc_root : entry->parent->p;
snd_assert(root, return -ENXIO);
mutex_lock(&info_mutex);
snd_remove_proc_entry(root, entry->p);
mutex_unlock(&info_mutex);
snd_info_free_entry(entry);
return 0;
}
EXPORT_SYMBOL(snd_info_unregister);
/*
*/
@ -999,8 +998,7 @@ static int __init snd_info_version_init(void)
static int __exit snd_info_version_done(void)
{
if (snd_info_version_entry)
snd_info_unregister(snd_info_version_entry);
snd_info_free_entry(snd_info_version_entry);
return 0;
}

View File

@ -131,10 +131,8 @@ int snd_info_minor_register(void)
int snd_info_minor_unregister(void)
{
if (snd_sndstat_proc_entry) {
snd_info_unregister(snd_sndstat_proc_entry);
snd_sndstat_proc_entry = NULL;
}
snd_info_free_entry(snd_sndstat_proc_entry);
snd_sndstat_proc_entry = NULL;
return 0;
}

View File

@ -310,6 +310,7 @@ int snd_card_disconnect(struct snd_card *card)
if (err < 0)
snd_printk(KERN_ERR "not all devices for card %i can be disconnected\n", card->number);
snd_info_card_disconnect(card);
return 0;
}
@ -360,7 +361,7 @@ int snd_card_free(struct snd_card *card)
}
if (card->private_free)
card->private_free(card);
snd_info_unregister(card->proc_id);
snd_info_free_entry(card->proc_id);
if (snd_info_card_free(card) < 0) {
snd_printk(KERN_WARNING "unable to free card info\n");
/* Not fatal error */
@ -625,9 +626,9 @@ int __init snd_card_info_init(void)
int __exit snd_card_info_done(void)
{
snd_info_unregister(snd_card_info_entry);
snd_info_free_entry(snd_card_info_entry);
#ifdef MODULE
snd_info_unregister(snd_card_module_info_entry);
snd_info_free_entry(snd_card_module_info_entry);
#endif
return 0;
}

View File

@ -1193,10 +1193,8 @@ static void snd_mixer_oss_proc_init(struct snd_mixer_oss *mixer)
static void snd_mixer_oss_proc_done(struct snd_mixer_oss *mixer)
{
if (mixer->proc_entry) {
snd_info_unregister(mixer->proc_entry);
mixer->proc_entry = NULL;
}
snd_info_free_entry(mixer->proc_entry);
mixer->proc_entry = NULL;
}
#else /* !CONFIG_PROC_FS */
#define snd_mixer_oss_proc_init(mix)

View File

@ -2846,11 +2846,9 @@ static void snd_pcm_oss_proc_done(struct snd_pcm *pcm)
int stream;
for (stream = 0; stream < 2; ++stream) {
struct snd_pcm_str *pstr = &pcm->streams[stream];
if (pstr->oss.proc_entry) {
snd_info_unregister(pstr->oss.proc_entry);
pstr->oss.proc_entry = NULL;
snd_pcm_oss_proc_free_setup_list(pstr);
}
snd_info_free_entry(pstr->oss.proc_entry);
pstr->oss.proc_entry = NULL;
snd_pcm_oss_proc_free_setup_list(pstr);
}
}
#else /* !CONFIG_SND_VERBOSE_PROCFS */

View File

@ -494,19 +494,13 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
static int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr)
{
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
if (pstr->proc_xrun_debug_entry) {
snd_info_unregister(pstr->proc_xrun_debug_entry);
pstr->proc_xrun_debug_entry = NULL;
}
snd_info_free_entry(pstr->proc_xrun_debug_entry);
pstr->proc_xrun_debug_entry = NULL;
#endif
if (pstr->proc_info_entry) {
snd_info_unregister(pstr->proc_info_entry);
pstr->proc_info_entry = NULL;
}
if (pstr->proc_root) {
snd_info_unregister(pstr->proc_root);
pstr->proc_root = NULL;
}
snd_info_free_entry(pstr->proc_info_entry);
pstr->proc_info_entry = NULL;
snd_info_free_entry(pstr->proc_root);
pstr->proc_root = NULL;
return 0;
}
@ -570,29 +564,19 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
return 0;
}
static int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream)
{
if (substream->proc_info_entry) {
snd_info_unregister(substream->proc_info_entry);
substream->proc_info_entry = NULL;
}
if (substream->proc_hw_params_entry) {
snd_info_unregister(substream->proc_hw_params_entry);
substream->proc_hw_params_entry = NULL;
}
if (substream->proc_sw_params_entry) {
snd_info_unregister(substream->proc_sw_params_entry);
substream->proc_sw_params_entry = NULL;
}
if (substream->proc_status_entry) {
snd_info_unregister(substream->proc_status_entry);
substream->proc_status_entry = NULL;
}
if (substream->proc_root) {
snd_info_unregister(substream->proc_root);
substream->proc_root = NULL;
}
snd_info_free_entry(substream->proc_info_entry);
substream->proc_info_entry = NULL;
snd_info_free_entry(substream->proc_hw_params_entry);
substream->proc_hw_params_entry = NULL;
snd_info_free_entry(substream->proc_sw_params_entry);
substream->proc_sw_params_entry = NULL;
snd_info_free_entry(substream->proc_status_entry);
substream->proc_status_entry = NULL;
snd_info_free_entry(substream->proc_root);
substream->proc_root = NULL;
return 0;
}
#else /* !CONFIG_SND_VERBOSE_PROCFS */
@ -1090,8 +1074,7 @@ static void snd_pcm_proc_init(void)
static void snd_pcm_proc_done(void)
{
if (snd_pcm_proc_entry)
snd_info_unregister(snd_pcm_proc_entry);
snd_info_free_entry(snd_pcm_proc_entry);
}
#else /* !CONFIG_PROC_FS */

View File

@ -101,7 +101,7 @@ int snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream)
{
snd_pcm_lib_preallocate_dma_free(substream);
#ifdef CONFIG_SND_VERBOSE_PROCFS
snd_info_unregister(substream->proc_prealloc_entry);
snd_info_free_entry(substream->proc_prealloc_entry);
substream->proc_prealloc_entry = NULL;
#endif
return 0;

View File

@ -1599,7 +1599,7 @@ static int snd_rawmidi_dev_unregister(struct snd_device *device)
mutex_lock(&register_mutex);
list_del(&rmidi->list);
if (rmidi->proc_entry) {
snd_info_unregister(rmidi->proc_entry);
snd_info_free_entry(rmidi->proc_entry);
rmidi->proc_entry = NULL;
}
#ifdef CONFIG_SND_OSSEMUL

View File

@ -303,8 +303,7 @@ register_proc(void)
static void
unregister_proc(void)
{
if (info_entry)
snd_info_unregister(info_entry);
snd_info_free_entry(info_entry);
info_entry = NULL;
}
#endif /* CONFIG_PROC_FS */

View File

@ -573,7 +573,7 @@ static void __exit alsa_seq_device_exit(void)
{
remove_drivers();
#ifdef CONFIG_PROC_FS
snd_info_unregister(info_entry);
snd_info_free_entry(info_entry);
#endif
if (num_ops)
snd_printk(KERN_ERR "drivers not released (%d)\n", num_ops);

View File

@ -64,9 +64,9 @@ int __init snd_seq_info_init(void)
int __exit snd_seq_info_done(void)
{
snd_info_unregister(queues_entry);
snd_info_unregister(clients_entry);
snd_info_unregister(timer_entry);
snd_info_free_entry(queues_entry);
snd_info_free_entry(clients_entry);
snd_info_free_entry(timer_entry);
return 0;
}
#endif

View File

@ -387,8 +387,7 @@ int __init snd_minor_info_init(void)
int __exit snd_minor_info_done(void)
{
if (snd_minor_info_entry)
snd_info_unregister(snd_minor_info_entry);
snd_info_free_entry(snd_minor_info_entry);
return 0;
}
#endif /* CONFIG_PROC_FS */

View File

@ -270,8 +270,7 @@ int __init snd_minor_info_oss_init(void)
int __exit snd_minor_info_oss_done(void)
{
if (snd_minor_info_oss_entry)
snd_info_unregister(snd_minor_info_oss_entry);
snd_info_free_entry(snd_minor_info_oss_entry);
return 0;
}
#endif /* CONFIG_PROC_FS */

View File

@ -1126,7 +1126,7 @@ static void __init snd_timer_proc_init(void)
static void __exit snd_timer_proc_done(void)
{
snd_info_unregister(snd_timer_proc_entry);
snd_info_free_entry(snd_timer_proc_entry);
}
#else /* !CONFIG_PROC_FS */
#define snd_timer_proc_init()

View File

@ -159,8 +159,7 @@ int snd_opl4_create_proc(struct snd_opl4 *opl4)
void snd_opl4_free_proc(struct snd_opl4 *opl4)
{
if (opl4->proc_entry)
snd_info_unregister(opl4->proc_entry);
snd_info_free_entry(opl4->proc_entry);
}
#endif /* CONFIG_PROC_FS */

View File

@ -457,14 +457,10 @@ void snd_ac97_proc_init(struct snd_ac97 * ac97)
void snd_ac97_proc_done(struct snd_ac97 * ac97)
{
if (ac97->proc_regs) {
snd_info_unregister(ac97->proc_regs);
ac97->proc_regs = NULL;
}
if (ac97->proc) {
snd_info_unregister(ac97->proc);
ac97->proc = NULL;
}
snd_info_free_entry(ac97->proc_regs);
ac97->proc_regs = NULL;
snd_info_free_entry(ac97->proc);
ac97->proc = NULL;
}
void snd_ac97_bus_proc_init(struct snd_ac97_bus * bus)
@ -485,8 +481,6 @@ void snd_ac97_bus_proc_init(struct snd_ac97_bus * bus)
void snd_ac97_bus_proc_done(struct snd_ac97_bus * bus)
{
if (bus->proc) {
snd_info_unregister(bus->proc);
bus->proc = NULL;
}
snd_info_free_entry(bus->proc);
bus->proc = NULL;
}

View File

@ -868,35 +868,23 @@ int cs46xx_dsp_proc_done (struct snd_cs46xx *chip)
struct dsp_spos_instance * ins = chip->dsp_spos_instance;
int i;
if (ins->proc_sym_info_entry) {
snd_info_unregister(ins->proc_sym_info_entry);
ins->proc_sym_info_entry = NULL;
}
if (ins->proc_modules_info_entry) {
snd_info_unregister(ins->proc_modules_info_entry);
ins->proc_modules_info_entry = NULL;
}
if (ins->proc_parameter_dump_info_entry) {
snd_info_unregister(ins->proc_parameter_dump_info_entry);
ins->proc_parameter_dump_info_entry = NULL;
}
if (ins->proc_sample_dump_info_entry) {
snd_info_unregister(ins->proc_sample_dump_info_entry);
ins->proc_sample_dump_info_entry = NULL;
}
if (ins->proc_scb_info_entry) {
snd_info_unregister(ins->proc_scb_info_entry);
ins->proc_scb_info_entry = NULL;
}
if (ins->proc_task_info_entry) {
snd_info_unregister(ins->proc_task_info_entry);
ins->proc_task_info_entry = NULL;
}
snd_info_free_entry(ins->proc_sym_info_entry);
ins->proc_sym_info_entry = NULL;
snd_info_free_entry(ins->proc_modules_info_entry);
ins->proc_modules_info_entry = NULL;
snd_info_free_entry(ins->proc_parameter_dump_info_entry);
ins->proc_parameter_dump_info_entry = NULL;
snd_info_free_entry(ins->proc_sample_dump_info_entry);
ins->proc_sample_dump_info_entry = NULL;
snd_info_free_entry(ins->proc_scb_info_entry);
ins->proc_scb_info_entry = NULL;
snd_info_free_entry(ins->proc_task_info_entry);
ins->proc_task_info_entry = NULL;
mutex_lock(&chip->spos_mutex);
for (i = 0; i < ins->nscb; ++i) {
@ -905,10 +893,8 @@ int cs46xx_dsp_proc_done (struct snd_cs46xx *chip)
}
mutex_unlock(&chip->spos_mutex);
if (ins->proc_dsp_dir) {
snd_info_unregister (ins->proc_dsp_dir);
ins->proc_dsp_dir = NULL;
}
snd_info_free_entry(ins->proc_dsp_dir);
ins->proc_dsp_dir = NULL;
return 0;
}

View File

@ -233,7 +233,7 @@ void cs46xx_dsp_proc_free_scb_desc (struct dsp_scb_descriptor * scb)
snd_printdd("cs46xx_dsp_proc_free_scb_desc: freeing %s\n",scb->scb_name);
snd_info_unregister(scb->proc_info);
snd_info_free_entry(scb->proc_info);
scb->proc_info = NULL;
snd_assert (scb_info != NULL, return);

View File

@ -128,10 +128,8 @@ void snd_emux_proc_init(struct snd_emux *emu, struct snd_card *card, int device)
void snd_emux_proc_free(struct snd_emux *emu)
{
if (emu->proc) {
snd_info_unregister(emu->proc);
emu->proc = NULL;
}
snd_info_free_entry(emu->proc);
emu->proc = NULL;
}
#endif /* CONFIG_PROC_FS */