]>
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 | |
9c799827 | 12 | #include "libxfs_priv.h" |
b626fb59 | 13 | #include "xfs_fs.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 | ||
143 | void | |
ac419944 | 144 | platform_flush_device(int fd, dev_t device) |
9440d84d | 145 | { |
f594a0d1 | 146 | struct stat st; |
06ac92fd DC |
147 | if (major(device) == RAMDISK_MAJOR) |
148 | return; | |
149 | ||
f594a0d1 | 150 | if (fstat(fd, &st) < 0) |
06ac92fd DC |
151 | return; |
152 | ||
153 | if (S_ISREG(st.st_mode)) | |
154 | fsync(fd); | |
155 | else | |
ac419944 | 156 | ioctl(fd, BLKFLSBUF, 0); |
9440d84d NS |
157 | } |
158 | ||
f02037ce NS |
159 | void |
160 | platform_findsizes(char *path, int fd, long long *sz, int *bsz) | |
9440d84d | 161 | { |
f594a0d1 | 162 | struct stat st; |
14f8b681 | 163 | uint64_t size; |
f02037ce | 164 | int error; |
9440d84d | 165 | |
f594a0d1 | 166 | if (fstat(fd, &st) < 0) { |
9440d84d NS |
167 | fprintf(stderr, _("%s: " |
168 | "cannot stat the device file \"%s\": %s\n"), | |
169 | progname, path, strerror(errno)); | |
170 | exit(1); | |
171 | } | |
98dd72d3 | 172 | |
f02037ce | 173 | if ((st.st_mode & S_IFMT) == S_IFREG) { |
98dd72d3 | 174 | struct dioattr da; |
5a7d5937 | 175 | |
f02037ce | 176 | *sz = (long long)(st.st_size >> 9); |
98dd72d3 ES |
177 | |
178 | if (ioctl(fd, XFS_IOC_DIOINFO, &da) < 0) { | |
5a7d5937 ES |
179 | /* |
180 | * fall back to BBSIZE; mkfs might fail if there's a | |
181 | * size mismatch between the image & the host fs... | |
182 | */ | |
183 | *bsz = BBSIZE; | |
184 | } else | |
98dd72d3 | 185 | *bsz = da.d_miniosz; |
5a7d5937 ES |
186 | |
187 | if (*bsz > max_block_alignment) | |
188 | max_block_alignment = *bsz; | |
f02037ce | 189 | return; |
9440d84d NS |
190 | } |
191 | ||
192 | error = ioctl(fd, BLKGETSIZE64, &size); | |
193 | if (error >= 0) { | |
194 | /* BLKGETSIZE64 returns size in bytes not 512-byte blocks */ | |
f02037ce | 195 | *sz = (long long)(size >> 9); |
9440d84d NS |
196 | } else { |
197 | /* If BLKGETSIZE64 fails, try BLKGETSIZE */ | |
198 | unsigned long tmpsize; | |
f02037ce | 199 | |
9440d84d NS |
200 | error = ioctl(fd, BLKGETSIZE, &tmpsize); |
201 | if (error < 0) { | |
202 | fprintf(stderr, _("%s: can't determine device size\n"), | |
203 | progname); | |
204 | exit(1); | |
205 | } | |
f02037ce | 206 | *sz = (long long)tmpsize; |
9440d84d NS |
207 | } |
208 | ||
f02037ce NS |
209 | if (ioctl(fd, BLKSSZGET, bsz) < 0) { |
210 | fprintf(stderr, _("%s: warning - cannot get sector size " | |
211 | "from block device %s: %s\n"), | |
212 | progname, path, strerror(errno)); | |
213 | *bsz = BBSIZE; | |
214 | } | |
b74a1f6a NS |
215 | if (*bsz > max_block_alignment) |
216 | max_block_alignment = *bsz; | |
9440d84d | 217 | } |
cb5b3ef4 | 218 | |
cb5b3ef4 MV |
219 | char * |
220 | platform_findrawpath(char *path) | |
221 | { | |
b74a1f6a NS |
222 | return path; |
223 | } | |
224 | ||
225 | char * | |
226 | platform_findblockpath(char *path) | |
227 | { | |
228 | return path; | |
229 | } | |
230 | ||
231 | int | |
232 | platform_direct_blockdev(void) | |
233 | { | |
234 | return 1; | |
235 | } | |
236 | ||
237 | int | |
238 | platform_align_blockdev(void) | |
239 | { | |
240 | if (!max_block_alignment) | |
76956054 | 241 | return getpagesize(); |
b74a1f6a | 242 | return max_block_alignment; |
cb5b3ef4 | 243 | } |
3b6ac903 MV |
244 | |
245 | int | |
246 | platform_nproc(void) | |
247 | { | |
248 | return sysconf(_SC_NPROCESSORS_ONLN); | |
249 | } | |
2556c98b BN |
250 | |
251 | unsigned long | |
252 | platform_physmem(void) | |
253 | { | |
254 | struct sysinfo si; | |
255 | ||
256 | if (sysinfo(&si) < 0) { | |
257 | fprintf(stderr, _("%s: can't determine memory size\n"), | |
258 | progname); | |
259 | exit(1); | |
260 | } | |
261 | return (si.totalram >> 10) * si.mem_unit; /* kilobytes */ | |
262 | } |