static int has_discard(const char *devname, struct path_cxt **wholedisk) { struct path_cxt *pc = NULL; uint64_t dg = 0; dev_t disk = 0, dev; int rc = -1; dev = sysfs_devname_to_devno(devname); if (!dev) goto fail; pc = ul_new_sysfs_path(dev, NULL, NULL); if (!pc) goto fail; /* * This is tricky to read the info from sys/, because the queue * attributes are provided for whole devices (disk) only. We're trying * to reuse the whole-disk sysfs context to optimize this stuff (as * system usually have just one disk only). */ rc = sysfs_blkdev_get_wholedisk(pc, NULL, 0, &disk); if (rc != 0 || !disk) goto fail; if (dev != disk) { /* Partition, try reuse whole-disk context if valid for the * current device, otherwise create new context for the * whole-disk. */ if (*wholedisk && sysfs_blkdev_get_devno(*wholedisk) != disk) { ul_unref_path(*wholedisk); *wholedisk = NULL; } if (!*wholedisk) { *wholedisk = ul_new_sysfs_path(disk, NULL, NULL); if (!*wholedisk) goto fail; } sysfs_blkdev_set_parent(pc, *wholedisk); } rc = ul_path_read_u64(pc, &dg, "queue/discard_granularity"); ul_unref_path(pc); return rc == 0 && dg > 0; fail: ul_unref_path(pc); return 1; }
static int get_cad(void) { uint64_t val; if (ul_path_read_u64(NULL, &val, _PATH_PROC_CTRL_ALT_DEL) != 0) err(EXIT_FAILURE, _("cannot read %s"), _PATH_PROC_CTRL_ALT_DEL); switch (val) { case 0: fputs("soft\n", stdout); break; case 1: fputs("hard\n", stdout); break; default: printf("%s hard\n", _("implicit")); warnx(_("unexpected value in %s: %ju"), _PATH_PROC_CTRL_ALT_DEL, val); return EXIT_FAILURE; } return EXIT_SUCCESS; }
int ipc_msg_get_limits(struct ipc_limits *lim) { if (access(_PATH_PROC_IPC_MSGMNI, F_OK) == 0 && access(_PATH_PROC_IPC_MSGMNB, F_OK) == 0 && access(_PATH_PROC_IPC_MSGMAX, F_OK) == 0) { ul_path_read_s32(NULL, &lim->msgmni, _PATH_PROC_IPC_MSGMNI); ul_path_read_s32(NULL, &lim->msgmnb, _PATH_PROC_IPC_MSGMNB); ul_path_read_u64(NULL, &lim->msgmax, _PATH_PROC_IPC_MSGMAX); } else { struct msginfo msginfo; if (msgctl(0, IPC_INFO, (struct msqid_ds *) &msginfo) < 0) return 1; lim->msgmni = msginfo.msgmni; lim->msgmnb = msginfo.msgmnb; lim->msgmax = msginfo.msgmax; } return 0; }
int ipc_sem_get_limits(struct ipc_limits *lim) { FILE *f; int rc = 0; lim->semvmx = SEMVMX; f = fopen(_PATH_PROC_IPC_SEM, "r"); if (f) { rc = fscanf(f, "%d\t%d\t%d\t%d", &lim->semmsl, &lim->semmns, &lim->semopm, &lim->semmni); fclose(f); } if (rc != 4) { struct seminfo seminfo = { .semmni = 0 }; union semun arg = { .array = (ushort *) &seminfo }; if (semctl(0, 0, IPC_INFO, arg) < 0) return 1; lim->semmni = seminfo.semmni; lim->semmsl = seminfo.semmsl; lim->semmns = seminfo.semmns; lim->semopm = seminfo.semopm; } return 0; } int ipc_shm_get_limits(struct ipc_limits *lim) { lim->shmmin = SHMMIN; if (access(_PATH_PROC_IPC_SHMALL, F_OK) == 0 && access(_PATH_PROC_IPC_SHMMAX, F_OK) == 0 && access(_PATH_PROC_IPC_SHMMNI, F_OK) == 0) { ul_path_read_u64(NULL, &lim->shmall, _PATH_PROC_IPC_SHMALL); ul_path_read_u64(NULL, &lim->shmmax, _PATH_PROC_IPC_SHMMAX); ul_path_read_u64(NULL, &lim->shmmni, _PATH_PROC_IPC_SHMMNI); } else { struct shminfo *shminfo; struct shmid_ds shmbuf; if (shmctl(0, IPC_INFO, &shmbuf) < 0) return 1; shminfo = (struct shminfo *) &shmbuf; lim->shmmni = shminfo->shmmni; lim->shmall = shminfo->shmall; lim->shmmax = shminfo->shmmax; } return 0; } int ipc_shm_get_info(int id, struct shm_data **shmds) { FILE *f; int i = 0, maxid; char buf[BUFSIZ]; struct shm_data *p; struct shmid_ds dummy; p = *shmds = xcalloc(1, sizeof(struct shm_data)); p->next = NULL; f = fopen(_PATH_PROC_SYSV_SHM, "r"); if (!f) goto shm_fallback; while (fgetc(f) != '\n'); /* skip header */ while (fgets(buf, sizeof(buf), f) != NULL) { /* scan for the first 14-16 columns (e.g. Linux 2.6.32 has 14) */ p->shm_rss = 0xdead; p->shm_swp = 0xdead; if (sscanf(buf, "%d %d %o %"SCNu64 " %u %u " "%"SCNu64 " %u %u %u %u %"SCNi64 " %"SCNi64 " %"SCNi64 " %"SCNu64 " %"SCNu64 "\n", &p->shm_perm.key, &p->shm_perm.id, &p->shm_perm.mode, &p->shm_segsz, &p->shm_cprid, &p->shm_lprid, &p->shm_nattch, &p->shm_perm.uid, &p->shm_perm.gid, &p->shm_perm.cuid, &p->shm_perm.cgid, &p->shm_atim, &p->shm_dtim, &p->shm_ctim, &p->shm_rss, &p->shm_swp) < 14) continue; /* invalid line, skipped */ if (id > -1) { /* ID specified */ if (id == p->shm_perm.id) { i = 1; break; } else continue; } p->next = xcalloc(1, sizeof(struct shm_data)); p = p->next; p->next = NULL; i++; } if (i == 0) free(*shmds); fclose(f); return i; /* Fallback; /proc or /sys file(s) missing. */ shm_fallback: maxid = shmctl(0, SHM_INFO, &dummy); for (int j = 0; j <= maxid; j++) { int shmid; struct shmid_ds shmseg; struct ipc_perm *ipcp = &shmseg.shm_perm; shmid = shmctl(j, SHM_STAT, &shmseg); if (shmid < 0 || (id > -1 && shmid != id)) { continue; } i++; p->shm_perm.key = ipcp->KEY; p->shm_perm.id = shmid; p->shm_perm.mode = ipcp->mode; p->shm_segsz = shmseg.shm_segsz; p->shm_cprid = shmseg.shm_cpid; p->shm_lprid = shmseg.shm_lpid; p->shm_nattch = shmseg.shm_nattch; p->shm_perm.uid = ipcp->uid; p->shm_perm.gid = ipcp->gid; p->shm_perm.cuid = ipcp->cuid; p->shm_perm.cgid = ipcp->cuid; p->shm_atim = shmseg.shm_atime; p->shm_dtim = shmseg.shm_dtime; p->shm_ctim = shmseg.shm_ctime; p->shm_rss = 0xdead; p->shm_swp = 0xdead; if (id < 0) { p->next = xcalloc(1, sizeof(struct shm_data)); p = p->next; p->next = NULL; } else break; } if (i == 0) free(*shmds); return i; }