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"); } }
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"); }
/* * 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; }
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; }
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; }
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; }
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; }