mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 18:21:39 +01:00
As recommended in http://www.gnu.org/licenses/gpl-howto.en.html. This is the result of: $ git grep -El Mass\|Temple\|Franklin | xargs ./fsf.pl Where fsf.pl is: #!/usr/bin/perl -w -pi.bak -0777 my $repl = 'If not, see <http://www.gnu.org/licenses/>.'; my $br = qr/(?:\s*\n\s*(?:[\*\#]|\/\/|\.\\" )?\s*|\s+)/; my $inwt = qr/[Ii]f${br}not,${br}write${br}(?:to${br})?the${br}Free${br}Software${br}Foundation,(?:${br}Inc\.,)?/; my $mass = qr/675${br}Mass${br}Ave,?${br}Cambridge,?${br}MA${br}02139,?${br}USA,?\.?/; my $franklin = qr/51${br}Franklin${br}St(?:reet)?(?:,${br}| - )Fifth${br}Floor,?${br}Boston,?${br}MA,?${br}02110-1301,?${br}USA,?\.?/; my $temple = qr/59${br}Temple${br}Place(?:,${br}| - )Suite${br}330,?${br}Boston,?${br}MA,?${br}021110?-1307,?${br}USA,?\.?/; s|$inwt$br$mass|$repl|m; s|$inwt$br$franklin|$repl|m; s|$inwt$br$temple|$repl|m; The only remaining mentions of these addresses are in COPYING files which I haven't touched. Some of the changed files are imports from elsewhere, however filtering them out is tricky, I think it is tolerable to have these files be modified here and then perhaps reverted on the next sync, since it's only 1-2 lines and obvious what is going on. Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
201 lines
4.9 KiB
C
201 lines
4.9 KiB
C
/*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation;
|
|
* version 2.1 of the License.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
|
|
#include "xc_private.h"
|
|
#include "xenguest.h"
|
|
|
|
#define SUSPEND_LOCK_FILE XEN_RUN_DIR "/suspend-evtchn-%d.lock"
|
|
|
|
/*
|
|
* locking
|
|
*/
|
|
|
|
#define ERR(x) do{ \
|
|
ERROR("Can't " #x " lock file for suspend event channel %s: %s\n", \
|
|
suspend_file, strerror(errno)); \
|
|
goto err; \
|
|
}while(0)
|
|
|
|
#define SUSPEND_FILE_BUFLEN (sizeof(SUSPEND_LOCK_FILE) + 10)
|
|
|
|
static void get_suspend_file(char buf[], int domid)
|
|
{
|
|
snprintf(buf, SUSPEND_FILE_BUFLEN, SUSPEND_LOCK_FILE, domid);
|
|
}
|
|
|
|
static int lock_suspend_event(xc_interface *xch, int domid, int *lockfd)
|
|
{
|
|
int fd = -1, r;
|
|
char suspend_file[SUSPEND_FILE_BUFLEN];
|
|
struct stat ours, theirs;
|
|
struct flock fl;
|
|
|
|
get_suspend_file(suspend_file, domid);
|
|
|
|
*lockfd = -1;
|
|
|
|
for (;;) {
|
|
if (fd >= 0)
|
|
close (fd);
|
|
|
|
fd = open(suspend_file, O_CREAT | O_RDWR, 0600);
|
|
if (fd < 0)
|
|
ERR("create");
|
|
|
|
r = fcntl(fd, F_SETFD, FD_CLOEXEC);
|
|
if (r)
|
|
ERR("fcntl F_SETFD FD_CLOEXEC");
|
|
|
|
memset(&fl, 0, sizeof(fl));
|
|
fl.l_type = F_WRLCK;
|
|
fl.l_whence = SEEK_SET;
|
|
fl.l_len = 1;
|
|
r = fcntl(fd, F_SETLK, &fl);
|
|
if (r)
|
|
ERR("fcntl F_SETLK");
|
|
|
|
r = fstat(fd, &ours);
|
|
if (r)
|
|
ERR("fstat");
|
|
|
|
r = stat(suspend_file, &theirs);
|
|
if (r) {
|
|
if (errno == ENOENT)
|
|
/* try again */
|
|
continue;
|
|
ERR("stat");
|
|
}
|
|
|
|
if (ours.st_ino != theirs.st_ino)
|
|
/* someone else must have removed it while we were locking it */
|
|
continue;
|
|
|
|
break;
|
|
}
|
|
|
|
*lockfd = fd;
|
|
return 0;
|
|
|
|
err:
|
|
if (fd >= 0)
|
|
close(fd);
|
|
|
|
return -1;
|
|
}
|
|
|
|
static int unlock_suspend_event(xc_interface *xch, int domid, int *lockfd)
|
|
{
|
|
int r;
|
|
char suspend_file[SUSPEND_FILE_BUFLEN];
|
|
|
|
if (*lockfd < 0)
|
|
return 0;
|
|
|
|
get_suspend_file(suspend_file, domid);
|
|
|
|
r = unlink(suspend_file);
|
|
if (r)
|
|
ERR("unlink");
|
|
|
|
r = close(*lockfd);
|
|
*lockfd = -1;
|
|
if (r)
|
|
ERR("close");
|
|
|
|
err:
|
|
if (*lockfd >= 0)
|
|
close(*lockfd);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int xc_await_suspend(xc_interface *xch, xc_evtchn *xce, int suspend_evtchn)
|
|
{
|
|
int rc;
|
|
|
|
do {
|
|
rc = xc_evtchn_pending(xce);
|
|
if (rc < 0) {
|
|
ERROR("error polling suspend notification channel: %d", rc);
|
|
return -1;
|
|
}
|
|
} while (rc != suspend_evtchn);
|
|
|
|
/* harmless for one-off suspend */
|
|
if (xc_evtchn_unmask(xce, suspend_evtchn) < 0)
|
|
ERROR("failed to unmask suspend notification channel: %d", rc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Internal callers are allowed to call this with suspend_evtchn<0
|
|
* but *lockfd>0. */
|
|
int xc_suspend_evtchn_release(xc_interface *xch, xc_evtchn *xce,
|
|
int domid, int suspend_evtchn, int *lockfd)
|
|
{
|
|
if (suspend_evtchn >= 0)
|
|
xc_evtchn_unbind(xce, suspend_evtchn);
|
|
|
|
return unlock_suspend_event(xch, domid, lockfd);
|
|
}
|
|
|
|
int xc_suspend_evtchn_init_sane(xc_interface *xch, xc_evtchn *xce,
|
|
int domid, int port, int *lockfd)
|
|
{
|
|
int rc, suspend_evtchn = -1;
|
|
|
|
if (lock_suspend_event(xch, domid, lockfd)) {
|
|
errno = EINVAL;
|
|
goto cleanup;
|
|
}
|
|
|
|
suspend_evtchn = xc_evtchn_bind_interdomain(xce, domid, port);
|
|
if (suspend_evtchn < 0) {
|
|
ERROR("failed to bind suspend event channel: %d", suspend_evtchn);
|
|
goto cleanup;
|
|
}
|
|
|
|
rc = xc_domain_subscribe_for_suspend(xch, domid, port);
|
|
if (rc < 0) {
|
|
ERROR("failed to subscribe to domain: %d", rc);
|
|
goto cleanup;
|
|
}
|
|
|
|
return suspend_evtchn;
|
|
|
|
cleanup:
|
|
xc_suspend_evtchn_release(xch, xce, domid, suspend_evtchn, lockfd);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int xc_suspend_evtchn_init_exclusive(xc_interface *xch, xc_evtchn *xce,
|
|
int domid, int port, int *lockfd)
|
|
{
|
|
int suspend_evtchn;
|
|
|
|
suspend_evtchn = xc_suspend_evtchn_init_sane(xch, xce, domid, port, lockfd);
|
|
if (suspend_evtchn < 0)
|
|
return suspend_evtchn;
|
|
|
|
/* event channel is pending immediately after binding */
|
|
xc_await_suspend(xch, xce, suspend_evtchn);
|
|
|
|
return suspend_evtchn;
|
|
}
|