diff options
author | Jeremy Kerr <jk@ozlabs.org> | 2015-09-29 12:14:16 +0800 |
---|---|---|
committer | Jeremy Kerr <jk@ozlabs.org> | 2015-09-30 13:23:49 +0800 |
commit | 420f0e2c5d8338b42047c58f055cdb944685ead7 (patch) | |
tree | 4a57a7a3680df4cdf6d4442acb85a6c9898b2ca1 /discover/ipmi.c | |
parent | 9e0b6b31c9bb5ce3ad72756c918f02e6e909c737 (diff) | |
download | petitboot-420f0e2c5d8338b42047c58f055cdb944685ead7.zip petitboot-420f0e2c5d8338b42047c58f055cdb944685ead7.tar.gz |
discover/ipmi: Use advisory locking on ipmi device
The ipmi module is shared between pb-config and pb-discover. During
system initilisation, we're likely to have a few invocations of
pb-config running, as well as pb-discover starting.
We may have multiple potential concurrent accesses to the ipmi device
node. To avoid problems, this change introduces a fcntl lock on the
device node.
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Diffstat (limited to 'discover/ipmi.c')
-rw-r--r-- | discover/ipmi.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/discover/ipmi.c b/discover/ipmi.c index 710a47d..54d4e06 100644 --- a/discover/ipmi.c +++ b/discover/ipmi.c @@ -107,11 +107,21 @@ int ipmi_transaction(struct ipmi *ipmi, uint8_t netfn, uint8_t cmd, { struct timeval start, now, delta; struct pollfd pollfds[1]; + struct flock lock; int expired_ms, rc; + memset(&lock, 0, sizeof(lock)); + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + rc = fcntl(ipmi->fd, F_SETLKW, &lock); + if (rc == -1) { + pb_log("IPMI: error locking IPMI device: %m\n"); + return rc; + } + rc = ipmi_send(ipmi, netfn, cmd, req_buf, req_len); if (rc) - return rc; + goto out; pollfds[0].fd = ipmi->fd; pollfds[0].events = POLLIN; @@ -132,11 +142,13 @@ int ipmi_transaction(struct ipmi *ipmi, uint8_t netfn, uint8_t cmd, if (rc == 0) { pb_log("IPMI: timeout waiting for response " "(netfn %d, cmd %d)\n", netfn, cmd); + rc = -1; break; } if (!(pollfds[0].revents & POLLIN)) { pb_log("IPMI: unexpected fd status from poll?\n"); + rc = -1; break; } @@ -156,17 +168,23 @@ int ipmi_transaction(struct ipmi *ipmi, uint8_t netfn, uint8_t cmd, expired_ms = (delta.tv_sec * 1000) + (delta.tv_usec / 1000); - if (expired_ms >= timeout_ms) + if (expired_ms >= timeout_ms) { + rc = -1; break; + } } } else { pb_debug("IPMI: netfn(%x->%x), cmd(%x->%x)\n", netfn, resp_netfn, cmd, resp_cmd); - return 0; + rc = 0; + goto out; } } - return -1; +out: + lock.l_type = F_UNLCK; + fcntl(ipmi->fd, F_SETLKW, &lock); + return rc ? -1 : 0; } static int ipmi_destroy(void *p) |