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