From: Karsten Wiese <annabellesgarden@yahoo.de>
To: Takashi Iwai <tiwai@suse.de>
Cc: linux-kernel@vger.kernel.org, alsa-devel@lists.sourceforge.net,
mingo@elte.hu
Subject: Re: [PATCH] Reset file->f_op in snd_card_file_remove(). Take 2
Date: Wed, 4 Oct 2006 22:01:53 +0200 [thread overview]
Message-ID: <200610042201.53337.annabellesgarden@yahoo.de> (raw)
In-Reply-To: <s5hmz8cjcp6.wl%tiwai@suse.de>
Am Mittwoch, 4. Oktober 2006 17:57 schrieb Takashi Iwai:
> > >
> > > The problem is that we use kmalloc for allocating a dummy f_op.
> > > IMO, the simlest solution is to use a static dummy f_op.
> > >
> > That'd take 1 static dummy f_op per snd_*_release().
>
> Yes, but it'll remove extra codes at the same time, too.
> Well, OTOH, it requires more additions for assignment of dummy ops...
>
> > I prefer the patch at the start of this thread :-)
>
> I think it's not good to set NULL always there. The NULL is necessary
I disagree. In snd_card_file_remove() the file has already been
released. Is file->f_op still used anywhere later on
except from __fput()'s call to fops_put(file->f_op); ?
First glance didn't show....
> only when the card is freed. So, I prefer the patch like below. Is
> it OK?
>
IMO not:
Lets assume 2 cpus CA, CB and two processes PA, PB,
closing their file's after usb disconnect of 1 snd_card.
PA running on CA going through snd_card_file_remove() first would not
have it's file->f_op set NULL.
Now PA is back in __fput() right after the
file->f_op->release(inode, file);
Some third process happens to be scheduled an CA.
Meanwhile PB running on CB goes through snd_card_file_remove()
and calls snd_card_do_free(card).
snd_card_do_free(card) frees PA's file->f_op.
PA is scheduled again and has a freed, non NULL file->f_op.
>
> Takashi
>
> diff -r f38b12373137 sound/core/init.c
> --- a/sound/core/init.c Wed Oct 04 17:17:32 2006 +0200
> +++ b/sound/core/init.c Wed Oct 04 17:50:11 2006 +0200
> @@ -721,8 +721,14 @@ int snd_card_file_remove(struct snd_card
> spin_unlock(&card->files_lock);
> if (last_close) {
> wake_up(&card->shutdown_sleep);
> - if (card->free_on_last_close)
> + if (card->free_on_last_close) {
> + /* release and clear f_op here since the dummy f_ops will
> + * be freed in snd_card_do_free().
> + */
> + fops_put(file->f_op);
> + file->f_op = NULL;
> snd_card_do_free(card);
> + }
> }
> if (!mfile) {
> snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file);
>
How about a "disconnecting device" that can emulate a real one
for diconnect reasons?
I've sketched one here:
-------------------------------------------------------------------
/* virtual device
hides a real device's f_ops,
exept for release
*/
struct snd_disconnected_file {
struct file *file;
int (*release) (struct inode *, struct file *);
struct snd_disconnected_file *next;
};
static struct snd_disconnected_file *disconnecting_files;
static struct file_operations snd_disconnect_f_ops;
int snd_disconnect_file(struct file *file, int (*release) (struct inode *, struct file *))
{
int err;
// TODO: zmalloc and initialize struct snd_disconnected_file,
// rechain
return err;
file->f_op = snd_disconnect_f_ops;
return 0;
}
static loff_t snd_disconnect_llseek(struct file *file, loff_t offset, int orig)
{
return -ENODEV;
}
static ssize_t snd_disconnect_read(struct file *file, char __user *buf,
size_t count, loff_t *offset)
{
return -ENODEV;
}
static ssize_t snd_disconnect_write(struct file *file, const char __user *buf,
size_t count, loff_t *offset)
{
return -ENODEV;
}
static int snd_disconnect_release(struct inode *inode, struct file *file)
{
struct snd_disconnected_file * df = disconnecting_files;
int err = 0;
while (df)
if (df->file == file) {
err = df->release(inode, file);
// TODO: free df, rechain
}
return err;
}
static unsigned int snd_disconnect_poll(struct file * file, poll_table * wait)
{
return POLLERR | POLLNVAL;
}
static long snd_disconnect_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
return -ENODEV;
}
static int snd_disconnect_mmap(struct file *file, struct vm_area_struct *vma)
{
return -ENODEV;
}
static int snd_disconnect_fasync(int fd, struct file *file, int on)
{
return -ENODEV;
}
static struct file_operations snd_disconnect_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,
.ioctl = snd_disconnect_ioctl,
.mmap = snd_disconnect_mmap,
.fasync = snd_disconnect_fasync
};
----------------------------------------
snd_card_disconnect() would call
int snd_disconnect_file(file, file->f_op->release)
instead of allocating/initing the special f_ops by itself.
We'd win memory by the difference
sizeof(struct snd_shutdown_f_ops) - sizeof(struct snd_disconnected_file)
.
And play safe.
We would need to be sure, a file->f_op's
int (*release) (struct inode *, struct file *);
id called exactly one time during a file's life though.
Karsten
next prev parent reply other threads:[~2006-10-04 20:00 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-09-28 20:28 Karsten Wiese
2006-09-29 10:48 ` Takashi Iwai
2006-09-29 12:29 ` Karsten Wiese
2006-09-29 12:26 ` Ingo Molnar
2006-09-29 12:45 ` Takashi Iwai
2006-10-01 18:29 ` Karsten Wiese
2006-10-04 9:22 ` Takashi Iwai
[not found] ` <200610041247.19624.annabellesgarden@yahoo.de>
2006-10-04 14:18 ` Takashi Iwai
2006-10-04 15:36 ` Karsten Wiese
2006-10-04 15:57 ` Takashi Iwai
2006-10-04 20:01 ` Karsten Wiese [this message]
2006-10-04 20:15 ` Takashi Iwai
2006-10-04 23:41 ` Karsten Wiese
2006-10-05 10:43 ` [Alsa-devel] " Takashi Iwai
2006-10-05 11:33 ` Karsten Wiese
2006-10-05 14:12 ` Karsten Wiese
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200610042201.53337.annabellesgarden@yahoo.de \
--to=annabellesgarden@yahoo.de \
--cc=alsa-devel@lists.sourceforge.net \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=tiwai@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®