Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 39073
b: refs/heads/master
c: a9edfc6
h: refs/heads/master
i:
  39071: d8a25da
v: v3
  • Loading branch information
Karsten Wiese authored and Jaroslav Kysela committed Oct 6, 2006
1 parent dbc34ae commit 691fa15
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 43 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 4130d59b1ac6e32c130bd59dbce5eb30fede0197
refs/heads/master: a9edfc60227a1dc5c741666ff252a6055b73b184
4 changes: 2 additions & 2 deletions trunk/include/sound/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,10 @@ struct snd_device {
struct snd_monitor_file {
struct file *file;
struct snd_monitor_file *next;
const struct file_operations *disconnected_f_op;
struct list_head shutdown_list;
};

struct snd_shutdown_f_ops; /* define it later in init.c */

/* main structure for soundcard */

struct snd_card {
Expand Down
92 changes: 52 additions & 40 deletions trunk/sound/core/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@
#include <sound/control.h>
#include <sound/info.h>

struct snd_shutdown_f_ops {
struct file_operations f_ops;
struct snd_shutdown_f_ops *next;
};
static DEFINE_SPINLOCK(shutdown_lock);
static LIST_HEAD(shutdown_files);

static struct file_operations snd_shutdown_f_ops;

static unsigned int snd_cards_lock; /* locked for registering/using */
struct snd_card *snd_cards[SNDRV_CARDS];
Expand Down Expand Up @@ -198,6 +198,25 @@ static ssize_t snd_disconnect_write(struct file *file, const char __user *buf,
return -ENODEV;
}

static int snd_disconnect_release(struct inode *inode, struct file *file)
{
struct snd_monitor_file *df = NULL, *_df;

spin_lock(&shutdown_lock);
list_for_each_entry(_df, &shutdown_files, shutdown_list) {
if (_df->file == file) {
df = _df;
break;
}
}
spin_unlock(&shutdown_lock);

if (likely(df))
return df->disconnected_f_op->release(inode, file);

panic("%s(%p, %p) failed!", __FUNCTION__, inode, file);
}

static unsigned int snd_disconnect_poll(struct file * file, poll_table * wait)
{
return POLLERR | POLLNVAL;
Expand All @@ -219,6 +238,22 @@ static int snd_disconnect_fasync(int fd, struct file *file, int on)
return -ENODEV;
}

static struct file_operations snd_shutdown_f_ops =
{
.owner = THIS_MODULE,
.llseek = snd_disconnect_llseek,
.read = snd_disconnect_read,
.write = snd_disconnect_write,
.release = snd_disconnect_release,
.poll = snd_disconnect_poll,
.unlocked_ioctl = snd_disconnect_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = snd_disconnect_ioctl,
#endif
.mmap = snd_disconnect_mmap,
.fasync = snd_disconnect_fasync
};

/**
* snd_card_disconnect - disconnect all APIs from the file-operations (user space)
* @card: soundcard structure
Expand All @@ -234,9 +269,6 @@ int snd_card_disconnect(struct snd_card *card)
{
struct snd_monitor_file *mfile;
struct file *file;
struct snd_shutdown_f_ops *s_f_ops;
struct file_operations *f_ops;
const struct file_operations *old_f_ops;
int err;

spin_lock(&card->files_lock);
Expand All @@ -261,34 +293,14 @@ int snd_card_disconnect(struct snd_card *card)

/* it's critical part, use endless loop */
/* we have no room to fail */
s_f_ops = kmalloc(sizeof(struct snd_shutdown_f_ops), GFP_ATOMIC);
if (s_f_ops == NULL)
panic("Atomic allocation failed for snd_shutdown_f_ops!");

f_ops = &s_f_ops->f_ops;

memset(f_ops, 0, sizeof(*f_ops));
f_ops->owner = file->f_op->owner;
f_ops->release = file->f_op->release;
f_ops->llseek = snd_disconnect_llseek;
f_ops->read = snd_disconnect_read;
f_ops->write = snd_disconnect_write;
f_ops->poll = snd_disconnect_poll;
f_ops->unlocked_ioctl = snd_disconnect_ioctl;
#ifdef CONFIG_COMPAT
f_ops->compat_ioctl = snd_disconnect_ioctl;
#endif
f_ops->mmap = snd_disconnect_mmap;
f_ops->fasync = snd_disconnect_fasync;
mfile->disconnected_f_op = mfile->file->f_op;

s_f_ops->next = card->s_f_ops;
card->s_f_ops = s_f_ops;

f_ops = fops_get(f_ops);
spin_lock(&shutdown_lock);
list_add(&mfile->shutdown_list, &shutdown_files);
spin_unlock(&shutdown_lock);

old_f_ops = file->f_op;
file->f_op = f_ops; /* must be atomic */
fops_put(old_f_ops);
fops_get(&snd_shutdown_f_ops);
mfile->file->f_op = &snd_shutdown_f_ops;

mfile = mfile->next;
}
Expand Down Expand Up @@ -326,8 +338,6 @@ EXPORT_SYMBOL(snd_card_disconnect);
*/
static int snd_card_do_free(struct snd_card *card)
{
struct snd_shutdown_f_ops *s_f_ops;

#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
if (snd_mixer_oss_notify_callback)
snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE);
Expand All @@ -351,11 +361,6 @@ static int snd_card_do_free(struct snd_card *card)
snd_printk(KERN_WARNING "unable to free card info\n");
/* Not fatal error */
}
while (card->s_f_ops) {
s_f_ops = card->s_f_ops;
card->s_f_ops = s_f_ops->next;
kfree(s_f_ops);
}
kfree(card);
return 0;
}
Expand Down Expand Up @@ -670,6 +675,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file)
if (mfile == NULL)
return -ENOMEM;
mfile->file = file;
mfile->disconnected_f_op = NULL;
mfile->next = NULL;
spin_lock(&card->files_lock);
if (card->shutdown) {
Expand Down Expand Up @@ -716,6 +722,12 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
pfile = mfile;
mfile = mfile->next;
}
if (mfile && mfile->disconnected_f_op) {
fops_put(mfile->disconnected_f_op);
spin_lock(&shutdown_lock);
list_del(&mfile->shutdown_list);
spin_unlock(&shutdown_lock);
}
if (card->files == NULL)
last_close = 1;
spin_unlock(&card->files_lock);
Expand Down

0 comments on commit 691fa15

Please sign in to comment.