]>
Commit | Line | Data |
---|---|---|
959ef981 | 1 | // SPDX-License-Identifier: GPL-2.0 |
9440d84d | 2 | /* |
da23017d NS |
3 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. |
4 | * All Rights Reserved. | |
9440d84d NS |
5 | */ |
6 | ||
9440d84d NS |
7 | #include <mntent.h> |
8 | #include <sys/stat.h> | |
9440d84d | 9 | #include <sys/ioctl.h> |
2556c98b | 10 | #include <sys/sysinfo.h> |
9440d84d | 11 | |
33c692a2 DW |
12 | #include "platform_defs.h" |
13 | #include "xfs.h" | |
12812407 | 14 | #include "init.h" |
a946664d | 15 | #include "libfrog/platform.h" |
b626fb59 | 16 | |
9440d84d | 17 | extern char *progname; |
b74a1f6a | 18 | static int max_block_alignment; |
9440d84d NS |
19 | |
20 | #ifndef BLKGETSIZE64 | |
7f090a57 | 21 | # define BLKGETSIZE64 _IOR(0x12,114,size_t) |
9440d84d NS |
22 | #endif |
23 | #ifndef BLKBSZSET | |
7f090a57 | 24 | # define BLKBSZSET _IOW(0x12,113,size_t) |
9440d84d | 25 | #endif |
74668075 NS |
26 | #ifndef BLKSSZGET |
27 | # define BLKSSZGET _IO(0x12,104) | |
28 | #endif | |
9440d84d | 29 | |
ac419944 NS |
30 | #ifndef RAMDISK_MAJOR |
31 | #define RAMDISK_MAJOR 1 /* ramdisk major number */ | |
32 | #endif | |
33 | ||
9440d84d NS |
34 | #define PROC_MOUNTED "/proc/mounts" |
35 | ||
4d457e24 ES |
36 | /* |
37 | * Check if the filesystem is mounted. Be verbose if asked, and | |
38 | * optionally restrict check to /writable/ mounts (i.e. RO is OK) | |
39 | */ | |
40 | #define CHECK_MOUNT_VERBOSE 0x1 | |
41 | #define CHECK_MOUNT_WRITABLE 0x2 | |
42 | ||
43 | static int | |
f594a0d1 | 44 | platform_check_mount(char *name, char *block, struct stat *s, int flags) |
9440d84d | 45 | { |
4e7a824f | 46 | FILE *f; |
f594a0d1 | 47 | struct stat st, mst; |
4e7a824f FJ |
48 | struct mntent *mnt; |
49 | char mounts[MAXPATHLEN]; | |
9440d84d NS |
50 | |
51 | if (!s) { | |
4d457e24 | 52 | /* If either fails we are not mounted */ |
f594a0d1 | 53 | if (stat(block, &st) < 0) |
9440d84d NS |
54 | return 0; |
55 | if ((st.st_mode & S_IFMT) != S_IFBLK) | |
56 | return 0; | |
57 | s = &st; | |
58 | } | |
59 | ||
4e7a824f FJ |
60 | strcpy(mounts, (!access(PROC_MOUNTED, R_OK)) ? PROC_MOUNTED : MOUNTED); |
61 | if ((f = setmntent(mounts, "r")) == NULL) { | |
4d457e24 | 62 | /* Unexpected failure, warn unconditionally */ |
4e7a824f FJ |
63 | fprintf(stderr, |
64 | _("%s: %s possibly contains a mounted filesystem\n"), | |
65 | progname, name); | |
66 | return 1; | |
67 | } | |
98c4a01c ES |
68 | /* |
69 | * This whole business is to work out if our block device is mounted | |
70 | * after we lost ustat(2), see: | |
71 | * 4e7a824 libxfs/linux.c: Replace use of ustat by stat | |
72 | * We don't really want to stat every single mounted directory, | |
73 | * as that may include tmpfs, cgroups, procfs or - worst - hung nfs | |
74 | * servers. So first, a simple check: does the "dev" start with "/" ? | |
75 | */ | |
4e7a824f | 76 | while ((mnt = getmntent(f)) != NULL) { |
5ca4d781 IK |
77 | if (!strcmp(mnt->mnt_type, "autofs")) |
78 | continue; | |
98c4a01c ES |
79 | if (mnt->mnt_fsname[0] != '/') |
80 | continue; | |
f594a0d1 | 81 | if (stat(mnt->mnt_dir, &mst) < 0) |
4e7a824f FJ |
82 | continue; |
83 | if (mst.st_dev != s->st_rdev) | |
84 | continue; | |
4d457e24 ES |
85 | /* Found our device, is RO OK? */ |
86 | if ((flags & CHECK_MOUNT_WRITABLE) && hasmntopt(mnt, MNTOPT_RO)) | |
87 | continue; | |
88 | else | |
89 | break; | |
90 | } | |
91 | endmntent(f); | |
4e7a824f | 92 | |
4d457e24 ES |
93 | /* No mounts contained the condition we were looking for */ |
94 | if (mnt == NULL) | |
95 | return 0; | |
96 | ||
97 | if (flags & CHECK_MOUNT_VERBOSE) { | |
98 | if (flags & CHECK_MOUNT_WRITABLE) { | |
99 | fprintf(stderr, | |
100 | _("%s: %s contains a mounted and writable filesystem\n"), | |
101 | progname, name); | |
102 | } else { | |
9440d84d | 103 | fprintf(stderr, |
4d457e24 | 104 | _("%s: %s contains a mounted filesystem\n"), |
9440d84d | 105 | progname, name); |
4d457e24 | 106 | } |
9440d84d | 107 | } |
4d457e24 | 108 | return 1; |
9440d84d NS |
109 | } |
110 | ||
111 | int | |
f594a0d1 | 112 | platform_check_ismounted(char *name, char *block, struct stat *s, int verbose) |
9440d84d | 113 | { |
4d457e24 | 114 | int flags; |
9440d84d | 115 | |
4d457e24 ES |
116 | flags = verbose ? CHECK_MOUNT_VERBOSE : 0; |
117 | return platform_check_mount(name, block, s, flags); | |
118 | } | |
7f510afb | 119 | |
4d457e24 | 120 | int |
f594a0d1 | 121 | platform_check_iswritable(char *name, char *block, struct stat *s) |
4d457e24 ES |
122 | { |
123 | int flags; | |
124 | ||
125 | /* Writable checks are always verbose */ | |
126 | flags = CHECK_MOUNT_WRITABLE | CHECK_MOUNT_VERBOSE; | |
127 | return platform_check_mount(name, block, s, flags); | |
9440d84d NS |
128 | } |
129 | ||
a3106f32 CH |
130 | void |
131 | platform_set_blocksize(int fd, char *path, dev_t device, int blocksize, | |
132 | bool fatal) | |
9440d84d | 133 | { |
a3106f32 CH |
134 | int error; |
135 | ||
136 | if (major(device) == RAMDISK_MAJOR) | |
137 | return; | |
138 | error = ioctl(fd, BLKBSZSET, &blocksize); | |
139 | if (error < 0) { | |
140 | fprintf(stderr, _("%s: %s - cannot set blocksize " | |
141 | "%d on block device %s: %s\n"), | |
142 | progname, fatal ? "error": "warning", | |
143 | blocksize, path, strerror(errno)); | |
144 | if (fatal) | |
145 | exit(1); | |
9440d84d NS |
146 | } |
147 | } | |
148 | ||
a688242b DW |
149 | /* |
150 | * Flush dirty pagecache and disk write cache to stable media. Returns 0 for | |
151 | * success or -1 (with errno set) for failure. | |
152 | */ | |
153 | int | |
154 | platform_flush_device( | |
155 | int fd, | |
156 | dev_t device) | |
9440d84d | 157 | { |
f594a0d1 | 158 | struct stat st; |
a688242b DW |
159 | int ret; |
160 | ||
06ac92fd | 161 | if (major(device) == RAMDISK_MAJOR) |
a688242b | 162 | return 0; |
06ac92fd | 163 | |
7c8e6ac7 DW |
164 | ret = fsync(fd); |
165 | if (ret) | |
166 | return ret; | |
167 | ||
a688242b DW |
168 | ret = fstat(fd, &st); |
169 | if (ret) | |
170 | return ret; | |
06ac92fd | 171 | |
7c8e6ac7 DW |
172 | if (S_ISBLK(st.st_mode)) |
173 | return ioctl(fd, BLKFLSBUF, 0); | |
a688242b | 174 | |
7c8e6ac7 | 175 | return 0; |
9440d84d NS |
176 | } |
177 | ||
f02037ce NS |
178 | void |
179 | platform_findsizes(char *path, int fd, long long *sz, int *bsz) | |
9440d84d | 180 | { |
f594a0d1 | 181 | struct stat st; |
14f8b681 | 182 | uint64_t size; |
f02037ce | 183 | int error; |
9440d84d | 184 | |
f594a0d1 | 185 | if (fstat(fd, &st) < 0) { |
9440d84d NS |
186 | fprintf(stderr, _("%s: " |
187 | "cannot stat the device file \"%s\": %s\n"), | |
188 | progname, path, strerror(errno)); | |
189 | exit(1); | |
190 | } | |
98dd72d3 | 191 | |
f02037ce | 192 | if ((st.st_mode & S_IFMT) == S_IFREG) { |
98dd72d3 | 193 | struct dioattr da; |
5a7d5937 | 194 | |
f02037ce | 195 | *sz = (long long)(st.st_size >> 9); |
98dd72d3 ES |
196 | |
197 | if (ioctl(fd, XFS_IOC_DIOINFO, &da) < 0) { | |
5a7d5937 ES |
198 | /* |
199 | * fall back to BBSIZE; mkfs might fail if there's a | |
200 | * size mismatch between the image & the host fs... | |
201 | */ | |
202 | *bsz = BBSIZE; | |
203 | } else | |
98dd72d3 | 204 | *bsz = da.d_miniosz; |
5a7d5937 ES |
205 | |
206 | if (*bsz > max_block_alignment) | |
207 | max_block_alignment = *bsz; | |
f02037ce | 208 | return; |
9440d84d NS |
209 | } |
210 | ||
211 | error = ioctl(fd, BLKGETSIZE64, &size); | |
212 | if (error >= 0) { | |
213 | /* BLKGETSIZE64 returns size in bytes not 512-byte blocks */ | |
f02037ce | 214 | *sz = (long long)(size >> 9); |
9440d84d NS |
215 | } else { |
216 | /* If BLKGETSIZE64 fails, try BLKGETSIZE */ | |
217 | unsigned long tmpsize; | |
f02037ce | 218 | |
9440d84d NS |
219 | error = ioctl(fd, BLKGETSIZE, &tmpsize); |
220 | if (error < 0) { | |
221 | fprintf(stderr, _("%s: can't determine device size\n"), | |
222 | progname); | |
223 | exit(1); | |
224 | } | |
f02037ce | 225 | *sz = (long long)tmpsize; |
9440d84d NS |
226 | } |
227 | ||
f02037ce NS |
228 | if (ioctl(fd, BLKSSZGET, bsz) < 0) { |
229 | fprintf(stderr, _("%s: warning - cannot get sector size " | |
230 | "from block device %s: %s\n"), | |
231 | progname, path, strerror(errno)); | |
232 | *bsz = BBSIZE; | |
233 | } | |
b74a1f6a NS |
234 | if (*bsz > max_block_alignment) |
235 | max_block_alignment = *bsz; | |
9440d84d | 236 | } |
cb5b3ef4 | 237 | |
b74a1f6a NS |
238 | int |
239 | platform_direct_blockdev(void) | |
240 | { | |
241 | return 1; | |
242 | } | |
243 | ||
244 | int | |
245 | platform_align_blockdev(void) | |
246 | { | |
247 | if (!max_block_alignment) | |
76956054 | 248 | return getpagesize(); |
b74a1f6a | 249 | return max_block_alignment; |
cb5b3ef4 | 250 | } |
3b6ac903 | 251 | |
d530e589 | 252 | /* How many CPUs are online? */ |
3b6ac903 MV |
253 | int |
254 | platform_nproc(void) | |
255 | { | |
d530e589 DW |
256 | long nproc = sysconf(_SC_NPROCESSORS_ONLN); |
257 | ||
258 | if (nproc < 1) | |
259 | return 1; | |
260 | if (nproc >= INT_MAX) | |
261 | return INT_MAX; | |
262 | return nproc; | |
3b6ac903 | 263 | } |
2556c98b BN |
264 | |
265 | unsigned long | |
266 | platform_physmem(void) | |
267 | { | |
268 | struct sysinfo si; | |
269 | ||
270 | if (sysinfo(&si) < 0) { | |
271 | fprintf(stderr, _("%s: can't determine memory size\n"), | |
272 | progname); | |
273 | exit(1); | |
274 | } | |
275 | return (si.totalram >> 10) * si.mem_unit; /* kilobytes */ | |
276 | } |