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