mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-28 22:54:05 +08:00
[PATCH 1/2] proc: fix inode number bogorithmetic
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>
This commit is contained in:
parent
8266602033
commit
67935df49d
@ -303,7 +303,7 @@ out:
|
|||||||
static DEFINE_IDR(proc_inum_idr);
|
static DEFINE_IDR(proc_inum_idr);
|
||||||
static DEFINE_SPINLOCK(proc_inum_lock); /* protects the above */
|
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
|
||||||
@ -311,7 +311,7 @@ static DEFINE_SPINLOCK(proc_inum_lock); /* protects the above */
|
|||||||
*/
|
*/
|
||||||
static unsigned int get_inode_number(void)
|
static unsigned int get_inode_number(void)
|
||||||
{
|
{
|
||||||
int i, inum = 0;
|
unsigned int i;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
@ -326,21 +326,18 @@ retry:
|
|||||||
else if (error)
|
else if (error)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
inum = (i & MAX_ID_MASK) + PROC_DYNAMIC_FIRST;
|
if (i > UINT_MAX - PROC_DYNAMIC_FIRST) {
|
||||||
|
spin_lock(&proc_inum_lock);
|
||||||
/* inum will never be more than 0xf0ffffff, so no check
|
idr_remove(&proc_inum_idr, i);
|
||||||
* for overflow.
|
spin_unlock(&proc_inum_lock);
|
||||||
*/
|
}
|
||||||
|
return PROC_DYNAMIC_FIRST + i;
|
||||||
return inum;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user