예제 #1
0
void sigint_allow(void)
{
	struct sigaction handler;
	sigset_t sigs;

	if (memlock_count_daemon())
		return;
	/*
	 * Do not overwrite the backed-up handler data -
	 * just increase nesting count.
	 */
	if (++_handler_installed >= MAX_SIGINTS)
		return;

	/* Grab old sigaction for SIGINT: shall not fail. */
	if (sigaction(SIGINT, NULL, &handler))
		log_sys_debug("sigaction", "SIGINT");

	handler.sa_flags &= ~SA_RESTART; /* Clear restart flag */
	handler.sa_handler = _catch_sigint;

	/* Override the signal handler: shall not fail. */
	if (sigaction(SIGINT, &handler, &_oldhandler[_handler_installed  - 1]))
		log_sys_debug("sigaction", "SIGINT");

	/* Unmask SIGINT.  Remember to mask it again on restore. */
	if (sigprocmask(0, NULL, &sigs))
		log_sys_debug("sigprocmask", "");

	if ((_oldmasked[_handler_installed] = sigismember(&sigs, SIGINT))) {
		sigdelset(&sigs, SIGINT);
		if (sigprocmask(SIG_SETMASK, &sigs, NULL))
			log_sys_debug("sigprocmask", "SIG_SETMASK");
	}
}
예제 #2
0
void sigint_restore(void)
{
	if (memlock_count_daemon())
		return;

	if (!_handler_installed ||
	    --_handler_installed >= MAX_SIGINTS)
		return;

	/* Nesting count went below MAX_SIGINTS. */
	if (_oldmasked[_handler_installed]) {
		sigset_t sigs;
		sigprocmask(0, NULL, &sigs);
		sigaddset(&sigs, SIGINT);
		if (sigprocmask(SIG_SETMASK, &sigs, NULL))
			log_sys_debug("sigprocmask", "SIG_SETMASK");
	}

	if (sigaction(SIGINT, &_oldhandler[_handler_installed], NULL))
		log_sys_debug("sigaction", "SIGINT restore");
}
예제 #3
0
파일: log.c 프로젝트: Distrotech/LVM2
/*
 * Support envvar LVM_LOG_FILE_EPOCH and allow to attach
 * extra keyword (consist of upto 32 alpha chars) to
 * opened log file. After this 'epoch' word pid and starttime
 * (in kernel units, read from /proc/self/stat)
 * is automatically attached.
 * If command/daemon forks multiple times, it could create multiple
 * log files ensuring, there are no overwrites.
 */
void init_log_file(const char *log_file, int append)
{
	static const char statfile[] = "/proc/self/stat";
	const char *env;
	int pid;
	unsigned long long starttime;
	FILE *st;
	int i = 0;

	_log_file_path[0] = '\0';
	if ((env = getenv("LVM_LOG_FILE_EPOCH"))) {
		while (isalpha(env[i]) && i < 32) /* Up to 32 alphas */
			i++;
		if (env[i]) {
			if (i)
				log_warn("WARNING: Ignoring invalid LVM_LOG_FILE_EPOCH envvar \"%s\".", env);
			goto no_epoch;
		}

		if (!(st = fopen(statfile, "r")))
			log_sys_error("fopen", statfile);
		else if (fscanf(st, "%d %*s %*c %*d %*d %*d %*d " /* tty_nr */
			   "%*d %*u %*u %*u %*u " /* mjflt */
			   "%*u %*u %*u %*d %*d " /* cstim */
			   "%*d %*d %*d %*d " /* itrealvalue */
			   "%llu", &pid, &starttime) != 2) {
			log_warn("WARNING: Cannot parse content of %s.", statfile);
		} else {
			if (dm_snprintf(_log_file_path, sizeof(_log_file_path),
					"%s_%s_%d_%lld", log_file, env, pid, starttime) < 0) {
				log_warn("WARNING: Debug log file path is too long for epoch.");
				_log_file_path[0] = '\0';
			} else {
				log_file = _log_file_path;
				append = 1; /* force */
			}
		}

		if (st && fclose(st))
			log_sys_debug("fclose", statfile);
	}

no_epoch:
	if (!(_log_file = fopen(log_file, append ? "a" : "w"))) {
		log_sys_error("fopen", log_file);
		return;
	}

	_log_to_file = 1;
}
예제 #4
0
파일: vdo_manip.c 프로젝트: tasleson/lvm2
static int _sysfs_get_kvdo_value(const char *dm_name, const char *vdo_param, uint64_t *value)
{
	char path[PATH_MAX];
	char temp[64];
	int fd, size, r = 0;

	if (dm_snprintf(path, sizeof(path), "%skvdo/%s/%s",
			dm_sysfs_dir(), dm_name, vdo_param) < 0) {
		log_error("Failed to build kmod path.");
		return 0;
	}

	if ((fd = open(path, O_RDONLY)) < 0) {
		if (errno != ENOENT)
			log_sys_error("open", path);
		else
			log_sys_debug("open", path);
		goto bad;
	}

	if ((size = read(fd, temp, sizeof(temp) - 1)) < 0) {
		log_sys_error("read", path);
		goto bad;
	}
	temp[size] = 0;
	errno = 0;
	*value = strtoll(temp, NULL, 0);
	if (errno) {
		log_sys_error("strtool", path);
		goto bad;
	}

	r = 1;
bad:
	if (fd >= 0 && close(fd))
		log_sys_error("close", path);

	return r;
}
예제 #5
0
int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
{
	struct stat buf;
	const char *name;
	int need_excl = 0, need_rw = 0;

	if ((flags & O_ACCMODE) == O_RDWR)
		need_rw = 1;

	if ((flags & O_EXCL))
		need_excl = 1;

	if (dev->fd >= 0) {
		if (((dev->flags & DEV_OPENED_RW) || !need_rw) &&
		    ((dev->flags & DEV_OPENED_EXCL) || !need_excl)) {
			dev->open_count++;
			return 1;
		}

		if (dev->open_count && !need_excl) {
			/* FIXME Ensure we never get here */
			log_error(INTERNAL_ERROR "%s already opened read-only",
				 dev_name(dev));
			dev->open_count++;
		}

		dev_close_immediate(dev);
	}

	if (critical_section())
		/* FIXME Make this log_error */
		log_verbose("dev_open(%s) called while suspended",
			 dev_name(dev));

	if (dev->flags & DEV_REGULAR)
		name = dev_name(dev);
	else if (!(name = dev_name_confirmed(dev, quiet)))
		return_0;

	if (!(dev->flags & DEV_REGULAR)) {
		if (stat(name, &buf) < 0) {
			log_sys_error("%s: stat failed", name);
			return 0;
		}
		if (buf.st_rdev != dev->dev) {
			log_error("%s: device changed", name);
			return 0;
		}
	}

#ifdef O_DIRECT_SUPPORT
	if (direct) {
		if (!(dev->flags & DEV_O_DIRECT_TESTED))
			dev->flags |= DEV_O_DIRECT;

		if ((dev->flags & DEV_O_DIRECT))
			flags |= O_DIRECT;
	}
#endif

#ifdef O_NOATIME
	/* Don't update atime on device inodes */
	if (!(dev->flags & DEV_REGULAR))
		flags |= O_NOATIME;
#endif

	if ((dev->fd = open(name, flags, 0777)) < 0) {
#ifdef O_DIRECT_SUPPORT
		if (direct && !(dev->flags & DEV_O_DIRECT_TESTED)) {
			flags &= ~O_DIRECT;
			if ((dev->fd = open(name, flags, 0777)) >= 0) {
				dev->flags &= ~DEV_O_DIRECT;
				log_debug("%s: Not using O_DIRECT", name);
				goto opened;
			}
		}
#endif
		if (quiet)
			log_sys_debug("open", name);
		else
			log_sys_error("open", name);
		return 0;
	}

#ifdef O_DIRECT_SUPPORT
      opened:
	if (direct)
		dev->flags |= DEV_O_DIRECT_TESTED;
#endif
	dev->open_count++;
	dev->flags &= ~DEV_ACCESSED_W;

	if (need_rw)
		dev->flags |= DEV_OPENED_RW;
	else
		dev->flags &= ~DEV_OPENED_RW;

	if (need_excl)
		dev->flags |= DEV_OPENED_EXCL;
	else
		dev->flags &= ~DEV_OPENED_EXCL;

	if (!(dev->flags & DEV_REGULAR) &&
	    ((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev))) {
		log_error("%s: fstat failed: Has device name changed?", name);
		dev_close_immediate(dev);
		return 0;
	}

#ifndef O_DIRECT_SUPPORT
	if (!(dev->flags & DEV_REGULAR))
		dev_flush(dev);
#endif

	if ((flags & O_CREAT) && !(flags & O_TRUNC))
		dev->end = lseek(dev->fd, (off_t) 0, SEEK_END);

	dm_list_add(&_open_devices, &dev->open_list);

	log_debug("Opened %s %s%s%s", dev_name(dev),
		  dev->flags & DEV_OPENED_RW ? "RW" : "RO",
		  dev->flags & DEV_OPENED_EXCL ? " O_EXCL" : "",
		  dev->flags & DEV_O_DIRECT ? " O_DIRECT" : "");

	return 1;
}
예제 #6
0
static unsigned long _dev_topology_attribute(struct dev_types *dt,
					     const char *attribute,
					     struct device *dev,
					     unsigned long default_value)
{
	const char *sysfs_dir = dm_sysfs_dir();
	char path[PATH_MAX], buffer[64];
	FILE *fp;
	struct stat info;
	dev_t uninitialized_var(primary);
	unsigned long result = default_value;
	unsigned long value = 0UL;

	if (!attribute || !*attribute)
		goto_out;

	if (!sysfs_dir || !*sysfs_dir)
		goto_out;

	if (!_snprintf_attr(path, sizeof(path), sysfs_dir, attribute, dev->dev))
                goto_out;

	/*
	 * check if the desired sysfs attribute exists
	 * - if not: either the kernel doesn't have topology support
	 *   or the device could be a partition
	 */
	if (stat(path, &info) == -1) {
		if (errno != ENOENT) {
			log_sys_debug("stat", path);
			goto out;
		}
		if (!dev_get_primary_dev(dt, dev, &primary))
			goto out;

		/* get attribute from partition's primary device */
		if (!_snprintf_attr(path, sizeof(path), sysfs_dir, attribute, primary))
			goto_out;

		if (stat(path, &info) == -1) {
			if (errno != ENOENT)
				log_sys_debug("stat", path);
			goto out;
		}
	}

	if (!(fp = fopen(path, "r"))) {
		log_sys_debug("fopen", path);
		goto out;
	}

	if (!fgets(buffer, sizeof(buffer), fp)) {
		log_sys_debug("fgets", path);
		goto out_close;
	}

	if (sscanf(buffer, "%lu", &value) != 1) {
		log_warn("sysfs file %s not in expected format: %s", path, buffer);
		goto out_close;
	}

	log_very_verbose("Device %s: %s is %lu%s.",
			 dev_name(dev), attribute, result, default_value ? "" : " bytes");

	result = value >> SECTOR_SHIFT;

out_close:
	if (fclose(fp))
		log_sys_debug("fclose", path);

out:
	return result;
}
예제 #7
0
파일: libdm-file.c 프로젝트: tasleson/lvm2
int dm_create_lockfile(const char *lockfile)
{
	int fd, value;
	size_t bufferlen;
	ssize_t write_out;
	struct flock lock;
	char buffer[50];
	int retries = 0;

	if ((fd = open(lockfile, O_CREAT | O_WRONLY,
		       (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) < 0) {
		log_error("Cannot open lockfile [%s], error was [%s]",
			  lockfile, strerror(errno));
		return 0;
	}

	lock.l_type = F_WRLCK;
	lock.l_start = 0;
	lock.l_whence = SEEK_SET;
	lock.l_len = 0;
retry_fcntl:
	if (fcntl(fd, F_SETLK, &lock) < 0) {
		switch (errno) {
		case EINTR:
			goto retry_fcntl;
		case EACCES:
		case EAGAIN:
			if (retries == 20) {
				log_error("Cannot lock lockfile [%s], error was [%s]",
					  lockfile, strerror(errno));
				break;
			} else {
				++ retries;
				usleep(1000);
				goto retry_fcntl;
			}
		default:
			log_error("process is already running");
		}

		goto fail_close;
	}

	if (ftruncate(fd, 0) < 0) {
		log_error("Cannot truncate pidfile [%s], error was [%s]",
			  lockfile, strerror(errno));

		goto fail_close_unlink;
	}

	snprintf(buffer, sizeof(buffer), "%u\n", getpid());

	bufferlen = strlen(buffer);
	write_out = write(fd, buffer, bufferlen);

	if ((write_out < 0) || (write_out == 0 && errno)) {
		log_error("Cannot write pid to pidfile [%s], error was [%s]",
			  lockfile, strerror(errno));

		goto fail_close_unlink;
	}

	if ((write_out == 0) || ((size_t)write_out < bufferlen)) {
		log_error("Cannot write pid to pidfile [%s], shortwrite of"
			  "[%" PRIsize_t "] bytes, expected [%" PRIsize_t "]\n",
			  lockfile, write_out, bufferlen);

		goto fail_close_unlink;
	}

	if ((value = fcntl(fd, F_GETFD, 0)) < 0) {
		log_error("Cannot get close-on-exec flag from pidfile [%s], "
			  "error was [%s]", lockfile, strerror(errno));

		goto fail_close_unlink;
	}
	value |= FD_CLOEXEC;
	if (fcntl(fd, F_SETFD, value) < 0) {
		log_error("Cannot set close-on-exec flag from pidfile [%s], "
			  "error was [%s]", lockfile, strerror(errno));

		goto fail_close_unlink;
	}

	/* coverity[leaked_handle] intentional leak of fd handle here  */

	return 1;

fail_close_unlink:
	if (unlink(lockfile))
		log_sys_debug("unlink", lockfile);
fail_close:
	if (close(fd))
		log_sys_debug("close", lockfile);

	return 0;
}