static int sysfs_open_file(struct inode *inode, struct file *file) { struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; struct sysfs_buffer *buffer; const struct sysfs_ops *ops; int error = -EACCES; /* need attr_sd for attr and ops, its parent for kobj */ if (!sysfs_get_active(attr_sd)) return -ENODEV; /* every kobject with an attribute needs a ktype assigned */ if (kobj->ktype && kobj->ktype->sysfs_ops) ops = kobj->ktype->sysfs_ops; else { WARN(1, KERN_ERR "missing sysfs attribute operations for " "kobject: %s\n", kobject_name(kobj)); goto err_out; } /* File needs write support. * The inode's perms must say it's ok, * and we must have a store method. */ if (file->f_mode & FMODE_WRITE) { if (!(inode->i_mode & S_IWUGO) || !ops->store) goto err_out; } /* File needs read support. * The inode's perms must say it's ok, and we there * must be a show method for it. */ if (file->f_mode & FMODE_READ) { if (!(inode->i_mode & S_IRUGO) || !ops->show) goto err_out; } /* No error? Great, allocate a buffer for the file, and store it * it in file->private_data for easy access. */ error = -ENOMEM; buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL); if (!buffer) goto err_out; mutex_init(&buffer->mutex); buffer->needs_read_fill = 1; buffer->ops = ops; file->private_data = buffer; /* make sure we have open dirent struct */ error = sysfs_get_open_dirent(attr_sd, buffer); if (error) goto err_free; /* open succeeded, put active references */ sysfs_put_active(attr_sd); return 0; err_free: kfree(buffer); err_out: sysfs_put_active(attr_sd); return error; }
static int sysfs_open_file(struct inode *inode, struct file *file) { struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; struct sysfs_buffer * buffer; struct sysfs_ops * ops = NULL; int error; /* need attr_sd for attr and ops, its parent for kobj */ if (!sysfs_get_active_two(attr_sd)) return -ENODEV; /* if the kobject has no ktype, then we assume that it is a subsystem * itself, and use ops for it. */ if (kobj->kset && kobj->kset->ktype) ops = kobj->kset->ktype->sysfs_ops; else if (kobj->ktype) ops = kobj->ktype->sysfs_ops; else ops = &subsys_sysfs_ops; error = -EACCES; /* No sysfs operations, either from having no subsystem, * or the subsystem have no operations. */ if (!ops) goto err_out; /* File needs write support. * The inode's perms must say it's ok, * and we must have a store method. */ if (file->f_mode & FMODE_WRITE) { if (!(inode->i_mode & S_IWUGO) || !ops->store) goto err_out; } /* File needs read support. * The inode's perms must say it's ok, and we there * must be a show method for it. */ if (file->f_mode & FMODE_READ) { if (!(inode->i_mode & S_IRUGO) || !ops->show) goto err_out; } /* No error? Great, allocate a buffer for the file, and store it * it in file->private_data for easy access. */ error = -ENOMEM; buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL); if (!buffer) goto err_out; mutex_init(&buffer->mutex); buffer->needs_read_fill = 1; buffer->ops = ops; file->private_data = buffer; /* make sure we have open dirent struct */ error = sysfs_get_open_dirent(attr_sd, buffer); if (error) goto err_free; /* open succeeded, put active references */ sysfs_put_active_two(attr_sd); return 0; err_free: kfree(buffer); err_out: sysfs_put_active_two(attr_sd); return error; }