Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 085e5676 authored by Hannes Reinecke's avatar Hannes Reinecke Committed by Martin K. Petersen
Browse files

scsi: ch: add refcounting



struct scsi_changer needs refcounting as the device might be removed
while the fd is still open.

[mkp: whitespace]

Signed-off-by: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent db269932
Loading
Loading
Loading
Loading
+19 −3
Original line number Diff line number Diff line
@@ -105,6 +105,7 @@ do { \
static struct class * ch_sysfs_class;

typedef struct {
	struct kref         ref;
	struct list_head    list;
	int                 minor;
	char                name[8];
@@ -563,13 +564,23 @@ static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest)

/* ------------------------------------------------------------------------ */

static void ch_destroy(struct kref *ref)
{
	scsi_changer *ch = container_of(ref, scsi_changer, ref);

	kfree(ch->dt);
	kfree(ch);
}

static int
ch_release(struct inode *inode, struct file *file)
{
	scsi_changer *ch = file->private_data;

	scsi_device_put(ch->device);
	ch->device = NULL;
	file->private_data = NULL;
	kref_put(&ch->ref, ch_destroy);
	return 0;
}

@@ -588,6 +599,7 @@ ch_open(struct inode *inode, struct file *file)
		mutex_unlock(&ch_mutex);
		return -ENXIO;
	}
	kref_get(&ch->ref);
	spin_unlock(&ch_index_lock);

	file->private_data = ch;
@@ -935,8 +947,11 @@ static int ch_probe(struct device *dev)
	}

	mutex_init(&ch->lock);
	kref_init(&ch->ref);
	ch->device = sd;
	ch_readconfig(ch);
	ret = ch_readconfig(ch);
	if (ret)
		goto destroy_dev;
	if (init)
		ch_init_elem(ch);

@@ -944,6 +959,8 @@ static int ch_probe(struct device *dev)
	sdev_printk(KERN_INFO, sd, "Attached scsi changer %s\n", ch->name);

	return 0;
destroy_dev:
	device_destroy(ch_sysfs_class, MKDEV(SCSI_CHANGER_MAJOR, ch->minor));
remove_idr:
	idr_remove(&ch_index_idr, ch->minor);
free_ch:
@@ -960,8 +977,7 @@ static int ch_remove(struct device *dev)
	spin_unlock(&ch_index_lock);

	device_destroy(ch_sysfs_class, MKDEV(SCSI_CHANGER_MAJOR,ch->minor));
	kfree(ch->dt);
	kfree(ch);
	kref_put(&ch->ref, ch_destroy);
	return 0;
}