Id which proc gets from IDR for inode number and id which proc removes
from IDR do not match. E.g. 0x11a transforms into 0x8000011a.
Which stayed unnoticed for a long time because, surprise, idr_remove()
masks out that high bit before doing anything.
All of this due to "| ~MAX_ID_MASK" in release_inode_number().
I still don't understand how it's supposed to work, because "| ~MASK"
is not an inversion for "& MAX" operation.
So, use just one nice, working addition. Make start offset unsigned int,
while I'm at it. It's longness is not used anywhere.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
static DEFINE_IDR(proc_inum_idr);
static DEFINE_SPINLOCK(proc_inum_lock); /* protects the above */
static DEFINE_IDR(proc_inum_idr);
static DEFINE_SPINLOCK(proc_inum_lock); /* protects the above */
-#define PROC_DYNAMIC_FIRST 0xF0000000UL
+#define PROC_DYNAMIC_FIRST 0xF0000000U
/*
* Return an inode number between PROC_DYNAMIC_FIRST and
/*
* Return an inode number between PROC_DYNAMIC_FIRST and
*/
static unsigned int get_inode_number(void)
{
*/
static unsigned int get_inode_number(void)
{
else if (error)
return 0;
else if (error)
return 0;
- inum = (i & MAX_ID_MASK) + PROC_DYNAMIC_FIRST;
-
- /* inum will never be more than 0xf0ffffff, so no check
- * for overflow.
- */
-
- return inum;
+ if (i > UINT_MAX - PROC_DYNAMIC_FIRST) {
+ spin_lock(&proc_inum_lock);
+ idr_remove(&proc_inum_idr, i);
+ spin_unlock(&proc_inum_lock);
+ }
+ return PROC_DYNAMIC_FIRST + i;
}
static void release_inode_number(unsigned int inum)
{
}
static void release_inode_number(unsigned int inum)
{
- int id = (inum - PROC_DYNAMIC_FIRST) | ~MAX_ID_MASK;
-
spin_lock(&proc_inum_lock);
spin_lock(&proc_inum_lock);
- idr_remove(&proc_inum_idr, id);
+ idr_remove(&proc_inum_idr, inum - PROC_DYNAMIC_FIRST);
spin_unlock(&proc_inum_lock);
}
spin_unlock(&proc_inum_lock);
}