"struct inode" and internal "struct cdev*"?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



  i recall asking a question about something like this not that long
ago, but i'm still a bit fuzzy on what happens when you open a
character device file in terms of its "struct cdev*" member.

  from <linux/fs.h>:

struct inode {

	... snip ...

        struct list_head        i_devices;
        union {
                struct pipe_inode_info  *i_pipe;
                struct block_device     *i_bdev;
                struct cdev             *i_cdev;
        };
        int                     i_cindex;
	... snip ...
};

  so it's easy to see that an inode can hold at most one pointer to
one of a pipe, block dev or char dev structure.  but, under normal
circumstances, when is that "i_cdev" field actually set to point to
the appropriate "struct cdev"?

  from the discussion in ch 3 of LDD3, if you're writing a module that
represents a character device, you have to set up your driver by
calling, among other things, cdev_init() and cdev_add() and
associating a FOPS structure with your driver, but does any of that
actually set that i_cdev pointer in the inode?

  i have to guess that it doesn't since the corresponding special
device file might not even *exist* yet, so i'm assuming that has to be
done in the chrdev_open() routine in fs/char_dev.c:

==========
/*
 * Called every time a character special file is opened
 */
static int chrdev_open(struct inode *inode, struct file *filp)
{
        struct cdev *p;
        struct cdev *new = NULL;
        int ret = 0;

        spin_lock(&cdev_lock);
        p = inode->i_cdev;
        if (!p) {
                struct kobject *kobj;
                int idx;
                spin_unlock(&cdev_lock);
                kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx);
                if (!kobj)
                        return -ENXIO;
                new = container_of(kobj, struct cdev, kobj);
                spin_lock(&cdev_lock);
                p = inode->i_cdev;
                if (!p) {
                        inode->i_cdev = p = new;
                        inode->i_cindex = idx;
                        list_add(&inode->i_devices, &p->list);
                        new = NULL;
                } else if (!cdev_get(p))
                        ret = -ENXIO;
        } else if (!cdev_get(p))
	...
==========

  unless something weird is happening underneath, i'm concluding that,
the *very first time* you try to open that special device file, the
code recognizes that i_cdev has no value, and has to invoke
kobj_lookup() to track down the corresponding kobject in the
system-wide cdev_map, from which you extract the cdev and fill in
inode->i_cdev.

  of course, after that's done *once*, it shouldn't have to be done
again as long as that device file and inode exist, is this correct?

rday
--

========================================================================
Robert P. J. Day
Linux Consulting, Training and Annoying Kernel Pedantry:
    Have classroom, will lecture.

http://crashcourse.ca                          Waterloo, Ontario, CANADA
========================================================================

--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx
Please read the FAQ at http://kernelnewbies.org/FAQ


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux