]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libfrog/linux.c
xfsprogs: Release v6.8.0
[thirdparty/xfsprogs-dev.git] / libfrog / linux.c
CommitLineData
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 17extern char *progname;
b74a1f6a 18static 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
43static int
f594a0d1 44platform_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
111int
f594a0d1 112platform_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 120int
f594a0d1 121platform_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
130void
131platform_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 */
153int
154platform_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
178void
179platform_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
238int
239platform_direct_blockdev(void)
240{
241 return 1;
242}
243
244int
245platform_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
253int
254platform_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
265unsigned long
266platform_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}