* Re: linux-next: Tree for Feb 7 (fakeroot BROKEN due to SYSV IPC support?)
2013-02-07 11:52 ` Sedat Dilek
@ 2013-02-07 13:39 ` Sedat Dilek
2013-02-07 14:40 ` Sedat Dilek
0 siblings, 1 reply; 9+ messages in thread
From: Sedat Dilek @ 2013-02-07 13:39 UTC (permalink / raw)
To: Tejun Heo
Cc: Stephen Rothwell, linux-next, linux-kernel, Al Viro,
Eric W. Biederman, Andrew Morton
[-- Attachment #1: Type: text/plain, Size: 7103 bytes --]
On Thu, Feb 7, 2013 at 12:52 PM, Sedat Dilek <sedat.dilek@gmail.com> wrote:
> On Thu, Feb 7, 2013 at 12:14 PM, Eric W. Biederman
> <ebiederm@xmission.com> wrote:
>> Sedat Dilek <sedat.dilek@gmail.com> writes:
>>
>>> On Thu, Feb 7, 2013 at 11:20 AM, Sedat Dilek <sedat.dilek@gmail.com> wrote:
>>>> On Thu, Feb 7, 2013 at 10:38 AM, Sedat Dilek <sedat.dilek@gmail.com> wrote:
>>>>> On Thu, Feb 7, 2013 at 7:37 AM, Stephen Rothwell <sfr@canb.auug.org.au> wrote:
>>>>>> Hi all,
>>>>>>
>>>>>> Changes since 20130206:
>>>>>>
>>>>>> Removed tree: kvmtool (still present via the tip tree)
>>>>>>
>>>>>> The block tree lost its build failure.
>>>>>>
>>>>>> The tip tree gained a conflict against the s390 tree.
>>>>>>
>>>>>> The kvm tree gained a conflict against Linus' tree.
>>>>>>
>>>>>> The tty tree lost its build failure.
>>>>>>
>>>>>> The arm-soc tree gained conflicts against the iommu tree.
>>>>>>
>>>>>> The signal tree gained a conflict against the s390 tree.
>>>>>>
>>>>>> The akpm tree gained a conflict against the kvm tree and lost its build
>>>>>> failure.
>>>>>>
>>>>>> ----------------------------------------------------------------------------
>>>>>>
>>>>>
>>>>> My build-script uses fakeroot and does no more start:
>>>>>
>>>>> $ ./scripts/build_linux-next.sh
>>>>> make options ...... CC=gcc-4.6 -j4
>>>>> KBUILD_BUILD_USER=sedat.dilek@gmail.com
>>>>> LOCALVERSION=-next20130207-2-iniza-small
>>>>> dep-pkg options ... KDEB_PKGVERSION=3.8.0~rc6~next20130207-2~iniza+dileks1
>>>>> fakeroot, while creating message channels: Invalid argument
>>>>> This may be due to a lack of SYSV IPC support.
>>>>> fakeroot: error while starting the `faked' daemon.
>>>>> kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec
>>>>> ... or kill -l [sigspec]
>>>>>
>>>>>
>>>>> Any hints?
>>>>> ( I could run strace... )
>>>>>
>>>>> - Sedat -
>>>>
>>>> Attached strace outputs within yesterday's (GOOD) and today's (BAD) Linux-Next.
>>>>
>>>> - Sedat -
>>>
>>> [ CCing Al and Eric ]
>>>
>>> I compared quickly the diff between the -next versions and saw changes
>>> coming from signal and userns trees.
>>> ( Sorry for re-attaching the strace outputs. )
>>
>> It has been about a week and a half since I have pushed anything into
>> the userns tree, and I don't have anything ipc related in my tree.
>> So the reason for the suspicion seems odd.
>>
>> The straces are useless because all they show is that fakeroot was
>> forked, but there is not a trace of fakeroot itself.
>>
>> Given the timing my initial suspect would be the idr_preload patches
>> from Tejun that were merged via Andrew's akpm tree. I didn't see
>> anything in there that would kill ipc but that is likely the most recent
>> touch to the ipc code.
>>
>
> [ CCing Tejun ]
>
> Hmm, still stepping in the dark...
>
> OK, fakeroot does PRELOADing so your assumption makes sense.
>
> How can I trigger fakeroot calls?
> Here I have...
> /usr/bin/faked-sysv
> /usr/bin/faked-tcp
>
> I think that is the main commit but I am not sure if I can revert the
> idr_preload part, otherwise it gets complicated:
>
> commit e2802c2defba1e5c88d7d168eb5c66813c86f249
> "idr: implement idr_preload[_end]() and idr_alloc()"
>
> $ grep idr ../Linux-Next-v20130206-VS-v20130207.diff | grep ^'++Applying:'
> ++Applying: block: fix ext_devt_idr handling
> ++Applying: idr: fix a subtle bug in idr_get_next()
> ++Applying: nfsd: idr_destroy() no longer needs idr_remove_all()
> ++Applying: idr: cosmetic updates to struct / initializer definitions
> ++Applying: idr: relocate idr_for_each_entry() and reorganize id[r|a]_get_new()
> ++Applying: idr: remove _idr_rc_to_errno() hack
> ++Applying: idr: refactor idr_get_new_above()
> ++Applying: idr: implement idr_preload[_end]() and idr_alloc()
> ++Applying: block: convert to idr_alloc()
> ++Applying: block/loop: convert to idr_alloc()
> ++Applying: atm/nicstar: convert to idr_alloc()
> ++Applying: drbd: convert to idr_alloc()
> ++Applying: dca: convert to idr_alloc()
> ++Applying: dmaengine: convert to idr_alloc()
> ++Applying: firewire: convert to idr_alloc()
> ++Applying: gpio: convert to idr_alloc()
> ++Applying: drm: convert to idr_alloc()
> ++Applying: drm/exynos: convert to idr_alloc()
> ++Applying: drm/i915: convert to idr_alloc()
> ++Applying: drm/sis: convert to idr_alloc()
> ++Applying: drm/via: convert to idr_alloc()
> ++Applying: drm/vmwgfx: convert to idr_alloc()
> ++Applying: i2c: convert to idr_alloc()
> ++Applying: IB/core: convert to idr_alloc()
> ++Applying: IB/amso1100: convert to idr_alloc()
> ++Applying: IB/cxgb3: convert to idr_alloc()
> ++Applying: IB/cxgb4: convert to idr_alloc()
> ++Applying: IB/ehca: convert to idr_alloc()
> ++Applying: IB/ipath: convert to idr_alloc()
> ++Applying: IB/mlx4: convert to idr_alloc()
> ++Applying: IB/ocrdma: convert to idr_alloc()
> ++Applying: IB/qib: convert to idr_alloc()
> ++Applying: dm: convert to idr_alloc()
> ++Applying: memstick: convert to idr_alloc()
> ++Applying: mfd: convert to idr_alloc()
> ++Applying: misc/c2port: convert to idr_alloc()
> ++Applying: misc/tifm_core: convert to idr_alloc()
> ++Applying: mmc: convert to idr_alloc()
> ++Applying: mtd: convert to idr_alloc()
> ++Applying: macvtap: convert to idr_alloc()
> ++Applying: ppp: convert to idr_alloc()
> ++Applying: power: convert to idr_alloc()
> ++Applying: pps: convert to idr_alloc()
> ++Applying: remoteproc: convert to idr_alloc()
> ++Applying: rpmsg: convert to idr_alloc()
> ++Applying: scsi/bfa: convert to idr_alloc()
> ++Applying: scsi: convert to idr_alloc()
> ++Applying: target/iscsi: convert to idr_alloc()
> ++Applying: scsi/lpfc: convert to idr_alloc()
> ++Applying: thermal: convert to idr_alloc()
> ++Applying: uio: convert to idr_alloc()
> ++Applying: vfio: convert to idr_alloc()
> ++Applying: dlm: convert to idr_alloc()
> ++Applying: inotify: convert to idr_alloc()
> ++Applying: ocfs2: convert to idr_alloc()
> ++Applying: ipc: convert to idr_alloc()
> ++Applying: cgroup: convert to idr_alloc()
> ++Applying: events: convert to idr_alloc()
> ++Applying: posix-timers: convert to idr_alloc()
> ++Applying: net/9p: convert to idr_alloc()
> ++Applying: mac80211: convert to idr_alloc()
> ++Applying: sctp: convert to idr_alloc()
> ++Applying: nfs4client: convert to idr_alloc()
>
> - Sedat -
>
> [1] http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git;a=commitdiff;h=e2802c2defba1e5c88d7d168eb5c66813c86f249
>
>> Eric
Hi Tejun,
Eric was right that your idr_preload/idr_alloc patches from mmotm-tree
in Linux-Next (next-20130207) caused that fakeroot crazyness.
I can't say if the whole series is BORKED or the IPC part.
Changelog in [1] says "compile-tested-only" :-).
commitdiff aebcb5a5f97e6e567bdd1b2651253de073afa572
"ipc: convert to idr_alloc()"
Reverting the series let me build my kernels with fakeroot!
Tejun, can you have a look at this?
Thanks!
Thank you Eric for the hints and sorry for my wrong suspicions.
Please, have a look at the attachments.
Regards,
- Sedat -
[1] http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git;a=commitdiff;h=aebcb5a5f97e6e567bdd1b2651253de073afa572
[-- Attachment #2: strace_3.8.0-rc6-next20130207-2-iniza-small.txt --]
[-- Type: text/plain, Size: 10108 bytes --]
execve("./scripts/build_linux-next.sh", ["./scripts/build_linux-next.sh"], [/* 48 vars */]) = 0
brk(0) = 0x2488000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f97e92d1000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=93838, ...}) = 0
mmap(NULL, 93838, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f97e92ba000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\200\30\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1811128, ...}) = 0
mmap(NULL, 3925208, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f97e8cf2000
mprotect(0x7f97e8ea7000, 2093056, PROT_NONE) = 0
mmap(0x7f97e90a6000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b4000) = 0x7f97e90a6000
mmap(0x7f97e90ac000, 17624, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f97e90ac000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f97e92b9000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f97e92b8000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f97e92b7000
arch_prctl(ARCH_SET_FS, 0x7f97e92b8700) = 0
mprotect(0x7f97e90a6000, 16384, PROT_READ) = 0
mprotect(0x619000, 4096, PROT_READ) = 0
mprotect(0x7f97e92d3000, 4096, PROT_READ) = 0
munmap(0x7f97e92ba000, 93838) = 0
getpid() = 2988
rt_sigaction(SIGCHLD, {0x40f100, ~[RTMIN RT_1], SA_RESTORER, 0x7f97e8d284a0}, NULL, 8) = 0
geteuid() = 1000
brk(0) = 0x2488000
brk(0x24a9000) = 0x24a9000
getppid() = 2985
stat("/home/wearefam/src/linux-kernel", {st_mode=S_IFDIR|0775, st_size=12288, ...}) = 0
stat(".", {st_mode=S_IFDIR|0775, st_size=12288, ...}) = 0
open("./scripts/build_linux-next.sh", O_RDONLY) = 3
fcntl(3, F_DUPFD, 10) = 10
close(3) = 0
fcntl(10, F_SETFD, FD_CLOEXEC) = 0
rt_sigaction(SIGINT, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGINT, {0x40f100, ~[RTMIN RT_1], SA_RESTORER, 0x7f97e8d284a0}, NULL, 8) = 0
rt_sigaction(SIGQUIT, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGQUIT, {SIG_DFL, ~[RTMIN RT_1], SA_RESTORER, 0x7f97e8d284a0}, NULL, 8) = 0
rt_sigaction(SIGTERM, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGTERM, {SIG_DFL, ~[RTMIN RT_1], SA_RESTORER, 0x7f97e8d284a0}, NULL, 8) = 0
read(10, "#!/bin/sh\n\n### HELP\n# 1. make de"..., 8192) = 3852
pipe([3, 4]) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f97e92b89d0) = 2989
close(4) = 0
read(3, "/home/wearefam/src/linux-kernel\n", 128) = 32
read(3, "", 128) = 0
--- SIGCHLD (Child exited) @ 0 (0) ---
rt_sigreturn(0x11) = 0
close(3) = 0
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 2989
chdir("/home/wearefam/src/linux-kernel/linux-next") = 0
pipe([3, 4]) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f97e92b89d0) = 2990
close(4) = 0
read(3, "4\n", 128) = 2
--- SIGCHLD (Child exited) @ 0 (0) ---
rt_sigreturn(0x11) = 2
read(3, "", 128) = 0
close(3) = 0
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 2990
pipe([3, 4]) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f97e92b89d0) = 2991
close(4) = 0
read(3, "3\n", 128) = 2
read(3, "", 128) = 0
--- SIGCHLD (Child exited) @ 0 (0) ---
rt_sigreturn(0x11) = 0
close(3) = 0
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 2991
pipe([3, 4]) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f97e92b89d0) = 2992
close(4) = 0
read(3, "8\n", 128) = 2
read(3, "", 128) = 0
--- SIGCHLD (Child exited) @ 0 (0) ---
rt_sigreturn(0x11) = 0
close(3) = 0
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 2992
pipe([3, 4]) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f97e92b89d0) = 2993
close(4) = 0
read(3, "0\n", 128) = 2
read(3, "", 128) = 0
--- SIGCHLD (Child exited) @ 0 (0) ---
rt_sigreturn(0x11) = 0
close(3) = 0
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 2993
pipe([3, 4]) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f97e92b89d0) = 2994
close(4) = 0
read(3, "-rc6\n", 128) = 5
read(3, "", 128) = 0
--- SIGCHLD (Child exited) @ 0 (0) ---
rt_sigreturn(0x11) = 0
close(3) = 0
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 2994
pipe([3, 4]) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f97e92b89d0) = 2995
close(4) = 0
read(3, "next20130207\n", 128) = 13
read(3, "", 128) = 0
--- SIGCHLD (Child exited) @ 0 (0) ---
rt_sigreturn(0x11) = 0
close(3) = 0
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 2995
pipe([3, 4]) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f97e92b89d0) = 3000
close(4) = 0
read(3, "3.8.0~rc6\n", 128) = 10
read(3, "", 128) = 0
close(3) = 0
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 3000
--- SIGCHLD (Child exited) @ 0 (0) ---
rt_sigreturn(0x11) = 3000
write(1, "make options ...... CC=gcc-4.6 -"..., 116make options ...... CC=gcc-4.6 -j4 KBUILD_BUILD_USER=sedat.dilek@gmail.com LOCALVERSION=-next20130207-2-iniza-small
) = 116
write(1, "dep-pkg options ... KDEB_PKGVERS"..., 75dep-pkg options ... KDEB_PKGVERSION=3.8.0~rc6~next20130207-2~iniza+dileks1
) = 75
openat(AT_FDCWD, ".", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3
getdents(3, /* 56 entries */, 32768) = 1800
getdents(3, /* 0 entries */, 32768) = 0
close(3) = 0
stat("/opt/llvm/bin/rm", 0x7fff3460ed60) = -1 ENOENT (No such file or directory)
stat("/usr/lib/lightdm/lightdm/rm", 0x7fff3460ed60) = -1 ENOENT (No such file or directory)
stat("/usr/local/sbin/rm", 0x7fff3460ed60) = -1 ENOENT (No such file or directory)
stat("/usr/local/bin/rm", 0x7fff3460ed60) = -1 ENOENT (No such file or directory)
stat("/usr/sbin/rm", 0x7fff3460ed60) = -1 ENOENT (No such file or directory)
stat("/usr/bin/rm", 0x7fff3460ed60) = -1 ENOENT (No such file or directory)
stat("/sbin/rm", 0x7fff3460ed60) = -1 ENOENT (No such file or directory)
stat("/bin/rm", {st_mode=S_IFREG|0755, st_size=55888, ...}) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f97e92b89d0) = 3003
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 3003
--- SIGCHLD (Child exited) @ 0 (0) ---
rt_sigreturn(0x11) = 3003
stat("/opt/llvm/bin/fakeroot", 0x7fff3460edc0) = -1 ENOENT (No such file or directory)
stat("/usr/lib/lightdm/lightdm/fakeroot", 0x7fff3460edc0) = -1 ENOENT (No such file or directory)
stat("/usr/local/sbin/fakeroot", 0x7fff3460edc0) = -1 ENOENT (No such file or directory)
stat("/usr/local/bin/fakeroot", 0x7fff3460edc0) = -1 ENOENT (No such file or directory)
stat("/usr/sbin/fakeroot", 0x7fff3460edc0) = -1 ENOENT (No such file or directory)
stat("/usr/bin/fakeroot", {st_mode=S_IFREG|0755, st_size=3895, ...}) = 0
pipe([3, 4]) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f97e92b89d0) = 3004
close(4) = 0
stat("/opt/llvm/bin/tee", 0x7fff3460edc0) = -1 ENOENT (No such file or directory)
stat("/usr/lib/lightdm/lightdm/tee", 0x7fff3460edc0) = -1 ENOENT (No such file or directory)
stat("/usr/local/sbin/tee", 0x7fff3460edc0) = -1 ENOENT (No such file or directory)
stat("/usr/local/bin/tee", 0x7fff3460edc0) = -1 ENOENT (No such file or directory)
stat("/usr/sbin/tee", 0x7fff3460edc0) = -1 ENOENT (No such file or directory)
stat("/usr/bin/tee", {st_mode=S_IFREG|0755, st_size=27072, ...}) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f97e92b89d0) = 3005
close(3) = 0
close(4294967295) = -1 EBADF (Bad file descriptor)
wait4(-1, make KBUILD_SRC=
make[3]: Nothing to be done for `all'.
CHK include/generated/uapi/linux/version.h
CHK include/generated/utsrelease.h
CC scripts/mod/devicetable-offsets.s
GEN scripts/mod/devicetable-offsets.h
HOSTCC scripts/mod/file2alias.o
HOSTLD scripts/mod/modpost
make[3]: Nothing to be done for `relocs'.
[-- Attachment #3: 3.8.0-rc6-next20130207-2-iniza-small.patch --]
[-- Type: application/octet-stream, Size: 100947 bytes --]
Sedat Dilek (62):
kbuild: deb-pkg: Try to determine distribution
kbuild: deb-pkg: Bump year in debian/copyright file
kbuild: deb-pkg: Update git repository URL in debian/copyright file
Merge tag 'next-20130207' of git://git.kernel.org/.../next/linux-next into Linux-Next-v20130207
Revert "nfs4client: convert to idr_alloc()"
Revert "sctp: convert to idr_alloc()"
Revert "mac80211: convert to idr_alloc()"
Revert "net/9p: convert to idr_alloc()"
Revert "posix-timers: convert to idr_alloc()"
Revert "events: convert to idr_alloc()"
Revert "cgroup: convert to idr_alloc()"
Revert "ipc: convert to idr_alloc()"
Revert "ocfs2: convert to idr_alloc()"
Revert "inotify: convert to idr_alloc()"
Revert "dlm: convert to idr_alloc()"
Revert "vfio: convert to idr_alloc()"
Revert "uio: convert to idr_alloc()"
Revert "thermal: convert to idr_alloc()"
Revert "scsi/lpfc: convert to idr_alloc()"
Revert "target/iscsi: convert to idr_alloc()"
Revert "scsi: convert to idr_alloc()"
Revert "scsi/bfa: convert to idr_alloc()"
Revert "rpmsg: convert to idr_alloc()"
Revert "remoteproc: convert to idr_alloc()"
Revert "pps: convert to idr_alloc()"
Revert "power: convert to idr_alloc()"
Revert "ppp: convert to idr_alloc()"
Revert "macvtap: convert to idr_alloc()"
Revert "mtd: convert to idr_alloc()"
Revert "mmc: convert to idr_alloc()"
Revert "misc/tifm_core: convert to idr_alloc()"
Revert "misc/c2port: convert to idr_alloc()"
Revert "mfd: convert to idr_alloc()"
Revert "memstick: convert to idr_alloc()"
Revert "dm: convert to idr_alloc()"
Revert "IB/qib: convert to idr_alloc()"
Revert "IB/ocrdma: convert to idr_alloc()"
Revert "IB/mlx4: convert to idr_alloc()"
Revert "IB/ipath: convert to idr_alloc()"
Revert "IB/ehca: convert to idr_alloc()"
Revert "IB/cxgb4: convert to idr_alloc()"
Revert "IB/cxgb3: convert to idr_alloc()"
Revert "IB/amso1100: convert to idr_alloc()"
Revert "IB/core: convert to idr_alloc()"
Revert "i2c: convert to idr_alloc()"
Revert "drm/vmwgfx: convert to idr_alloc()"
Revert "drm/via: convert to idr_alloc()"
Revert "drm/sis: convert to idr_alloc()"
Revert "drm/i915: convert to idr_alloc()"
Revert "drm/exynos: convert to idr_alloc()"
Revert "drm: convert to idr_alloc()"
Revert "gpio: convert to idr_alloc()"
Revert "firewire: convert to idr_alloc()"
Revert "dmaengine: convert to idr_alloc()"
Revert "dca: convert to idr_alloc()"
Revert "drbd: convert to idr_alloc()"
Revert "atm/nicstar: convert to idr_alloc()"
Revert "block/loop: convert to idr_alloc()"
Revert "block: convert to idr_alloc()"
Revert "idr: implement idr_preload[_end]() and idr_alloc()"
Merge branch 'deb-pkg-fixes' into 3.8.0-rc6-next20130207-2-iniza-small
Merge branch 'revert-idr-from-akpm' into 3.8.0-rc6-next20130207-2-iniza-small
block/bsg.c | 26 +++--
block/genhd.c | 21 +++-
drivers/atm/nicstar.c | 24 +++-
drivers/block/drbd/drbd_main.c | 29 ++---
drivers/block/loop.c | 23 +++-
drivers/dca/dca-sysfs.c | 23 ++--
drivers/dma/dmaengine.c | 16 ++-
drivers/firewire/core-cdev.c | 19 ++--
drivers/firewire/core-device.c | 8 +-
drivers/gpio/gpiolib.c | 11 +-
drivers/gpu/drm/drm_context.c | 17 ++-
drivers/gpu/drm/drm_crtc.c | 19 +++-
drivers/gpu/drm/drm_gem.c | 35 +++---
drivers/gpu/drm/drm_stub.c | 19 +++-
drivers/gpu/drm/exynos/exynos_drm_ipp.c | 16 ++-
drivers/gpu/drm/i915/i915_gem_context.c | 21 +++-
drivers/gpu/drm/sis/sis_mm.c | 13 ++-
drivers/gpu/drm/via/via_mm.c | 13 ++-
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 17 +--
drivers/i2c/i2c-core.c | 45 ++++++--
drivers/infiniband/core/cm.c | 22 ++--
drivers/infiniband/core/cma.c | 24 ++--
drivers/infiniband/core/sa_query.c | 18 ++-
drivers/infiniband/core/ucm.c | 16 ++-
drivers/infiniband/core/ucma.c | 32 ++++--
drivers/infiniband/core/uverbs_cmd.c | 17 +--
drivers/infiniband/hw/amso1100/c2_qp.c | 19 ++--
drivers/infiniband/hw/cxgb3/iwch.h | 24 ++--
drivers/infiniband/hw/cxgb4/iw_cxgb4.h | 27 +++--
drivers/infiniband/hw/ehca/ehca_cq.c | 27 +++--
drivers/infiniband/hw/ehca/ehca_qp.c | 34 +++---
drivers/infiniband/hw/ipath/ipath_driver.c | 16 ++-
drivers/infiniband/hw/mlx4/cm.c | 32 +++---
drivers/infiniband/hw/ocrdma/ocrdma_main.c | 14 ++-
drivers/infiniband/hw/qib/qib_init.c | 21 ++--
drivers/md/dm.c | 54 ++++++---
drivers/memstick/core/memstick.c | 21 ++--
drivers/memstick/core/mspro_block.c | 17 ++-
drivers/mfd/rtsx_pcr.c | 13 ++-
drivers/misc/c2port/core.c | 22 ++--
drivers/misc/tifm_core.c | 11 +-
drivers/mmc/core/host.c | 11 +-
drivers/mtd/mtdcore.c | 9 +-
drivers/net/macvtap.c | 21 +++-
drivers/net/ppp/ppp_generic.c | 33 +++++-
drivers/power/bq2415x_charger.c | 11 +-
drivers/power/bq27x00_battery.c | 9 +-
drivers/power/ds2782_battery.c | 9 +-
drivers/pps/kapi.c | 2 +-
drivers/pps/pps.c | 36 +++---
drivers/remoteproc/remoteproc_core.c | 10 +-
drivers/rpmsg/virtio_rpmsg_bus.c | 30 +++--
drivers/scsi/bfa/bfad_im.c | 15 ++-
drivers/scsi/ch.c | 21 ++--
drivers/scsi/lpfc/lpfc_init.c | 12 +-
drivers/scsi/sg.c | 43 +++++---
drivers/scsi/st.c | 27 +++--
drivers/target/iscsi/iscsi_target.c | 15 ++-
drivers/target/iscsi/iscsi_target_login.c | 15 ++-
drivers/thermal/cpu_cooling.c | 17 ++-
drivers/thermal/thermal_sys.c | 17 ++-
drivers/uio/uio.c | 19 +++-
drivers/vfio/vfio.c | 17 ++-
fs/dlm/lock.c | 18 ++-
fs/dlm/recover.c | 27 ++---
fs/nfs/nfs4client.c | 13 ++-
fs/notify/inotify/inotify_user.c | 24 ++--
fs/ocfs2/cluster/tcp.c | 32 +++---
include/linux/idr.h | 14 ---
ipc/util.c | 30 +++--
kernel/cgroup.c | 27 +++--
kernel/events/core.c | 10 +-
kernel/posix-timers.c | 18 +--
lib/idr.c | 171 ++---------------------------
net/9p/util.c | 17 ++-
net/mac80211/main.c | 2 +
net/mac80211/tx.c | 18 ++-
net/sctp/associola.c | 31 +++---
scripts/package/builddeb | 19 +++-
79 files changed, 1049 insertions(+), 717 deletions(-)
diff --git a/block/bsg.c b/block/bsg.c
index 420a5a9..e334bd9 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -996,7 +996,7 @@ int bsg_register_queue(struct request_queue *q, struct device *parent,
{
struct bsg_class_device *bcd;
dev_t dev;
- int ret;
+ int ret, minor;
struct device *class_dev = NULL;
const char *devname;
@@ -1016,16 +1016,23 @@ int bsg_register_queue(struct request_queue *q, struct device *parent,
mutex_lock(&bsg_mutex);
- ret = idr_alloc(&bsg_minor_idr, bcd, 0, BSG_MAX_DEVS, GFP_KERNEL);
- if (ret < 0) {
- if (ret == -ENOSPC) {
- printk(KERN_ERR "bsg: too many bsg devices\n");
- ret = -EINVAL;
- }
+ ret = idr_pre_get(&bsg_minor_idr, GFP_KERNEL);
+ if (!ret) {
+ ret = -ENOMEM;
goto unlock;
}
- bcd->minor = ret;
+ ret = idr_get_new(&bsg_minor_idr, bcd, &minor);
+ if (ret < 0)
+ goto unlock;
+
+ if (minor >= BSG_MAX_DEVS) {
+ printk(KERN_ERR "bsg: too many bsg devices\n");
+ ret = -EINVAL;
+ goto remove_idr;
+ }
+
+ bcd->minor = minor;
bcd->queue = q;
bcd->parent = get_device(parent);
bcd->release = release;
@@ -1051,7 +1058,8 @@ unregister_class_dev:
device_unregister(class_dev);
put_dev:
put_device(parent);
- idr_remove(&bsg_minor_idr, bcd->minor);
+remove_idr:
+ idr_remove(&bsg_minor_idr, minor);
unlock:
mutex_unlock(&bsg_mutex);
return ret;
diff --git a/block/genhd.c b/block/genhd.c
index a1ed52a..d4e7370 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -411,7 +411,7 @@ static int blk_mangle_minor(int minor)
int blk_alloc_devt(struct hd_struct *part, dev_t *devt)
{
struct gendisk *disk = part_to_disk(part);
- int idx;
+ int idx, rc;
/* in consecutive minor range? */
if (part->partno < disk->minors) {
@@ -420,11 +420,20 @@ int blk_alloc_devt(struct hd_struct *part, dev_t *devt)
}
/* allocate ext devt */
- mutex_lock(&ext_devt_mutex);
- idx = idr_alloc(&ext_devt_idr, part, 0, NR_EXT_DEVT, GFP_KERNEL);
- mutex_unlock(&ext_devt_mutex);
- if (idx < 0)
- return idx == -ENOSPC ? -EBUSY : idx;
+ do {
+ if (!idr_pre_get(&ext_devt_idr, GFP_KERNEL))
+ return -ENOMEM;
+ mutex_lock(&ext_devt_mutex);
+ rc = idr_get_new(&ext_devt_idr, part, &idx);
+ if (!rc && idx >= NR_EXT_DEVT) {
+ idr_remove(&ext_devt_idr, idx);
+ rc = -EBUSY;
+ }
+ mutex_unlock(&ext_devt_mutex);
+ } while (rc == -EAGAIN);
+
+ if (rc)
+ return rc;
*devt = MKDEV(BLOCK_EXT_MAJOR, blk_mangle_minor(idx));
return 0;
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
index 6587dc2..628787e 100644
--- a/drivers/atm/nicstar.c
+++ b/drivers/atm/nicstar.c
@@ -949,10 +949,11 @@ static void free_scq(ns_dev *card, scq_info *scq, struct atm_vcc *vcc)
static void push_rxbufs(ns_dev * card, struct sk_buff *skb)
{
struct sk_buff *handle1, *handle2;
- int id1, id2;
+ u32 id1 = 0, id2 = 0;
u32 addr1, addr2;
u32 stat;
unsigned long flags;
+ int err;
/* *BARF* */
handle2 = NULL;
@@ -1025,12 +1026,23 @@ static void push_rxbufs(ns_dev * card, struct sk_buff *skb)
card->lbfqc += 2;
}
- id1 = idr_alloc(&card->idr, handle1, 0, 0, GFP_ATOMIC);
- if (id1 < 0)
- goto out;
+ do {
+ if (!idr_pre_get(&card->idr, GFP_ATOMIC)) {
+ printk(KERN_ERR
+ "nicstar%d: no free memory for idr\n",
+ card->index);
+ goto out;
+ }
+
+ if (!id1)
+ err = idr_get_new_above(&card->idr, handle1, 0, &id1);
+
+ if (!id2 && err == 0)
+ err = idr_get_new_above(&card->idr, handle2, 0, &id2);
+
+ } while (err == -EAGAIN);
- id2 = idr_alloc(&card->idr, handle2, 0, 0, GFP_ATOMIC);
- if (id2 < 0)
+ if (err)
goto out;
spin_lock_irqsave(&card->res_lock, flags);
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index e98da67..8c13eeb 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -2660,24 +2660,25 @@ enum drbd_ret_code conn_new_minor(struct drbd_tconn *tconn, unsigned int minor,
mdev->read_requests = RB_ROOT;
mdev->write_requests = RB_ROOT;
- minor_got = idr_alloc(&minors, mdev, minor, minor + 1, GFP_KERNEL);
- if (minor_got < 0) {
- if (minor_got == -ENOSPC) {
- err = ERR_MINOR_EXISTS;
- drbd_msg_put_info("requested minor exists already");
- }
+ if (!idr_pre_get(&minors, GFP_KERNEL))
+ goto out_no_minor_idr;
+ if (idr_get_new_above(&minors, mdev, minor, &minor_got))
goto out_no_minor_idr;
+ if (minor_got != minor) {
+ err = ERR_MINOR_EXISTS;
+ drbd_msg_put_info("requested minor exists already");
+ goto out_idr_remove_minor;
}
- vnr_got = idr_alloc(&tconn->volumes, mdev, vnr, vnr + 1, GFP_KERNEL);
- if (vnr_got < 0) {
- if (vnr_got == -ENOSPC) {
- err = ERR_INVALID_REQUEST;
- drbd_msg_put_info("requested volume exists already");
- }
+ if (!idr_pre_get(&tconn->volumes, GFP_KERNEL))
+ goto out_idr_remove_minor;
+ if (idr_get_new_above(&tconn->volumes, mdev, vnr, &vnr_got))
goto out_idr_remove_minor;
+ if (vnr_got != vnr) {
+ err = ERR_INVALID_REQUEST;
+ drbd_msg_put_info("requested volume exists already");
+ goto out_idr_remove_vol;
}
-
add_disk(disk);
kref_init(&mdev->kref); /* one ref for both idrs and the the add_disk */
@@ -2688,6 +2689,8 @@ enum drbd_ret_code conn_new_minor(struct drbd_tconn *tconn, unsigned int minor,
return NO_ERROR;
+out_idr_remove_vol:
+ idr_remove(&tconn->volumes, vnr_got);
out_idr_remove_minor:
idr_remove(&minors, minor_got);
synchronize_rcu();
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 56a3963..dc3891e 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1611,17 +1611,30 @@ static int loop_add(struct loop_device **l, int i)
if (!lo)
goto out;
- /* allocate id, if @id >= 0, we're requesting that specific id */
+ if (!idr_pre_get(&loop_index_idr, GFP_KERNEL))
+ goto out_free_dev;
+
if (i >= 0) {
- err = idr_alloc(&loop_index_idr, lo, i, i + 1, GFP_KERNEL);
- if (err == -ENOSPC)
+ int m;
+
+ /* create specific i in the index */
+ err = idr_get_new_above(&loop_index_idr, lo, i, &m);
+ if (err >= 0 && i != m) {
+ idr_remove(&loop_index_idr, m);
err = -EEXIST;
+ }
+ } else if (i == -1) {
+ int m;
+
+ /* get next free nr */
+ err = idr_get_new(&loop_index_idr, lo, &m);
+ if (err >= 0)
+ i = m;
} else {
- err = idr_alloc(&loop_index_idr, lo, 0, 0, GFP_KERNEL);
+ err = -EINVAL;
}
if (err < 0)
goto out_free_dev;
- i = err;
lo->lo_queue = blk_alloc_queue(GFP_KERNEL);
if (!lo->lo_queue)
diff --git a/drivers/dca/dca-sysfs.c b/drivers/dca/dca-sysfs.c
index 126cf29..591b659 100644
--- a/drivers/dca/dca-sysfs.c
+++ b/drivers/dca/dca-sysfs.c
@@ -53,19 +53,22 @@ void dca_sysfs_remove_req(struct dca_provider *dca, int slot)
int dca_sysfs_add_provider(struct dca_provider *dca, struct device *dev)
{
struct device *cd;
- int ret;
+ int err = 0;
- idr_preload(GFP_KERNEL);
+idr_try_again:
+ if (!idr_pre_get(&dca_idr, GFP_KERNEL))
+ return -ENOMEM;
spin_lock(&dca_idr_lock);
-
- ret = idr_alloc(&dca_idr, dca, 0, 0, GFP_NOWAIT);
- if (ret >= 0)
- dca->id = ret;
-
+ err = idr_get_new(&dca_idr, dca, &dca->id);
spin_unlock(&dca_idr_lock);
- idr_preload_end();
- if (ret < 0)
- return ret;
+ switch (err) {
+ case 0:
+ break;
+ case -EAGAIN:
+ goto idr_try_again;
+ default:
+ return err;
+ }
cd = device_create(dca_class, dev, MKDEV(0, 0), NULL, "dca%d", dca->id);
if (IS_ERR(cd)) {
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index b2728d6..242b8c0 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -686,14 +686,18 @@ static int get_dma_id(struct dma_device *device)
{
int rc;
+ idr_retry:
+ if (!idr_pre_get(&dma_idr, GFP_KERNEL))
+ return -ENOMEM;
mutex_lock(&dma_list_mutex);
-
- rc = idr_alloc(&dma_idr, NULL, 0, 0, GFP_KERNEL);
- if (rc >= 0)
- device->dev_id = rc;
-
+ rc = idr_get_new(&dma_idr, NULL, &device->dev_id);
mutex_unlock(&dma_list_mutex);
- return rc < 0 ? rc : 0;
+ if (rc == -EAGAIN)
+ goto idr_retry;
+ else if (rc != 0)
+ return rc;
+
+ return 0;
}
/**
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index 27ac423..68c3138 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -487,28 +487,27 @@ static int ioctl_get_info(struct client *client, union ioctl_arg *arg)
static int add_client_resource(struct client *client,
struct client_resource *resource, gfp_t gfp_mask)
{
- bool preload = gfp_mask & __GFP_WAIT;
unsigned long flags;
int ret;
- if (preload)
- idr_preload(gfp_mask);
- spin_lock_irqsave(&client->lock, flags);
+ retry:
+ if (idr_pre_get(&client->resource_idr, gfp_mask) == 0)
+ return -ENOMEM;
+ spin_lock_irqsave(&client->lock, flags);
if (client->in_shutdown)
ret = -ECANCELED;
else
- ret = idr_alloc(&client->resource_idr, resource, 0, 0,
- GFP_NOWAIT);
+ ret = idr_get_new(&client->resource_idr, resource,
+ &resource->handle);
if (ret >= 0) {
- resource->handle = ret;
client_get(client);
schedule_if_iso_resource(resource);
}
-
spin_unlock_irqrestore(&client->lock, flags);
- if (preload)
- idr_preload_end();
+
+ if (ret == -EAGAIN)
+ goto retry;
return ret < 0 ? ret : 0;
}
diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c
index b946330..af3e8aa 100644
--- a/drivers/firewire/core-device.c
+++ b/drivers/firewire/core-device.c
@@ -1017,7 +1017,13 @@ static void fw_device_init(struct work_struct *work)
fw_device_get(device);
down_write(&fw_device_rwsem);
- ret = idr_alloc(&fw_device_idr, device, 0, 1 << MINORBITS, GFP_KERNEL);
+ ret = idr_pre_get(&fw_device_idr, GFP_KERNEL) ?
+ idr_get_new(&fw_device_idr, device, &minor) :
+ -ENOMEM;
+ if (minor >= 1 << MINORBITS) {
+ idr_remove(&fw_device_idr, minor);
+ minor = -ENOSPC;
+ }
up_write(&fw_device_rwsem);
if (ret < 0)
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 9b37b90..e14eb88 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -358,10 +358,15 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,
goto err_out;
}
- ret = idr_alloc(&dirent_idr, value_sd, 1, 0, GFP_KERNEL);
- if (ret < 0)
+ do {
+ ret = -ENOMEM;
+ if (idr_pre_get(&dirent_idr, GFP_KERNEL))
+ ret = idr_get_new_above(&dirent_idr, value_sd,
+ 1, &id);
+ } while (ret == -EAGAIN);
+
+ if (ret)
goto free_sd;
- id = ret;
desc->flags &= GPIO_FLAGS_MASK;
desc->flags |= (unsigned long)id << ID_SHIFT;
diff --git a/drivers/gpu/drm/drm_context.c b/drivers/gpu/drm/drm_context.c
index 725968d..75f62c5 100644
--- a/drivers/gpu/drm/drm_context.c
+++ b/drivers/gpu/drm/drm_context.c
@@ -74,13 +74,24 @@ void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
*/
static int drm_ctxbitmap_next(struct drm_device * dev)
{
+ int new_id;
int ret;
+again:
+ if (idr_pre_get(&dev->ctx_idr, GFP_KERNEL) == 0) {
+ DRM_ERROR("Out of memory expanding drawable idr\n");
+ return -ENOMEM;
+ }
mutex_lock(&dev->struct_mutex);
- ret = idr_alloc(&dev->ctx_idr, NULL, DRM_RESERVED_CONTEXTS, 0,
- GFP_KERNEL);
+ ret = idr_get_new_above(&dev->ctx_idr, NULL,
+ DRM_RESERVED_CONTEXTS, &new_id);
mutex_unlock(&dev->struct_mutex);
- return ret;
+ if (ret == -EAGAIN)
+ goto again;
+ else if (ret)
+ return ret;
+
+ return new_id;
}
/**
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 838c9b6..775102d 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -252,21 +252,32 @@ char *drm_get_connector_status_name(enum drm_connector_status status)
static int drm_mode_object_get(struct drm_device *dev,
struct drm_mode_object *obj, uint32_t obj_type)
{
+ int new_id = 0;
int ret;
+again:
+ if (idr_pre_get(&dev->mode_config.crtc_idr, GFP_KERNEL) == 0) {
+ DRM_ERROR("Ran out memory getting a mode number\n");
+ return -ENOMEM;
+ }
+
mutex_lock(&dev->mode_config.idr_mutex);
- ret = idr_alloc(&dev->mode_config.crtc_idr, obj, 1, 0, GFP_KERNEL);
- if (ret >= 0) {
+ ret = idr_get_new_above(&dev->mode_config.crtc_idr, obj, 1, &new_id);
+
+ if (!ret) {
/*
* Set up the object linking under the protection of the idr
* lock so that other users can't see inconsistent state.
*/
- obj->id = ret;
+ obj->id = new_id;
obj->type = obj_type;
}
mutex_unlock(&dev->mode_config.idr_mutex);
- return ret < 0 ? ret : 0;
+ if (ret == -EAGAIN)
+ goto again;
+
+ return ret;
}
/**
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 6577514..e775859 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -270,19 +270,21 @@ drm_gem_handle_create(struct drm_file *file_priv,
int ret;
/*
- * Get the user-visible handle using idr. Preload and perform
- * allocation under our spinlock.
+ * Get the user-visible handle using idr.
*/
- idr_preload(GFP_KERNEL);
- spin_lock(&file_priv->table_lock);
-
- ret = idr_alloc(&file_priv->object_idr, obj, 1, 0, GFP_NOWAIT);
+again:
+ /* ensure there is space available to allocate a handle */
+ if (idr_pre_get(&file_priv->object_idr, GFP_KERNEL) == 0)
+ return -ENOMEM;
+ /* do the allocation under our spinlock */
+ spin_lock(&file_priv->table_lock);
+ ret = idr_get_new_above(&file_priv->object_idr, obj, 1, (int *)handlep);
spin_unlock(&file_priv->table_lock);
- idr_preload_end();
- if (ret < 0)
+ if (ret == -EAGAIN)
+ goto again;
+ else if (ret)
return ret;
- *handlep = ret;
drm_gem_object_handle_reference(obj);
@@ -449,15 +451,22 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data,
if (obj == NULL)
return -ENOENT;
- idr_preload(GFP_KERNEL);
+again:
+ if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
spin_lock(&dev->object_name_lock);
if (!obj->name) {
- ret = idr_alloc(&dev->object_name_idr, obj, 1, 0, GFP_NOWAIT);
- obj->name = ret;
+ ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
+ &obj->name);
args->name = (uint64_t) obj->name;
spin_unlock(&dev->object_name_lock);
- if (ret < 0)
+ if (ret == -EAGAIN)
+ goto again;
+ else if (ret)
goto err;
/* Allocate a reference for the name table. */
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 7d30802..200e104 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -109,6 +109,7 @@ EXPORT_SYMBOL(drm_ut_debug_printk);
static int drm_minor_get_id(struct drm_device *dev, int type)
{
+ int new_id;
int ret;
int base = 0, limit = 63;
@@ -120,11 +121,25 @@ static int drm_minor_get_id(struct drm_device *dev, int type)
limit = base + 255;
}
+again:
+ if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) {
+ DRM_ERROR("Out of memory expanding drawable idr\n");
+ return -ENOMEM;
+ }
mutex_lock(&dev->struct_mutex);
- ret = idr_alloc(&drm_minors_idr, NULL, base, limit, GFP_KERNEL);
+ ret = idr_get_new_above(&drm_minors_idr, NULL,
+ base, &new_id);
mutex_unlock(&dev->struct_mutex);
+ if (ret == -EAGAIN)
+ goto again;
+ else if (ret)
+ return ret;
- return ret == -ENOSPC ? -EINVAL : ret;
+ if (new_id >= limit) {
+ idr_remove(&drm_minors_idr, new_id);
+ return -EINVAL;
+ }
+ return new_id;
}
struct drm_master *drm_master_create(struct drm_minor *minor)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
index 1adce07..90398df 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
@@ -137,15 +137,21 @@ static int ipp_create_id(struct idr *id_idr, struct mutex *lock, void *obj,
DRM_DEBUG_KMS("%s\n", __func__);
+again:
+ /* ensure there is space available to allocate a handle */
+ if (idr_pre_get(id_idr, GFP_KERNEL) == 0) {
+ DRM_ERROR("failed to get idr.\n");
+ return -ENOMEM;
+ }
+
/* do the allocation under our mutexlock */
mutex_lock(lock);
- ret = idr_alloc(id_idr, obj, 1, 0, GFP_KERNEL);
+ ret = idr_get_new_above(id_idr, obj, 1, (int *)idp);
mutex_unlock(lock);
- if (ret < 0)
- return ret;
+ if (ret == -EAGAIN)
+ goto again;
- *idp = ret;
- return 0;
+ return ret;
}
static void *ipp_find_obj(struct idr *id_idr, struct mutex *lock, u32 id)
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 27e586a..a3f06bc 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -144,7 +144,7 @@ create_hw_context(struct drm_device *dev,
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct i915_hw_context *ctx;
- int ret;
+ int ret, id;
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (ctx == NULL)
@@ -169,11 +169,22 @@ create_hw_context(struct drm_device *dev,
ctx->file_priv = file_priv;
- ret = idr_alloc(&file_priv->context_idr, ctx, DEFAULT_CONTEXT_ID + 1, 0,
- GFP_KERNEL);
- if (ret < 0)
+again:
+ if (idr_pre_get(&file_priv->context_idr, GFP_KERNEL) == 0) {
+ ret = -ENOMEM;
+ DRM_DEBUG_DRIVER("idr allocation failed\n");
+ goto err_out;
+ }
+
+ ret = idr_get_new_above(&file_priv->context_idr, ctx,
+ DEFAULT_CONTEXT_ID + 1, &id);
+ if (ret == 0)
+ ctx->id = id;
+
+ if (ret == -EAGAIN)
+ goto again;
+ else if (ret)
goto err_out;
- ctx->id = ret;
return ctx;
diff --git a/drivers/gpu/drm/sis/sis_mm.c b/drivers/gpu/drm/sis/sis_mm.c
index 9a43d98..2b2f78c 100644
--- a/drivers/gpu/drm/sis/sis_mm.c
+++ b/drivers/gpu/drm/sis/sis_mm.c
@@ -128,10 +128,17 @@ static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file,
if (retval)
goto fail_alloc;
- retval = idr_alloc(&dev_priv->object_idr, item, 1, 0, GFP_KERNEL);
- if (retval < 0)
+again:
+ if (idr_pre_get(&dev_priv->object_idr, GFP_KERNEL) == 0) {
+ retval = -ENOMEM;
+ goto fail_idr;
+ }
+
+ retval = idr_get_new_above(&dev_priv->object_idr, item, 1, &user_key);
+ if (retval == -EAGAIN)
+ goto again;
+ if (retval)
goto fail_idr;
- user_key = retval;
list_add(&item->owner_list, &file_priv->obj_list);
mutex_unlock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/via/via_mm.c b/drivers/gpu/drm/via/via_mm.c
index 0ab93ff..0d55432 100644
--- a/drivers/gpu/drm/via/via_mm.c
+++ b/drivers/gpu/drm/via/via_mm.c
@@ -148,10 +148,17 @@ int via_mem_alloc(struct drm_device *dev, void *data,
if (retval)
goto fail_alloc;
- retval = idr_alloc(&dev_priv->object_idr, item, 1, 0, GFP_KERNEL);
- if (retval < 0)
+again:
+ if (idr_pre_get(&dev_priv->object_idr, GFP_KERNEL) == 0) {
+ retval = -ENOMEM;
+ goto fail_idr;
+ }
+
+ retval = idr_get_new_above(&dev_priv->object_idr, item, 1, &user_key);
+ if (retval == -EAGAIN)
+ goto again;
+ if (retval)
goto fail_idr;
- user_key = retval;
list_add(&item->owner_list, &file_priv->obj_list);
mutex_unlock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index c9d0676..e01a17b 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -177,16 +177,17 @@ int vmw_resource_alloc_id(struct vmw_resource *res)
BUG_ON(res->id != -1);
- idr_preload(GFP_KERNEL);
- write_lock(&dev_priv->resource_lock);
+ do {
+ if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0))
+ return -ENOMEM;
- ret = idr_alloc(idr, res, 1, 0, GFP_NOWAIT);
- if (ret >= 0)
- res->id = ret;
+ write_lock(&dev_priv->resource_lock);
+ ret = idr_get_new_above(idr, res, 1, &res->id);
+ write_unlock(&dev_priv->resource_lock);
- write_unlock(&dev_priv->resource_lock);
- idr_preload_end();
- return ret < 0 ? ret : 0;
+ } while (ret == -EAGAIN);
+
+ return ret;
}
/**
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 795c916..66a30f7 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -935,16 +935,25 @@ out_list:
*/
int i2c_add_adapter(struct i2c_adapter *adapter)
{
- int res;
+ int id, res = 0;
+
+retry:
+ if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
+ return -ENOMEM;
mutex_lock(&core_lock);
- res = idr_alloc(&i2c_adapter_idr, adapter,
- __i2c_first_dynamic_bus_num, 0, GFP_KERNEL);
+ /* "above" here means "above or equal to", sigh */
+ res = idr_get_new_above(&i2c_adapter_idr, adapter,
+ __i2c_first_dynamic_bus_num, &id);
mutex_unlock(&core_lock);
- if (res < 0)
+
+ if (res < 0) {
+ if (res == -EAGAIN)
+ goto retry;
return res;
+ }
- adapter->nr = res;
+ adapter->nr = id;
return i2c_register_adapter(adapter);
}
EXPORT_SYMBOL(i2c_add_adapter);
@@ -975,17 +984,33 @@ EXPORT_SYMBOL(i2c_add_adapter);
int i2c_add_numbered_adapter(struct i2c_adapter *adap)
{
int id;
+ int status;
if (adap->nr == -1) /* -1 means dynamically assign bus id */
return i2c_add_adapter(adap);
+ if (adap->nr & ~MAX_IDR_MASK)
+ return -EINVAL;
+
+retry:
+ if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
+ return -ENOMEM;
mutex_lock(&core_lock);
- id = idr_alloc(&i2c_adapter_idr, adap, adap->nr, adap->nr + 1,
- GFP_KERNEL);
+ /* "above" here means "above or equal to", sigh;
+ * we need the "equal to" result to force the result
+ */
+ status = idr_get_new_above(&i2c_adapter_idr, adap, adap->nr, &id);
+ if (status == 0 && id != adap->nr) {
+ status = -EBUSY;
+ idr_remove(&i2c_adapter_idr, id);
+ }
mutex_unlock(&core_lock);
- if (id < 0)
- return id == -ENOSPC ? -EBUSY : id;
- return 0;
+ if (status == -EAGAIN)
+ goto retry;
+
+ if (status == 0)
+ status = i2c_register_adapter(adap);
+ return status;
}
EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter);
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 98281fe..394fea2 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -382,21 +382,20 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
static int cm_alloc_id(struct cm_id_private *cm_id_priv)
{
unsigned long flags;
- int id;
+ int ret, id;
static int next_id;
- idr_preload(GFP_KERNEL);
- spin_lock_irqsave(&cm.lock, flags);
-
- id = idr_alloc(&cm.local_id_table, cm_id_priv, next_id, 0, GFP_NOWAIT);
- if (id >= 0)
- next_id = ((unsigned) id + 1) & MAX_IDR_MASK;
-
- spin_unlock_irqrestore(&cm.lock, flags);
- idr_preload_end();
+ do {
+ spin_lock_irqsave(&cm.lock, flags);
+ ret = idr_get_new_above(&cm.local_id_table, cm_id_priv,
+ next_id, &id);
+ if (!ret)
+ next_id = ((unsigned) id + 1) & MAX_IDR_MASK;
+ spin_unlock_irqrestore(&cm.lock, flags);
+ } while( (ret == -EAGAIN) && idr_pre_get(&cm.local_id_table, GFP_KERNEL) );
cm_id_priv->id.local_id = (__force __be32)id ^ cm.random_id_operand;
- return id < 0 ? id : 0;
+ return ret;
}
static void cm_free_id(__be32 local_id)
@@ -3845,6 +3844,7 @@ static int __init ib_cm_init(void)
cm.remote_sidr_table = RB_ROOT;
idr_init(&cm.local_id_table);
get_random_bytes(&cm.random_id_operand, sizeof cm.random_id_operand);
+ idr_pre_get(&cm.local_id_table, GFP_KERNEL);
INIT_LIST_HEAD(&cm.timewait_list);
ret = class_register(&cm_class);
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 71c2c71..0822536 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -2143,23 +2143,33 @@ static int cma_alloc_port(struct idr *ps, struct rdma_id_private *id_priv,
unsigned short snum)
{
struct rdma_bind_list *bind_list;
- int ret;
+ int port, ret;
bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL);
if (!bind_list)
return -ENOMEM;
- ret = idr_alloc(ps, bind_list, snum, snum + 1, GFP_KERNEL);
- if (ret < 0)
- goto err;
+ do {
+ ret = idr_get_new_above(ps, bind_list, snum, &port);
+ } while ((ret == -EAGAIN) && idr_pre_get(ps, GFP_KERNEL));
+
+ if (ret)
+ goto err1;
+
+ if (port != snum) {
+ ret = -EADDRNOTAVAIL;
+ goto err2;
+ }
bind_list->ps = ps;
- bind_list->port = (unsigned short)ret;
+ bind_list->port = (unsigned short) port;
cma_bind_port(bind_list, id_priv);
return 0;
-err:
+err2:
+ idr_remove(ps, port);
+err1:
kfree(bind_list);
- return ret == -ENOSPC ? -EADDRNOTAVAIL : ret;
+ return ret;
}
static int cma_alloc_any_port(struct idr *ps, struct rdma_id_private *id_priv)
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index 934f45e..a8905ab 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -611,21 +611,19 @@ static void init_mad(struct ib_sa_mad *mad, struct ib_mad_agent *agent)
static int send_mad(struct ib_sa_query *query, int timeout_ms, gfp_t gfp_mask)
{
- bool preload = gfp_mask & __GFP_WAIT;
unsigned long flags;
int ret, id;
- if (preload)
- idr_preload(gfp_mask);
+retry:
+ if (!idr_pre_get(&query_idr, gfp_mask))
+ return -ENOMEM;
spin_lock_irqsave(&idr_lock, flags);
-
- id = idr_alloc(&query_idr, query, 0, 0, GFP_NOWAIT);
-
+ ret = idr_get_new(&query_idr, query, &id);
spin_unlock_irqrestore(&idr_lock, flags);
- if (preload)
- idr_preload_end();
- if (id < 0)
- return id;
+ if (ret == -EAGAIN)
+ goto retry;
+ if (ret)
+ return ret;
query->mad_buf->timeout_ms = timeout_ms;
query->mad_buf->context[0] = query;
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index f2f6393..49b15ac 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -176,6 +176,7 @@ static void ib_ucm_cleanup_events(struct ib_ucm_context *ctx)
static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
{
struct ib_ucm_context *ctx;
+ int result;
ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
if (!ctx)
@@ -186,10 +187,17 @@ static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
ctx->file = file;
INIT_LIST_HEAD(&ctx->events);
- mutex_lock(&ctx_id_mutex);
- ctx->id = idr_alloc(&ctx_id_table, ctx, 0, 0, GFP_KERNEL);
- mutex_unlock(&ctx_id_mutex);
- if (ctx->id < 0)
+ do {
+ result = idr_pre_get(&ctx_id_table, GFP_KERNEL);
+ if (!result)
+ goto error;
+
+ mutex_lock(&ctx_id_mutex);
+ result = idr_get_new(&ctx_id_table, ctx, &ctx->id);
+ mutex_unlock(&ctx_id_mutex);
+ } while (result == -EAGAIN);
+
+ if (result)
goto error;
list_add_tail(&ctx->file_list, &file->ctxs);
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index 5ca44cd..2709ff5 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -145,6 +145,7 @@ static void ucma_put_ctx(struct ucma_context *ctx)
static struct ucma_context *ucma_alloc_ctx(struct ucma_file *file)
{
struct ucma_context *ctx;
+ int ret;
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
@@ -155,10 +156,17 @@ static struct ucma_context *ucma_alloc_ctx(struct ucma_file *file)
INIT_LIST_HEAD(&ctx->mc_list);
ctx->file = file;
- mutex_lock(&mut);
- ctx->id = idr_alloc(&ctx_idr, ctx, 0, 0, GFP_KERNEL);
- mutex_unlock(&mut);
- if (ctx->id < 0)
+ do {
+ ret = idr_pre_get(&ctx_idr, GFP_KERNEL);
+ if (!ret)
+ goto error;
+
+ mutex_lock(&mut);
+ ret = idr_get_new(&ctx_idr, ctx, &ctx->id);
+ mutex_unlock(&mut);
+ } while (ret == -EAGAIN);
+
+ if (ret)
goto error;
list_add_tail(&ctx->list, &file->ctx_list);
@@ -172,15 +180,23 @@ error:
static struct ucma_multicast* ucma_alloc_multicast(struct ucma_context *ctx)
{
struct ucma_multicast *mc;
+ int ret;
mc = kzalloc(sizeof(*mc), GFP_KERNEL);
if (!mc)
return NULL;
- mutex_lock(&mut);
- mc->id = idr_alloc(&multicast_idr, mc, 0, 0, GFP_KERNEL);
- mutex_unlock(&mut);
- if (mc->id < 0)
+ do {
+ ret = idr_pre_get(&multicast_idr, GFP_KERNEL);
+ if (!ret)
+ goto error;
+
+ mutex_lock(&mut);
+ ret = idr_get_new(&multicast_idr, mc, &mc->id);
+ mutex_unlock(&mut);
+ } while (ret == -EAGAIN);
+
+ if (ret)
goto error;
mc->ctx = ctx;
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 83bc309..0cb0007 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -124,17 +124,18 @@ static int idr_add_uobj(struct idr *idr, struct ib_uobject *uobj)
{
int ret;
- idr_preload(GFP_KERNEL);
- spin_lock(&ib_uverbs_idr_lock);
-
- ret = idr_alloc(idr, uobj, 0, 0, GFP_NOWAIT);
- if (ret >= 0)
- uobj->id = ret;
+retry:
+ if (!idr_pre_get(idr, GFP_KERNEL))
+ return -ENOMEM;
+ spin_lock(&ib_uverbs_idr_lock);
+ ret = idr_get_new(idr, uobj, &uobj->id);
spin_unlock(&ib_uverbs_idr_lock);
- idr_preload_end();
- return ret < 0 ? ret : 0;
+ if (ret == -EAGAIN)
+ goto retry;
+
+ return ret;
}
void idr_remove_uobj(struct idr *idr, struct ib_uobject *uobj)
diff --git a/drivers/infiniband/hw/amso1100/c2_qp.c b/drivers/infiniband/hw/amso1100/c2_qp.c
index 0ab826b..28cd5cb 100644
--- a/drivers/infiniband/hw/amso1100/c2_qp.c
+++ b/drivers/infiniband/hw/amso1100/c2_qp.c
@@ -382,17 +382,14 @@ static int c2_alloc_qpn(struct c2_dev *c2dev, struct c2_qp *qp)
{
int ret;
- idr_preload(GFP_KERNEL);
- spin_lock_irq(&c2dev->qp_table.lock);
-
- ret = idr_alloc(&c2dev->qp_table.idr, qp, c2dev->qp_table.last++, 0,
- GFP_NOWAIT);
- if (ret >= 0)
- qp->qpn = ret;
-
- spin_unlock_irq(&c2dev->qp_table.lock);
- idr_preload_end();
- return ret < 0 ? ret : 0;
+ do {
+ spin_lock_irq(&c2dev->qp_table.lock);
+ ret = idr_get_new_above(&c2dev->qp_table.idr, qp,
+ c2dev->qp_table.last++, &qp->qpn);
+ spin_unlock_irq(&c2dev->qp_table.lock);
+ } while ((ret == -EAGAIN) &&
+ idr_pre_get(&c2dev->qp_table.idr, GFP_KERNEL));
+ return ret;
}
static void c2_free_qpn(struct c2_dev *c2dev, int qpn)
diff --git a/drivers/infiniband/hw/cxgb3/iwch.h b/drivers/infiniband/hw/cxgb3/iwch.h
index 8378622..a1c4457 100644
--- a/drivers/infiniband/hw/cxgb3/iwch.h
+++ b/drivers/infiniband/hw/cxgb3/iwch.h
@@ -153,17 +153,19 @@ static inline int insert_handle(struct iwch_dev *rhp, struct idr *idr,
void *handle, u32 id)
{
int ret;
-
- idr_preload(GFP_KERNEL);
- spin_lock_irq(&rhp->lock);
-
- ret = idr_alloc(idr, handle, id, id + 1, GFP_NOWAIT);
-
- spin_unlock_irq(&rhp->lock);
- idr_preload_end();
-
- BUG_ON(ret == -ENOSPC);
- return ret < 0 ? ret : 0;
+ int newid;
+
+ do {
+ if (!idr_pre_get(idr, GFP_KERNEL)) {
+ return -ENOMEM;
+ }
+ spin_lock_irq(&rhp->lock);
+ ret = idr_get_new_above(idr, handle, id, &newid);
+ BUG_ON(newid != id);
+ spin_unlock_irq(&rhp->lock);
+ } while (ret == -EAGAIN);
+
+ return ret;
}
static inline void remove_handle(struct iwch_dev *rhp, struct idr *idr, u32 id)
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index 7f862da..9c1644f 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -260,21 +260,20 @@ static inline int _insert_handle(struct c4iw_dev *rhp, struct idr *idr,
void *handle, u32 id, int lock)
{
int ret;
+ int newid;
- if (lock) {
- idr_preload(GFP_KERNEL);
- spin_lock_irq(&rhp->lock);
- }
-
- ret = idr_alloc(idr, handle, id, id + 1, GFP_ATOMIC);
-
- if (lock) {
- spin_unlock_irq(&rhp->lock);
- idr_preload_end();
- }
-
- BUG_ON(ret == -ENOSPC);
- return ret < 0 ? ret : 0;
+ do {
+ if (!idr_pre_get(idr, lock ? GFP_KERNEL : GFP_ATOMIC))
+ return -ENOMEM;
+ if (lock)
+ spin_lock_irq(&rhp->lock);
+ ret = idr_get_new_above(idr, handle, id, &newid);
+ BUG_ON(!ret && newid != id);
+ if (lock)
+ spin_unlock_irq(&rhp->lock);
+ } while (ret == -EAGAIN);
+
+ return ret;
}
static inline int insert_handle(struct c4iw_dev *rhp, struct idr *idr,
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
index 212150c..8f52901 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -128,7 +128,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
void *vpage;
u32 counter;
u64 rpage, cqx_fec, h_ret;
- int ipz_rc, i;
+ int ipz_rc, ret, i;
unsigned long flags;
if (cqe >= 0xFFFFFFFF - 64 - additional_cqe)
@@ -163,19 +163,32 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
adapter_handle = shca->ipz_hca_handle;
param.eq_handle = shca->eq.ipz_eq_handle;
- idr_preload(GFP_KERNEL);
- write_lock_irqsave(&ehca_cq_idr_lock, flags);
- my_cq->token = idr_alloc(&ehca_cq_idr, my_cq, 0, 0x2000000, GFP_NOWAIT);
- write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
- idr_preload_end();
+ do {
+ if (!idr_pre_get(&ehca_cq_idr, GFP_KERNEL)) {
+ cq = ERR_PTR(-ENOMEM);
+ ehca_err(device, "Can't reserve idr nr. device=%p",
+ device);
+ goto create_cq_exit1;
+ }
+
+ write_lock_irqsave(&ehca_cq_idr_lock, flags);
+ ret = idr_get_new(&ehca_cq_idr, my_cq, &my_cq->token);
+ write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+ } while (ret == -EAGAIN);
- if (my_cq->token < 0) {
+ if (ret) {
cq = ERR_PTR(-ENOMEM);
ehca_err(device, "Can't allocate new idr entry. device=%p",
device);
goto create_cq_exit1;
}
+ if (my_cq->token > 0x1FFFFFF) {
+ cq = ERR_PTR(-ENOMEM);
+ ehca_err(device, "Invalid number of cq. device=%p", device);
+ goto create_cq_exit2;
+ }
+
/*
* CQs maximum depth is 4GB-64, but we need additional 20 as buffer
* for receiving errors CQEs.
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index 00d6861..1493939 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -636,26 +636,30 @@ static struct ehca_qp *internal_create_qp(
my_qp->send_cq =
container_of(init_attr->send_cq, struct ehca_cq, ib_cq);
- idr_preload(GFP_KERNEL);
- write_lock_irqsave(&ehca_qp_idr_lock, flags);
-
- ret = idr_alloc(&ehca_qp_idr, my_qp, 0, 0x2000000, GFP_NOWAIT);
- if (ret >= 0)
- my_qp->token = ret;
-
- write_unlock_irqrestore(&ehca_qp_idr_lock, flags);
- idr_preload_end();
- if (ret < 0) {
- if (ret == -ENOSPC) {
- ret = -EINVAL;
- ehca_err(pd->device, "Invalid number of qp");
- } else {
+ do {
+ if (!idr_pre_get(&ehca_qp_idr, GFP_KERNEL)) {
ret = -ENOMEM;
- ehca_err(pd->device, "Can't allocate new idr entry.");
+ ehca_err(pd->device, "Can't reserve idr resources.");
+ goto create_qp_exit0;
}
+
+ write_lock_irqsave(&ehca_qp_idr_lock, flags);
+ ret = idr_get_new(&ehca_qp_idr, my_qp, &my_qp->token);
+ write_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+ } while (ret == -EAGAIN);
+
+ if (ret) {
+ ret = -ENOMEM;
+ ehca_err(pd->device, "Can't allocate new idr entry.");
goto create_qp_exit0;
}
+ if (my_qp->token > 0x1FFFFFF) {
+ ret = -EINVAL;
+ ehca_err(pd->device, "Invalid number of qp");
+ goto create_qp_exit1;
+ }
+
if (has_srq)
parms.srq_token = my_qp->token;
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
index fcdaeea..7b371f5 100644
--- a/drivers/infiniband/hw/ipath/ipath_driver.c
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -194,6 +194,11 @@ static struct ipath_devdata *ipath_alloc_devdata(struct pci_dev *pdev)
struct ipath_devdata *dd;
int ret;
+ if (!idr_pre_get(&unit_table, GFP_KERNEL)) {
+ dd = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
dd = vzalloc(sizeof(*dd));
if (!dd) {
dd = ERR_PTR(-ENOMEM);
@@ -201,10 +206,9 @@ static struct ipath_devdata *ipath_alloc_devdata(struct pci_dev *pdev)
}
dd->ipath_unit = -1;
- idr_preload(GFP_KERNEL);
spin_lock_irqsave(&ipath_devs_lock, flags);
- ret = idr_alloc(&unit_table, dd, 0, 0, GFP_KERNEL);
+ ret = idr_get_new(&unit_table, dd, &dd->ipath_unit);
if (ret < 0) {
printk(KERN_ERR IPATH_DRV_NAME
": Could not allocate unit ID: error %d\n", -ret);
@@ -212,7 +216,6 @@ static struct ipath_devdata *ipath_alloc_devdata(struct pci_dev *pdev)
dd = ERR_PTR(ret);
goto bail_unlock;
}
- dd->ipath_unit = ret;
dd->pcidev = pdev;
pci_set_drvdata(pdev, dd);
@@ -221,7 +224,7 @@ static struct ipath_devdata *ipath_alloc_devdata(struct pci_dev *pdev)
bail_unlock:
spin_unlock_irqrestore(&ipath_devs_lock, flags);
- idr_preload_end();
+
bail:
return dd;
}
@@ -2500,6 +2503,11 @@ static int __init infinipath_init(void)
* the PCI subsystem.
*/
idr_init(&unit_table);
+ if (!idr_pre_get(&unit_table, GFP_KERNEL)) {
+ printk(KERN_ERR IPATH_DRV_NAME ": idr_pre_get() failed\n");
+ ret = -ENOMEM;
+ goto bail;
+ }
ret = pci_register_driver(&ipath_driver);
if (ret < 0) {
diff --git a/drivers/infiniband/hw/mlx4/cm.c b/drivers/infiniband/hw/mlx4/cm.c
index 80e59ed..dbc99d4 100644
--- a/drivers/infiniband/hw/mlx4/cm.c
+++ b/drivers/infiniband/hw/mlx4/cm.c
@@ -203,7 +203,7 @@ static void sl_id_map_add(struct ib_device *ibdev, struct id_map_entry *new)
static struct id_map_entry *
id_map_alloc(struct ib_device *ibdev, int slave_id, u32 sl_cm_id)
{
- int ret;
+ int ret, id;
static int next_id;
struct id_map_entry *ent;
struct mlx4_ib_sriov *sriov = &to_mdev(ibdev)->sriov;
@@ -220,23 +220,25 @@ id_map_alloc(struct ib_device *ibdev, int slave_id, u32 sl_cm_id)
ent->dev = to_mdev(ibdev);
INIT_DELAYED_WORK(&ent->timeout, id_map_ent_timeout);
- idr_preload(GFP_KERNEL);
- spin_lock(&to_mdev(ibdev)->sriov.id_map_lock);
+ do {
+ spin_lock(&to_mdev(ibdev)->sriov.id_map_lock);
+ ret = idr_get_new_above(&sriov->pv_id_table, ent,
+ next_id, &id);
+ if (!ret) {
+ next_id = ((unsigned) id + 1) & MAX_IDR_MASK;
+ ent->pv_cm_id = (u32)id;
+ sl_id_map_add(ibdev, ent);
+ }
- ret = idr_alloc(&sriov->pv_id_table, ent, next_id, 0, GFP_NOWAIT);
- if (ret >= 0) {
- next_id = ((unsigned)ret + 1) & MAX_IDR_MASK;
- ent->pv_cm_id = (u32)ret;
- sl_id_map_add(ibdev, ent);
+ spin_unlock(&sriov->id_map_lock);
+ } while (ret == -EAGAIN && idr_pre_get(&sriov->pv_id_table, GFP_KERNEL));
+ /*the function idr_get_new_above can return -ENOSPC, so don't insert in that case.*/
+ if (!ret) {
+ spin_lock(&sriov->id_map_lock);
list_add_tail(&ent->list, &sriov->cm_list);
- }
-
- spin_unlock(&sriov->id_map_lock);
- idr_preload_end();
-
- if (ret >= 0)
+ spin_unlock(&sriov->id_map_lock);
return ent;
-
+ }
/*error flow*/
kfree(ent);
mlx4_ib_warn(ibdev, "No more space in the idr (err:0x%x)\n", ret);
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
index 48928c8..c4e0131 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
@@ -51,6 +51,18 @@ static DEFINE_IDR(ocrdma_dev_id);
static union ib_gid ocrdma_zero_sgid;
+static int ocrdma_get_instance(void)
+{
+ int instance = 0;
+
+ /* Assign an unused number */
+ if (!idr_pre_get(&ocrdma_dev_id, GFP_KERNEL))
+ return -1;
+ if (idr_get_new(&ocrdma_dev_id, NULL, &instance))
+ return -1;
+ return instance;
+}
+
void ocrdma_get_guid(struct ocrdma_dev *dev, u8 *guid)
{
u8 mac_addr[6];
@@ -404,7 +416,7 @@ static struct ocrdma_dev *ocrdma_add(struct be_dev_info *dev_info)
goto idr_err;
memcpy(&dev->nic_info, dev_info, sizeof(*dev_info));
- dev->id = idr_alloc(&ocrdma_dev_id, NULL, 0, 0, GFP_KERNEL);
+ dev->id = ocrdma_get_instance();
if (dev->id < 0)
goto idr_err;
diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c
index 50e33aa..ddf066d 100644
--- a/drivers/infiniband/hw/qib/qib_init.c
+++ b/drivers/infiniband/hw/qib/qib_init.c
@@ -1060,23 +1060,22 @@ struct qib_devdata *qib_alloc_devdata(struct pci_dev *pdev, size_t extra)
struct qib_devdata *dd;
int ret;
+ if (!idr_pre_get(&qib_unit_table, GFP_KERNEL)) {
+ dd = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
dd = (struct qib_devdata *) ib_alloc_device(sizeof(*dd) + extra);
if (!dd) {
dd = ERR_PTR(-ENOMEM);
goto bail;
}
- idr_preload(GFP_KERNEL);
spin_lock_irqsave(&qib_devs_lock, flags);
-
- ret = idr_alloc(&qib_unit_table, dd, 0, 0, GFP_NOWAIT);
- if (ret >= 0) {
- dd->unit = ret;
+ ret = idr_get_new(&qib_unit_table, dd, &dd->unit);
+ if (ret >= 0)
list_add(&dd->list, &qib_dev_list);
- }
-
spin_unlock_irqrestore(&qib_devs_lock, flags);
- idr_preload_end();
if (ret < 0) {
qib_early_err(&pdev->dev,
@@ -1181,6 +1180,11 @@ static int __init qlogic_ib_init(void)
* the PCI subsystem.
*/
idr_init(&qib_unit_table);
+ if (!idr_pre_get(&qib_unit_table, GFP_KERNEL)) {
+ pr_err("idr_pre_get() failed\n");
+ ret = -ENOMEM;
+ goto bail_cq_wq;
+ }
ret = pci_register_driver(&qib_driver);
if (ret < 0) {
@@ -1195,6 +1199,7 @@ static int __init qlogic_ib_init(void)
bail_unit:
idr_destroy(&qib_unit_table);
+bail_cq_wq:
destroy_workqueue(qib_cq_wq);
bail_dev:
qib_dev_cleanup();
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index ac74b81..c644eb6 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1801,38 +1801,62 @@ static void free_minor(int minor)
*/
static int specific_minor(int minor)
{
- int r;
+ int r, m;
if (minor >= (1 << MINORBITS))
return -EINVAL;
- idr_preload(GFP_KERNEL);
+ r = idr_pre_get(&_minor_idr, GFP_KERNEL);
+ if (!r)
+ return -ENOMEM;
+
spin_lock(&_minor_lock);
- r = idr_alloc(&_minor_idr, MINOR_ALLOCED, minor, minor + 1, GFP_NOWAIT);
+ if (idr_find(&_minor_idr, minor)) {
+ r = -EBUSY;
+ goto out;
+ }
+
+ r = idr_get_new_above(&_minor_idr, MINOR_ALLOCED, minor, &m);
+ if (r)
+ goto out;
+ if (m != minor) {
+ idr_remove(&_minor_idr, m);
+ r = -EBUSY;
+ goto out;
+ }
+
+out:
spin_unlock(&_minor_lock);
- idr_preload_end();
- if (r < 0)
- return r == -ENOSPC ? -EBUSY : r;
- return 0;
+ return r;
}
static int next_free_minor(int *minor)
{
- int r;
+ int r, m;
+
+ r = idr_pre_get(&_minor_idr, GFP_KERNEL);
+ if (!r)
+ return -ENOMEM;
- idr_preload(GFP_KERNEL);
spin_lock(&_minor_lock);
- r = idr_alloc(&_minor_idr, MINOR_ALLOCED, 0, 1 << MINORBITS, GFP_NOWAIT);
+ r = idr_get_new(&_minor_idr, MINOR_ALLOCED, &m);
+ if (r)
+ goto out;
+
+ if (m >= (1 << MINORBITS)) {
+ idr_remove(&_minor_idr, m);
+ r = -ENOSPC;
+ goto out;
+ }
+
+ *minor = m;
+out:
spin_unlock(&_minor_lock);
- idr_preload_end();
- if (r < 0)
- return r;
- *minor = r;
- return 0;
+ return r;
}
static const struct block_device_operations dm_blk_dops;
diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c
index ffcb10a..56ff19c 100644
--- a/drivers/memstick/core/memstick.c
+++ b/drivers/memstick/core/memstick.c
@@ -512,17 +512,18 @@ int memstick_add_host(struct memstick_host *host)
{
int rc;
- idr_preload(GFP_KERNEL);
- spin_lock(&memstick_host_lock);
-
- rc = idr_alloc(&memstick_host_idr, host, 0, 0, GFP_NOWAIT);
- if (rc >= 0)
- host->id = rc;
+ while (1) {
+ if (!idr_pre_get(&memstick_host_idr, GFP_KERNEL))
+ return -ENOMEM;
- spin_unlock(&memstick_host_lock);
- idr_preload_end();
- if (rc < 0)
- return rc;
+ spin_lock(&memstick_host_lock);
+ rc = idr_get_new(&memstick_host_idr, host, &host->id);
+ spin_unlock(&memstick_host_lock);
+ if (!rc)
+ break;
+ else if (rc != -EAGAIN)
+ return rc;
+ }
dev_set_name(&host->dev, "memstick%u", host->id);
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
index f12b78d..9729b92 100644
--- a/drivers/memstick/core/mspro_block.c
+++ b/drivers/memstick/core/mspro_block.c
@@ -1213,10 +1213,21 @@ static int mspro_block_init_disk(struct memstick_dev *card)
msb->page_size = be16_to_cpu(sys_info->unit_size);
mutex_lock(&mspro_block_disk_lock);
- disk_id = idr_alloc(&mspro_block_disk_idr, card, 0, 256, GFP_KERNEL);
+ if (!idr_pre_get(&mspro_block_disk_idr, GFP_KERNEL)) {
+ mutex_unlock(&mspro_block_disk_lock);
+ return -ENOMEM;
+ }
+
+ rc = idr_get_new(&mspro_block_disk_idr, card, &disk_id);
mutex_unlock(&mspro_block_disk_lock);
- if (disk_id < 0)
- return disk_id;
+
+ if (rc)
+ return rc;
+
+ if ((disk_id << MSPRO_BLOCK_PART_SHIFT) > 255) {
+ rc = -ENOSPC;
+ goto out_release_id;
+ }
msb->disk = alloc_disk(1 << MSPRO_BLOCK_PART_SHIFT);
if (!msb->disk) {
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c
index 45e97b4..822237e 100644
--- a/drivers/mfd/rtsx_pcr.c
+++ b/drivers/mfd/rtsx_pcr.c
@@ -1061,14 +1061,15 @@ static int rtsx_pci_probe(struct pci_dev *pcidev,
}
handle->pcr = pcr;
- idr_preload(GFP_KERNEL);
+ if (!idr_pre_get(&rtsx_pci_idr, GFP_KERNEL)) {
+ ret = -ENOMEM;
+ goto free_handle;
+ }
+
spin_lock(&rtsx_pci_lock);
- ret = idr_alloc(&rtsx_pci_idr, pcr, 0, 0, GFP_NOWAIT);
- if (ret >= 0)
- pcr->id = ret;
+ ret = idr_get_new(&rtsx_pci_idr, pcr, &pcr->id);
spin_unlock(&rtsx_pci_lock);
- idr_preload_end();
- if (ret < 0)
+ if (ret)
goto free_handle;
pcr->pci = pcidev;
diff --git a/drivers/misc/c2port/core.c b/drivers/misc/c2port/core.c
index f32550a..f428d86 100644
--- a/drivers/misc/c2port/core.c
+++ b/drivers/misc/c2port/core.c
@@ -885,7 +885,7 @@ struct c2port_device *c2port_device_register(char *name,
struct c2port_ops *ops, void *devdata)
{
struct c2port_device *c2dev;
- int ret;
+ int id, ret;
if (unlikely(!ops) || unlikely(!ops->access) || \
unlikely(!ops->c2d_dir) || unlikely(!ops->c2ck_set) || \
@@ -897,18 +897,22 @@ struct c2port_device *c2port_device_register(char *name,
if (unlikely(!c2dev))
return ERR_PTR(-ENOMEM);
- idr_preload(GFP_KERNEL);
+ ret = idr_pre_get(&c2port_idr, GFP_KERNEL);
+ if (!ret) {
+ ret = -ENOMEM;
+ goto error_idr_get_new;
+ }
+
spin_lock_irq(&c2port_idr_lock);
- ret = idr_alloc(&c2port_idr, c2dev, 0, 0, GFP_NOWAIT);
+ ret = idr_get_new(&c2port_idr, c2dev, &id);
spin_unlock_irq(&c2port_idr_lock);
- idr_preload_end();
if (ret < 0)
- goto error_idr_alloc;
- c2dev->id = ret;
+ goto error_idr_get_new;
+ c2dev->id = id;
c2dev->dev = device_create(c2port_class, NULL, 0, c2dev,
- "c2port%d", c2dev->id);
+ "c2port%d", id);
if (unlikely(IS_ERR(c2dev->dev))) {
ret = PTR_ERR(c2dev->dev);
goto error_device_create;
@@ -942,10 +946,10 @@ error_device_create_bin_file:
error_device_create:
spin_lock_irq(&c2port_idr_lock);
- idr_remove(&c2port_idr, c2dev->id);
+ idr_remove(&c2port_idr, id);
spin_unlock_irq(&c2port_idr_lock);
-error_idr_alloc:
+error_idr_get_new:
kfree(c2dev);
return ERR_PTR(ret);
diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c
index 0ab7c92..0bd5349 100644
--- a/drivers/misc/tifm_core.c
+++ b/drivers/misc/tifm_core.c
@@ -196,14 +196,13 @@ int tifm_add_adapter(struct tifm_adapter *fm)
{
int rc;
- idr_preload(GFP_KERNEL);
+ if (!idr_pre_get(&tifm_adapter_idr, GFP_KERNEL))
+ return -ENOMEM;
+
spin_lock(&tifm_adapter_lock);
- rc = idr_alloc(&tifm_adapter_idr, fm, 0, 0, GFP_NOWAIT);
- if (rc >= 0)
- fm->id = rc;
+ rc = idr_get_new(&tifm_adapter_idr, fm, &fm->id);
spin_unlock(&tifm_adapter_lock);
- idr_preload_end();
- if (rc < 0)
+ if (rc)
return rc;
dev_set_name(&fm->dev, "tifm%u", fm->id);
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 1117de7..ee2e16b 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -306,20 +306,19 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
int err;
struct mmc_host *host;
+ if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
+ return NULL;
+
host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
if (!host)
return NULL;
/* scanning will be enabled when we're ready */
host->rescan_disable = 1;
- idr_preload(GFP_KERNEL);
spin_lock(&mmc_host_lock);
- err = idr_alloc(&mmc_host_idr, host, 0, 0, GFP_NOWAIT);
- if (err >= 0)
- host->index = err;
+ err = idr_get_new(&mmc_host_idr, host, &host->index);
spin_unlock(&mmc_host_lock);
- idr_preload_end();
- if (err < 0)
+ if (err)
goto free;
dev_set_name(&host->class_dev, "mmc%d", host->index);
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 61d5f56..ec794a7 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -349,8 +349,13 @@ int add_mtd_device(struct mtd_info *mtd)
BUG_ON(mtd->writesize == 0);
mutex_lock(&mtd_table_mutex);
- i = idr_alloc(&mtd_idr, mtd, 0, 0, GFP_KERNEL);
- if (i < 0)
+ do {
+ if (!idr_pre_get(&mtd_idr, GFP_KERNEL))
+ goto fail_locked;
+ error = idr_get_new(&mtd_idr, mtd, &i);
+ } while (error == -EAGAIN);
+
+ if (error)
goto fail_locked;
mtd->index = i;
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 1814cfe..b181dfb 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -279,17 +279,28 @@ static int macvtap_receive(struct sk_buff *skb)
static int macvtap_get_minor(struct macvlan_dev *vlan)
{
int retval = -ENOMEM;
+ int id;
mutex_lock(&minor_lock);
- retval = idr_alloc(&minor_idr, vlan, 1, MACVTAP_NUM_DEVS, GFP_KERNEL);
- if (retval >= 0) {
- vlan->minor = retval;
- } else if (retval == -ENOSPC) {
+ if (idr_pre_get(&minor_idr, GFP_KERNEL) == 0)
+ goto exit;
+
+ retval = idr_get_new_above(&minor_idr, vlan, 1, &id);
+ if (retval < 0) {
+ if (retval == -EAGAIN)
+ retval = -ENOMEM;
+ goto exit;
+ }
+ if (id < MACVTAP_NUM_DEVS) {
+ vlan->minor = id;
+ } else {
printk(KERN_ERR "too many macvtap devices\n");
retval = -EINVAL;
+ idr_remove(&minor_idr, id);
}
+exit:
mutex_unlock(&minor_lock);
- return retval < 0 ? retval : 0;
+ return retval;
}
static void macvtap_free_minor(struct macvlan_dev *vlan)
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 7efdb91..0b2706a 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -2946,21 +2946,46 @@ static void __exit ppp_cleanup(void)
* by holding all_ppp_mutex
*/
+static int __unit_alloc(struct idr *p, void *ptr, int n)
+{
+ int unit, err;
+
+again:
+ if (!idr_pre_get(p, GFP_KERNEL)) {
+ pr_err("PPP: No free memory for idr\n");
+ return -ENOMEM;
+ }
+
+ err = idr_get_new_above(p, ptr, n, &unit);
+ if (err < 0) {
+ if (err == -EAGAIN)
+ goto again;
+ return err;
+ }
+
+ return unit;
+}
+
/* associate pointer with specified number */
static int unit_set(struct idr *p, void *ptr, int n)
{
int unit;
- unit = idr_alloc(p, ptr, n, n + 1, GFP_KERNEL);
- if (unit == -ENOSPC)
- unit = -EINVAL;
+ unit = __unit_alloc(p, ptr, n);
+ if (unit < 0)
+ return unit;
+ else if (unit != n) {
+ idr_remove(p, unit);
+ return -EINVAL;
+ }
+
return unit;
}
/* get new free unit number and associate pointer with it */
static int unit_get(struct idr *p, void *ptr)
{
- return idr_alloc(p, ptr, 0, 0, GFP_KERNEL);
+ return __unit_alloc(p, ptr, 0);
}
/* put unit number back to a pool */
diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c
index 3f00568..ca70365 100644
--- a/drivers/power/bq2415x_charger.c
+++ b/drivers/power/bq2415x_charger.c
@@ -1504,11 +1504,16 @@ static int bq2415x_probe(struct i2c_client *client,
}
/* Get new ID for the new device */
+ ret = idr_pre_get(&bq2415x_id, GFP_KERNEL);
+ if (ret == 0)
+ return -ENOMEM;
+
mutex_lock(&bq2415x_id_mutex);
- num = idr_alloc(&bq2415x_id, client, 0, 0, GFP_KERNEL);
+ ret = idr_get_new(&bq2415x_id, client, &num);
mutex_unlock(&bq2415x_id_mutex);
- if (num < 0)
- return num;
+
+ if (ret < 0)
+ return ret;
name = kasprintf(GFP_KERNEL, "%s-%d", id->name, num);
if (!name) {
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index 26037ca..8ccf5d7 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -791,11 +791,14 @@ static int bq27x00_battery_probe(struct i2c_client *client,
int retval = 0;
/* Get new ID for the new battery device */
+ retval = idr_pre_get(&battery_id, GFP_KERNEL);
+ if (retval == 0)
+ return -ENOMEM;
mutex_lock(&battery_mutex);
- num = idr_alloc(&battery_id, client, 0, 0, GFP_KERNEL);
+ retval = idr_get_new(&battery_id, client, &num);
mutex_unlock(&battery_mutex);
- if (num < 0)
- return num;
+ if (retval < 0)
+ return retval;
name = kasprintf(GFP_KERNEL, "%s-%d", id->name, num);
if (!name) {
diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c
index c09e772..e7301b3 100644
--- a/drivers/power/ds2782_battery.c
+++ b/drivers/power/ds2782_battery.c
@@ -395,12 +395,17 @@ static int ds278x_battery_probe(struct i2c_client *client,
}
/* Get an ID for this battery */
+ ret = idr_pre_get(&battery_id, GFP_KERNEL);
+ if (ret == 0) {
+ ret = -ENOMEM;
+ goto fail_id;
+ }
+
mutex_lock(&battery_lock);
- ret = idr_alloc(&battery_id, client, 0, 0, GFP_KERNEL);
+ ret = idr_get_new(&battery_id, client, &num);
mutex_unlock(&battery_lock);
if (ret < 0)
goto fail_id;
- num = ret;
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info) {
diff --git a/drivers/pps/kapi.c b/drivers/pps/kapi.c
index cdad4d9..f197e8e 100644
--- a/drivers/pps/kapi.c
+++ b/drivers/pps/kapi.c
@@ -102,7 +102,7 @@ struct pps_device *pps_register_source(struct pps_source_info *info,
goto pps_register_source_exit;
}
- /* These initializations must be done before calling idr_alloc()
+ /* These initializations must be done before calling idr_get_new()
* in order to avoid reces into pps_event().
*/
pps->params.api_version = PPS_API_VERS;
diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c
index de8e663..2420d5a 100644
--- a/drivers/pps/pps.c
+++ b/drivers/pps/pps.c
@@ -290,22 +290,30 @@ int pps_register_cdev(struct pps_device *pps)
dev_t devt;
mutex_lock(&pps_idr_lock);
- /*
- * Get new ID for the new PPS source. After idr_alloc() calling
- * the new source will be freely available into the kernel.
- */
- err = idr_alloc(&pps_idr, pps, 0, PPS_MAX_SOURCES, GFP_KERNEL);
- if (err < 0) {
- if (err == -ENOSPC) {
- pr_err("%s: too many PPS sources in the system\n",
- pps->info.name);
- err = -EBUSY;
- }
- goto out_unlock;
+ /* Get new ID for the new PPS source */
+ if (idr_pre_get(&pps_idr, GFP_KERNEL) == 0) {
+ mutex_unlock(&pps_idr_lock);
+ return -ENOMEM;
}
- pps->id = err;
+
+ /* Now really allocate the PPS source.
+ * After idr_get_new() calling the new source will be freely available
+ * into the kernel.
+ */
+ err = idr_get_new(&pps_idr, pps, &pps->id);
mutex_unlock(&pps_idr_lock);
+ if (err < 0)
+ return err;
+
+ pps->id &= MAX_IDR_MASK;
+ if (pps->id >= PPS_MAX_SOURCES) {
+ pr_err("%s: too many PPS sources in the system\n",
+ pps->info.name);
+ err = -EBUSY;
+ goto free_idr;
+ }
+
devt = MKDEV(MAJOR(pps_devt), pps->id);
cdev_init(&pps->cdev, &pps_cdev_fops);
@@ -337,8 +345,8 @@ del_cdev:
free_idr:
mutex_lock(&pps_idr_lock);
idr_remove(&pps_idr, pps->id);
-out_unlock:
mutex_unlock(&pps_idr_lock);
+
return err;
}
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 29387df..634d367 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -199,6 +199,11 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
/* actual size of vring (in bytes) */
size = PAGE_ALIGN(vring_size(rvring->len, rvring->align));
+ if (!idr_pre_get(&rproc->notifyids, GFP_KERNEL)) {
+ dev_err(dev, "idr_pre_get failed\n");
+ return -ENOMEM;
+ }
+
/*
* Allocate non-cacheable memory for the vring. In the future
* this call will also configure the IOMMU for us
@@ -216,13 +221,12 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
* TODO: let the rproc know the notifyid of this vring
* TODO: support predefined notifyids (via resource table)
*/
- ret = idr_alloc(&rproc->notifyids, rvring, 0, 0, GFP_KERNEL);
+ ret = idr_get_new(&rproc->notifyids, rvring, ¬ifyid);
if (ret) {
- dev_err(dev, "idr_alloc failed: %d\n", ret);
+ dev_err(dev, "idr_get_new failed: %d\n", ret);
dma_free_coherent(dev->parent, size, va, dma);
return ret;
}
- notifyid = ret;
/* Store largest notifyid */
rproc->max_notifyid = max(rproc->max_notifyid, notifyid);
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index a59684b..aaa6840 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -213,10 +213,13 @@ static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp,
struct rpmsg_channel *rpdev, rpmsg_rx_cb_t cb,
void *priv, u32 addr)
{
- int id_min, id_max, id;
+ int err, tmpaddr, request;
struct rpmsg_endpoint *ept;
struct device *dev = rpdev ? &rpdev->dev : &vrp->vdev->dev;
+ if (!idr_pre_get(&vrp->endpoints, GFP_KERNEL))
+ return NULL;
+
ept = kzalloc(sizeof(*ept), GFP_KERNEL);
if (!ept) {
dev_err(dev, "failed to kzalloc a new ept\n");
@@ -231,28 +234,31 @@ static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp,
ept->priv = priv;
/* do we need to allocate a local address ? */
- if (addr == RPMSG_ADDR_ANY) {
- id_min = RPMSG_RESERVED_ADDRESSES;
- id_max = 0;
- } else {
- id_min = addr;
- id_max = addr + 1;
- }
+ request = addr == RPMSG_ADDR_ANY ? RPMSG_RESERVED_ADDRESSES : addr;
mutex_lock(&vrp->endpoints_lock);
/* bind the endpoint to an rpmsg address (and allocate one if needed) */
- id = idr_alloc(&vrp->endpoints, ept, id_min, id_max, GFP_KERNEL);
- if (id < 0) {
- dev_err(dev, "idr_alloc failed: %d\n", id);
+ err = idr_get_new_above(&vrp->endpoints, ept, request, &tmpaddr);
+ if (err) {
+ dev_err(dev, "idr_get_new_above failed: %d\n", err);
goto free_ept;
}
- ept->addr = id;
+
+ /* make sure the user's address request is fulfilled, if relevant */
+ if (addr != RPMSG_ADDR_ANY && tmpaddr != addr) {
+ dev_err(dev, "address 0x%x already in use\n", addr);
+ goto rem_idr;
+ }
+
+ ept->addr = tmpaddr;
mutex_unlock(&vrp->endpoints_lock);
return ept;
+rem_idr:
+ idr_remove(&vrp->endpoints, request);
free_ept:
mutex_unlock(&vrp->endpoints_lock);
kref_put(&ept->refcount, __ept_release);
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c
index 5864f98..8f92732 100644
--- a/drivers/scsi/bfa/bfad_im.c
+++ b/drivers/scsi/bfa/bfad_im.c
@@ -523,13 +523,20 @@ bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port,
int error = 1;
mutex_lock(&bfad_mutex);
- error = idr_alloc(&bfad_im_port_index, im_port, 0, 0, GFP_KERNEL);
- if (error < 0) {
+ if (!idr_pre_get(&bfad_im_port_index, GFP_KERNEL)) {
mutex_unlock(&bfad_mutex);
- printk(KERN_WARNING "idr_alloc failure\n");
+ printk(KERN_WARNING "idr_pre_get failure\n");
goto out;
}
- im_port->idr_id = error;
+
+ error = idr_get_new(&bfad_im_port_index, im_port,
+ &im_port->idr_id);
+ if (error) {
+ mutex_unlock(&bfad_mutex);
+ printk(KERN_WARNING "idr_get_new failure\n");
+ goto out;
+ }
+
mutex_unlock(&bfad_mutex);
im_port->shost = bfad_scsi_host_alloc(im_port, bfad);
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index 2a32374..a15474e 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -895,7 +895,7 @@ static int ch_probe(struct device *dev)
{
struct scsi_device *sd = to_scsi_device(dev);
struct device *class_dev;
- int ret;
+ int minor, ret = -ENOMEM;
scsi_changer *ch;
if (sd->type != TYPE_MEDIUM_CHANGER)
@@ -905,19 +905,22 @@ static int ch_probe(struct device *dev)
if (NULL == ch)
return -ENOMEM;
- idr_preload(GFP_KERNEL);
+ if (!idr_pre_get(&ch_index_idr, GFP_KERNEL))
+ goto free_ch;
+
spin_lock(&ch_index_lock);
- ret = idr_alloc(&ch_index_idr, ch, 0, CH_MAX_DEVS + 1, GFP_NOWAIT);
+ ret = idr_get_new(&ch_index_idr, ch, &minor);
spin_unlock(&ch_index_lock);
- idr_preload_end();
- if (ret < 0) {
- if (ret == -ENOSPC)
- ret = -ENODEV;
+ if (ret)
goto free_ch;
+
+ if (minor > CH_MAX_DEVS) {
+ ret = -ENODEV;
+ goto remove_idr;
}
- ch->minor = ret;
+ ch->minor = minor;
sprintf(ch->name,"ch%d",ch->minor);
class_dev = device_create(ch_sysfs_class, dev,
@@ -941,7 +944,7 @@ static int ch_probe(struct device *dev)
return 0;
remove_idr:
- idr_remove(&ch_index_idr, ch->minor);
+ idr_remove(&ch_index_idr, minor);
free_ch:
kfree(ch);
return ret;
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 314b4f6..26ca2ef 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -3165,10 +3165,14 @@ destroy_port(struct lpfc_vport *vport)
int
lpfc_get_instance(void)
{
- int ret;
-
- ret = idr_alloc(&lpfc_hba_index, NULL, 0, 0, GFP_KERNEL);
- return ret < 0 ? -1 : ret;
+ int instance = 0;
+
+ /* Assign an unused number */
+ if (!idr_pre_get(&lpfc_hba_index, GFP_KERNEL))
+ return -1;
+ if (idr_get_new(&lpfc_hba_index, NULL, &instance))
+ return -1;
+ return instance;
}
/**
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index df5e961..afa5bfc 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1392,23 +1392,24 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
return ERR_PTR(-ENOMEM);
}
- idr_preload(GFP_KERNEL);
+ if (!idr_pre_get(&sg_index_idr, GFP_KERNEL)) {
+ printk(KERN_WARNING "idr expansion Sg_device failure\n");
+ error = -ENOMEM;
+ goto out;
+ }
+
write_lock_irqsave(&sg_index_lock, iflags);
- error = idr_alloc(&sg_index_idr, sdp, 0, SG_MAX_DEVS, GFP_NOWAIT);
- if (error < 0) {
- if (error == -ENOSPC) {
- sdev_printk(KERN_WARNING, scsidp,
- "Unable to attach sg device type=%d, minor number exceeds %d\n",
- scsidp->type, SG_MAX_DEVS - 1);
- error = -ENODEV;
- } else {
- printk(KERN_WARNING
- "idr allocation Sg_device failure: %d\n", error);
- }
- goto out_unlock;
+ error = idr_get_new(&sg_index_idr, sdp, &k);
+ if (error) {
+ write_unlock_irqrestore(&sg_index_lock, iflags);
+ printk(KERN_WARNING "idr allocation Sg_device failure: %d\n",
+ error);
+ goto out;
}
- k = error;
+
+ if (unlikely(k >= SG_MAX_DEVS))
+ goto overflow;
SCSI_LOG_TIMEOUT(3, printk("sg_alloc: dev=%d \n", k));
sprintf(disk->disk_name, "sg%d", k);
@@ -1420,17 +1421,25 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
sdp->sg_tablesize = queue_max_segments(q);
sdp->index = k;
kref_init(&sdp->d_ref);
- error = 0;
-out_unlock:
write_unlock_irqrestore(&sg_index_lock, iflags);
- idr_preload_end();
+ error = 0;
+ out:
if (error) {
kfree(sdp);
return ERR_PTR(error);
}
return sdp;
+
+ overflow:
+ idr_remove(&sg_index_idr, k);
+ write_unlock_irqrestore(&sg_index_lock, iflags);
+ sdev_printk(KERN_WARNING, scsidp,
+ "Unable to attach sg device type=%d, minor "
+ "number exceeds %d\n", scsidp->type, SG_MAX_DEVS - 1);
+ error = -ENODEV;
+ goto out;
}
static int
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 7c6edca..98156a9 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -4076,7 +4076,7 @@ static int st_probe(struct device *dev)
struct st_modedef *STm;
struct st_partstat *STps;
struct st_buffer *buffer;
- int i, error;
+ int i, dev_num, error;
char *stp;
if (SDp->type != TYPE_TAPE)
@@ -4178,17 +4178,27 @@ static int st_probe(struct device *dev)
tpnt->blksize_changed = 0;
mutex_init(&tpnt->lock);
- idr_preload(GFP_KERNEL);
+ if (!idr_pre_get(&st_index_idr, GFP_KERNEL)) {
+ pr_warn("st: idr expansion failed\n");
+ error = -ENOMEM;
+ goto out_put_disk;
+ }
+
spin_lock(&st_index_lock);
- error = idr_alloc(&st_index_idr, tpnt, 0, ST_MAX_TAPES + 1, GFP_NOWAIT);
+ error = idr_get_new(&st_index_idr, tpnt, &dev_num);
spin_unlock(&st_index_lock);
- idr_preload_end();
- if (error < 0) {
+ if (error) {
pr_warn("st: idr allocation failed: %d\n", error);
goto out_put_disk;
}
- tpnt->index = error;
- sprintf(disk->disk_name, "st%d", tpnt->index);
+
+ if (dev_num > ST_MAX_TAPES) {
+ pr_err("st: Too many tape devices (max. %d).\n", ST_MAX_TAPES);
+ goto out_put_index;
+ }
+
+ tpnt->index = dev_num;
+ sprintf(disk->disk_name, "st%d", dev_num);
dev_set_drvdata(dev, tpnt);
@@ -4208,8 +4218,9 @@ static int st_probe(struct device *dev)
out_remove_devs:
remove_cdevs(tpnt);
+out_put_index:
spin_lock(&st_index_lock);
- idr_remove(&st_index_idr, tpnt->index);
+ idr_remove(&st_index_idr, dev_num);
spin_unlock(&st_index_lock);
out_put_disk:
put_disk(disk);
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index f1fdf4f..339f97f 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -144,24 +144,23 @@ struct iscsi_tiqn *iscsit_add_tiqn(unsigned char *buf)
spin_lock_init(&tiqn->login_stats.lock);
spin_lock_init(&tiqn->logout_stats.lock);
+ if (!idr_pre_get(&tiqn_idr, GFP_KERNEL)) {
+ pr_err("idr_pre_get() for tiqn_idr failed\n");
+ kfree(tiqn);
+ return ERR_PTR(-ENOMEM);
+ }
tiqn->tiqn_state = TIQN_STATE_ACTIVE;
- idr_preload(GFP_KERNEL);
spin_lock(&tiqn_lock);
-
- ret = idr_alloc(&tiqn_idr, NULL, 0, 0, GFP_NOWAIT);
+ ret = idr_get_new(&tiqn_idr, NULL, &tiqn->tiqn_index);
if (ret < 0) {
- pr_err("idr_alloc() failed for tiqn->tiqn_index\n");
+ pr_err("idr_get_new() failed for tiqn->tiqn_index\n");
spin_unlock(&tiqn_lock);
- idr_preload_end();
kfree(tiqn);
return ERR_PTR(ret);
}
- tiqn->tiqn_index = ret;
list_add_tail(&tiqn->tiqn_list, &g_tiqn_list);
-
spin_unlock(&tiqn_lock);
- idr_preload_end();
pr_debug("CORE[0] - Added iSCSI Target IQN: %s\n", tiqn->tiqn);
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index 2535d4d..fdb632f 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -247,16 +247,19 @@ static int iscsi_login_zero_tsih_s1(
spin_lock_init(&sess->session_usage_lock);
spin_lock_init(&sess->ttt_lock);
- idr_preload(GFP_KERNEL);
+ if (!idr_pre_get(&sess_idr, GFP_KERNEL)) {
+ pr_err("idr_pre_get() for sess_idr failed\n");
+ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+ ISCSI_LOGIN_STATUS_NO_RESOURCES);
+ kfree(sess);
+ return -ENOMEM;
+ }
spin_lock_bh(&sess_idr_lock);
- ret = idr_alloc(&sess_idr, NULL, 0, 0, GFP_NOWAIT);
- if (ret >= 0)
- sess->session_index = ret;
+ ret = idr_get_new(&sess_idr, NULL, &sess->session_index);
spin_unlock_bh(&sess_idr_lock);
- idr_preload_end();
if (ret < 0) {
- pr_err("idr_alloc() for sess_idr failed\n");
+ pr_err("idr_get_new() for sess_idr failed\n");
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
ISCSI_LOGIN_STATUS_NO_RESOURCES);
kfree(sess);
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 8dc44cb..455c77a 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -73,14 +73,21 @@ static struct cpufreq_cooling_device *notify_device;
*/
static int get_idr(struct idr *idr, int *id)
{
- int ret;
+ int err;
+again:
+ if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0))
+ return -ENOMEM;
mutex_lock(&cooling_cpufreq_lock);
- ret = idr_alloc(idr, NULL, 0, 0, GFP_KERNEL);
+ err = idr_get_new(idr, NULL, id);
mutex_unlock(&cooling_cpufreq_lock);
- if (unlikely(ret < 0))
- return ret;
- *id = ret;
+
+ if (unlikely(err == -EAGAIN))
+ goto again;
+ else if (unlikely(err))
+ return err;
+
+ *id = *id & MAX_IDR_MASK;
return 0;
}
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 2eaaaa6..6472e7e 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -131,16 +131,23 @@ EXPORT_SYMBOL_GPL(thermal_unregister_governor);
static int get_idr(struct idr *idr, struct mutex *lock, int *id)
{
- int ret;
+ int err;
+
+again:
+ if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0))
+ return -ENOMEM;
if (lock)
mutex_lock(lock);
- ret = idr_alloc(idr, NULL, 0, 0, GFP_KERNEL);
+ err = idr_get_new(idr, NULL, id);
if (lock)
mutex_unlock(lock);
- if (unlikely(ret < 0))
- return ret;
- *id = ret;
+ if (unlikely(err == -EAGAIN))
+ goto again;
+ else if (unlikely(err))
+ return err;
+
+ *id = *id & MAX_IDR_MASK;
return 0;
}
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index c8b9262..5110f36 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -369,15 +369,26 @@ static void uio_dev_del_attributes(struct uio_device *idev)
static int uio_get_minor(struct uio_device *idev)
{
int retval = -ENOMEM;
+ int id;
mutex_lock(&minor_lock);
- retval = idr_alloc(&uio_idr, idev, 0, UIO_MAX_DEVICES, GFP_KERNEL);
- if (retval >= 0) {
- idev->minor = retval;
- } else if (retval == -ENOSPC) {
+ if (idr_pre_get(&uio_idr, GFP_KERNEL) == 0)
+ goto exit;
+
+ retval = idr_get_new(&uio_idr, idev, &id);
+ if (retval < 0) {
+ if (retval == -EAGAIN)
+ retval = -ENOMEM;
+ goto exit;
+ }
+ if (id < UIO_MAX_DEVICES) {
+ idev->minor = id;
+ } else {
dev_err(idev->dev, "too many uio devices\n");
retval = -EINVAL;
+ idr_remove(&uio_idr, id);
}
+exit:
mutex_unlock(&minor_lock);
return retval;
}
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 7f61abf..12c264d 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -139,8 +139,23 @@ EXPORT_SYMBOL_GPL(vfio_unregister_iommu_driver);
*/
static int vfio_alloc_group_minor(struct vfio_group *group)
{
+ int ret, minor;
+
+again:
+ if (unlikely(idr_pre_get(&vfio.group_idr, GFP_KERNEL) == 0))
+ return -ENOMEM;
+
/* index 0 is used by /dev/vfio/vfio */
- return idr_alloc(&vfio.group_idr, group, 1, MINORMASK + 1, GFP_KERNEL);
+ ret = idr_get_new_above(&vfio.group_idr, group, 1, &minor);
+ if (ret == -EAGAIN)
+ goto again;
+ if (ret || minor > MINORMASK) {
+ if (minor > MINORMASK)
+ idr_remove(&vfio.group_idr, minor);
+ return -ENOSPC;
+ }
+
+ return minor;
}
static void vfio_free_group_minor(int minor)
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index 1b11466..f750165 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -1183,7 +1183,7 @@ static void detach_lkb(struct dlm_lkb *lkb)
static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)
{
struct dlm_lkb *lkb;
- int rv;
+ int rv, id;
lkb = dlm_allocate_lkb(ls);
if (!lkb)
@@ -1199,13 +1199,19 @@ static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)
mutex_init(&lkb->lkb_cb_mutex);
INIT_WORK(&lkb->lkb_cb_work, dlm_callback_work);
- idr_preload(GFP_NOFS);
+ retry:
+ rv = idr_pre_get(&ls->ls_lkbidr, GFP_NOFS);
+ if (!rv)
+ return -ENOMEM;
+
spin_lock(&ls->ls_lkbidr_spin);
- rv = idr_alloc(&ls->ls_lkbidr, lkb, 1, 0, GFP_NOWAIT);
- if (rv >= 0)
- lkb->lkb_id = rv;
+ rv = idr_get_new_above(&ls->ls_lkbidr, lkb, 1, &id);
+ if (!rv)
+ lkb->lkb_id = id;
spin_unlock(&ls->ls_lkbidr_spin);
- idr_preload_end();
+
+ if (rv == -EAGAIN)
+ goto retry;
if (rv < 0) {
log_error(ls, "create_lkb idr error %d", rv);
diff --git a/fs/dlm/recover.c b/fs/dlm/recover.c
index a6bc63f..236d108 100644
--- a/fs/dlm/recover.c
+++ b/fs/dlm/recover.c
@@ -305,26 +305,27 @@ static int recover_idr_empty(struct dlm_ls *ls)
static int recover_idr_add(struct dlm_rsb *r)
{
struct dlm_ls *ls = r->res_ls;
- int rv;
+ int rv, id;
+
+ rv = idr_pre_get(&ls->ls_recover_idr, GFP_NOFS);
+ if (!rv)
+ return -ENOMEM;
- idr_preload(GFP_NOFS);
spin_lock(&ls->ls_recover_idr_lock);
if (r->res_id) {
- rv = -1;
- goto out_unlock;
+ spin_unlock(&ls->ls_recover_idr_lock);
+ return -1;
}
- rv = idr_alloc(&ls->ls_recover_idr, r, 1, 0, GFP_NOWAIT);
- if (rv < 0)
- goto out_unlock;
-
- r->res_id = rv;
+ rv = idr_get_new_above(&ls->ls_recover_idr, r, 1, &id);
+ if (rv) {
+ spin_unlock(&ls->ls_recover_idr_lock);
+ return rv;
+ }
+ r->res_id = id;
ls->ls_recover_list_count++;
dlm_hold_rsb(r);
- rv = 0;
-out_unlock:
spin_unlock(&ls->ls_recover_idr_lock);
- idr_preload_end();
- return rv;
+ return 0;
}
static void recover_idr_del(struct dlm_rsb *r)
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index 47d1008..2e9779b 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -29,14 +29,15 @@ static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
if (clp->rpc_ops->version != 4 || minorversion != 0)
return ret;
- idr_preload(GFP_KERNEL);
+retry:
+ if (!idr_pre_get(&nn->cb_ident_idr, GFP_KERNEL))
+ return -ENOMEM;
spin_lock(&nn->nfs_client_lock);
- ret = idr_alloc(&nn->cb_ident_idr, clp, 0, 0, GFP_NOWAIT);
- if (ret >= 0)
- clp->cl_cb_ident = ret;
+ ret = idr_get_new(&nn->cb_ident_idr, clp, &clp->cl_cb_ident);
spin_unlock(&nn->nfs_client_lock);
- idr_preload_end();
- return ret < 0 ? ret : 0;
+ if (ret == -EAGAIN)
+ goto retry;
+ return ret;
}
#ifdef CONFIG_NFS_V4_1
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index e0f7c12..07f7a92 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -364,20 +364,22 @@ static int inotify_add_to_idr(struct idr *idr, spinlock_t *idr_lock,
{
int ret;
- idr_preload(GFP_KERNEL);
- spin_lock(idr_lock);
+ do {
+ if (unlikely(!idr_pre_get(idr, GFP_KERNEL)))
+ return -ENOMEM;
- ret = idr_alloc(idr, i_mark, *last_wd + 1, 0, GFP_NOWAIT);
- if (ret >= 0) {
+ spin_lock(idr_lock);
+ ret = idr_get_new_above(idr, i_mark, *last_wd + 1,
+ &i_mark->wd);
/* we added the mark to the idr, take a reference */
- i_mark->wd = ret;
- *last_wd = i_mark->wd;
- fsnotify_get_mark(&i_mark->fsn_mark);
- }
+ if (!ret) {
+ *last_wd = i_mark->wd;
+ fsnotify_get_mark(&i_mark->fsn_mark);
+ }
+ spin_unlock(idr_lock);
+ } while (ret == -EAGAIN);
- spin_unlock(idr_lock);
- idr_preload_end();
- return ret < 0 ? ret : 0;
+ return ret;
}
static struct inotify_inode_mark *inotify_idr_find_locked(struct fsnotify_group *group,
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index 33b8924..a1d83c5 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -304,22 +304,28 @@ static u8 o2net_num_from_nn(struct o2net_node *nn)
static int o2net_prep_nsw(struct o2net_node *nn, struct o2net_status_wait *nsw)
{
- int ret;
+ int ret = 0;
- spin_lock(&nn->nn_lock);
- ret = idr_alloc(&nn->nn_status_idr, nsw, 0, 0, GFP_ATOMIC);
- if (ret >= 0) {
- nsw->ns_id = ret;
- list_add_tail(&nsw->ns_node_item, &nn->nn_status_list);
+ do {
+ if (!idr_pre_get(&nn->nn_status_idr, GFP_ATOMIC)) {
+ ret = -EAGAIN;
+ break;
+ }
+ spin_lock(&nn->nn_lock);
+ ret = idr_get_new(&nn->nn_status_idr, nsw, &nsw->ns_id);
+ if (ret == 0)
+ list_add_tail(&nsw->ns_node_item,
+ &nn->nn_status_list);
+ spin_unlock(&nn->nn_lock);
+ } while (ret == -EAGAIN);
+
+ if (ret == 0) {
+ init_waitqueue_head(&nsw->ns_wq);
+ nsw->ns_sys_status = O2NET_ERR_NONE;
+ nsw->ns_status = 0;
}
- spin_unlock(&nn->nn_lock);
- if (ret < 0)
- return ret;
- init_waitqueue_head(&nsw->ns_wq);
- nsw->ns_sys_status = O2NET_ERR_NONE;
- nsw->ns_status = 0;
- return 0;
+ return ret;
}
static void o2net_complete_nsw_locked(struct o2net_node *nn,
diff --git a/include/linux/idr.h b/include/linux/idr.h
index 8d3ffe1..92e84f7 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -94,29 +94,15 @@ struct idr {
void *idr_find(struct idr *idp, int id);
int idr_pre_get(struct idr *idp, gfp_t gfp_mask);
int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id);
-void idr_preload(gfp_t gfp_mask);
-int idr_alloc(struct idr *idp, void *ptr, int start, int end, gfp_t gfp_mask);
int idr_for_each(struct idr *idp,
int (*fn)(int id, void *p, void *data), void *data);
void *idr_get_next(struct idr *idp, int *nextid);
void *idr_replace(struct idr *idp, void *ptr, int id);
void idr_remove(struct idr *idp, int id);
-void idr_free(struct idr *idp, int id);
void idr_destroy(struct idr *idp);
void idr_init(struct idr *idp);
/**
- * idr_preload_end - end preload section started with idr_preload()
- *
- * Each idr_preload() should be matched with an invocation of this
- * function. See idr_preload() for details.
- */
-static inline void idr_preload_end(void)
-{
- preempt_enable();
-}
-
-/**
* idr_get_new - allocate new idr entry
* @idp: idr handle
* @ptr: pointer you want associated with the id
diff --git a/ipc/util.c b/ipc/util.c
index 91ce0bc..74e1d9c 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -252,7 +252,7 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
{
kuid_t euid;
kgid_t egid;
- int id;
+ int id, err;
int next_id = ids->next_id;
if (size > IPCMNI)
@@ -261,21 +261,17 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
if (ids->in_use >= size)
return -ENOSPC;
- idr_preload(GFP_KERNEL);
-
spin_lock_init(&new->lock);
new->deleted = 0;
rcu_read_lock();
spin_lock(&new->lock);
- id = idr_alloc(&ids->ipcs_idr, new,
- (next_id < 0) ? 0 : ipcid_to_idx(next_id), 0,
- GFP_NOWAIT);
- idr_preload_end();
- if (id < 0) {
+ err = idr_get_new_above(&ids->ipcs_idr, new,
+ (next_id < 0) ? 0 : ipcid_to_idx(next_id), &id);
+ if (err) {
spin_unlock(&new->lock);
rcu_read_unlock();
- return id;
+ return err;
}
ids->in_use++;
@@ -311,10 +307,19 @@ static int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids,
struct ipc_ops *ops, struct ipc_params *params)
{
int err;
+retry:
+ err = idr_pre_get(&ids->ipcs_idr, GFP_KERNEL);
+
+ if (!err)
+ return -ENOMEM;
down_write(&ids->rw_mutex);
err = ops->getnew(ns, params);
up_write(&ids->rw_mutex);
+
+ if (err == -EAGAIN)
+ goto retry;
+
return err;
}
@@ -370,7 +375,9 @@ static int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids,
{
struct kern_ipc_perm *ipcp;
int flg = params->flg;
- int err = 0;
+ int err;
+retry:
+ err = idr_pre_get(&ids->ipcs_idr, GFP_KERNEL);
/*
* Take the lock as a writer since we are potentially going to add
@@ -406,6 +413,9 @@ static int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids,
}
up_write(&ids->rw_mutex);
+ if (err == -EAGAIN)
+ goto retry;
+
return err;
}
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 3710ba8..5bff65a 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -5282,7 +5282,7 @@ EXPORT_SYMBOL_GPL(free_css_id);
static struct css_id *get_new_cssid(struct cgroup_subsys *ss, int depth)
{
struct css_id *newid;
- int ret, size;
+ int myid, error, size;
BUG_ON(!ss->use_id);
@@ -5290,24 +5290,35 @@ static struct css_id *get_new_cssid(struct cgroup_subsys *ss, int depth)
newid = kzalloc(size, GFP_KERNEL);
if (!newid)
return ERR_PTR(-ENOMEM);
-
- idr_preload(GFP_KERNEL);
+ /* get id */
+ if (unlikely(!idr_pre_get(&ss->idr, GFP_KERNEL))) {
+ error = -ENOMEM;
+ goto err_out;
+ }
spin_lock(&ss->id_lock);
/* Don't use 0. allocates an ID of 1-65535 */
- ret = idr_alloc(&ss->idr, newid, 1, CSS_ID_MAX + 1, GFP_NOWAIT);
+ error = idr_get_new_above(&ss->idr, newid, 1, &myid);
spin_unlock(&ss->id_lock);
- idr_preload_end();
/* Returns error when there are no free spaces for new ID.*/
- if (ret < 0)
+ if (error) {
+ error = -ENOSPC;
goto err_out;
+ }
+ if (myid > CSS_ID_MAX)
+ goto remove_idr;
- newid->id = ret;
+ newid->id = myid;
newid->depth = depth;
return newid;
+remove_idr:
+ error = -ENOSPC;
+ spin_lock(&ss->id_lock);
+ idr_remove(&ss->idr, myid);
+ spin_unlock(&ss->id_lock);
err_out:
kfree(newid);
- return ERR_PTR(ret);
+ return ERR_PTR(error);
}
diff --git a/kernel/events/core.c b/kernel/events/core.c
index d6df1b9..19e9809 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5963,9 +5963,13 @@ int perf_pmu_register(struct pmu *pmu, char *name, int type)
pmu->name = name;
if (type < 0) {
- type = idr_alloc(&pmu_idr, pmu, PERF_TYPE_MAX, 0, GFP_KERNEL);
- if (type < 0) {
- ret = type;
+ int err = idr_pre_get(&pmu_idr, GFP_KERNEL);
+ if (!err)
+ goto free_pdc;
+
+ err = idr_get_new_above(&pmu_idr, pmu, PERF_TYPE_MAX, &type);
+ if (err) {
+ ret = err;
goto free_pdc;
}
}
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index b51bb08..10349d5 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -552,22 +552,24 @@ SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock,
return -EAGAIN;
spin_lock_init(&new_timer->it_lock);
-
- idr_preload(GFP_KERNEL);
+ retry:
+ if (unlikely(!idr_pre_get(&posix_timers_id, GFP_KERNEL))) {
+ error = -EAGAIN;
+ goto out;
+ }
spin_lock_irq(&idr_lock);
- error = idr_alloc(&posix_timers_id, new_timer, 0, 0, GFP_NOWAIT);
+ error = idr_get_new(&posix_timers_id, new_timer, &new_timer_id);
spin_unlock_irq(&idr_lock);
- idr_preload_end();
- if (error < 0) {
+ if (error) {
+ if (error == -EAGAIN)
+ goto retry;
/*
* Weird looking, but we return EAGAIN if the IDR is
* full (proper POSIX return value for this)
*/
- if (error == -ENOSPC)
- error = -EAGAIN;
+ error = -EAGAIN;
goto out;
}
- new_timer_id = error;
it_id_set = IT_ID_SET;
new_timer->it_id = (timer_t) new_timer_id;
diff --git a/lib/idr.c b/lib/idr.c
index 5115705..b13aae5 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -35,12 +35,8 @@
#include <linux/string.h>
#include <linux/idr.h>
#include <linux/spinlock.h>
-#include <linux/percpu.h>
-#include <linux/hardirq.h>
static struct kmem_cache *idr_layer_cache;
-static DEFINE_PER_CPU(struct idr_layer *, idr_preload_head);
-static DEFINE_PER_CPU(int, idr_preload_cnt);
static DEFINE_SPINLOCK(simple_ida_lock);
static struct idr_layer *get_from_free_list(struct idr *idp)
@@ -58,50 +54,6 @@ static struct idr_layer *get_from_free_list(struct idr *idp)
return(p);
}
-/**
- * idr_layer_alloc - allocate a new idr_layer
- * @gfp_mask: allocation mask
- * @layer_idr: optional idr to allocate from
- *
- * If @layer_idr is %NULL, directly allocate one using @gfp_mask or fetch
- * one from the per-cpu preload buffer. If @layer_idr is not %NULL, fetch
- * an idr_layer from @idr->id_free.
- *
- * @layer_idr is to maintain backward compatibility with the old alloc
- * interface - idr_pre_get() and idr_get_new*() - and will be removed
- * together with per-pool preload buffer.
- */
-static struct idr_layer *idr_layer_alloc(gfp_t gfp_mask, struct idr *layer_idr)
-{
- struct idr_layer *new;
-
- /* this is the old path, bypass to get_from_free_list() */
- if (layer_idr)
- return get_from_free_list(layer_idr);
-
- /* try to allocate directly from kmem_cache */
- new = kmem_cache_zalloc(idr_layer_cache, gfp_mask);
- if (new)
- return new;
-
- /*
- * Try to fetch one from the per-cpu preload buffer if in process
- * context. See idr_preload() for details.
- */
- if (in_interrupt())
- return NULL;
-
- preempt_disable();
- new = __this_cpu_read(idr_preload_head);
- if (new) {
- __this_cpu_write(idr_preload_head, new->ary[0]);
- __this_cpu_dec(idr_preload_cnt);
- new->ary[0] = NULL;
- }
- preempt_enable();
- return new;
-}
-
static void idr_layer_rcu_free(struct rcu_head *head)
{
struct idr_layer *layer;
@@ -187,8 +139,6 @@ EXPORT_SYMBOL(idr_pre_get);
* @starting_id: id to start search at
* @id: pointer to the allocated handle
* @pa: idr_layer[MAX_IDR_LEVEL] used as backtrack buffer
- * @gfp_mask: allocation mask for idr_layer_alloc()
- * @layer_idr: optional idr passed to idr_layer_alloc()
*
* Allocate an id in range [@starting_id, INT_MAX] from @idp without
* growing its depth. Returns
@@ -198,8 +148,7 @@ EXPORT_SYMBOL(idr_pre_get);
* -ENOSPC if the id space is exhausted,
* -ENOMEM if more idr_layers need to be allocated.
*/
-static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa,
- gfp_t gfp_mask, struct idr *layer_idr)
+static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa)
{
int n, m, sh;
struct idr_layer *p, *new;
@@ -253,7 +202,7 @@ static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa,
* Create the layer below if it is missing.
*/
if (!p->ary[m]) {
- new = idr_layer_alloc(gfp_mask, layer_idr);
+ new = get_from_free_list(idp);
if (!new)
return -ENOMEM;
new->layer = l-1;
@@ -269,8 +218,7 @@ static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa,
}
static int idr_get_empty_slot(struct idr *idp, int starting_id,
- struct idr_layer **pa, gfp_t gfp_mask,
- struct idr *layer_idr)
+ struct idr_layer **pa)
{
struct idr_layer *p, *new;
int layers, v, id;
@@ -281,7 +229,7 @@ build_up:
p = idp->top;
layers = idp->layers;
if (unlikely(!p)) {
- if (!(p = idr_layer_alloc(gfp_mask, layer_idr)))
+ if (!(p = get_from_free_list(idp)))
return -ENOMEM;
p->layer = 0;
layers = 1;
@@ -300,7 +248,7 @@ build_up:
p->layer++;
continue;
}
- if (!(new = idr_layer_alloc(gfp_mask, layer_idr))) {
+ if (!(new = get_from_free_list(idp))) {
/*
* The allocation failed. If we built part of
* the structure tear it down.
@@ -324,7 +272,7 @@ build_up:
}
rcu_assign_pointer(idp->top, p);
idp->layers = layers;
- v = sub_alloc(idp, &id, pa, gfp_mask, layer_idr);
+ v = sub_alloc(idp, &id, pa);
if (v == -EAGAIN)
goto build_up;
return(v);
@@ -364,7 +312,7 @@ int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id)
struct idr_layer *pa[MAX_IDR_LEVEL];
int rv;
- rv = idr_get_empty_slot(idp, starting_id, pa, 0, idp);
+ rv = idr_get_empty_slot(idp, starting_id, pa);
if (rv < 0)
return rv == -ENOMEM ? -EAGAIN : rv;
@@ -374,109 +322,6 @@ int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id)
}
EXPORT_SYMBOL(idr_get_new_above);
-/**
- * idr_preload - preload for idr_alloc()
- * @gfp_mask: allocation mask to use for preloading
- *
- * Preload per-cpu layer buffer for idr_alloc(). Can only be used from
- * process context and each idr_preload() invocation should be matched with
- * idr_preload_end(). Note that preemption is disabled while preloaded.
- *
- * The first idr_alloc() in the preloaded section can be treated as if it
- * were invoked with @gfp_mask used for preloading. This allows using more
- * permissive allocation masks for idrs protected by spinlocks.
- *
- * For example, if idr_alloc() below fails, the failure can be treated as
- * if idr_alloc() were called with GFP_KERNEL rather than GFP_NOWAIT.
- *
- * idr_preload(GFP_KERNEL);
- * spin_lock(lock);
- *
- * id = idr_alloc(idr, ptr, start, end, GFP_NOWAIT);
- *
- * spin_unlock(lock);
- * idr_preload_end();
- * if (id < 0)
- * error;
- */
-void idr_preload(gfp_t gfp_mask)
-{
- /*
- * Consuming preload buffer from non-process context breaks preload
- * allocation guarantee. Disallow usage from those contexts.
- */
- WARN_ON_ONCE(in_interrupt());
- might_sleep_if(gfp_mask & __GFP_WAIT);
-
- preempt_disable();
-
- /*
- * idr_alloc() is likely to succeed w/o full idr_layer buffer and
- * return value from idr_alloc() needs to be checked for failure
- * anyway. Silently give up if allocation fails. The caller can
- * treat failures from idr_alloc() as if idr_alloc() were called
- * with @gfp_mask which should be enough.
- */
- while (__this_cpu_read(idr_preload_cnt) < MAX_IDR_FREE) {
- struct idr_layer *new;
-
- preempt_enable();
- new = kmem_cache_zalloc(idr_layer_cache, gfp_mask);
- preempt_disable();
- if (!new)
- break;
-
- /* link the new one to per-cpu preload list */
- new->ary[0] = __this_cpu_read(idr_preload_head);
- __this_cpu_write(idr_preload_head, new);
- __this_cpu_inc(idr_preload_cnt);
- }
-}
-EXPORT_SYMBOL(idr_preload);
-
-/**
- * idr_alloc - allocate new idr entry
- * @idr: the (initialized) idr
- * @ptr: pointer to be associated with the new id
- * @start: the minimum id (inclusive)
- * @end: the maximum id (exclusive, 0 for max)
- * @gfp_mask: memory allocation flags
- *
- * Allocate an id in [start, end) and associate it with @ptr. If no ID is
- * available in the specified range, returns -ENOSPC. On memory allocation
- * failure, returns -ENOMEM.
- *
- * The user is responsible for exclusively synchronizing all operations
- * which may modify @idr. However, read-only accesses such as idr_find()
- * or iteration can be performed under RCU read lock provided the user
- * destroys @ptr in RCU-safe way after removal from idr.
- */
-int idr_alloc(struct idr *idr, void *ptr, int start, int end, gfp_t gfp_mask)
-{
- int max = end ? end - 1 : INT_MAX; /* inclusive upper limit */
- struct idr_layer *pa[MAX_IDR_LEVEL];
- int id;
-
- might_sleep_if(gfp_mask & __GFP_WAIT);
-
- /* sanity checks */
- if (WARN_ON_ONCE(start < 0 || end < 0))
- return -EINVAL;
- if (unlikely(max < start))
- return -ENOSPC;
-
- /* allocate id */
- id = idr_get_empty_slot(idr, start, pa, gfp_mask, NULL);
- if (unlikely(id < 0))
- return id;
- if (unlikely(id > max))
- return -ENOSPC;
-
- idr_fill_slot(ptr, id, pa);
- return id;
-}
-EXPORT_SYMBOL_GPL(idr_alloc);
-
static void idr_remove_warning(int id)
{
printk(KERN_WARNING
@@ -924,7 +769,7 @@ int ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
restart:
/* get vacant slot */
- t = idr_get_empty_slot(&ida->idr, idr_id, pa, 0, &ida->idr);
+ t = idr_get_empty_slot(&ida->idr, idr_id, pa);
if (t < 0)
return t == -ENOMEM ? -EAGAIN : t;
diff --git a/net/9p/util.c b/net/9p/util.c
index 59f278e..6ceeeb3 100644
--- a/net/9p/util.c
+++ b/net/9p/util.c
@@ -87,18 +87,23 @@ EXPORT_SYMBOL(p9_idpool_destroy);
int p9_idpool_get(struct p9_idpool *p)
{
- int i;
+ int i = 0;
+ int error;
unsigned long flags;
- idr_preload(GFP_NOFS);
+retry:
+ if (idr_pre_get(&p->pool, GFP_NOFS) == 0)
+ return -1;
+
spin_lock_irqsave(&p->lock, flags);
/* no need to store exactly p, we just need something non-null */
- i = idr_alloc(&p->pool, p, 0, 0, GFP_NOWAIT);
-
+ error = idr_get_new(&p->pool, p, &i);
spin_unlock_irqrestore(&p->lock, flags);
- idr_preload_end();
- if (i < 0)
+
+ if (error == -EAGAIN)
+ goto retry;
+ else if (error)
return -1;
p9_debug(P9_DEBUG_MUX, " id %d pool %p\n", i, p);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 632f2a7..2bdd454 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -647,6 +647,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
spin_lock_init(&local->ack_status_lock);
idr_init(&local->ack_status_frames);
+ /* preallocate at least one entry */
+ idr_pre_get(&local->ack_status_frames, GFP_KERNEL);
sta_info_init(local);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 5a62468..a2cb6a3 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1999,14 +1999,24 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
skb = skb_clone(skb, GFP_ATOMIC);
if (skb) {
unsigned long flags;
- int id;
+ int id, r;
spin_lock_irqsave(&local->ack_status_lock, flags);
- id = idr_alloc(&local->ack_status_frames, orig_skb,
- 1, 0x10000, GFP_ATOMIC);
+ r = idr_get_new_above(&local->ack_status_frames,
+ orig_skb, 1, &id);
+ if (r == -EAGAIN) {
+ idr_pre_get(&local->ack_status_frames,
+ GFP_ATOMIC);
+ r = idr_get_new_above(&local->ack_status_frames,
+ orig_skb, 1, &id);
+ }
+ if (WARN_ON(!id) || id > 0xffff) {
+ idr_remove(&local->ack_status_frames, id);
+ r = -ERANGE;
+ }
spin_unlock_irqrestore(&local->ack_status_lock, flags);
- if (id >= 0) {
+ if (!r) {
info_id = id;
info_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
} else if (skb_shared(skb)) {
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 43cd0dd..2f95f5a 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -1591,31 +1591,32 @@ int sctp_assoc_lookup_laddr(struct sctp_association *asoc,
/* Set an association id for a given association */
int sctp_assoc_set_id(struct sctp_association *asoc, gfp_t gfp)
{
- bool preload = gfp & __GFP_WAIT;
- int ret;
+ int assoc_id;
+ int error = 0;
/* If the id is already assigned, keep it. */
if (asoc->assoc_id)
- return 0;
+ return error;
+retry:
+ if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp)))
+ return -ENOMEM;
- if (preload)
- idr_preload(gfp);
spin_lock_bh(&sctp_assocs_id_lock);
- /* 0 is not a valid id, idr_low is always >= 1 */
- ret = idr_alloc(&sctp_assocs_id, asoc, idr_low, 0, GFP_NOWAIT);
- if (ret >= 0) {
- idr_low = ret + 1;
+ error = idr_get_new_above(&sctp_assocs_id, (void *)asoc,
+ idr_low, &assoc_id);
+ if (!error) {
+ idr_low = assoc_id + 1;
if (idr_low == INT_MAX)
idr_low = 1;
}
spin_unlock_bh(&sctp_assocs_id_lock);
- if (preload)
- idr_preload_end();
- if (ret < 0)
- return ret;
+ if (error == -EAGAIN)
+ goto retry;
+ else if (error)
+ return error;
- asoc->assoc_id = (sctp_assoc_t)ret;
- return 0;
+ asoc->assoc_id = (sctp_assoc_t) assoc_id;
+ return error;
}
/* Free the ASCONF queue */
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index acb8650..7d7c9d8 100644
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -172,9 +172,22 @@ else
fi
maintainer="$name <$email>"
+# Try to determine distribution
+if [ -e $(which lsb_release) ]; then
+ codename=$(lsb_release --codename --short)
+ if [ "$codename" != "" ]; then
+ distribution=$codename
+ else
+ distribution="UNRELEASED"
+ echo "WARNING: The distribution could NOT be determined!"
+ fi
+else
+ echo "HINT: Install lsb_release binary, this helps to identify your distribution!"
+fi
+
# Generate a simple changelog template
cat <<EOF > debian/changelog
-linux-upstream ($packageversion) unstable; urgency=low
+linux-upstream ($packageversion) $distribution; urgency=low
* Custom built Linux kernel.
@@ -188,10 +201,10 @@ This is a packacked upstream version of the Linux kernel.
The sources may be found at most Linux ftp sites, including:
ftp://ftp.kernel.org/pub/linux/kernel
-Copyright: 1991 - 2009 Linus Torvalds and others.
+Copyright: 1991 - 2013 Linus Torvalds and others.
The git repository for mainline kernel development is at:
-git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
+git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
^ permalink raw reply related [flat|nested] 9+ messages in thread