why struct cdev has kobject member? - linux

It's strange that struct cdev has struct kobject member, do any body knows the reason?

When kobjects are embedded inside other structures, the structures receive the standardized functions that a kobject provides. Most importantly, the structure's embedded kobject now enables the structure to become part of an object hierarchy. For example the cdev structure is presentable in an object hierarchy via the parent pointer cdev->kobj.parent and the list cdev->kobj.entry
Source: Linux Kernel Development by Robert Love

Sysfs is a Virtual filesystem that describes the devices available to the system in hierarchical pattern. This is done by using struct kobj.
struct kobject {
char *k_name;
char name[KOBJ_NAME_LEN];
struct kref kref;
struct list_head entry;
struct kobject *parent;
struct kset *kset;
struct kobj_type *ktype;
struct dentry *dentry;
};
For any driver kobj is required to export the device attributes to sysfs
if we consider like i2c_client spi_device(spi client). we have kobj inside member struct dev to export the driver attributes to the user space virtual filesystem(Sysfs). The Kobj structure members handles all the operations including referring to the device numbers(major/minor) and file operations involved for open, read/write,close etc... of device.
In your case cdev_init & cdev_add will internally uses kobj to do the above operation.

There are two reasons:
for reference counting, which is offered by kref internally.
static struct kobject *cdev_get(struct cdev *p)
{
struct module *owner = p->owner;
struct kobject *kobj;
if (owner && !try_module_get(owner))
return NULL;
kobj = kobject_get_unless_zero(&p->kobj);
if (!kobj)
module_put(owner);
return kobj;
}
void cdev_put(struct cdev *p)
{
if (p) {
struct module *owner = p->owner;
kobject_put(&p->kobj);
module_put(owner);
}
}
for release, that's also why kref is not enough(kref doesn't have a release hook).
static void cdev_default_release(struct kobject *kobj)
{
struct cdev *p = container_of(kobj, struct cdev, kobj);
struct kobject *parent = kobj->parent;
cdev_purge(p);
kobject_put(parent);
}
static void cdev_dynamic_release(struct kobject *kobj)
{
struct cdev *p = container_of(kobj, struct cdev, kobj);
struct kobject *parent = kobj->parent;
cdev_purge(p);
kfree(p);
kobject_put(parent);
}
static struct kobj_type ktype_cdev_default = {
.release = cdev_default_release,
};
static struct kobj_type ktype_cdev_dynamic = {
.release = cdev_dynamic_release,
};

Related

How can I get kobject and kset in Linux

I want to get the kobject and kset struct of /sys/fs/f2fs in Linux kernel.
I tried the following method:
kset_find_obj(fs_kobj->kset, "f2fs")
But null pointer error happened.
fs_kobj->kset seems to be null.
How can I do it?
I find a method as below:
struct kernfs_node *node = kernfs_find_and_get(fs_kobj->sd, "f2fs");
struct kobject *kobj = (struct kobject *)(node->priv);

the definition of spinlock_t in linux kernel

in include/linux/spinlock_types.h
the definition of spinlock_t like below
typedef struct spinlock {
union {
struct raw_spinlock rlock;
struct {
u8 __padding[];
struct lockdep_map dep_map;
};
};
} spinlock_t;
why the "__padding[]" and "dep_map" variable should put inside a struct which has no name
but not just like below?
typedef struct spinlock {
union {
struct raw_spinlock rlock;
u8 __padding[];
struct lockdep_map dep_map;
};
} spinlock_t;
is there any special meaning?
thank you
Because it is union of two structures and the other structure is enabled during debugging.
What you are trying to do is creating structure members that are not needed at all.And you should understand in union of two structures we can use one at a time.
typedef struct spinlock {
union {
struct raw_spinlock rlock;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
# define LOCK_PADSIZE (offsetof(struct raw_spinlock, dep_map))
struct {
u8 __padding[LOCK_PADSIZE];
struct lockdep_map dep_map;
};
#endif
};
} spinlock_t;

Why device->kobj->parent is equal to &device->parent->kobj as per LDD3?

I was going though chapter 14 of LDD3 and found following in the section 4;
As a general rule, device->kobj->parent is equal to
&device->parent->kobj
Can someone please explain why so?
I read section 1,2,3. But I guess I missed something or couldn't digest it.
You can think this as inheritance of the object oriented concept.
A struct kobject represents a kernel object, so device is kind subclass of a kobject.
struct device {
struct device * parent;
struct device_private * p;
struct kobject kobj;
..
}
struct kobject {
char *k_name;
char name[KOBJ_NAME_LEN];
struct kref kref;
struct list_head entry;
struct kobject *parent;
struct kset *kset;
struct kobj_type *ktype;
struct dentry *dentry;
};
A device has its parent device, and parent device's kobject is also parent of device's kobject. This relationship is taken care by the the linux kernel.
That's why device->kobj->parent equal to device->parent->kobj. (Device's kobject's parent equals to device's parent's kobject).

What is the point of magic value?

what is the 'magic' value in tty_driver struct
struct tty_driver {
int magic; /* magic number for this structure */
struct kref kref; /* Reference management */
struct cdev cdev;
struct module *owner;
const char *driver_name;
....
....
/* tty driver magic number */
#define TTY_DRIVER_MAGIC 0x5402
From tty_driver.h listing here.

Is it possible to find the corresponding task_struct from sched_entity?

I know if we have task_struct, surly we can get the contained sched_entity because it's one field in the task struct. But can we get the pointer to the task_struct given the shed_entity? Following is the sched_entity structure:
struct sched_entity {
struct load_weight load; /* for load-balancing */
struct rb_node run_node;
struct list_head group_node;
unsigned int on_rq;
u64 exec_start;
u64 sum_exec_runtime;
u64 vruntime;
u64 prev_sum_exec_runtime;
u64 nr_migrations;
#ifdef CONFIG_SCHEDSTATS
struct sched_statistics statistics;
#endif
#ifdef CONFIG_FAIR_GROUP_SCHED
struct sched_entity *parent;
/* rq on which this entity is (to be) queued: */
struct cfs_rq *cfs_rq;
/* rq "owned" by this entity/group: */
struct cfs_rq *my_q;
#endif
};
It seems that there is no place where I can get the task_struct. My final goal is to get the sched_entity of the task group_leader containing the task with this shed_entity :>
The Linux kernel code provides a standard way to take a pointer to an element contained within a structure, and get back a pointer to the containing structure: the container_of macro, which is used extensively throughout the kernel.
In this case, if you have a struct sched_entity *foo, you can get the enclosing task_struct with:
struct task_struct *task = container_of(foo, struct task_struct, se);
(Obviously this is only safe if you know for sure that the original struct sched_entity * pointer is pointing to a struct sched_entity which is inside a struct task_struct, so be careful...)

Resources