1 /* SPDX-License-Identifier: LGPL-2.1+ */
7 #ifndef FUSE_USE_VERSION
8 #define FUSE_USE_VERSION 26
11 #define _FILE_OFFSET_BITS 64
13 #define __STDC_FORMAT_MACROS
30 #include <linux/magic.h>
31 #include <linux/sched.h>
32 #include <sys/epoll.h>
34 #include <sys/mount.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
37 #include <sys/syscall.h>
38 #include <sys/sysinfo.h>
42 #include "memory_utils.h"
43 #include "cgroups/cgroup.h"
45 #include "sysfs_fuse.h"
48 static int sys_devices_system_cpu_online_read(char *buf
, size_t size
,
50 struct fuse_file_info
*fi
)
52 __do_free
char *cg
= NULL
, *cpuset
= NULL
;
53 struct fuse_context
*fc
= fuse_get_context();
54 struct file_info
*d
= INTTYPE_TO_PTR(fi
->fh
);
60 ssize_t total_len
= 0;
71 left
= d
->size
- offset
;
72 total_len
= left
> size
? size
: left
;
73 memcpy(buf
, cache
+ offset
, total_len
);
78 initpid
= lookup_initpid_in_store(fc
->pid
);
79 if (initpid
<= 1 || is_shared_pidns(initpid
))
82 cg
= get_pid_cgroup(initpid
, "cpuset");
84 return read_file_fuse("/sys/devices/system/cpu/online", buf
, size
, d
);
87 cpuset
= get_cpuset(cg
);
91 use_view
= cgroup_ops
->can_use_cpuview(cgroup_ops
);
93 max_cpus
= max_cpu_count(cg
);
96 return read_file_fuse("/sys/devices/system/cpu/online", buf
, size
, d
);
98 total_len
= snprintf(d
->buf
, d
->buflen
, "0-%d\n", max_cpus
- 1);
100 total_len
= snprintf(d
->buf
, d
->buflen
, "0\n");
101 if (total_len
< 0 || total_len
>= d
->buflen
) {
102 lxcfs_error("%s\n", "failed to write to cache");
106 d
->size
= (int)total_len
;
109 if (total_len
> size
)
112 memcpy(buf
, d
->buf
, total_len
);
117 static off_t
get_sysfile_size(const char *which
)
119 __do_fclose
FILE *f
= NULL
;
120 __do_free
char *line
= NULL
;
122 ssize_t sz
, answer
= 0;
124 f
= fopen(which
, "re");
128 while ((sz
= getline(&line
, &len
, f
)) != -1)
134 int sys_getattr(const char *path
, struct stat
*sb
)
138 memset(sb
, 0, sizeof(struct stat
));
139 if (clock_gettime(CLOCK_REALTIME
, &now
) < 0)
141 sb
->st_uid
= sb
->st_gid
= 0;
142 sb
->st_atim
= sb
->st_mtim
= sb
->st_ctim
= now
;
143 if (strcmp(path
, "/sys") == 0) {
144 sb
->st_mode
= S_IFDIR
| 00555;
148 if (strcmp(path
, "/sys/devices") == 0) {
149 sb
->st_mode
= S_IFDIR
| 00555;
153 if (strcmp(path
, "/sys/devices/system") == 0) {
154 sb
->st_mode
= S_IFDIR
| 00555;
158 if (strcmp(path
, "/sys/devices/system/cpu") == 0) {
159 sb
->st_mode
= S_IFDIR
| 00555;
163 if (strcmp(path
, "/sys/devices/system/cpu/online") == 0) {
165 sb
->st_mode
= S_IFREG
| 00444;
173 int sys_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
,
174 off_t offset
, struct fuse_file_info
*fi
)
176 if (strcmp(path
, "/sys") == 0) {
177 if (filler(buf
, ".", NULL
, 0) != 0 ||
178 filler(buf
, "..", NULL
, 0) != 0 ||
179 filler(buf
, "devices", NULL
, 0) != 0)
183 if (strcmp(path
, "/sys/devices") == 0) {
184 if (filler(buf
, ".", NULL
, 0) != 0 ||
185 filler(buf
, "..", NULL
, 0) != 0 ||
186 filler(buf
, "system", NULL
, 0) != 0)
190 if (strcmp(path
, "/sys/devices/system") == 0) {
191 if (filler(buf
, ".", NULL
, 0) != 0 ||
192 filler(buf
, "..", NULL
, 0) != 0 ||
193 filler(buf
, "cpu", NULL
, 0) != 0)
197 if (strcmp(path
, "/sys/devices/system/cpu") == 0) {
198 if (filler(buf
, ".", NULL
, 0) != 0 ||
199 filler(buf
, "..", NULL
, 0) != 0 ||
200 filler(buf
, "online", NULL
, 0) != 0)
208 int sys_open(const char *path
, struct fuse_file_info
*fi
)
210 __do_free
struct file_info
*info
= NULL
;
213 if (strcmp(path
, "/sys/devices") == 0)
214 type
= LXC_TYPE_SYS_DEVICES
;
215 if (strcmp(path
, "/sys/devices/system") == 0)
216 type
= LXC_TYPE_SYS_DEVICES_SYSTEM
;
217 if (strcmp(path
, "/sys/devices/system/cpu") == 0)
218 type
= LXC_TYPE_SYS_DEVICES_SYSTEM_CPU
;
219 if (strcmp(path
, "/sys/devices/system/cpu/online") == 0)
220 type
= LXC_TYPE_SYS_DEVICES_SYSTEM_CPU_ONLINE
;
224 info
= malloc(sizeof(*info
));
228 memset(info
, 0, sizeof(*info
));
231 info
->buflen
= get_sysfile_size(path
) + BUF_RESERVE_SIZE
;
233 info
->buf
= malloc(info
->buflen
);
237 memset(info
->buf
, 0, info
->buflen
);
238 /* set actual size to buffer size */
239 info
->size
= info
->buflen
;
241 fi
->fh
= PTR_TO_UINT64(move_ptr(info
));
245 int sys_access(const char *path
, int mask
)
247 if (strcmp(path
, "/sys") == 0 && access(path
, R_OK
) == 0)
249 if (strcmp(path
, "/sys/devices") == 0 && access(path
, R_OK
) == 0)
251 if (strcmp(path
, "/sys/devices/system") == 0 && access(path
, R_OK
) == 0)
253 if (strcmp(path
, "/sys/devices/system/cpu") == 0 &&
254 access(path
, R_OK
) == 0)
256 /* these are all read-only */
257 if ((mask
& ~R_OK
) != 0)
262 int sys_release(const char *path
, struct fuse_file_info
*fi
)
264 do_release_file_info(fi
);
268 int sys_releasedir(const char *path
, struct fuse_file_info
*fi
)
270 do_release_file_info(fi
);
274 int sys_read(const char *path
, char *buf
, size_t size
, off_t offset
,
275 struct fuse_file_info
*fi
)
277 struct file_info
*f
= INTTYPE_TO_PTR(fi
->fh
);
280 case LXC_TYPE_SYS_DEVICES_SYSTEM_CPU_ONLINE
:
281 return sys_devices_system_cpu_online_read(buf
, size
, offset
, fi
);
282 case LXC_TYPE_SYS_DEVICES
:
284 case LXC_TYPE_SYS_DEVICES_SYSTEM
:
286 case LXC_TYPE_SYS_DEVICES_SYSTEM_CPU
: