diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2009-03-26 17:24:11 +0300 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-03-26 17:24:14 +0300 |
commit | 90ac24a5aeb8d4bef001bd3589564a52846d0eee (patch) | |
tree | f57ed4032783a546507d244d147ce56f69b4c751 /drivers | |
parent | 87fa5af80cdd5053b27a546725948c2b74ec82b2 (diff) | |
download | linux-90ac24a5aeb8d4bef001bd3589564a52846d0eee.tar.xz |
[S390] cio: device scan oom fallback.
Since some callers rely on for_each_subchannel_staged to not fail,
fall back to brute force scanning using get_subchannel_by_schid in
case of a oom situation.
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/s390/cio/css.c | 31 |
1 files changed, 27 insertions, 4 deletions
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index a5fc56371ba8..1f2e424596af 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -83,6 +83,25 @@ static int call_fn_unknown_sch(struct subchannel_id schid, void *data) return rc; } +static int call_fn_all_sch(struct subchannel_id schid, void *data) +{ + struct cb_data *cb = data; + struct subchannel *sch; + int rc = 0; + + sch = get_subchannel_by_schid(schid); + if (sch) { + if (cb->fn_known_sch) + rc = cb->fn_known_sch(sch, cb->data); + put_device(&sch->dev); + } else { + if (cb->fn_unknown_sch) + rc = cb->fn_unknown_sch(schid, cb->data); + } + + return rc; +} + int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *), int (*fn_unknown)(struct subchannel_id, void *), void *data) @@ -90,13 +109,17 @@ int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *), struct cb_data cb; int rc; - cb.set = idset_sch_new(); - if (!cb.set) - return -ENOMEM; - idset_fill(cb.set); cb.data = data; cb.fn_known_sch = fn_known; cb.fn_unknown_sch = fn_unknown; + + cb.set = idset_sch_new(); + if (!cb.set) + /* fall back to brute force scanning in case of oom */ + return for_each_subchannel(call_fn_all_sch, &cb); + + idset_fill(cb.set); + /* Process registered subchannels. */ rc = bus_for_each_dev(&css_bus_type, NULL, &cb, call_fn_known_sch); if (rc) |