Hi,
I've a kernel module which needs to get hold of the gen_disk structure. To make
it a bit interactive I've a user space program which uses stat sys call to get
the respective device's dev_t number (I use s_rdev of the struct stat) and pass
it on to my module via an ioctl call. This part works good.
When my module tries to use the get_gendisk function it returns NULL. I printed
out the MAJOR(dev_t) and MINOR(dev_t) and was surprised to get the value 0 for
MAJOR(dev_t). A little more digging got me to this code snippet, the file is
kdev_t.h
-----------------------------------------------------------%------------------------------------------------------------
#ifdef __KERNEL__
#define MINORBITS 20
#define MINORMASK ((1U << MINORBITS) - 1)
#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS))
#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK))
#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))
.....
#else /* __KERNEL__ */
/*
Some programs want their definitions of MAJOR and MINOR and MKDEV
from the kernel sources. These must be the externally visible ones.
*/
#define MAJOR(dev) ((dev)>>8)
#define MINOR(dev) ((dev) & 0xff)
#define MKDEV(ma,mi) ((ma)<<8 | (mi))
#endif /* __KERNEL__ */
-----------------------------------------------------------%------------------------------------------------------------
Since __KERNEL__ is defined in the topmost Makefile, the first definition of
macros would be used which is giving me the wrong result. But what I really
want is the #else one.
Surprisingly doing a major and minor in user space works. I traced it back to
the following code snippet, in file /usr/include/sys/sysmacros.h
-----------------------------------------------------------%------------------------------------------------------------
# if defined __GNUC__ && __GNUC__ >= 2 && defined __USE_EXTERN_INLINES
__extension__ __extern_inline unsigned int
__NTH (gnu_dev_major (unsigned long long int __dev))
{
return ((__dev >> 8) & 0xfff) | ((unsigned int) (__dev >> 32) & ~0xfff);
}
__extension__ __extern_inline unsigned int
__NTH (gnu_dev_minor (unsigned long long int __dev))
{
return (__dev & 0xff) | ((unsigned int) (__dev >> 12) & ~0xff);
}
....
#endif
# define major(dev) gnu_dev_major (dev)
# define minor(dev) gnu_dev_minor (dev)
-----------------------------------------------------------%------------------------------------------------------------
So basically the user space code doing stat and then major/minor works because
its doing the dev_t>>8.
My questions are,
1. How does MAJOR, MINOR are able to work within kernel with 32 bit
definitions?, since dev_t>>20 would make the major number 0 and get_gendisk
should then fail and most of the devices listed like my disks don't report a
quite big dev_t when I do stat on them.
2. Should I be checking for wether or not 32 bits dev_t is in effect? But if
I've to do this what's the purpose of using the macros MAJOR and MINOR? Aren't
these there to do the same job?
As an example, doing stat reported stat.s_rdev field to be 2065, which
accordingly translate to 8,17.
I'm using SLES 11 SP1, kernel 2.6.32
Regards,
Pranay Kr. Srivastava
[email protected]
Software Engineer
ERS,HCL Technologies
A-5, Sector 24, Noida 201301, U.P. (India)
::DISCLAIMER::
-----------------------------------------------------------------------------------------------------------------------
The contents of this e-mail and any attachment(s) are confidential and intended
for the named recipient(s) only.
It shall not attach any liability on the originator or HCL or its affiliates.
Any views or opinions presented in
this email are solely those of the author and may not necessarily reflect the
opinions of HCL or its affiliates.
Any form of reproduction, dissemination, copying, disclosure, modification,
distribution and / or publication of
this message without the prior written consent of the author of this e-mail is
strictly prohibited. If you have
received this email in error please delete it and notify the sender
immediately. Before opening any mail and
attachments please check them for viruses and defect.
-----------------------------------------------------------------------------------------------------------------------
_______________________________________________
Kernelnewbies mailing list
[email protected]
http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies