Compare commits
No commits in common. 'c9' and 'i8c' have entirely different histories.
@ -1 +1 @@
|
|||||||
SOURCES/xfsprogs-5.19.0.tar.xz
|
SOURCES/xfsprogs-5.0.0.tar.xz
|
||||||
|
@ -1 +1 @@
|
|||||||
12afbdd497603b98945ea18f9aa5a78c671a6e4c SOURCES/xfsprogs-5.19.0.tar.xz
|
1a3d7ce8ebf75e001463162e4a44c0f5bf0beab7 SOURCES/xfsprogs-5.0.0.tar.xz
|
||||||
|
@ -1,185 +0,0 @@
|
|||||||
pub rsa4096 2011-11-03 [SC]
|
|
||||||
2B8185919E8D248981869DED20AE1692E13DDEE0
|
|
||||||
uid Eric R. Sandeen <sandeen@sandeen.net>
|
|
||||||
uid Eric R. Sandeen <sandeen@redhat.com>
|
|
||||||
sub rsa4096 2011-11-03 [E]
|
|
||||||
048CA40C8F5B5507E3A6CD6BE2C297037B26BEB4
|
|
||||||
|
|
||||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
|
||||||
|
|
||||||
mQINBE6x99QBEADMR+yNFBc1Y5avoUhzI/sdR9ANwznsNpiCtZlaO4pIWvqQJCjB
|
|
||||||
zp96cpCsnQZV32nqJBYnDpBDITBqTa/EF+IrHx8gKq8TaSBLHUq2ju2gJJLfBoL7
|
|
||||||
V3807PQcI18YzkF+WL05ODFQ2cemDhx5uLghHEeOxuGj+1AI+kh/FCzMedHc6k87
|
|
||||||
Yu2ZuaWF+Gh1W2ix6hikRJmQvj5BEeAx7xKkyBhzdbNIbbjV/iGi9b26B/dNcyd5
|
|
||||||
w2My2gxMtxaiP7q5b6GM2rsQklHP8FtWZiYO7jsg/qIppR1C6Zr5jK1GQlMUIclY
|
|
||||||
FeBbKggJ9mSwXJH7MIftilGQ8KDvNuV5AbkronGCsEEHj2khs7GfVv4pmUUHf1MR
|
|
||||||
IvV0x3WJkpmhuZaYg8AdJlyGKgp+TQ7B+wCjNTdVqMI1vDk2BS6Rg851ay7AypbC
|
|
||||||
Px2w4d8jIkQEgNjACHVDU89PNKAjScK1aTnW+HNUqg9BliCvuX5g4z2jgJBs57lo
|
|
||||||
TWAGe2Ve3cMy3VoQ40Wt3yKK0Eno8jfgzgb48wyycINZgnseMRhxc2c8hd51tftK
|
|
||||||
LKhPj4c7uqjnBjrgOVaVBupGUmvLiePlnW56zJZ51BR5igWnILeOJ1ZIcf7KsaHy
|
|
||||||
E6B1mG+XdmYtjDhjf3NAcoBWJuj8euxMB6TcQN2MrSXy5wSKaw40evooGwARAQAB
|
|
||||||
tCRFcmljIFIuIFNhbmRlZW4gPHNhbmRlZW5AcmVkaGF0LmNvbT6JARwEEAECAAYF
|
|
||||||
AlGk2F4ACgkQxSPxCi2dA1qtnQgAxUcCAANdBtDJ2n3W8t+wuKxP8kvd8Hw67KWg
|
|
||||||
TJ7N67yoxBhypyHM5QQFFuggyhC8S725oInE8arX17vqEQUOrqOgGvgrOXqrdTwd
|
|
||||||
aKypurWCsCqKjrMqVor8G5kX1AmlFC27p1oJUYsjSEFcy+HLN84W1uymPPh8epYQ
|
|
||||||
arLzz1A+heJH6AOVhCF9/XcbgCS4oTiBn9XqZhn58cPYttrKM2UIYYfEO9WOl5JL
|
|
||||||
95IUPLme8Cu1JKqq1Rzityg3gCFhLoTVDunjJQTlo8DSaSBca8CrJKGBiqTPrmSa
|
|
||||||
cQz0/eJoCl3gjmxuf4tNmteBA1nuSAAVJl9gOwgkpYr0LSnU54kBHAQQAQIABgUC
|
|
||||||
VMKlPwAKCRDXi2HT3/d6O4htB/9ROEE8n5wwQ2NOUCLNvOLX628JzF3wVG5FsZsr
|
|
||||||
Hf4wgtgn321UlIYR/wxQXaRA56JDksaV9zUZxVmPhRa36pqh0l3I/t825v3k9q3G
|
|
||||||
Bbg0MnrMMNRkZanfkBV/0Nm4lkDSQcioBptuEMX3xiNQeaVh953UEejrQJy6yZ3x
|
|
||||||
mTuoYNgIj1cQh24Up5PLkEYlUECiKRS8d055ewnB1FXNrY6zawFoc3ldgbbSVAoC
|
|
||||||
ypSSt8EDBxj54MzEO9Yb2Z/PIO1IROSKF9w2WhRfHccs00jLbyHdTvHzH/PS1SnY
|
|
||||||
HTanniKkb2BRJuyRVi/77gzczFSadpdAC92n2DpXlzlYMelXiQIcBBABAgAGBQJO
|
|
||||||
u7WDAAoJEA+eU2VSBFGDJqkP/0O/f3TjkXLp0qMtCp6XG64muw2gd64D6rv+7Qrh
|
|
||||||
aDxG2LOm6/pkrQDsoswZ9p5r3SBrRu0G86m2fqJdEdicDlVE7xh/3bjR7cQFMNrk
|
|
||||||
T+y5eDXgfAjLBqvjDa1s6aY7BzirsrR7wExLWo5AZmr2oRaaeXA9QFUkh5pP8+jJ
|
|
||||||
8K49FzzXXVrrNumkU1eDlO9MY0AiPe/mgkvwykySWd7fmrL1wtET7E4UauBwyNLp
|
|
||||||
gcZlsJAlWqv9jOVURqw396bKgYv19nhejbwhJ2gAmUxf4qbYrHkMg/QloyLGr2sT
|
|
||||||
VhCsTkurME11pqdN5+XlFUL9OM/eKYyN6flhiEc6qKDkbaBiY5lM788MnJHmFgKa
|
|
||||||
VKr4kkD2v9ZPYOHfoNlDL3FXqr1mQve0+ZAMS7+8T90P31Pgv3bMQA/JNv55brQU
|
|
||||||
QP1zDafUg6UUKl2R68LgCDLLyEP6MV3yifdTwTaFYQdBb/gy4jqZ1bDsqfQZPlhB
|
|
||||||
esEDNE3/HMoLD9c711SJ88aoyok2aK7lC6nvGIEos331XmxQnIx8l2QRaZWxH5kq
|
|
||||||
y1KQoh1QsEGunu2MiSTnb4oIQT5Knmqt3BStUNzVPRvbxEpSEPTEnr+DH1KSaswg
|
|
||||||
clGVx4T78Iu1/79wiaqJIksMYikFH5/6zC7YCBfZGVkOK2MSoN9BtA8VUH4LDN4S
|
|
||||||
eMpFiQIcBBABAgAGBQJOvZKZAAoJEHzR5hkv+fQ1RVAP/j8qvNTHXY0FxtDqMaN4
|
|
||||||
VK7zycTAAGvRDr2eA9NXmDRPWExZapJnbCTKUy5Y5+ZAZqYYVhv3//r1npagfkZf
|
|
||||||
1EGnnh/MYwJ7h1oYVXlXPQu+rf2pQFoxbiVkOmtTN8CBCZRWRtUUzVyMdIT2FTkD
|
|
||||||
Co2voKKWfy5gHVyfmqM3RsljFW0GFAwdykx75YzwyMLZAktq7hO9tlEP2bu/Omjh
|
|
||||||
Q+1KiiRFO2nvPjW6fMYM8Aebw/j/RD7vCeRe4FWBLYXB4n5vKBAv787jPt0tmMr7
|
|
||||||
uiGY9IhwMEaVYyel24Iup+nMy509CWzkXM5u6s3peXZpEk2vspU9wKcPIcfd+cRv
|
|
||||||
m7BpcnvixppMsFU46WVSxzTvmgrqAh0bG7jvVFCoM8QdRxRXrxv4pHXMxA6yZRmk
|
|
||||||
06dgVtgiUT1yF1Rc2hdIuCHc9Zun93kkdM2fakkHr7nmOD4aWjjMGm4tSoPq/FG+
|
|
||||||
3Lcl5xJOtvxsKRO0ynTJIygb6Z9BDzdSESgOM77/+YAOsY74LNE112TUwO82rZlm
|
|
||||||
m7Xry/bIRmWc3EeB3ma2Ntph8TGbTfzIB5vBogfrBohwnzzrP1SCSVLyoe828Ek9
|
|
||||||
rxYnfcw+XDYlloitpB1QAyOk0bcOsCdm5P4i0vtcPgs8PhMeDVB5MOlJRPl1BHl4
|
|
||||||
0ENVfJHEkTgj7DSoVNcl5iGViQIcBBABAgAGBQJPe18bAAoJENaLyazVq6ZO9tkP
|
|
||||||
/RgboRxgjqrY6vLnrM7/c1zSwpD8EaUkk3M2pMSJ9cI3ZPmll066pKljMPjz/MNF
|
|
||||||
F6QVECPLq3adBir2nvrVynzxnyuS+8eXKYxkav2j9zsfoDjoVE7F3ClcDQzXe7Io
|
|
||||||
Mhb0sb2JYUIi+1lgm6NSuhp8NvO0z7/TYmj7FcaeLJ+sAQ2zC0yf4N3+vL8YxXTv
|
|
||||||
2xpvjUyBa4QveM5mX87/GLjiY6g3bbJ9ASbsONrIrgaCv5YCpPloCioyAeKC4+jJ
|
|
||||||
IQRmVaUwBNdtUpM4t1X5N9bN5XmrA+HQ49tsgPUNmzSQRRNrlvPz3l95il3i7Dpj
|
|
||||||
kF2stoHe/hSTWMf7vUwSwWwjhTRw+R0gGvBKXeQIv8Momcyhyh4IXvKg6F7adFWH
|
|
||||||
mZLNhHuH3Mn7hce6Kcnbx7ozK+cVAx3Kn0MDy2OmJQNOIhUk2PLnwlchgICK8rxF
|
|
||||||
MuAfRWBwesN6xgnKn+Gi6YvDnf/y8Yf694pfQCmHhDRnrb/UBibXrUzsBi6+LV34
|
|
||||||
QXuDSlRFyQHsfCeyCX/INLc3bWH4H8r9UF17Kv2zCXUavY8EYYNiWe4xWSDq6QD2
|
|
||||||
Jqn856R/2iwcnr0kxHyarbGZk5xFe/UIUHp9+br2lNzYKOyfAVgWoKTxOn1ZN6U8
|
|
||||||
MhkVNXGOT8o4/shNXg5lKykxHqLoYrP/GZ1b3aaPzOXEiQIcBBABAgAGBQJYUamo
|
|
||||||
AAoJEPh/dxk0SrTr980P/0ZtLVn6S6RyQbycLHfP0wqa18B3ilquwKqY8Gz4Dwpg
|
|
||||||
3E1J0SC0NGhumWFVWI6hpEa9UXbQW1xKw8ZQ7uUiteMrj7Kwo5eRBd8zw6WFDuMS
|
|
||||||
QRB3z0LeeeXDGGW5ATwXTOey3s57s1MRDboZIyd5KcKUXSdM/e0/d4PFCKWxNX3v
|
|
||||||
N+1sFi86+aQR6cMpsw2N1p6pq7cdhGBFJES574XyBbtcdfuVIVtlBql7XG4r7IlL
|
|
||||||
yvxaxRErU4PdF5cXvadMDhh+tubWNgP6f0UP2etiZMrn+1TDgQPB47pxRIYZMPAK
|
|
||||||
/EQ1y/JqGudesDeWfqBDK58GjEu5u1vgS3ceyokpef/y0BLsfS2DlOlBBj/HzC4U
|
|
||||||
HEgNjCBPXboLg9JUohSLVMaBx20L6K9KmilJpNtbcTlH3o31+4X4z9MjFwYLK86P
|
|
||||||
TqsWvtYavbyOnAeEXMWNPvnuRadnsXUFtHggmYJHqMUBeKFt7+Wa3JQeQJu4AXO+
|
|
||||||
rIcfo5wV9PJFGQiqbhwbYOw0Qx9RZqxV5RPtJhqmARj2OwVPNnh6ZRnpuwTOoFiQ
|
|
||||||
EvWuBT/Wh/puxgpjkplOEP17BmpmUlHBsSDiN97KPG+N5hsfeTMK9aAminh/Owp4
|
|
||||||
UeUBhjPMsT2XbKybTkGNE28mc2FE0rjN4Q2ueV9gfk+9wxqcPsG81zRpZAVpnYeY
|
|
||||||
iQI4BBMBAgAiBQJOsq5eAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRAg
|
|
||||||
rhaS4T3e4IdpD/wOgkZiBdjErbXm8gZPuj6ceO3LfinJqWKJMHyPYmoUj4kPi5pg
|
|
||||||
WRPjzGHrBPvPpbEogL88+mBF7H1jJRsx4qohO+ndsUjmFTztq1+8ZeE9iffMmZWK
|
|
||||||
4zA5kOoKRXtGQaVZeOQhVGJAWnrpRDLKc2mCx+sxrD44H1ScmJ1veGVy1nK0k4sQ
|
|
||||||
TyXA7ZOI+o622NyvHlRYpivkUqugqmYFGfrmgwP8CeJB62LrzN0D27B0K/22EjZF
|
|
||||||
QBcYJRumuAkieMO9P3U/RRW+48499J5mgZgxXLgvsc3nKXH5Wi77hWsrgSbJTKeH
|
|
||||||
m2i/H4Jb57VrEGTPN+tQpI7fNrqaNiUWIk65RPV4khBrMVtxKXRU971JiJYGNP16
|
|
||||||
OTxr98ksHBbnEVJNUPY/mV+IAml+bB6UDNN1E2g8eIxXRqji5009YX6zEGdxIs1W
|
|
||||||
50FvRzdLJ5vZQ+T+jtXccim2aXr31gX8HUN+UVwWyCg5pmZ8CRiYGJeQc4eQ5U9C
|
|
||||||
e6DFTs3RFWIqVsfNsAah1VuCNbT7p8oK2DvozZ/gS8EQjmESZuQQDcGMdDL1pZtz
|
|
||||||
LdzpJFtqW1/gtz+aAHMa35WsNx3hAYvymJMoMaL1pfdyC07FtN0dGjXCOm0nWEf+
|
|
||||||
vKS+BC3cexv0i22h39vBc81BY0bzeeZwaDHjzhaNTuirZF10OBm11Xm3b7QlRXJp
|
|
||||||
YyBSLiBTYW5kZWVuIDxzYW5kZWVuQHNhbmRlZW4ubmV0PokBHAQQAQIABgUCUaTY
|
|
||||||
XgAKCRDFI/EKLZ0DWgBkCADkocbmrcfH/DT/wleLtiujyj96+QYQvHlAIf8p43b0
|
|
||||||
1DvdRJmmHAQZ57zGwr5DfM0KhGZayROxsYTI/Ej4hQci4v/v7w4fmHv6fAWcZyYL
|
|
||||||
XgCqSITZDeHtX4zJAfBj6PoTXdSn0XXTHUzNyb0vyXMW7oxPb2P7Stm14GJThRqN
|
|
||||||
WHCtHOpK6Z6VUt3EwA9RTLbFGJy9uD/aRedYnMFCOSq5uBOpIjfw57oNKc2GITZ6
|
|
||||||
MmGpjy6Mn4cffWpoCaAFoFIR/0miicBNyGd4EqgveixxOMd2N08so5wJXxX5J+o3
|
|
||||||
hduhRuhXLjuCSgV4HL12O9FG3hXUw8cnQPBATX8ITDsziQEcBBABAgAGBQJUwqU/
|
|
||||||
AAoJENeLYdPf93o7gisIAIrZxPXYJ+Jt1ErYUmRHu2gUGRQAiq4CNKlRIc+iQQbC
|
|
||||||
IfGE1whtgbWzT4lNjrJ4DB37ZbgD6mPnC+MY0yYFIS1r4Bgo8tBUkSM3b/kC2V89
|
|
||||||
B6l9eXp+wQ8ZtSr2+mXkHZ7AJa+4UCkK6k+0+9cCmGezyKEMNG1OsAnuBtfioUeJ
|
|
||||||
yYd662///wfL603dEZMuMuzHagcfeBwE6ui1h5zPrQVd8BNZSUgH+BEqBlrWppbJ
|
|
||||||
NVOW9K7q7F2AqMT69VWag9wNBuIHjIqczLT/pyz+mB4pUVOrUHDOi9YGJvploNpp
|
|
||||||
HzoLm36nfIeWgzUd/upR4k18HOHG/VeT1dhx532qHOGJAhwEEAECAAYFAk6yrAkA
|
|
||||||
CgkQfNHmGS/59DUfpA//SLgO7Pb9JMKIgbLlCOtxIgFS60eW9kY1EdpvgN25CCQD
|
|
||||||
HB7RdcadIEd95iIBx89SFBZr75HgedZrFsP1dbaQG893R5n5aGX0W5c1SX5Q/eKP
|
|
||||||
SiULRhOODrTXRNOd8Eoo/WTSQxIlX5/hM1NXVVfKchzMRyJKaDG3cRRrgZqL8K6x
|
|
||||||
FNtRyyp6c+SChyVhCzlc0Hxis03YicLNa2BY5PX0MJZhV3B2UOhHKrB+0JOdxktW
|
|
||||||
Sn49q06plxcbC22Q4Tbnn2zou6snR9xgC3nKno/U4alawt6Eu1+UgYSVFwpOnhOS
|
|
||||||
zq6EuDyGaRZwok8vzeCvJ4kUhO7vMPxqSPvFjQHo7Vo2rO0X1ieIEfWnGgjZdxWt
|
|
||||||
l7DYzOBo4kb3BCPX1wclfiRSnnLSjEIC6p3JsKvIpaF44vt8jf2bPLcdGHw7xU/t
|
|
||||||
9yLs3UkOJE/cuy3BO2EDQ6pZo0/X0H6spwyj0hbZ9O3ngPaqFAjbUFpL0sPf9xzJ
|
|
||||||
5KEKz/L4XJjbzrn+L/16xJUQ7/8XQioHxF89XudIjUGTdv9Ry08y8VaFl3uQmDXH
|
|
||||||
PMbT4B3uo6gXHhI9n9Un+51qj5rD1dPWfQ/XRpELI9RpANc5h4m2HgQhgqts9tcp
|
|
||||||
ChwnSf2Oc2Pe1Emszyx4tUHt3dNEHbpk3VPWSU4ZryCeTnAHi8JKMqiiyv42PWaJ
|
|
||||||
AhwEEAECAAYFAk67tYMACgkQD55TZVIEUYOAAw/+M28DXVvVd6BuA8RprANaeZ5M
|
|
||||||
CubcN2Fh1/CotBKB0kWIViJJOgAW/20z9M7LkqCg4IzHd0sDjbELp3r1kKwMdwD/
|
|
||||||
3sxiE4LzfS2/HnLf5R46cyc10zNASmPYm3YuN02VFsUDlGW1JUQxR4FqWbjzb2bu
|
|
||||||
x+autnl63vwCtBtYML5xMqk+f4Ud3HJJ4WSa0cFXFmopS6EvQjXxQk8jDNIQemM2
|
|
||||||
YGC/YI2c4zjDx5ZJjFy5eqms7svCQCfJQWBVVpsO/WwVs+nWAYP+6i5cyGR9HbGq
|
|
||||||
ipn/XfXILfx64z1j7WC0BmFYRvUdRvaU5EP5ly3ubhzb/9+Lmy+AI0DPnGebYKNJ
|
|
||||||
5DQcDr1g3X25OCTjo3Z2CHxE/U5sM4fqH4g15Hrpls2W/5QIoaL11yAMRb8Pyxft
|
|
||||||
3aBMXzAqDGsjMb5UH5yHBEU0x3tCFTEyuXDMYSid7HvAPPIMQ2M8G/lTKvaaYzam
|
|
||||||
bTrwb3UJDLvOjqwI9HEJouCHKH04B8w7ZERLiQuenwmpFb4lZixFxy5d1FOQ7yqV
|
|
||||||
3WzMA5Ax8c+fyhkVoijAgeoCC5Qc/M2MP0W1s8QyzBQYSrTZIx253v63eP38/rN0
|
|
||||||
xUy8ek8paQHGtGdiC2eTZJDVS8VU7Lj5sjwL45aFSLuyqN4+0FuTk6/BHAOsumiB
|
|
||||||
UhL8XS70EPkwK87fiaeJAhwEEAECAAYFAk97XxsACgkQ1ovJrNWrpk4rqA/+Oua1
|
|
||||||
SnNBM1Jj5YyVFTkqBfB7Y9Xhkh0tuG9pnu+SVMipbjyaspgTeGTycUxGBW6b8AhP
|
|
||||||
Bmn6DgR8fuoMD2lVzHmgfwU/bZesncB+ZxMKlxXeKKbG5N9KUFaQXUcLPgWScVQB
|
|
||||||
g21CY3pYOWSXi4vC+uh5J3Nth5VniICc/03fm497ajPVcDmCZWrf4yXFiD7S9mvv
|
|
||||||
d++ru0js5s67LkzJ0ZEHdn5SxOpEe5rrZwbCnAw+S+bLLcLGB+oUez3TWoz08aYR
|
|
||||||
v3iegQpLXg2/eEFfFATxP2GV9k/q6Z1j5oYqRF6bdfASr0cANA33IqpNBStfAENf
|
|
||||||
ibP2GiT4PeZ4Ux4hPnFtsI90M/2Uj7aDtFtvfPkr5qLy3Q71G3iGqI2TxTlEm0he
|
|
||||||
jHBhXsoWf4zGxLCTCra9R3Ni4tGQYpWxHEawMBEQn9zif78jAuwLsFktiM1Tym/7
|
|
||||||
t8t4qECrzhFSuaPH+pRpQ9atS5AQl+/lPVW00L6NbOlpQ5g1WUWMQFDr+l7Q+5i/
|
|
||||||
3IDqMkxT0FZI5kalwClSIXNW99nZcIBmoI0hF9DY9f/H4saH5IcZ6tY9CHx2VJQK
|
|
||||||
KFqgWfkFRgCrz24oLLO4OKPP/QTmnUWzwkyU62D6AfCGAZLektedMVHDg+msOt5l
|
|
||||||
ZkHSXvUNMvFnhIPtivSeLHzYo/yfFtLH9Q7m2zeJAhwEEAECAAYFAlhRqagACgkQ
|
|
||||||
+H93GTRKtOtXgw//RxhpWKHB6OA5LJ5feFGvgZZogx3iTcbzBBPTYJkchowYpqQG
|
|
||||||
rsDw1l31s7Xxi9vI/r9nkL2nSM8A9EqP+9n5RpEjH64j5T8HM05lwWAcMQJNp0rJ
|
|
||||||
2QyfPAo44E0BnxkzBAjRYnvL+hweeyzKrXYrspnpHQCNPQPkwtbx3mbFq+aPMyKf
|
|
||||||
Il3wzUloFQH3dfuzm6Pa9ygYE1kHNODJmAqOTWnl0hA44aCSDaHJVt3b+romBQPQ
|
|
||||||
pOgECVMjXPND2WHxVgZKOmO0VZtIz5VcaDixzQAkSs6Bc1m5mcXDdfAMUPjFYLKG
|
|
||||||
Pe/Mipr8SN85AY4V4Zli2ZoeARKhubybzC5MzvTLvubgT178Mdj6pGuy7gRNlLAJ
|
|
||||||
MyUTEHuDk8kHw3rie69TtDEzce2PXK6u0DyLRDsgihFhLEvXLs89j2boRgZXGejV
|
|
||||||
HJzOIJg3L7nSdMDBT7aLnj9blRFFJhW1OjedYwPif2g6yw6wHDzaFbprZN7vy05V
|
|
||||||
C7QGVcDl35Trd9cHxO+Kqhzz1pDuw7XJuCzzMgkFmlvKIqF/5AIXwnZK2IC6NWL/
|
|
||||||
ssSwrHq2skNf3+lzhkQyUnN+ip7xytRcmM3Id3v7EcaaUX1N/eVy7+3AqfHFCyW7
|
|
||||||
Ya5SCqNOCKd6ppZU6GtgRn00YeEt+t450fWseEufPpveQrPPvjfC6Tm3hoqJAjsE
|
|
||||||
EwECACUCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheABQJTMzNsAhkBAAoJECCu
|
|
||||||
FpLhPd7gWvsP/A7596epW8eOrbVIKMMKu3wd1WNonbwHVKpJTa2jHKDkjXrQaWUD
|
|
||||||
EQeksUZ1sUCFB8G2eaVj14yPCYlvSwIiuSsHpc09I8D8HYFQ8hKHTPah0m/fn964
|
|
||||||
kXvWogWBbOnZzMkeQdbBVlpmkxZY2+wsiuhehH64D1zZXWFAVUAlnKQQTjHN+bX6
|
|
||||||
hW2MgLXYH21MK5LTSljcBTLbXLM2jBPpJKTscDOa0b88n+5IHnASTCV0HqNWzYCy
|
|
||||||
M6DXAzBW+H8keKWxCDgdKYN85uZmPV3RFaUxZxQTtyxGcITRlYEyn+21Of6iiyKg
|
|
||||||
ZrT0cBL2MCdq7OeZiDjehDkCR3yJBHHPkjnwX/4mx0q9aLKs8N9hm0VL5QiBYPvH
|
|
||||||
6YcFnndCNrOzOjGCPA716FmnBRDEGbgjSU8MArDcckD4bDCK5tNKWrk9Lc/tCgKN
|
|
||||||
pXyWUfVs0VkzPajzA8A2IPHkUeClFWDAsdqSgJTUZz4tcdcHMNe3sKPTZZgd0XMy
|
|
||||||
baFdqyVF2E0ajAujVJdkVdrjUoZOU17h2LnfL0IrnKdXTP5hRr7ktHpF0ese2DLB
|
|
||||||
0qeN5Z2qGhWmxYh45G3BYZfx6806IonuPRGweFpat49O5uvme5hMOxCqBzavhoEg
|
|
||||||
6l5JFHZuuVP9QTfAaDL0tjvwvgTA9HQzPN5x8TVazrSJKrA+7e+FvuHduQINBE6x
|
|
||||||
99QBEADQOtSJ9OtdDOrE7xqJA4Lmn1PPbk2n9N+m/Wuh87AvxU8Ey8lfg/mXVXbJ
|
|
||||||
3vQxlFRWCOYLJ0TLEsnobZjIc7YhlMRqNRjRSn5vcSs6kulnCG+BZq2OJ+mPpsFI
|
|
||||||
q4Nd5OGoV2SmEXmQCaB9UAiRqflLFYrf5LRXYX+jGy0hWIGEyEPAjpexGWdUGgst
|
|
||||||
hwSKXEDYWVFRLsw5kaZEmRG10YPmShVlIzrFVlBKZ8QFphD9YkEYlB0/L3ieeUBW
|
|
||||||
feUff43ule81S4IZX63hhS3e0txG4ilgEI5aVztumB4KmzldrR0hmAnwui67o4En
|
|
||||||
m9VeM/FOWQV1PRLT+56sIbnW7ynqwZEudR4BQaRB8hSoZSNbasdpeBY2/M5XqLe1
|
|
||||||
/1hqJcqXdq8Vo1bWQoGzRPkzVyeVZlRS2XqTTiXPk6Og1j0n9sbJXcNKWRuVdEwr
|
|
||||||
zuIthBKtxXpwXP09GXi9bUsZ9/fFFAeeB43l8/HN7xfk0TeFv5JLDIxISonGFVNc
|
|
||||||
lV9BZZbR1DE/sc3CqY5ZgX/qb7WAr9jaBjeMBCexZOu7hFVNkacrAQ+Y4KlJS+xN
|
|
||||||
FexUeCxYnvSp3TI5KNa6K/hvy+YPf5AWDK8IHE8x0/fGzE3l62F4sw6BHBakufrI
|
|
||||||
0Wr/G2Cz4QKAb6BHvzJdDIDuIKzm0WzY6sypXmO5IwaafSTElQARAQABiQIfBBgB
|
|
||||||
AgAJBQJOsffUAhsMAAoJECCuFpLhPd7gErAP/Rk46ZQ05kJI4sAyNnHea1i2NiB9
|
|
||||||
Q0qLSSJg+94ahFZOpuKzxSK0+02sbhfGDMs6KNJ04TNDCR04in9CdmEY2ywx6MKe
|
|
||||||
yW4rQZB35GQVVY2ZxBPvyEF4ZycQwBdkqrtuQgrO9zToYWaQxtf+ACXoOI0a/RQ0
|
|
||||||
Bf7kViH65wIllLICnewD738sqPGdN51fRrKBcDquSlfRjQW83/11+bjv4sartYCo
|
|
||||||
E7JhNTcTr/5nvZtmgb9wbsA0vFw+iiUs6tTjeioWcPxDBw3nrLhV8WPf+MMXYxff
|
|
||||||
G7i/Y6OCVWMwRgdMLE/eanF6wYe6o6K38VH6YXQw/0kZ+PrH5uP/0kwG0JbVtj9o
|
|
||||||
94x08ZMm9eMa05VhuUZmtKNdGfn75S7LfoK+RyuO7OJIMb4kR7EbFzNbA3ias5Ba
|
|
||||||
ExPknJv7XwI74JbEl8dpheIsRbt0jUDKcviOOfhbQxKJelYNTD5+wE4+TpqHXQLj
|
|
||||||
5HUlzt3JSwqSwx+++FFfWFMheG2HzkfXrvTpud5NrJkGGVn+ErXy6pNf6zSicb+b
|
|
||||||
UXe9i92UTina2zWaaLEwXspqM338TlFC2JICu8pNt+wHpPCjgy2Ei4u5/4zSYjiA
|
|
||||||
+X1I+V99YJhU+FpT2jzfLUoVsP/6WHWmM/tsS79i50G/PsXYzKOHj/0ZQCKOsJM1
|
|
||||||
4NMMCC8gkONe4tek
|
|
||||||
=EFoy
|
|
||||||
-----END PGP PUBLIC KEY BLOCK-----
|
|
@ -1,9 +0,0 @@
|
|||||||
# This is a sample mkfs.xfs config file that creates rhel-8 compatible
|
|
||||||
# XFS filesystem on rhel-9
|
|
||||||
# Usage:
|
|
||||||
# mkfs.xfs -c options=rhel8.0.conf device
|
|
||||||
#
|
|
||||||
[metadata]
|
|
||||||
inobtcount=0
|
|
||||||
bigtime=0
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
|||||||
|
Index: xfsprogs-4.19.0/mkfs/xfs_mkfs.c
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-4.19.0.orig/mkfs/xfs_mkfs.c
|
||||||
|
+++ xfsprogs-4.19.0/mkfs/xfs_mkfs.c
|
||||||
|
@@ -1973,15 +1973,15 @@ _("Directory ftype field always enabled
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
- } else {
|
||||||
|
+ } else { /* !crcs_enabled */
|
||||||
|
/*
|
||||||
|
- * The kernel doesn't currently support crc=0,finobt=1
|
||||||
|
- * filesystems. If crcs are not enabled and the user has not
|
||||||
|
- * explicitly turned finobt on, then silently turn it off to
|
||||||
|
- * avoid an unnecessary warning.
|
||||||
|
+ * The kernel doesn't support crc=0,finobt=1 filesystems.
|
||||||
|
+ * If crcs are not enabled and the user has not explicitly
|
||||||
|
+ * turned finobt on, then silently turn it off to avoid an
|
||||||
|
+ * unnecessary warning.
|
||||||
|
* If the user explicitly tried to use crc=0,finobt=1,
|
||||||
|
* then issue an error.
|
||||||
|
- * The same is also for sparse inodes.
|
||||||
|
+ * The same is also true for sparse inodes and reflink.
|
||||||
|
*/
|
||||||
|
if (cli->sb_feat.finobt && cli_opt_set(&mopts, M_FINOBT)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
@@ -2004,7 +2004,7 @@ _("rmapbt not supported without CRC supp
|
||||||
|
}
|
||||||
|
cli->sb_feat.rmapbt = false;
|
||||||
|
|
||||||
|
- if (cli->sb_feat.reflink) {
|
||||||
|
+ if (cli->sb_feat.reflink && cli_opt_set(&mopts, M_REFLINK)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
_("reflink not supported without CRC support\n"));
|
||||||
|
usage();
|
||||||
|
@@ -3788,7 +3788,7 @@ main(
|
||||||
|
.finobt = true,
|
||||||
|
.spinodes = true,
|
||||||
|
.rmapbt = false,
|
||||||
|
- .reflink = false,
|
||||||
|
+ .reflink = true,
|
||||||
|
.parent_pointers = false,
|
||||||
|
.nodalign = false,
|
||||||
|
.nortalign = false,
|
||||||
|
Index: xfsprogs-4.19.0/man/man8/mkfs.xfs.8
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-4.19.0.orig/man/man8/mkfs.xfs.8
|
||||||
|
+++ xfsprogs-4.19.0/man/man8/mkfs.xfs.8
|
||||||
|
@@ -229,9 +229,9 @@ mapping will be changed to the new block
|
||||||
|
enables the creation of per-file snapshots and deduplication. It is only
|
||||||
|
available for the data forks of regular files.
|
||||||
|
.IP
|
||||||
|
-By default,
|
||||||
|
+By default in Red Hat Enterprise Linux 8,
|
||||||
|
.B mkfs.xfs
|
||||||
|
-will not create reference count btrees and therefore will not enable the
|
||||||
|
+will create reference count btrees and therefore will enable the
|
||||||
|
reflink feature. This feature is only available for filesystems created with
|
||||||
|
the (default)
|
||||||
|
.B \-m crc=1
|
||||||
|
@@ -239,6 +239,13 @@ option set. When the option
|
||||||
|
.B \-m crc=0
|
||||||
|
is used, the reference count btree feature is not supported and reflink is
|
||||||
|
disabled.
|
||||||
|
+.IP
|
||||||
|
+Note: the filesystem DAX mount option (
|
||||||
|
+.B \-o dax
|
||||||
|
+) is incompatible with
|
||||||
|
+reflink-enabled XFS filesystems. To use filesystem DAX with XFS, specify the
|
||||||
|
+.B \-m reflink=0
|
||||||
|
+option to mkfs.xfs to disable the reflink feature.
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.BI \-d " data_section_options"
|
@ -0,0 +1,106 @@
|
|||||||
|
From b192e77cc38473964c718bd035502b702c6a6e34 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Date: Tue, 21 May 2019 11:03:43 -0500
|
||||||
|
Subject: [PATCH] libxfs: create current_time helper and sync
|
||||||
|
xfs_trans_ichgtime
|
||||||
|
|
||||||
|
Make xfs_trans_ichgtime() almost match kernelspace by creating a
|
||||||
|
new current_time() helper to match the kernel utility.
|
||||||
|
|
||||||
|
This reduces still more cosmetic change. We may want to sync the
|
||||||
|
creation flag over to the kernel even though it's not used today.
|
||||||
|
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/include/xfs_inode.h b/include/xfs_inode.h
|
||||||
|
index 52d79f3..76f9ac7 100644
|
||||||
|
--- a/include/xfs_inode.h
|
||||||
|
+++ b/include/xfs_inode.h
|
||||||
|
@@ -16,6 +16,16 @@ struct xfs_mount;
|
||||||
|
struct xfs_inode_log_item;
|
||||||
|
struct xfs_dir_ops;
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * These are not actually used, they are only for userspace build
|
||||||
|
+ * compatibility in code that looks at i_state
|
||||||
|
+ */
|
||||||
|
+#define I_DIRTY_TIME 0
|
||||||
|
+#define I_DIRTY_TIME_EXPIRED 0
|
||||||
|
+
|
||||||
|
+#define IS_I_VERSION(inode) (0)
|
||||||
|
+#define inode_maybe_inc_iversion(inode,flags) (0)
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Inode interface. This fakes up a "VFS inode" to make the xfs_inode appear
|
||||||
|
* similar to the kernel which now is used tohold certain parts of the on-disk
|
||||||
|
@@ -25,6 +35,7 @@ struct inode {
|
||||||
|
mode_t i_mode;
|
||||||
|
uint32_t i_nlink;
|
||||||
|
xfs_dev_t i_rdev; /* This actually holds xfs_dev_t */
|
||||||
|
+ unsigned long i_state; /* Not actually used in userspace */
|
||||||
|
uint32_t i_generation;
|
||||||
|
uint64_t i_version;
|
||||||
|
struct timespec i_atime;
|
||||||
|
@@ -150,6 +161,9 @@ extern void libxfs_trans_ichgtime(struct xfs_trans *,
|
||||||
|
struct xfs_inode *, int);
|
||||||
|
extern int libxfs_iflush_int (struct xfs_inode *, struct xfs_buf *);
|
||||||
|
|
||||||
|
+#define timespec64 timespec
|
||||||
|
+extern struct timespec64 current_time(struct inode *inode);
|
||||||
|
+
|
||||||
|
/* Inode Cache Interfaces */
|
||||||
|
extern bool libxfs_inode_verify_forks(struct xfs_inode *ip);
|
||||||
|
extern int libxfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
|
||||||
|
diff --git a/libxfs/util.c b/libxfs/util.c
|
||||||
|
index 9fe9a36..951f7cf 100644
|
||||||
|
--- a/libxfs/util.c
|
||||||
|
+++ b/libxfs/util.c
|
||||||
|
@@ -136,11 +136,21 @@ xfs_log_calc_unit_res(
|
||||||
|
return unit_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
+struct timespec64
|
||||||
|
+current_time(struct inode *inode)
|
||||||
|
+{
|
||||||
|
+ struct timespec64 tv;
|
||||||
|
+ struct timeval stv;
|
||||||
|
+
|
||||||
|
+ gettimeofday(&stv, (struct timezone *)0);
|
||||||
|
+ tv.tv_sec = stv.tv_sec;
|
||||||
|
+ tv.tv_nsec = stv.tv_usec * 1000;
|
||||||
|
+
|
||||||
|
+ return tv;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Change the requested timestamp in the given inode.
|
||||||
|
- *
|
||||||
|
- * This was once shared with the kernel, but has diverged to the point
|
||||||
|
- * where it's no longer worth the hassle of maintaining common code.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
libxfs_trans_ichgtime(
|
||||||
|
@@ -148,12 +158,14 @@ libxfs_trans_ichgtime(
|
||||||
|
struct xfs_inode *ip,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
- struct timespec tv;
|
||||||
|
- struct timeval stv;
|
||||||
|
+ struct inode *inode = VFS_I(ip);
|
||||||
|
+ struct timespec64 tv;
|
||||||
|
+
|
||||||
|
+ ASSERT(tp);
|
||||||
|
+ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
|
||||||
|
+
|
||||||
|
+ tv = current_time(inode);
|
||||||
|
|
||||||
|
- gettimeofday(&stv, (struct timezone *)0);
|
||||||
|
- tv.tv_sec = stv.tv_sec;
|
||||||
|
- tv.tv_nsec = stv.tv_usec * 1000;
|
||||||
|
if (flags & XFS_ICHGTIME_MOD)
|
||||||
|
VFS_I(ip)->i_mtime = tv;
|
||||||
|
if (flags & XFS_ICHGTIME_CHG)
|
@ -0,0 +1,60 @@
|
|||||||
|
From 9c726ef0d2d829ae83756d3817f271e9c2c8777a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Date: Wed, 10 Jul 2019 11:35:07 -0400
|
||||||
|
Subject: [PATCH] mkfs: don't use xfs_verify_fsbno() before m_sb is fully set
|
||||||
|
up
|
||||||
|
|
||||||
|
Commit 8da5298 mkfs: validate start and end of aligned logs stopped
|
||||||
|
open-coding log end block checks, and used xfs_verify_fsbno() instead.
|
||||||
|
It also used xfs_verify_fsbno() to validate the log start. This
|
||||||
|
seemed to make sense, but then xfs/306 started failing on 4k sector
|
||||||
|
filesystems, which leads to a log striep unite being set on a single
|
||||||
|
AG filesystem.
|
||||||
|
|
||||||
|
As it turns out, if xfs_verify_fsbno() is testing a block in the
|
||||||
|
last AG, it needs to have mp->m_sb.sb_dblocks set, which isn't done
|
||||||
|
until later. With sb_dblocks unset we can't know how many blocks
|
||||||
|
are in the last AG, and hence can't validate it.
|
||||||
|
|
||||||
|
To fix all this, go back to open-coding the checks; note that this
|
||||||
|
/does/ rely on m_sb.sb_agblklog being set, but that /is/ already
|
||||||
|
done in the early call to start_superblock_setup().
|
||||||
|
|
||||||
|
Fixes: 8da5298 ("mkfs: validate start and end of aligned logs")
|
||||||
|
Reported-by: Dave Chinner <david@fromorbit.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
mkfs/xfs_mkfs.c | 7 +++----
|
||||||
|
1 file changed, 3 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
|
||||||
|
index 468b8fde..4e576a5c 100644
|
||||||
|
--- a/mkfs/xfs_mkfs.c
|
||||||
|
+++ b/mkfs/xfs_mkfs.c
|
||||||
|
@@ -3040,7 +3040,7 @@ align_internal_log(
|
||||||
|
cfg->logstart = ((cfg->logstart + (sunit - 1)) / sunit) * sunit;
|
||||||
|
|
||||||
|
/* If our log start overlaps the next AG's metadata, fail. */
|
||||||
|
- if (!xfs_verify_fsbno(mp, cfg->logstart)) {
|
||||||
|
+ if (XFS_FSB_TO_AGBNO(mp, cfg->logstart) <= XFS_AGFL_BLOCK(mp)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
_("Due to stripe alignment, the internal log start (%lld) cannot be aligned\n"
|
||||||
|
"within an allocation group.\n"),
|
||||||
|
@@ -3051,10 +3051,9 @@ _("Due to stripe alignment, the internal log start (%lld) cannot be aligned\n"
|
||||||
|
/* round up/down the log size now */
|
||||||
|
align_log_size(cfg, sunit);
|
||||||
|
|
||||||
|
- /* check the aligned log still fits in an AG. */
|
||||||
|
+ /* check the aligned log still starts and ends in the same AG. */
|
||||||
|
logend = cfg->logstart + cfg->logblocks - 1;
|
||||||
|
- if (XFS_FSB_TO_AGNO(mp, cfg->logstart) != XFS_FSB_TO_AGNO(mp, logend) ||
|
||||||
|
- !xfs_verify_fsbno(mp, logend)) {
|
||||||
|
+ if (XFS_FSB_TO_AGNO(mp, cfg->logstart) != XFS_FSB_TO_AGNO(mp, logend)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
_("Due to stripe alignment, the internal log size (%lld) is too large.\n"
|
||||||
|
"Must fit within an allocation group.\n"),
|
||||||
|
--
|
||||||
|
2.17.0
|
||||||
|
|
@ -0,0 +1,52 @@
|
|||||||
|
From 8da52988ad210958f21c178620bb1e44f1188cd0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Tue, 25 Jun 2019 17:04:42 -0400
|
||||||
|
Subject: [PATCH] mkfs: validate start and end of aligned logs
|
||||||
|
|
||||||
|
Validate that the start and end of the log stay within a single AG if
|
||||||
|
we adjust either end to align to stripe units.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
mkfs/xfs_mkfs.c | 15 ++++++++++++++-
|
||||||
|
1 file changed, 14 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
|
||||||
|
index ddb25ecc..468b8fde 100644
|
||||||
|
--- a/mkfs/xfs_mkfs.c
|
||||||
|
+++ b/mkfs/xfs_mkfs.c
|
||||||
|
@@ -3033,15 +3033,28 @@ align_internal_log(
|
||||||
|
struct xfs_mount *mp,
|
||||||
|
int sunit)
|
||||||
|
{
|
||||||
|
+ uint64_t logend;
|
||||||
|
+
|
||||||
|
/* round up log start if necessary */
|
||||||
|
if ((cfg->logstart % sunit) != 0)
|
||||||
|
cfg->logstart = ((cfg->logstart + (sunit - 1)) / sunit) * sunit;
|
||||||
|
|
||||||
|
+ /* If our log start overlaps the next AG's metadata, fail. */
|
||||||
|
+ if (!xfs_verify_fsbno(mp, cfg->logstart)) {
|
||||||
|
+ fprintf(stderr,
|
||||||
|
+_("Due to stripe alignment, the internal log start (%lld) cannot be aligned\n"
|
||||||
|
+ "within an allocation group.\n"),
|
||||||
|
+ (long long) cfg->logstart);
|
||||||
|
+ usage();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* round up/down the log size now */
|
||||||
|
align_log_size(cfg, sunit);
|
||||||
|
|
||||||
|
/* check the aligned log still fits in an AG. */
|
||||||
|
- if (cfg->logblocks > cfg->agsize - XFS_FSB_TO_AGBNO(mp, cfg->logstart)) {
|
||||||
|
+ logend = cfg->logstart + cfg->logblocks - 1;
|
||||||
|
+ if (XFS_FSB_TO_AGNO(mp, cfg->logstart) != XFS_FSB_TO_AGNO(mp, logend) ||
|
||||||
|
+ !xfs_verify_fsbno(mp, logend)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
_("Due to stripe alignment, the internal log size (%lld) is too large.\n"
|
||||||
|
"Must fit within an allocation group.\n"),
|
||||||
|
--
|
||||||
|
2.17.0
|
||||||
|
|
@ -0,0 +1,42 @@
|
|||||||
|
From 59cf967983f6aaff4ce33a50135ae57032ebd8f2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Allison Collins <allison.henderson@oracle.com>
|
||||||
|
Date: Wed, 10 Jul 2019 11:38:04 -0400
|
||||||
|
Subject: [PATCH] xfsprogs: Fix uninitialized cfg->lsunit
|
||||||
|
|
||||||
|
While investigating another mkfs bug, noticed that cfg->lsunit is sometimes
|
||||||
|
left uninitialized when it should not. This is because calc_stripe_factors
|
||||||
|
in some cases needs cfg->loginternal to be set first. This is done in
|
||||||
|
validate_logdev. So move calc_stripe_factors below validate_logdev while
|
||||||
|
parsing configs.
|
||||||
|
|
||||||
|
Signed-off-by: Allison Collins <allison.henderson@oracle.com>
|
||||||
|
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
mkfs/xfs_mkfs.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
|
||||||
|
index 79377b12..65cf1e0f 100644
|
||||||
|
--- a/mkfs/xfs_mkfs.c
|
||||||
|
+++ b/mkfs/xfs_mkfs.c
|
||||||
|
@@ -4007,7 +4007,6 @@ main(
|
||||||
|
cfg.rtblocks = calc_dev_size(cli.rtsize, &cfg, &ropts, R_SIZE, "rt");
|
||||||
|
|
||||||
|
validate_rtextsize(&cfg, &cli, &ft);
|
||||||
|
- calc_stripe_factors(&cfg, &cli, &ft);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open and validate the device configurations
|
||||||
|
@@ -4017,6 +4016,7 @@ main(
|
||||||
|
validate_datadev(&cfg, &cli);
|
||||||
|
validate_logdev(&cfg, &cli, &logfile);
|
||||||
|
validate_rtdev(&cfg, &cli, &rtfile);
|
||||||
|
+ calc_stripe_factors(&cfg, &cli, &ft);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At this point when know exactly what size all the devices are,
|
||||||
|
--
|
||||||
|
2.17.0
|
||||||
|
|
@ -0,0 +1,81 @@
|
|||||||
|
From bf6d4cf988176ad7efd0089830bfbf200a5e0196 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 20 Nov 2020 17:03:27 -0500
|
||||||
|
Subject: [PATCH] libfrog: convert cvttime to return time64_t
|
||||||
|
|
||||||
|
Change the cvttime function to return 64-bit time values so that we can
|
||||||
|
put them to use with the bigtime feature.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/include/convert.h b/include/convert.h
|
||||||
|
index 0489a1d..2b427df 100644
|
||||||
|
--- a/include/convert.h
|
||||||
|
+++ b/include/convert.h
|
||||||
|
@@ -16,7 +16,7 @@ extern uint16_t cvt_u16(char *s, int base);
|
||||||
|
|
||||||
|
extern long long cvtnum(size_t blocksize, size_t sectorsize, char *s);
|
||||||
|
extern void cvtstr(double value, char *str, size_t sz);
|
||||||
|
-extern unsigned long cvttime(char *s);
|
||||||
|
+extern time64_t cvttime(char *s);
|
||||||
|
|
||||||
|
extern uid_t uid_from_string(char *user);
|
||||||
|
extern gid_t gid_from_string(char *group);
|
||||||
|
diff --git a/libfrog/convert.c b/libfrog/convert.c
|
||||||
|
index ed4cae7..209b874 100644
|
||||||
|
--- a/libfrog/convert.c
|
||||||
|
+++ b/libfrog/convert.c
|
||||||
|
@@ -267,14 +267,14 @@ cvtstr(
|
||||||
|
#define DAYS_TO_SECONDS(d) ((d) * HOURS_TO_SECONDS(24))
|
||||||
|
#define WEEKS_TO_SECONDS(w) ((w) * DAYS_TO_SECONDS(7))
|
||||||
|
|
||||||
|
-unsigned long
|
||||||
|
+time64_t
|
||||||
|
cvttime(
|
||||||
|
char *s)
|
||||||
|
{
|
||||||
|
- unsigned long i;
|
||||||
|
+ time64_t i;
|
||||||
|
char *sp;
|
||||||
|
|
||||||
|
- i = strtoul(s, &sp, 0);
|
||||||
|
+ i = strtoll(s, &sp, 0);
|
||||||
|
if (i == 0 && sp == s)
|
||||||
|
return 0;
|
||||||
|
if (*sp == '\0')
|
||||||
|
diff --git a/quota/edit.c b/quota/edit.c
|
||||||
|
index 01d358f..b3cad02 100644
|
||||||
|
--- a/quota/edit.c
|
||||||
|
+++ b/quota/edit.c
|
||||||
|
@@ -419,13 +419,13 @@ restore_f(
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_timer(
|
||||||
|
- uint32_t id,
|
||||||
|
- uint type,
|
||||||
|
- uint mask,
|
||||||
|
- char *dev,
|
||||||
|
- uint value)
|
||||||
|
+ uint32_t id,
|
||||||
|
+ uint type,
|
||||||
|
+ uint mask,
|
||||||
|
+ char *dev,
|
||||||
|
+ time64_t value)
|
||||||
|
{
|
||||||
|
- fs_disk_quota_t d;
|
||||||
|
+ struct fs_disk_quota d;
|
||||||
|
|
||||||
|
memset(&d, 0, sizeof(d));
|
||||||
|
|
||||||
|
@@ -476,7 +476,7 @@ timer_f(
|
||||||
|
int argc,
|
||||||
|
char **argv)
|
||||||
|
{
|
||||||
|
- uint value;
|
||||||
|
+ time64_t value;
|
||||||
|
char *name = NULL;
|
||||||
|
uint32_t id = 0;
|
||||||
|
int c, flags = 0, type = 0, mask = 0;
|
@ -0,0 +1,61 @@
|
|||||||
|
From 0160c1490d4b49889c9ed01a39f760cba762eac5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 20 Nov 2020 17:03:28 -0500
|
||||||
|
Subject: [PATCH] libfrog: list the bigtime feature when reporting geometry
|
||||||
|
|
||||||
|
When we're reporting on a filesystem's geometry, report if the bigtime
|
||||||
|
feature is enabled on this filesystem.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/libfrog/fsgeom.c b/libfrog/fsgeom.c
|
||||||
|
index 8879d16..ddacd59 100644
|
||||||
|
--- a/libfrog/fsgeom.c
|
||||||
|
+++ b/libfrog/fsgeom.c
|
||||||
|
@@ -25,6 +25,7 @@ xfs_report_geom(
|
||||||
|
int spinodes;
|
||||||
|
int rmapbt_enabled;
|
||||||
|
int reflink_enabled;
|
||||||
|
+ int bigtime_enabled;
|
||||||
|
|
||||||
|
isint = geo->logstart > 0;
|
||||||
|
lazycount = geo->flags & XFS_FSOP_GEOM_FLAGS_LAZYSB ? 1 : 0;
|
||||||
|
@@ -40,12 +41,13 @@ xfs_report_geom(
|
||||||
|
spinodes = geo->flags & XFS_FSOP_GEOM_FLAGS_SPINODES ? 1 : 0;
|
||||||
|
rmapbt_enabled = geo->flags & XFS_FSOP_GEOM_FLAGS_RMAPBT ? 1 : 0;
|
||||||
|
reflink_enabled = geo->flags & XFS_FSOP_GEOM_FLAGS_REFLINK ? 1 : 0;
|
||||||
|
+ bigtime_enabled = geo->flags & XFS_FSOP_GEOM_FLAGS_BIGTIME ? 1 : 0;
|
||||||
|
|
||||||
|
printf(_(
|
||||||
|
"meta-data=%-22s isize=%-6d agcount=%u, agsize=%u blks\n"
|
||||||
|
" =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n"
|
||||||
|
" =%-22s crc=%-8u finobt=%u, sparse=%u, rmapbt=%u\n"
|
||||||
|
-" =%-22s reflink=%u\n"
|
||||||
|
+" =%-22s reflink=%-4u bigtime=%u\n"
|
||||||
|
"data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n"
|
||||||
|
" =%-22s sunit=%-6u swidth=%u blks\n"
|
||||||
|
"naming =version %-14u bsize=%-6u ascii-ci=%d, ftype=%d\n"
|
||||||
|
@@ -55,7 +57,7 @@ xfs_report_geom(
|
||||||
|
mntpoint, geo->inodesize, geo->agcount, geo->agblocks,
|
||||||
|
"", geo->sectsize, attrversion, projid32bit,
|
||||||
|
"", crcs_enabled, finobt_enabled, spinodes, rmapbt_enabled,
|
||||||
|
- "", reflink_enabled,
|
||||||
|
+ "", reflink_enabled, bigtime_enabled,
|
||||||
|
"", geo->blocksize, (unsigned long long)geo->datablocks,
|
||||||
|
geo->imaxpct,
|
||||||
|
"", geo->sunit, geo->swidth,
|
||||||
|
diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
|
||||||
|
index 00f367e..a0452c2 100644
|
||||||
|
--- a/libxfs/libxfs_api_defs.h
|
||||||
|
+++ b/libxfs/libxfs_api_defs.h
|
||||||
|
@@ -115,6 +115,7 @@
|
||||||
|
#define xfs_calc_dquots_per_chunk libxfs_calc_dquots_per_chunk
|
||||||
|
#define xfs_dquot_verify libxfs_dquot_verify
|
||||||
|
#define xfs_dqblk_repair libxfs_dqblk_repair
|
||||||
|
+#define xfs_dquot_from_disk_ts libxfs_dquot_from_disk_ts
|
||||||
|
|
||||||
|
#define xfs_symlink_blocks libxfs_symlink_blocks
|
||||||
|
#define xfs_symlink_hdr_ok libxfs_symlink_hdr_ok
|
@ -0,0 +1,89 @@
|
|||||||
|
From ec24f6fa05f695af02b4e0fca5bc27cb1cab49b7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Tue, 10 Nov 2020 12:05:32 -0500
|
||||||
|
Subject: [PATCH] libxfs: create a real struct timespec64
|
||||||
|
|
||||||
|
Create a real struct timespec64 that supports 64-bit seconds counts.
|
||||||
|
The C library struct timespec doesn't support this on 32-bit
|
||||||
|
architectures and we cannot lose the upper bits in the incore inode.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/include/libxfs.h b/include/libxfs.h
|
||||||
|
index 731561c..2bdef70 100644
|
||||||
|
--- a/include/libxfs.h
|
||||||
|
+++ b/include/libxfs.h
|
||||||
|
@@ -36,8 +36,6 @@ extern uint32_t crc32c_le(uint32_t crc, unsigned char const *p, size_t len);
|
||||||
|
|
||||||
|
#include "xfs_cksum.h"
|
||||||
|
|
||||||
|
-#define timespec64 timespec
|
||||||
|
-
|
||||||
|
/*
|
||||||
|
* This mirrors the kernel include for xfs_buf.h - it's implicitly included in
|
||||||
|
* every files via a similar include in the kernel xfs_linux.h.
|
||||||
|
diff --git a/include/xfs_inode.h b/include/xfs_inode.h
|
||||||
|
index e03d1cb..ddd48be 100644
|
||||||
|
--- a/include/xfs_inode.h
|
||||||
|
+++ b/include/xfs_inode.h
|
||||||
|
@@ -32,15 +32,15 @@ struct xfs_dir_ops;
|
||||||
|
* metadata.
|
||||||
|
*/
|
||||||
|
struct inode {
|
||||||
|
- mode_t i_mode;
|
||||||
|
- uint32_t i_nlink;
|
||||||
|
- xfs_dev_t i_rdev; /* This actually holds xfs_dev_t */
|
||||||
|
- unsigned long i_state; /* Not actually used in userspace */
|
||||||
|
- uint32_t i_generation;
|
||||||
|
- uint64_t i_version;
|
||||||
|
- struct timespec i_atime;
|
||||||
|
- struct timespec i_mtime;
|
||||||
|
- struct timespec i_ctime;
|
||||||
|
+ mode_t i_mode;
|
||||||
|
+ uint32_t i_nlink;
|
||||||
|
+ xfs_dev_t i_rdev; /* This actually holds xfs_dev_t */
|
||||||
|
+ unsigned long i_state; /* Not actually used in userspace */
|
||||||
|
+ uint32_t i_generation;
|
||||||
|
+ uint64_t i_version;
|
||||||
|
+ struct timespec64 i_atime;
|
||||||
|
+ struct timespec64 i_mtime;
|
||||||
|
+ struct timespec64 i_ctime;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct xfs_inode {
|
||||||
|
diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h
|
||||||
|
index 8232f89..b45d07e 100644
|
||||||
|
--- a/libxfs/libxfs_priv.h
|
||||||
|
+++ b/libxfs/libxfs_priv.h
|
||||||
|
@@ -62,8 +62,6 @@ extern kmem_zone_t *xfs_buf_zone;
|
||||||
|
extern kmem_zone_t *xfs_inode_zone;
|
||||||
|
extern kmem_zone_t *xfs_trans_zone;
|
||||||
|
|
||||||
|
-#define timespec64 timespec
|
||||||
|
-
|
||||||
|
/* CRC stuff, buffer API dependent on it */
|
||||||
|
#define crc32c(c,p,l) crc32c_le((c),(unsigned char const *)(p),(l))
|
||||||
|
|
||||||
|
diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h
|
||||||
|
index c8a3b12..fbc9031 100644
|
||||||
|
--- a/libxfs/xfs_fs.h
|
||||||
|
+++ b/libxfs/xfs_fs.h
|
||||||
|
@@ -686,6 +686,14 @@ struct xfs_extent_data {
|
||||||
|
#define XFS_IOC_CLONE_RANGE _IOW (0x94, 13, struct xfs_clone_args)
|
||||||
|
#define XFS_IOC_FILE_EXTENT_SAME _IOWR(0x94, 54, struct xfs_extent_data)
|
||||||
|
|
||||||
|
+/* 64-bit seconds counter that works independently of the C library time_t. */
|
||||||
|
+typedef long long int time64_t;
|
||||||
|
+
|
||||||
|
+struct timespec64 {
|
||||||
|
+ time64_t tv_sec; /* seconds */
|
||||||
|
+ long tv_nsec; /* nanoseconds */
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
#ifndef HAVE_BBMACROS
|
||||||
|
/*
|
||||||
|
* Block I/O parameterization. A basic block (BB) is the lowest size of
|
@ -0,0 +1,53 @@
|
|||||||
|
From c0e580154e1469f1bcef132b1a7585409f66e1e5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Tue, 10 Nov 2020 14:52:31 -0500
|
||||||
|
Subject: [PATCH] libxfs: refactor NSEC_PER_SEC
|
||||||
|
|
||||||
|
Clean up all the open-coded and duplicate definitions of time unit
|
||||||
|
conversion factors.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
NOTE: scrub is not present in rhel8, so that hunk is omitted
|
||||||
|
|
||||||
|
diff --git a/include/platform_defs.h.in b/include/platform_defs.h.in
|
||||||
|
index d111ec6..0b7214e 100644
|
||||||
|
--- a/include/platform_defs.h.in
|
||||||
|
+++ b/include/platform_defs.h.in
|
||||||
|
@@ -77,4 +77,7 @@ typedef unsigned short umode_t;
|
||||||
|
# define ASSERT(EX) ((void) 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#define NSEC_PER_SEC (1000000000ULL)
|
||||||
|
+#define NSEC_PER_USEC (1000ULL)
|
||||||
|
+
|
||||||
|
#endif /* __XFS_PLATFORM_DEFS_H__ */
|
||||||
|
diff --git a/repair/dinode.c b/repair/dinode.c
|
||||||
|
index 77f78f1..8fa5f88 100644
|
||||||
|
--- a/repair/dinode.c
|
||||||
|
+++ b/repair/dinode.c
|
||||||
|
@@ -2216,7 +2216,7 @@ check_nsec(
|
||||||
|
struct xfs_timestamp *t,
|
||||||
|
int *dirty)
|
||||||
|
{
|
||||||
|
- if (be32_to_cpu(t->t_nsec) < 1000000000)
|
||||||
|
+ if (be32_to_cpu(t->t_nsec) < NSEC_PER_SEC)
|
||||||
|
return;
|
||||||
|
|
||||||
|
do_warn(
|
||||||
|
diff --git a/scrub/progress.c b/scrub/progress.c
|
||||||
|
index d0afe90..2058f59 100644
|
||||||
|
--- a/scrub/progress.c
|
||||||
|
+++ b/scrub/progress.c
|
||||||
|
@@ -110,7 +110,6 @@ progress_report(
|
||||||
|
fflush(pt.fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
-#define NSEC_PER_SEC (1000000000)
|
||||||
|
static void *
|
||||||
|
progress_report_thread(void *arg)
|
||||||
|
{
|
@ -0,0 +1,139 @@
|
|||||||
|
From 9eb0d6eb9066daa621e710139c8c8d50fedbabcf Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 20 Nov 2020 17:03:27 -0500
|
||||||
|
Subject: [PATCH] mkfs: enable the inode btree counter feature
|
||||||
|
|
||||||
|
Teach mkfs how to enable the inode btree counter feature.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Brian Foster <bfoster@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8
|
||||||
|
index 9d6f315..45b150f 100644
|
||||||
|
--- a/man/man8/mkfs.xfs.8
|
||||||
|
+++ b/man/man8/mkfs.xfs.8
|
||||||
|
@@ -188,6 +188,21 @@ option set. When the option
|
||||||
|
.B \-m crc=0
|
||||||
|
is used, the free inode btree feature is not supported and is disabled.
|
||||||
|
.TP
|
||||||
|
+.BI inobtcount= value
|
||||||
|
+This option causes the filesystem to record the number of blocks used by
|
||||||
|
+the inode btree and the free inode btree.
|
||||||
|
+This can be used to reduce mount times when the free inode btree is enabled.
|
||||||
|
+.IP
|
||||||
|
+By default,
|
||||||
|
+.B mkfs.xfs
|
||||||
|
+will not enable this option.
|
||||||
|
+This feature is only available for filesystems created with the (default)
|
||||||
|
+.B \-m finobt=1
|
||||||
|
+option set.
|
||||||
|
+When the option
|
||||||
|
+.B \-m finobt=0
|
||||||
|
+is used, the inode btree counter feature is not supported and is disabled.
|
||||||
|
+.TP
|
||||||
|
.BI uuid= value
|
||||||
|
Use the given value as the filesystem UUID for the newly created filesystem.
|
||||||
|
The default is to generate a random UUID.
|
||||||
|
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
|
||||||
|
index 16819d8..87f15f4 100644
|
||||||
|
--- a/mkfs/xfs_mkfs.c
|
||||||
|
+++ b/mkfs/xfs_mkfs.c
|
||||||
|
@@ -117,6 +117,7 @@ enum {
|
||||||
|
M_UUID,
|
||||||
|
M_RMAPBT,
|
||||||
|
M_REFLINK,
|
||||||
|
+ M_INOBTCNT,
|
||||||
|
M_MAX_OPTS,
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -651,6 +652,7 @@ static struct opt_params mopts = {
|
||||||
|
[M_UUID] = "uuid",
|
||||||
|
[M_RMAPBT] = "rmapbt",
|
||||||
|
[M_REFLINK] = "reflink",
|
||||||
|
+ [M_INOBTCNT] = "inobtcount",
|
||||||
|
},
|
||||||
|
.subopt_params = {
|
||||||
|
{ .index = M_CRC,
|
||||||
|
@@ -681,6 +683,12 @@ static struct opt_params mopts = {
|
||||||
|
.maxval = 1,
|
||||||
|
.defaultval = 1,
|
||||||
|
},
|
||||||
|
+ { .index = M_INOBTCNT,
|
||||||
|
+ .conflicts = { { NULL, LAST_CONFLICT } },
|
||||||
|
+ .minval = 0,
|
||||||
|
+ .maxval = 1,
|
||||||
|
+ .defaultval = 1,
|
||||||
|
+ },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -731,6 +739,7 @@ struct sb_feat_args {
|
||||||
|
bool spinodes; /* XFS_SB_FEAT_INCOMPAT_SPINODES */
|
||||||
|
bool rmapbt; /* XFS_SB_FEAT_RO_COMPAT_RMAPBT */
|
||||||
|
bool reflink; /* XFS_SB_FEAT_RO_COMPAT_REFLINK */
|
||||||
|
+ bool inobtcnt; /* XFS_SB_FEAT_RO_COMPAT_INOBTCNT */
|
||||||
|
bool nodalign;
|
||||||
|
bool nortalign;
|
||||||
|
};
|
||||||
|
@@ -853,7 +862,8 @@ usage( void )
|
||||||
|
{
|
||||||
|
fprintf(stderr, _("Usage: %s\n\
|
||||||
|
/* blocksize */ [-b size=num]\n\
|
||||||
|
-/* metadata */ [-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1]\n\
|
||||||
|
+/* metadata */ [-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1,\n\
|
||||||
|
+ inobtcnt=0|1]\n\
|
||||||
|
/* data subvol */ [-d agcount=n,agsize=n,file,name=xxx,size=num,\n\
|
||||||
|
(sunit=value,swidth=value|su=num,sw=num|noalign),\n\
|
||||||
|
sectsize=num\n\
|
||||||
|
@@ -1607,6 +1617,9 @@ meta_opts_parser(
|
||||||
|
case M_REFLINK:
|
||||||
|
cli->sb_feat.reflink = getnum(value, opts, subopt);
|
||||||
|
break;
|
||||||
|
+ case M_INOBTCNT:
|
||||||
|
+ cli->sb_feat.inobtcnt = getnum(value, opts, subopt);
|
||||||
|
+ break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
@@ -2037,6 +2050,22 @@ _("reflink not supported without CRC support\n"));
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
cli->sb_feat.reflink = false;
|
||||||
|
+
|
||||||
|
+ if (cli->sb_feat.inobtcnt && cli_opt_set(&mopts, M_INOBTCNT)) {
|
||||||
|
+ fprintf(stderr,
|
||||||
|
+_("inode btree counters not supported without CRC support\n"));
|
||||||
|
+ usage();
|
||||||
|
+ }
|
||||||
|
+ cli->sb_feat.inobtcnt = false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!cli->sb_feat.finobt) {
|
||||||
|
+ if (cli->sb_feat.inobtcnt && cli_opt_set(&mopts, M_INOBTCNT)) {
|
||||||
|
+ fprintf(stderr,
|
||||||
|
+_("inode btree counters not supported without finobt support\n"));
|
||||||
|
+ usage();
|
||||||
|
+ }
|
||||||
|
+ cli->sb_feat.inobtcnt = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cli->fsx.fsx_xflags & FS_XFLAG_COWEXTSIZE) &&
|
||||||
|
@@ -3002,6 +3031,8 @@ sb_set_features(
|
||||||
|
sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_RMAPBT;
|
||||||
|
if (fp->reflink)
|
||||||
|
sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_REFLINK;
|
||||||
|
+ if (fp->inobtcnt)
|
||||||
|
+ sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_INOBTCNT;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sparse inode chunk support has two main inode alignment requirements.
|
||||||
|
@@ -3917,6 +3948,7 @@ main(
|
||||||
|
.spinodes = true,
|
||||||
|
.rmapbt = false,
|
||||||
|
.reflink = true,
|
||||||
|
+ .inobtcnt = false,
|
||||||
|
.parent_pointers = false,
|
||||||
|
.nodalign = false,
|
||||||
|
.nortalign = false,
|
@ -0,0 +1,130 @@
|
|||||||
|
From e9601810beb7d5b36a5fbd03c593cf63f685bfff Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 20 Nov 2020 17:03:28 -0500
|
||||||
|
Subject: [PATCH] mkfs: format bigtime filesystems
|
||||||
|
|
||||||
|
Allow formatting with large timestamps.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8
|
||||||
|
index 45b150f..0a115cb 100644
|
||||||
|
--- a/man/man8/mkfs.xfs.8
|
||||||
|
+++ b/man/man8/mkfs.xfs.8
|
||||||
|
@@ -154,6 +154,22 @@ valid
|
||||||
|
are:
|
||||||
|
.RS 1.2i
|
||||||
|
.TP
|
||||||
|
+.BI bigtime= value
|
||||||
|
+This option enables filesystems that can handle inode timestamps from December
|
||||||
|
+1901 to July 2486, and quota timer expirations from January 1970 to July 2486.
|
||||||
|
+The value is either 0 to disable the feature, or 1 to enable large timestamps.
|
||||||
|
+.IP
|
||||||
|
+If this feature is not enabled, the filesystem can only handle timestamps from
|
||||||
|
+December 1901 to January 2038, and quota timers from January 1970 to February
|
||||||
|
+2106.
|
||||||
|
+.IP
|
||||||
|
+By default,
|
||||||
|
+.B mkfs.xfs
|
||||||
|
+will not enable this feature.
|
||||||
|
+If the option
|
||||||
|
+.B \-m crc=0
|
||||||
|
+is used, the large timestamp feature is not supported and is disabled.
|
||||||
|
+.TP
|
||||||
|
.BI crc= value
|
||||||
|
This is used to create a filesystem which maintains and checks CRC information
|
||||||
|
in all metadata objects on disk. The value is either 0 to disable the feature,
|
||||||
|
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
|
||||||
|
index 87f15f4..b74a00b 100644
|
||||||
|
--- a/mkfs/xfs_mkfs.c
|
||||||
|
+++ b/mkfs/xfs_mkfs.c
|
||||||
|
@@ -118,6 +118,7 @@ enum {
|
||||||
|
M_RMAPBT,
|
||||||
|
M_REFLINK,
|
||||||
|
M_INOBTCNT,
|
||||||
|
+ M_BIGTIME,
|
||||||
|
M_MAX_OPTS,
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -653,6 +654,7 @@ static struct opt_params mopts = {
|
||||||
|
[M_RMAPBT] = "rmapbt",
|
||||||
|
[M_REFLINK] = "reflink",
|
||||||
|
[M_INOBTCNT] = "inobtcount",
|
||||||
|
+ [M_BIGTIME] = "bigtime",
|
||||||
|
},
|
||||||
|
.subopt_params = {
|
||||||
|
{ .index = M_CRC,
|
||||||
|
@@ -689,6 +691,12 @@ static struct opt_params mopts = {
|
||||||
|
.maxval = 1,
|
||||||
|
.defaultval = 1,
|
||||||
|
},
|
||||||
|
+ { .index = M_BIGTIME,
|
||||||
|
+ .conflicts = { { NULL, LAST_CONFLICT } },
|
||||||
|
+ .minval = 0,
|
||||||
|
+ .maxval = 1,
|
||||||
|
+ .defaultval = 1,
|
||||||
|
+ },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -740,6 +748,7 @@ struct sb_feat_args {
|
||||||
|
bool rmapbt; /* XFS_SB_FEAT_RO_COMPAT_RMAPBT */
|
||||||
|
bool reflink; /* XFS_SB_FEAT_RO_COMPAT_REFLINK */
|
||||||
|
bool inobtcnt; /* XFS_SB_FEAT_RO_COMPAT_INOBTCNT */
|
||||||
|
+ bool bigtime; /* XFS_SB_FEAT_INCOMPAT_BIGTIME */
|
||||||
|
bool nodalign;
|
||||||
|
bool nortalign;
|
||||||
|
};
|
||||||
|
@@ -863,7 +872,7 @@ usage( void )
|
||||||
|
fprintf(stderr, _("Usage: %s\n\
|
||||||
|
/* blocksize */ [-b size=num]\n\
|
||||||
|
/* metadata */ [-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1,\n\
|
||||||
|
- inobtcnt=0|1]\n\
|
||||||
|
+ inobtcnt=0|1,bigtime=0|1]\n\
|
||||||
|
/* data subvol */ [-d agcount=n,agsize=n,file,name=xxx,size=num,\n\
|
||||||
|
(sunit=value,swidth=value|su=num,sw=num|noalign),\n\
|
||||||
|
sectsize=num\n\
|
||||||
|
@@ -1620,6 +1629,9 @@ meta_opts_parser(
|
||||||
|
case M_INOBTCNT:
|
||||||
|
cli->sb_feat.inobtcnt = getnum(value, opts, subopt);
|
||||||
|
break;
|
||||||
|
+ case M_BIGTIME:
|
||||||
|
+ cli->sb_feat.bigtime = getnum(value, opts, subopt);
|
||||||
|
+ break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
@@ -2057,6 +2069,13 @@ _("inode btree counters not supported without CRC support\n"));
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
cli->sb_feat.inobtcnt = false;
|
||||||
|
+
|
||||||
|
+ if (cli->sb_feat.bigtime && cli_opt_set(&mopts, M_BIGTIME)) {
|
||||||
|
+ fprintf(stderr,
|
||||||
|
+_("timestamps later than 2038 not supported without CRC support\n"));
|
||||||
|
+ usage();
|
||||||
|
+ }
|
||||||
|
+ cli->sb_feat.bigtime = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cli->sb_feat.finobt) {
|
||||||
|
@@ -3033,6 +3052,8 @@ sb_set_features(
|
||||||
|
sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_REFLINK;
|
||||||
|
if (fp->inobtcnt)
|
||||||
|
sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_INOBTCNT;
|
||||||
|
+ if (fp->bigtime)
|
||||||
|
+ sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_BIGTIME;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sparse inode chunk support has two main inode alignment requirements.
|
||||||
|
@@ -3952,6 +3973,7 @@ main(
|
||||||
|
.parent_pointers = false,
|
||||||
|
.nodalign = false,
|
||||||
|
.nortalign = false,
|
||||||
|
+ .bigtime = false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,32 @@
|
|||||||
|
From cac80700d88a32c1835cb37f982e98ddd73021e5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 20 Nov 2020 17:03:28 -0500
|
||||||
|
Subject: [PATCH] xfs: enable big timestamps
|
||||||
|
|
||||||
|
Source kernel commit: 29887a22713192509cfc6068ea3b200cdb8856da
|
||||||
|
|
||||||
|
Enable the big timestamp feature.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
|
||||||
|
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Reviewed-by: Gao Xiang <hsiangkao@redhat.com>
|
||||||
|
Reviewed-by: Dave Chinner <dchinner@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
|
||||||
|
index 4848de8..722c9de 100644
|
||||||
|
--- a/libxfs/xfs_format.h
|
||||||
|
+++ b/libxfs/xfs_format.h
|
||||||
|
@@ -471,7 +471,8 @@ xfs_sb_has_ro_compat_feature(
|
||||||
|
#define XFS_SB_FEAT_INCOMPAT_ALL \
|
||||||
|
(XFS_SB_FEAT_INCOMPAT_FTYPE| \
|
||||||
|
XFS_SB_FEAT_INCOMPAT_SPINODES| \
|
||||||
|
- XFS_SB_FEAT_INCOMPAT_META_UUID)
|
||||||
|
+ XFS_SB_FEAT_INCOMPAT_META_UUID| \
|
||||||
|
+ XFS_SB_FEAT_INCOMPAT_BIGTIME)
|
||||||
|
|
||||||
|
#define XFS_SB_FEAT_INCOMPAT_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_ALL
|
||||||
|
static inline bool
|
@ -0,0 +1,28 @@
|
|||||||
|
From 46da703382fa31bb02049a4131602f8a40002dbb Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 20 Nov 2020 17:03:27 -0500
|
||||||
|
Subject: [PATCH] xfs: enable new inode btree counters feature
|
||||||
|
|
||||||
|
Source kernel commit: b896a39faa5a2f97dadfb347928466afb12cc63a
|
||||||
|
|
||||||
|
Enable the new inode btree counters feature.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Brian Foster <bfoster@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
|
||||||
|
index 9ba65e5..4848de8 100644
|
||||||
|
--- a/libxfs/xfs_format.h
|
||||||
|
+++ b/libxfs/xfs_format.h
|
||||||
|
@@ -453,7 +453,8 @@ xfs_sb_has_compat_feature(
|
||||||
|
#define XFS_SB_FEAT_RO_COMPAT_ALL \
|
||||||
|
(XFS_SB_FEAT_RO_COMPAT_FINOBT | \
|
||||||
|
XFS_SB_FEAT_RO_COMPAT_RMAPBT | \
|
||||||
|
- XFS_SB_FEAT_RO_COMPAT_REFLINK)
|
||||||
|
+ XFS_SB_FEAT_RO_COMPAT_REFLINK| \
|
||||||
|
+ XFS_SB_FEAT_RO_COMPAT_INOBTCNT)
|
||||||
|
#define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL
|
||||||
|
static inline bool
|
||||||
|
xfs_sb_has_ro_compat_feature(
|
@ -0,0 +1,74 @@
|
|||||||
|
From 18e3b8c234fac67c6c96e9ff34f0ab4598220fa1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Tue, 10 Nov 2020 15:11:09 -0500
|
||||||
|
Subject: [PATCH] xfs: explicitly define inode timestamp range
|
||||||
|
|
||||||
|
Source kernel commit: 876fdc7c4f366a709ac272ef3336ae7dce58f2af
|
||||||
|
|
||||||
|
Formally define the inode timestamp ranges that existing filesystems
|
||||||
|
support, and switch the vfs timetamp ranges to use it.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
|
||||||
|
Reviewed-by: Gao Xiang <hsiangkao@redhat.com>
|
||||||
|
Reviewed-by: Dave Chinner <dchinner@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
NOTE: we hvae no xfs_compat.h so S32_MAX etc went in xfs_fs.h
|
||||||
|
|
||||||
|
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
|
||||||
|
index 7f7b03a..5712aa0 100644
|
||||||
|
--- a/libxfs/xfs_format.h
|
||||||
|
+++ b/libxfs/xfs_format.h
|
||||||
|
@@ -839,11 +839,33 @@ typedef struct xfs_agfl {
|
||||||
|
ASSERT(xfs_daddr_to_agno(mp, d) == \
|
||||||
|
xfs_daddr_to_agno(mp, (d) + (len) - 1)))
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * XFS Timestamps
|
||||||
|
+ * ==============
|
||||||
|
+ *
|
||||||
|
+ * Traditional ondisk inode timestamps consist of signed 32-bit counters for
|
||||||
|
+ * seconds and nanoseconds; time zero is the Unix epoch, Jan 1 00:00:00 UTC
|
||||||
|
+ * 1970, which means that the timestamp epoch is the same as the Unix epoch.
|
||||||
|
+ * Therefore, the ondisk min and max defined here can be used directly to
|
||||||
|
+ * constrain the incore timestamps on a Unix system.
|
||||||
|
+ */
|
||||||
|
typedef struct xfs_timestamp {
|
||||||
|
__be32 t_sec; /* timestamp seconds */
|
||||||
|
__be32 t_nsec; /* timestamp nanoseconds */
|
||||||
|
} xfs_timestamp_t;
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Smallest possible ondisk seconds value with traditional timestamps. This
|
||||||
|
+ * corresponds exactly with the incore timestamp Dec 13 20:45:52 UTC 1901.
|
||||||
|
+ */
|
||||||
|
+#define XFS_LEGACY_TIME_MIN ((int64_t)S32_MIN)
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Largest possible ondisk seconds value with traditional timestamps. This
|
||||||
|
+ * corresponds exactly with the incore timestamp Jan 19 03:14:07 UTC 2038.
|
||||||
|
+ */
|
||||||
|
+#define XFS_LEGACY_TIME_MAX ((int64_t)S32_MAX)
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* On-disk inode structure.
|
||||||
|
*
|
||||||
|
diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h
|
||||||
|
index fbc9031..4fa9852 100644
|
||||||
|
--- a/libxfs/xfs_fs.h
|
||||||
|
+++ b/libxfs/xfs_fs.h
|
||||||
|
@@ -694,6 +694,10 @@ struct timespec64 {
|
||||||
|
long tv_nsec; /* nanoseconds */
|
||||||
|
};
|
||||||
|
|
||||||
|
+#define U32_MAX ((uint32_t)~0U)
|
||||||
|
+#define S32_MAX ((int32_t)(U32_MAX >> 1))
|
||||||
|
+#define S32_MIN ((int32_t)(-S32_MAX - 1))
|
||||||
|
+
|
||||||
|
#ifndef HAVE_BBMACROS
|
||||||
|
/*
|
||||||
|
* Block I/O parameterization. A basic block (BB) is the lowest size of
|
@ -0,0 +1,94 @@
|
|||||||
|
From acaa814953273827f380262ba900f0d50a95bee2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Tue, 10 Nov 2020 15:13:50 -0500
|
||||||
|
Subject: [PATCH] xfs: move xfs_log_dinode_to_disk to the log recovery code
|
||||||
|
|
||||||
|
Source kernel commit: 88947ea0ba713c9b74b212755b3b58242f0e7a56
|
||||||
|
|
||||||
|
Move this function to xfs_inode_item_recover.c since there's only one
|
||||||
|
caller of it.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
|
||||||
|
Reviewed-by: Gao Xiang <hsiangkao@redhat.com>
|
||||||
|
Reviewed-by: Dave Chinner <dchinner@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
|
||||||
|
index 975f097..f80ce10 100644
|
||||||
|
--- a/libxfs/xfs_inode_buf.c
|
||||||
|
+++ b/libxfs/xfs_inode_buf.c
|
||||||
|
@@ -318,58 +318,6 @@ xfs_inode_to_disk(
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-void
|
||||||
|
-xfs_log_dinode_to_disk(
|
||||||
|
- struct xfs_log_dinode *from,
|
||||||
|
- struct xfs_dinode *to)
|
||||||
|
-{
|
||||||
|
- to->di_magic = cpu_to_be16(from->di_magic);
|
||||||
|
- to->di_mode = cpu_to_be16(from->di_mode);
|
||||||
|
- to->di_version = from->di_version;
|
||||||
|
- to->di_format = from->di_format;
|
||||||
|
- to->di_onlink = 0;
|
||||||
|
- to->di_uid = cpu_to_be32(from->di_uid);
|
||||||
|
- to->di_gid = cpu_to_be32(from->di_gid);
|
||||||
|
- to->di_nlink = cpu_to_be32(from->di_nlink);
|
||||||
|
- to->di_projid_lo = cpu_to_be16(from->di_projid_lo);
|
||||||
|
- to->di_projid_hi = cpu_to_be16(from->di_projid_hi);
|
||||||
|
- memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad));
|
||||||
|
-
|
||||||
|
- to->di_atime.t_sec = cpu_to_be32(from->di_atime.t_sec);
|
||||||
|
- to->di_atime.t_nsec = cpu_to_be32(from->di_atime.t_nsec);
|
||||||
|
- to->di_mtime.t_sec = cpu_to_be32(from->di_mtime.t_sec);
|
||||||
|
- to->di_mtime.t_nsec = cpu_to_be32(from->di_mtime.t_nsec);
|
||||||
|
- to->di_ctime.t_sec = cpu_to_be32(from->di_ctime.t_sec);
|
||||||
|
- to->di_ctime.t_nsec = cpu_to_be32(from->di_ctime.t_nsec);
|
||||||
|
-
|
||||||
|
- to->di_size = cpu_to_be64(from->di_size);
|
||||||
|
- to->di_nblocks = cpu_to_be64(from->di_nblocks);
|
||||||
|
- to->di_extsize = cpu_to_be32(from->di_extsize);
|
||||||
|
- to->di_nextents = cpu_to_be32(from->di_nextents);
|
||||||
|
- to->di_anextents = cpu_to_be16(from->di_anextents);
|
||||||
|
- to->di_forkoff = from->di_forkoff;
|
||||||
|
- to->di_aformat = from->di_aformat;
|
||||||
|
- to->di_dmevmask = cpu_to_be32(from->di_dmevmask);
|
||||||
|
- to->di_dmstate = cpu_to_be16(from->di_dmstate);
|
||||||
|
- to->di_flags = cpu_to_be16(from->di_flags);
|
||||||
|
- to->di_gen = cpu_to_be32(from->di_gen);
|
||||||
|
-
|
||||||
|
- if (from->di_version == 3) {
|
||||||
|
- to->di_changecount = cpu_to_be64(from->di_changecount);
|
||||||
|
- to->di_crtime.t_sec = cpu_to_be32(from->di_crtime.t_sec);
|
||||||
|
- to->di_crtime.t_nsec = cpu_to_be32(from->di_crtime.t_nsec);
|
||||||
|
- to->di_flags2 = cpu_to_be64(from->di_flags2);
|
||||||
|
- to->di_cowextsize = cpu_to_be32(from->di_cowextsize);
|
||||||
|
- to->di_ino = cpu_to_be64(from->di_ino);
|
||||||
|
- to->di_lsn = cpu_to_be64(from->di_lsn);
|
||||||
|
- memcpy(to->di_pad2, from->di_pad2, sizeof(to->di_pad2));
|
||||||
|
- uuid_copy(&to->di_uuid, &from->di_uuid);
|
||||||
|
- to->di_flushiter = 0;
|
||||||
|
- } else {
|
||||||
|
- to->di_flushiter = cpu_to_be16(from->di_flushiter);
|
||||||
|
- }
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static xfs_failaddr_t
|
||||||
|
xfs_dinode_verify_fork(
|
||||||
|
struct xfs_dinode *dip,
|
||||||
|
diff --git a/libxfs/xfs_inode_buf.h b/libxfs/xfs_inode_buf.h
|
||||||
|
index c9ac69c..0343368 100644
|
||||||
|
--- a/libxfs/xfs_inode_buf.h
|
||||||
|
+++ b/libxfs/xfs_inode_buf.h
|
||||||
|
@@ -59,8 +59,6 @@ void xfs_dinode_calc_crc(struct xfs_mount *, struct xfs_dinode *);
|
||||||
|
void xfs_inode_to_disk(struct xfs_inode *ip, struct xfs_dinode *to,
|
||||||
|
xfs_lsn_t lsn);
|
||||||
|
void xfs_inode_from_disk(struct xfs_inode *ip, struct xfs_dinode *from);
|
||||||
|
-void xfs_log_dinode_to_disk(struct xfs_log_dinode *from,
|
||||||
|
- struct xfs_dinode *to);
|
||||||
|
|
||||||
|
bool xfs_dinode_good_version(struct xfs_mount *mp, __u8 version);
|
||||||
|
|
@ -0,0 +1,101 @@
|
|||||||
|
From fc3e21db4a30d0d81158938cabba0fb59fc57ad8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Wed, 11 Nov 2020 13:48:47 -0500
|
||||||
|
Subject: [PATCH] xfs: redefine xfs_ictimestamp_t
|
||||||
|
|
||||||
|
Source kernel commit: 30e05599219f3c15bd5f24190af0e33cdb4a00e5
|
||||||
|
|
||||||
|
Redefine xfs_ictimestamp_t as a uint64_t typedef in preparation for the
|
||||||
|
bigtime functionality. Preserve the legacy structure format so that we
|
||||||
|
can let the compiler take care of the masking and shifting.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Reviewed-by: Gao Xiang <hsiangkao@redhat.com>
|
||||||
|
Reviewed-by: Dave Chinner <dchinner@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/libxfs/xfs_log_format.h b/libxfs/xfs_log_format.h
|
||||||
|
index e5f97c6..8dc0df0 100644
|
||||||
|
--- a/libxfs/xfs_log_format.h
|
||||||
|
+++ b/libxfs/xfs_log_format.h
|
||||||
|
@@ -368,10 +368,13 @@ static inline int xfs_ilog_fdata(int w)
|
||||||
|
* directly mirrors the xfs_dinode structure as it must contain all the same
|
||||||
|
* information.
|
||||||
|
*/
|
||||||
|
-typedef struct xfs_ictimestamp {
|
||||||
|
+typedef uint64_t xfs_ictimestamp_t;
|
||||||
|
+
|
||||||
|
+/* Legacy timestamp encoding format. */
|
||||||
|
+struct xfs_legacy_ictimestamp {
|
||||||
|
int32_t t_sec; /* timestamp seconds */
|
||||||
|
int32_t t_nsec; /* timestamp nanoseconds */
|
||||||
|
-} xfs_ictimestamp_t;
|
||||||
|
+};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the format of the inode core that is logged. This structure must be
|
||||||
|
diff --git a/logprint/log_misc.c b/logprint/log_misc.c
|
||||||
|
index c325f04..4fad82b 100644
|
||||||
|
--- a/logprint/log_misc.c
|
||||||
|
+++ b/logprint/log_misc.c
|
||||||
|
@@ -446,8 +446,10 @@ xlog_print_trans_inode_core(
|
||||||
|
(int)ip->di_format);
|
||||||
|
printf(_("nlink %hd uid %d gid %d\n"),
|
||||||
|
ip->di_nlink, ip->di_uid, ip->di_gid);
|
||||||
|
- printf(_("atime 0x%x mtime 0x%x ctime 0x%x\n"),
|
||||||
|
- ip->di_atime.t_sec, ip->di_mtime.t_sec, ip->di_ctime.t_sec);
|
||||||
|
+ printf(_("atime 0x%llx mtime 0x%llx ctime 0x%llx\n"),
|
||||||
|
+ xlog_extract_dinode_ts(ip->di_atime),
|
||||||
|
+ xlog_extract_dinode_ts(ip->di_mtime),
|
||||||
|
+ xlog_extract_dinode_ts(ip->di_ctime));
|
||||||
|
printf(_("size 0x%llx nblocks 0x%llx extsize 0x%x nextents 0x%x\n"),
|
||||||
|
(unsigned long long)ip->di_size, (unsigned long long)ip->di_nblocks,
|
||||||
|
ip->di_extsize, ip->di_nextents);
|
||||||
|
@@ -739,6 +741,16 @@ xlog_print_trans_icreate(
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
+time64_t
|
||||||
|
+xlog_extract_dinode_ts(
|
||||||
|
+ const xfs_ictimestamp_t its)
|
||||||
|
+{
|
||||||
|
+ struct xfs_legacy_ictimestamp *lits;
|
||||||
|
+
|
||||||
|
+ lits = (struct xfs_legacy_ictimestamp *)&its;
|
||||||
|
+ return (time64_t)lits->t_sec;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void
|
||||||
|
xlog_print_lseek(struct xlog *log, int fd, xfs_daddr_t blkno, int whence)
|
||||||
|
{
|
||||||
|
diff --git a/logprint/log_print_all.c b/logprint/log_print_all.c
|
||||||
|
index eafffe2..3ca01b1 100644
|
||||||
|
--- a/logprint/log_print_all.c
|
||||||
|
+++ b/logprint/log_print_all.c
|
||||||
|
@@ -249,8 +249,10 @@ xlog_recover_print_inode_core(
|
||||||
|
printf(_(" uid:%d gid:%d nlink:%d projid:0x%04x%04x\n"),
|
||||||
|
di->di_uid, di->di_gid, di->di_nlink,
|
||||||
|
di->di_projid_hi, di->di_projid_lo);
|
||||||
|
- printf(_(" atime:%d mtime:%d ctime:%d\n"),
|
||||||
|
- di->di_atime.t_sec, di->di_mtime.t_sec, di->di_ctime.t_sec);
|
||||||
|
+ printf(_(" atime:%lld mtime:%lld ctime:%lld\n"),
|
||||||
|
+ xlog_extract_dinode_ts(di->di_atime),
|
||||||
|
+ xlog_extract_dinode_ts(di->di_mtime),
|
||||||
|
+ xlog_extract_dinode_ts(di->di_ctime));
|
||||||
|
printf(_(" flushiter:%d\n"), di->di_flushiter);
|
||||||
|
printf(_(" size:0x%llx nblks:0x%llx exsize:%d "
|
||||||
|
"nextents:%d anextents:%d\n"), (unsigned long long)
|
||||||
|
diff --git a/logprint/logprint.h b/logprint/logprint.h
|
||||||
|
index 98ac0d4..0061d5a 100644
|
||||||
|
--- a/logprint/logprint.h
|
||||||
|
+++ b/logprint/logprint.h
|
||||||
|
@@ -18,6 +18,7 @@ extern int print_no_data;
|
||||||
|
extern int print_no_print;
|
||||||
|
|
||||||
|
/* exports */
|
||||||
|
+extern time64_t xlog_extract_dinode_ts(const xfs_ictimestamp_t);
|
||||||
|
extern void xlog_print_lseek(struct xlog *, int, xfs_daddr_t, int);
|
||||||
|
|
||||||
|
extern void xfs_log_copy(struct xlog *, int, char *);
|
@ -0,0 +1,196 @@
|
|||||||
|
From a252aadfc977473e0851acf0d529c930c6e8e181 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Tue, 10 Nov 2020 16:29:40 -0500
|
||||||
|
Subject: [PATCH] xfs: redefine xfs_timestamp_t
|
||||||
|
|
||||||
|
Source kernel commit: 5a0bb066f60fa02f453d7721844eae59f505c06e
|
||||||
|
|
||||||
|
Redefine xfs_timestamp_t as a __be64 typedef in preparation for the
|
||||||
|
bigtime functionality. Preserve the legacy structure format so that we
|
||||||
|
can let the compiler take care of masking and shifting.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Reviewed-by: Gao Xiang <hsiangkao@redhat.com>
|
||||||
|
Reviewed-by: Dave Chinner <dchinner@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/db/field.c b/db/field.c
|
||||||
|
index 66fa37e..4a45c66 100644
|
||||||
|
--- a/db/field.c
|
||||||
|
+++ b/db/field.c
|
||||||
|
@@ -350,7 +350,7 @@ const ftattr_t ftattrtab[] = {
|
||||||
|
{ FLDT_TIME, "time", fp_time, NULL, SI(bitsz(int32_t)), FTARG_SIGNED,
|
||||||
|
NULL, NULL },
|
||||||
|
{ FLDT_TIMESTAMP, "timestamp", NULL, (char *)timestamp_flds,
|
||||||
|
- SI(bitsz(xfs_timestamp_t)), 0, NULL, timestamp_flds },
|
||||||
|
+ SI(bitsz(struct xfs_legacy_timestamp)), 0, NULL, timestamp_flds },
|
||||||
|
{ FLDT_UINT1, "uint1", fp_num, "%u", SI(1), 0, NULL, NULL },
|
||||||
|
{ FLDT_UINT16D, "uint16d", fp_num, "%u", SI(bitsz(uint16_t)), 0, NULL,
|
||||||
|
NULL },
|
||||||
|
diff --git a/db/inode.c b/db/inode.c
|
||||||
|
index 697f7fe..b308538 100644
|
||||||
|
--- a/db/inode.c
|
||||||
|
+++ b/db/inode.c
|
||||||
|
@@ -176,7 +176,7 @@ const field_t inode_v3_flds[] = {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
-#define TOFF(f) bitize(offsetof(xfs_timestamp_t, t_ ## f))
|
||||||
|
+#define TOFF(f) bitize(offsetof(struct xfs_legacy_timestamp, t_ ## f))
|
||||||
|
const field_t timestamp_flds[] = {
|
||||||
|
{ "sec", FLDT_TIME, OI(TOFF(sec)), C1, 0, TYP_NONE },
|
||||||
|
{ "nsec", FLDT_NSEC, OI(TOFF(nsec)), C1, 0, TYP_NONE },
|
||||||
|
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
|
||||||
|
index 8858341..371f5cd 100644
|
||||||
|
--- a/libxfs/xfs_format.h
|
||||||
|
+++ b/libxfs/xfs_format.h
|
||||||
|
@@ -847,12 +847,16 @@ typedef struct xfs_agfl {
|
||||||
|
* seconds and nanoseconds; time zero is the Unix epoch, Jan 1 00:00:00 UTC
|
||||||
|
* 1970, which means that the timestamp epoch is the same as the Unix epoch.
|
||||||
|
* Therefore, the ondisk min and max defined here can be used directly to
|
||||||
|
- * constrain the incore timestamps on a Unix system.
|
||||||
|
+ * constrain the incore timestamps on a Unix system. Note that we actually
|
||||||
|
+ * encode a __be64 value on disk.
|
||||||
|
*/
|
||||||
|
-typedef struct xfs_timestamp {
|
||||||
|
+typedef __be64 xfs_timestamp_t;
|
||||||
|
+
|
||||||
|
+/* Legacy timestamp encoding format. */
|
||||||
|
+struct xfs_legacy_timestamp {
|
||||||
|
__be32 t_sec; /* timestamp seconds */
|
||||||
|
__be32 t_nsec; /* timestamp nanoseconds */
|
||||||
|
-} xfs_timestamp_t;
|
||||||
|
+};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Smallest possible ondisk seconds value with traditional timestamps. This
|
||||||
|
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
|
||||||
|
index f80ce10..d8831a1 100644
|
||||||
|
--- a/libxfs/xfs_inode_buf.c
|
||||||
|
+++ b/libxfs/xfs_inode_buf.c
|
||||||
|
@@ -195,6 +195,21 @@ xfs_imap_to_bp(
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Convert an ondisk timestamp to an incore timestamp. */
|
||||||
|
+struct timespec64
|
||||||
|
+xfs_inode_from_disk_ts(
|
||||||
|
+ const xfs_timestamp_t ts)
|
||||||
|
+{
|
||||||
|
+ struct timespec64 tv;
|
||||||
|
+ struct xfs_legacy_timestamp *lts;
|
||||||
|
+
|
||||||
|
+ lts = (struct xfs_legacy_timestamp *)&ts;
|
||||||
|
+ tv.tv_sec = (int)be32_to_cpu(lts->t_sec);
|
||||||
|
+ tv.tv_nsec = (int)be32_to_cpu(lts->t_nsec);
|
||||||
|
+
|
||||||
|
+ return tv;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void
|
||||||
|
xfs_inode_from_disk(
|
||||||
|
struct xfs_inode *ip,
|
||||||
|
@@ -231,12 +246,10 @@ xfs_inode_from_disk(
|
||||||
|
* a time before epoch is converted to a time long after epoch
|
||||||
|
* on 64 bit systems.
|
||||||
|
*/
|
||||||
|
- inode->i_atime.tv_sec = (int)be32_to_cpu(from->di_atime.t_sec);
|
||||||
|
- inode->i_atime.tv_nsec = (int)be32_to_cpu(from->di_atime.t_nsec);
|
||||||
|
- inode->i_mtime.tv_sec = (int)be32_to_cpu(from->di_mtime.t_sec);
|
||||||
|
- inode->i_mtime.tv_nsec = (int)be32_to_cpu(from->di_mtime.t_nsec);
|
||||||
|
- inode->i_ctime.tv_sec = (int)be32_to_cpu(from->di_ctime.t_sec);
|
||||||
|
- inode->i_ctime.tv_nsec = (int)be32_to_cpu(from->di_ctime.t_nsec);
|
||||||
|
+ inode->i_atime = xfs_inode_from_disk_ts(from->di_atime);
|
||||||
|
+ inode->i_mtime = xfs_inode_from_disk_ts(from->di_mtime);
|
||||||
|
+ inode->i_ctime = xfs_inode_from_disk_ts(from->di_ctime);
|
||||||
|
+
|
||||||
|
inode->i_generation = be32_to_cpu(from->di_gen);
|
||||||
|
inode->i_mode = be16_to_cpu(from->di_mode);
|
||||||
|
|
||||||
|
@@ -254,13 +267,27 @@ xfs_inode_from_disk(
|
||||||
|
if (to->di_version == 3) {
|
||||||
|
inode_set_iversion_queried(inode,
|
||||||
|
be64_to_cpu(from->di_changecount));
|
||||||
|
- to->di_crtime.tv_sec = be32_to_cpu(from->di_crtime.t_sec);
|
||||||
|
- to->di_crtime.tv_nsec = be32_to_cpu(from->di_crtime.t_nsec);
|
||||||
|
+ to->di_crtime = xfs_inode_from_disk_ts(from->di_crtime);
|
||||||
|
to->di_flags2 = be64_to_cpu(from->di_flags2);
|
||||||
|
to->di_cowextsize = be32_to_cpu(from->di_cowextsize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Convert an incore timestamp to an ondisk timestamp. */
|
||||||
|
+static inline xfs_timestamp_t
|
||||||
|
+xfs_inode_to_disk_ts(
|
||||||
|
+ const struct timespec64 tv)
|
||||||
|
+{
|
||||||
|
+ struct xfs_legacy_timestamp *lts;
|
||||||
|
+ xfs_timestamp_t ts;
|
||||||
|
+
|
||||||
|
+ lts = (struct xfs_legacy_timestamp *)&ts;
|
||||||
|
+ lts->t_sec = cpu_to_be32(tv.tv_sec);
|
||||||
|
+ lts->t_nsec = cpu_to_be32(tv.tv_nsec);
|
||||||
|
+
|
||||||
|
+ return ts;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void
|
||||||
|
xfs_inode_to_disk(
|
||||||
|
struct xfs_inode *ip,
|
||||||
|
@@ -281,12 +308,9 @@ xfs_inode_to_disk(
|
||||||
|
to->di_projid_hi = cpu_to_be16(from->di_projid_hi);
|
||||||
|
|
||||||
|
memset(to->di_pad, 0, sizeof(to->di_pad));
|
||||||
|
- to->di_atime.t_sec = cpu_to_be32(inode->i_atime.tv_sec);
|
||||||
|
- to->di_atime.t_nsec = cpu_to_be32(inode->i_atime.tv_nsec);
|
||||||
|
- to->di_mtime.t_sec = cpu_to_be32(inode->i_mtime.tv_sec);
|
||||||
|
- to->di_mtime.t_nsec = cpu_to_be32(inode->i_mtime.tv_nsec);
|
||||||
|
- to->di_ctime.t_sec = cpu_to_be32(inode->i_ctime.tv_sec);
|
||||||
|
- to->di_ctime.t_nsec = cpu_to_be32(inode->i_ctime.tv_nsec);
|
||||||
|
+ to->di_atime = xfs_inode_to_disk_ts(inode->i_atime);
|
||||||
|
+ to->di_mtime = xfs_inode_to_disk_ts(inode->i_mtime);
|
||||||
|
+ to->di_ctime = xfs_inode_to_disk_ts(inode->i_ctime);
|
||||||
|
to->di_nlink = cpu_to_be32(inode->i_nlink);
|
||||||
|
to->di_gen = cpu_to_be32(inode->i_generation);
|
||||||
|
to->di_mode = cpu_to_be16(inode->i_mode);
|
||||||
|
@@ -304,8 +328,7 @@ xfs_inode_to_disk(
|
||||||
|
|
||||||
|
if (from->di_version == 3) {
|
||||||
|
to->di_changecount = cpu_to_be64(inode_peek_iversion(inode));
|
||||||
|
- to->di_crtime.t_sec = cpu_to_be32(from->di_crtime.tv_sec);
|
||||||
|
- to->di_crtime.t_nsec = cpu_to_be32(from->di_crtime.tv_nsec);
|
||||||
|
+ to->di_crtime = xfs_inode_to_disk_ts(from->di_crtime);
|
||||||
|
to->di_flags2 = cpu_to_be64(from->di_flags2);
|
||||||
|
to->di_cowextsize = cpu_to_be32(from->di_cowextsize);
|
||||||
|
to->di_ino = cpu_to_be64(ip->i_ino);
|
||||||
|
diff --git a/libxfs/xfs_inode_buf.h b/libxfs/xfs_inode_buf.h
|
||||||
|
index 0343368..6147f42 100644
|
||||||
|
--- a/libxfs/xfs_inode_buf.h
|
||||||
|
+++ b/libxfs/xfs_inode_buf.h
|
||||||
|
@@ -76,4 +76,6 @@ xfs_failaddr_t xfs_inode_validate_cowextsize(struct xfs_mount *mp,
|
||||||
|
uint32_t cowextsize, uint16_t mode, uint16_t flags,
|
||||||
|
uint64_t flags2);
|
||||||
|
|
||||||
|
+struct timespec64 xfs_inode_from_disk_ts(const xfs_timestamp_t ts);
|
||||||
|
+
|
||||||
|
#endif /* __XFS_INODE_BUF_H__ */
|
||||||
|
diff --git a/repair/dinode.c b/repair/dinode.c
|
||||||
|
index 8fa5f88..0c40f2a 100644
|
||||||
|
--- a/repair/dinode.c
|
||||||
|
+++ b/repair/dinode.c
|
||||||
|
@@ -2213,9 +2213,12 @@ static void
|
||||||
|
check_nsec(
|
||||||
|
const char *name,
|
||||||
|
xfs_ino_t lino,
|
||||||
|
- struct xfs_timestamp *t,
|
||||||
|
+ xfs_timestamp_t *ts,
|
||||||
|
int *dirty)
|
||||||
|
{
|
||||||
|
+ struct xfs_legacy_timestamp *t;
|
||||||
|
+
|
||||||
|
+ t = (struct xfs_legacy_timestamp *)ts;
|
||||||
|
if (be32_to_cpu(t->t_nsec) < NSEC_PER_SEC)
|
||||||
|
return;
|
||||||
|
|
@ -0,0 +1,49 @@
|
|||||||
|
From abc0f20536e3bc1505f575f452c55585c34f6e06 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Tue, 10 Nov 2020 15:11:43 -0500
|
||||||
|
Subject: [PATCH] xfs: refactor default quota grace period setting code
|
||||||
|
|
||||||
|
Source kernel commit: ccc8e771aa7a80eb047fc263780816ca76dd02a6
|
||||||
|
|
||||||
|
Refactor the code that sets the default quota grace period into a helper
|
||||||
|
function so that we can override the ondisk behavior later.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
|
||||||
|
Reviewed-by: Dave Chinner <dchinner@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
|
||||||
|
index c67bd61..8858341 100644
|
||||||
|
--- a/libxfs/xfs_format.h
|
||||||
|
+++ b/libxfs/xfs_format.h
|
||||||
|
@@ -1190,6 +1190,11 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev)
|
||||||
|
* been reached, and therefore no expiration has been set. Therefore, the
|
||||||
|
* ondisk min and max defined here can be used directly to constrain the incore
|
||||||
|
* quota expiration timestamps on a Unix system.
|
||||||
|
+ *
|
||||||
|
+ * The grace period for each quota type is stored in the root dquot (id = 0)
|
||||||
|
+ * and is applied to a non-root dquot when it exceeds the soft or hard limits.
|
||||||
|
+ * The length of quota grace periods are unsigned 32-bit quantities measured in
|
||||||
|
+ * units of seconds. A value of zero means to use the default period.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -1204,6 +1209,14 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev)
|
||||||
|
*/
|
||||||
|
#define XFS_DQ_LEGACY_EXPIRY_MAX ((int64_t)U32_MAX)
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Default quota grace periods, ranging from zero (use the compiled defaults)
|
||||||
|
+ * to ~136 years. These are applied to a non-root dquot that has exceeded
|
||||||
|
+ * either limit.
|
||||||
|
+ */
|
||||||
|
+#define XFS_DQ_GRACE_MIN ((int64_t)0)
|
||||||
|
+#define XFS_DQ_GRACE_MAX ((int64_t)U32_MAX)
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* This is the main portion of the on-disk representation of quota
|
||||||
|
* information for a user. This is the q_core of the xfs_dquot_t that
|
@ -0,0 +1,54 @@
|
|||||||
|
From 94c5482a7e0cbb6fd289745a4b5f49a133a4f5e8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Tue, 10 Nov 2020 15:11:09 -0500
|
||||||
|
Subject: [PATCH] xfs: refactor quota expiration timer modification
|
||||||
|
|
||||||
|
Source kernel commit: 11d8a9190275855f79d62093d789e962cc7228fb
|
||||||
|
|
||||||
|
Define explicit limits on the range of quota grace period expiration
|
||||||
|
timeouts and refactor the code that modifies the timeouts into helpers
|
||||||
|
that clamp the values appropriately. Note that we'll refactor the
|
||||||
|
default grace period timer separately.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
|
||||||
|
Reviewed-by: Dave Chinner <dchinner@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
|
||||||
|
index 5712aa0..c67bd61 100644
|
||||||
|
--- a/libxfs/xfs_format.h
|
||||||
|
+++ b/libxfs/xfs_format.h
|
||||||
|
@@ -1180,6 +1180,30 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev)
|
||||||
|
#define XFS_DQUOT_MAGIC 0x4451 /* 'DQ' */
|
||||||
|
#define XFS_DQUOT_VERSION (uint8_t)0x01 /* latest version number */
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * XFS Quota Timers
|
||||||
|
+ * ================
|
||||||
|
+ *
|
||||||
|
+ * Traditional quota grace period expiration timers are an unsigned 32-bit
|
||||||
|
+ * seconds counter; time zero is the Unix epoch, Jan 1 00:00:01 UTC 1970.
|
||||||
|
+ * Note that an expiration value of zero means that the quota limit has not
|
||||||
|
+ * been reached, and therefore no expiration has been set. Therefore, the
|
||||||
|
+ * ondisk min and max defined here can be used directly to constrain the incore
|
||||||
|
+ * quota expiration timestamps on a Unix system.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Smallest possible ondisk quota expiration value with traditional timestamps.
|
||||||
|
+ * This corresponds exactly with the incore expiration Jan 1 00:00:01 UTC 1970.
|
||||||
|
+ */
|
||||||
|
+#define XFS_DQ_LEGACY_EXPIRY_MIN ((int64_t)1)
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Largest possible ondisk quota expiration value with traditional timestamps.
|
||||||
|
+ * This corresponds exactly with the incore expiration Feb 7 06:28:15 UTC 2106.
|
||||||
|
+ */
|
||||||
|
+#define XFS_DQ_LEGACY_EXPIRY_MAX ((int64_t)U32_MAX)
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* This is the main portion of the on-disk representation of quota
|
||||||
|
* information for a user. This is the q_core of the xfs_dquot_t that
|
@ -0,0 +1,58 @@
|
|||||||
|
From 68879320b482e73e6ce202a8e680c8ab7e6a2af4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Tue, 10 Nov 2020 15:12:50 -0500
|
||||||
|
Subject: [PATCH] xfs: refactor quota timestamp coding
|
||||||
|
|
||||||
|
Source kernel commit: 9f99c8fe551a056c0929dff13cbce62b6b150156
|
||||||
|
|
||||||
|
Refactor quota timestamp encoding and decoding into helper functions so
|
||||||
|
that we can add extra behavior in the next patch.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
|
||||||
|
Reviewed-by: Dave Chinner <dchinner@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/libxfs/xfs_dquot_buf.c b/libxfs/xfs_dquot_buf.c
|
||||||
|
index 324f528..963f8ea 100644
|
||||||
|
--- a/libxfs/xfs_dquot_buf.c
|
||||||
|
+++ b/libxfs/xfs_dquot_buf.c
|
||||||
|
@@ -286,3 +286,21 @@ const struct xfs_buf_ops xfs_dquot_buf_ra_ops = {
|
||||||
|
.verify_read = xfs_dquot_buf_readahead_verify,
|
||||||
|
.verify_write = xfs_dquot_buf_write_verify,
|
||||||
|
};
|
||||||
|
+
|
||||||
|
+/* Convert an on-disk timer value into an incore timer value. */
|
||||||
|
+time64_t
|
||||||
|
+xfs_dquot_from_disk_ts(
|
||||||
|
+ struct xfs_disk_dquot *ddq,
|
||||||
|
+ __be32 dtimer)
|
||||||
|
+{
|
||||||
|
+ return be32_to_cpu(dtimer);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Convert an incore timer value into an on-disk timer value. */
|
||||||
|
+__be32
|
||||||
|
+xfs_dquot_to_disk_ts(
|
||||||
|
+ struct xfs_dquot *dqp,
|
||||||
|
+ time64_t timer)
|
||||||
|
+{
|
||||||
|
+ return cpu_to_be32(timer);
|
||||||
|
+}
|
||||||
|
diff --git a/libxfs/xfs_quota_defs.h b/libxfs/xfs_quota_defs.h
|
||||||
|
index c69dba4..2f61cd3 100644
|
||||||
|
--- a/libxfs/xfs_quota_defs.h
|
||||||
|
+++ b/libxfs/xfs_quota_defs.h
|
||||||
|
@@ -149,4 +149,9 @@ extern int xfs_calc_dquots_per_chunk(unsigned int nbblks);
|
||||||
|
extern int xfs_dqblk_repair(struct xfs_mount *mp, struct xfs_dqblk *dqb,
|
||||||
|
xfs_dqid_t id, uint type);
|
||||||
|
|
||||||
|
+struct xfs_dquot;
|
||||||
|
+time64_t xfs_dquot_from_disk_ts(struct xfs_disk_dquot *ddq,
|
||||||
|
+ __be32 dtimer);
|
||||||
|
+__be32 xfs_dquot_to_disk_ts(struct xfs_dquot *ddq, time64_t timer);
|
||||||
|
+
|
||||||
|
#endif /* __XFS_QUOTA_H__ */
|
@ -0,0 +1,159 @@
|
|||||||
|
From 177c81e25b763c90f9815b1f4055d9d5c515a845 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Tue, 10 Nov 2020 15:11:09 -0500
|
||||||
|
Subject: [PATCH] xfs: store inode btree block counts in AGI header
|
||||||
|
|
||||||
|
Source kernel commit: 2a39946c984464e4aac82c556ba9915589be7323
|
||||||
|
|
||||||
|
Add a btree block usage counters for both inode btrees to the AGI header
|
||||||
|
so that we don't have to walk the entire finobt at mount time to create
|
||||||
|
the per-AG reservations.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Brian Foster <bfoster@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
NOTE: kernel routines are not used to initialize AGIs in this
|
||||||
|
version, so I added to the open-coded function in xfs_mkfs.c
|
||||||
|
|
||||||
|
diff --git a/libxfs/xfs_ag.c b/libxfs/xfs_ag.c
|
||||||
|
index a7d1a0d..850d6e3 100644
|
||||||
|
--- a/libxfs/xfs_ag.c
|
||||||
|
+++ b/libxfs/xfs_ag.c
|
||||||
|
@@ -258,6 +258,11 @@ xfs_agiblock_init(
|
||||||
|
}
|
||||||
|
for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++)
|
||||||
|
agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO);
|
||||||
|
+ if (xfs_sb_version_hasinobtcounts(&mp->m_sb)) {
|
||||||
|
+ agi->agi_iblocks = cpu_to_be32(1);
|
||||||
|
+ if (xfs_sb_version_hasfinobt(&mp->m_sb))
|
||||||
|
+ agi->agi_fblocks = cpu_to_be32(1);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef void (*aghdr_init_work_f)(struct xfs_mount *mp, struct xfs_buf *bp,
|
||||||
|
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
|
||||||
|
index 23eca3b..7f7b03a 100644
|
||||||
|
--- a/libxfs/xfs_format.h
|
||||||
|
+++ b/libxfs/xfs_format.h
|
||||||
|
@@ -449,6 +449,7 @@ xfs_sb_has_compat_feature(
|
||||||
|
#define XFS_SB_FEAT_RO_COMPAT_FINOBT (1 << 0) /* free inode btree */
|
||||||
|
#define XFS_SB_FEAT_RO_COMPAT_RMAPBT (1 << 1) /* reverse map btree */
|
||||||
|
#define XFS_SB_FEAT_RO_COMPAT_REFLINK (1 << 2) /* reflinked files */
|
||||||
|
+#define XFS_SB_FEAT_RO_COMPAT_INOBTCNT (1 << 3) /* inobt block counts */
|
||||||
|
#define XFS_SB_FEAT_RO_COMPAT_ALL \
|
||||||
|
(XFS_SB_FEAT_RO_COMPAT_FINOBT | \
|
||||||
|
XFS_SB_FEAT_RO_COMPAT_RMAPBT | \
|
||||||
|
@@ -546,6 +547,17 @@ static inline bool xfs_sb_version_hasreflink(struct xfs_sb *sbp)
|
||||||
|
(sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_REFLINK);
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Inode btree block counter. We record the number of inobt and finobt blocks
|
||||||
|
+ * in the AGI header so that we can skip the finobt walk at mount time when
|
||||||
|
+ * setting up per-AG reservations.
|
||||||
|
+ */
|
||||||
|
+static inline bool xfs_sb_version_hasinobtcounts(struct xfs_sb *sbp)
|
||||||
|
+{
|
||||||
|
+ return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 &&
|
||||||
|
+ (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_INOBTCNT);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* end of superblock version macros
|
||||||
|
*/
|
||||||
|
@@ -750,6 +762,9 @@ typedef struct xfs_agi {
|
||||||
|
__be32 agi_free_root; /* root of the free inode btree */
|
||||||
|
__be32 agi_free_level;/* levels in free inode btree */
|
||||||
|
|
||||||
|
+ __be32 agi_iblocks; /* inobt blocks used */
|
||||||
|
+ __be32 agi_fblocks; /* finobt blocks used */
|
||||||
|
+
|
||||||
|
/* structure must be padded to 64 bit alignment */
|
||||||
|
} xfs_agi_t;
|
||||||
|
|
||||||
|
@@ -770,7 +785,8 @@ typedef struct xfs_agi {
|
||||||
|
#define XFS_AGI_ALL_BITS_R1 ((1 << XFS_AGI_NUM_BITS_R1) - 1)
|
||||||
|
#define XFS_AGI_FREE_ROOT (1 << 11)
|
||||||
|
#define XFS_AGI_FREE_LEVEL (1 << 12)
|
||||||
|
-#define XFS_AGI_NUM_BITS_R2 13
|
||||||
|
+#define XFS_AGI_IBLOCKS (1 << 13) /* both inobt/finobt block counters */
|
||||||
|
+#define XFS_AGI_NUM_BITS_R2 14
|
||||||
|
|
||||||
|
/* disk block (xfs_daddr_t) in the AG */
|
||||||
|
#define XFS_AGI_DADDR(mp) ((xfs_daddr_t)(2 << (mp)->m_sectbb_log))
|
||||||
|
diff --git a/libxfs/xfs_ialloc.c b/libxfs/xfs_ialloc.c
|
||||||
|
index a600c03..9d380f9 100644
|
||||||
|
--- a/libxfs/xfs_ialloc.c
|
||||||
|
+++ b/libxfs/xfs_ialloc.c
|
||||||
|
@@ -2451,6 +2451,7 @@ xfs_ialloc_log_agi(
|
||||||
|
offsetof(xfs_agi_t, agi_unlinked),
|
||||||
|
offsetof(xfs_agi_t, agi_free_root),
|
||||||
|
offsetof(xfs_agi_t, agi_free_level),
|
||||||
|
+ offsetof(xfs_agi_t, agi_iblocks),
|
||||||
|
sizeof(xfs_agi_t)
|
||||||
|
};
|
||||||
|
#ifdef DEBUG
|
||||||
|
diff --git a/libxfs/xfs_ialloc_btree.c b/libxfs/xfs_ialloc_btree.c
|
||||||
|
index 716a81f..9db87e9 100644
|
||||||
|
--- a/libxfs/xfs_ialloc_btree.c
|
||||||
|
+++ b/libxfs/xfs_ialloc_btree.c
|
||||||
|
@@ -68,6 +68,25 @@ xfs_finobt_set_root(
|
||||||
|
XFS_AGI_FREE_ROOT | XFS_AGI_FREE_LEVEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Update the inode btree block counter for this btree. */
|
||||||
|
+static inline void
|
||||||
|
+xfs_inobt_mod_blockcount(
|
||||||
|
+ struct xfs_btree_cur *cur,
|
||||||
|
+ int howmuch)
|
||||||
|
+{
|
||||||
|
+ struct xfs_buf *agbp = cur->bc_private.a.agbp;
|
||||||
|
+ struct xfs_agi *agi = agbp->b_addr;
|
||||||
|
+
|
||||||
|
+ if (!xfs_sb_version_hasinobtcounts(&cur->bc_mp->m_sb))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ if (cur->bc_btnum == XFS_BTNUM_FINO)
|
||||||
|
+ be32_add_cpu(&agi->agi_fblocks, howmuch);
|
||||||
|
+ else if (cur->bc_btnum == XFS_BTNUM_INO)
|
||||||
|
+ be32_add_cpu(&agi->agi_iblocks, howmuch);
|
||||||
|
+ xfs_ialloc_log_agi(cur->bc_tp, agbp, XFS_AGI_IBLOCKS);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
STATIC int
|
||||||
|
__xfs_inobt_alloc_block(
|
||||||
|
struct xfs_btree_cur *cur,
|
||||||
|
@@ -103,6 +122,7 @@ __xfs_inobt_alloc_block(
|
||||||
|
|
||||||
|
new->s = cpu_to_be32(XFS_FSB_TO_AGBNO(args.mp, args.fsbno));
|
||||||
|
*stat = 1;
|
||||||
|
+ xfs_inobt_mod_blockcount(cur, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -135,6 +155,7 @@ __xfs_inobt_free_block(
|
||||||
|
struct xfs_buf *bp,
|
||||||
|
enum xfs_ag_resv_type resv)
|
||||||
|
{
|
||||||
|
+ xfs_inobt_mod_blockcount(cur, -1);
|
||||||
|
return xfs_free_extent(cur->bc_tp,
|
||||||
|
XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp)), 1,
|
||||||
|
&XFS_RMAP_OINFO_INOBT, resv);
|
||||||
|
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
|
||||||
|
index 16819d8..992224d 100644
|
||||||
|
--- a/mkfs/xfs_mkfs.c
|
||||||
|
+++ b/mkfs/xfs_mkfs.c
|
||||||
|
@@ -3588,6 +3588,11 @@ initialise_ag_headers(
|
||||||
|
platform_uuid_copy(&agi->agi_uuid, &sbp->sb_uuid);
|
||||||
|
for (c = 0; c < XFS_AGI_UNLINKED_BUCKETS; c++)
|
||||||
|
agi->agi_unlinked[c] = cpu_to_be32(NULLAGINO);
|
||||||
|
+ if (xfs_sb_version_hasinobtcounts(&mp->m_sb)) {
|
||||||
|
+ agi->agi_iblocks = cpu_to_be32(1);
|
||||||
|
+ if (xfs_sb_version_hasfinobt(&mp->m_sb))
|
||||||
|
+ agi->agi_fblocks = cpu_to_be32(1);
|
||||||
|
+ }
|
||||||
|
libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
|
||||||
|
|
||||||
|
/*
|
@ -0,0 +1,61 @@
|
|||||||
|
From eb2c6897f36d560f84ed5124b246f2759c470f11 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Tue, 10 Nov 2020 15:11:09 -0500
|
||||||
|
Subject: [PATCH] xfs: use the finobt block counts to speed up mount times
|
||||||
|
|
||||||
|
Source kernel commit: 1ac35f061af011442eeb731632f6daae991ecf7c
|
||||||
|
|
||||||
|
Now that we have reliable finobt block counts, use them to speed up the
|
||||||
|
per-AG block reservation calculations at mount time.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Brian Foster <bfoster@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/libxfs/xfs_ialloc_btree.c b/libxfs/xfs_ialloc_btree.c
|
||||||
|
index 9db87e9..b1adc80 100644
|
||||||
|
--- a/libxfs/xfs_ialloc_btree.c
|
||||||
|
+++ b/libxfs/xfs_ialloc_btree.c
|
||||||
|
@@ -593,6 +593,28 @@ xfs_inobt_count_blocks(
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Read finobt block count from AGI header. */
|
||||||
|
+static int
|
||||||
|
+xfs_finobt_read_blocks(
|
||||||
|
+ struct xfs_mount *mp,
|
||||||
|
+ struct xfs_trans *tp,
|
||||||
|
+ xfs_agnumber_t agno,
|
||||||
|
+ xfs_extlen_t *tree_blocks)
|
||||||
|
+{
|
||||||
|
+ struct xfs_buf *agbp;
|
||||||
|
+ struct xfs_agi *agi;
|
||||||
|
+ int error;
|
||||||
|
+
|
||||||
|
+ error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
|
||||||
|
+ if (error)
|
||||||
|
+ return error;
|
||||||
|
+
|
||||||
|
+ agi = agbp->b_addr;
|
||||||
|
+ *tree_blocks = be32_to_cpu(agi->agi_fblocks);
|
||||||
|
+ xfs_trans_brelse(tp, agbp);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Figure out how many blocks to reserve and how many are used by this btree.
|
||||||
|
*/
|
||||||
|
@@ -610,7 +632,11 @@ xfs_finobt_calc_reserves(
|
||||||
|
if (!xfs_sb_version_hasfinobt(&mp->m_sb))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
- error = xfs_inobt_count_blocks(mp, tp, agno, XFS_BTNUM_FINO, &tree_len);
|
||||||
|
+ if (xfs_sb_version_hasinobtcounts(&mp->m_sb))
|
||||||
|
+ error = xfs_finobt_read_blocks(mp, tp, agno, &tree_len);
|
||||||
|
+ else
|
||||||
|
+ error = xfs_inobt_count_blocks(mp, tp, agno, XFS_BTNUM_FINO,
|
||||||
|
+ &tree_len);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
@ -0,0 +1,371 @@
|
|||||||
|
From e7e3beb95efd751f227a0ced4c83fc5b88582e2e Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Wed, 11 Nov 2020 20:08:14 -0500
|
||||||
|
Subject: [PATCH] xfs: widen ondisk inode timestamps to deal with y2038+
|
||||||
|
|
||||||
|
Source kernel commit: f93e5436f0ee5a85eaa3a86d2614d215873fb18b
|
||||||
|
|
||||||
|
Redesign the ondisk inode timestamps to be a simple unsigned 64-bit
|
||||||
|
counter of nanoseconds since 14 Dec 1901 (i.e. the minimum time in the
|
||||||
|
32-bit unix time epoch). This enables us to handle dates up to 2486,
|
||||||
|
which solves the y2038 problem.
|
||||||
|
|
||||||
|
sandeen: update xfs_flags2diflags2() as well, to match
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Reviewed-by: Gao Xiang <hsiangkao@redhat.com>
|
||||||
|
Reviewed-by: Dave Chinner <dchinner@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
NOTE: xfs_trans_inode.c was not brought over in this version, so code
|
||||||
|
landed in trans.c
|
||||||
|
|
||||||
|
We also do not have the pre-computed geometry, so that needs to be
|
||||||
|
explicitly added to libxfs_ialloc rather than inheriting from igeo.
|
||||||
|
|
||||||
|
diff --git a/include/xfs_inode.h b/include/xfs_inode.h
|
||||||
|
index ddd48be..25f2eac 100644
|
||||||
|
--- a/include/xfs_inode.h
|
||||||
|
+++ b/include/xfs_inode.h
|
||||||
|
@@ -146,6 +146,11 @@ static inline bool xfs_is_reflink_inode(struct xfs_inode *ip)
|
||||||
|
return ip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static inline bool xfs_inode_has_bigtime(struct xfs_inode *ip)
|
||||||
|
+{
|
||||||
|
+ return ip->i_d.di_flags2 & XFS_DIFLAG2_BIGTIME;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
typedef struct cred {
|
||||||
|
uid_t cr_uid;
|
||||||
|
gid_t cr_gid;
|
||||||
|
diff --git a/libxfs/trans.c b/libxfs/trans.c
|
||||||
|
index db90624..54e4dd6 100644
|
||||||
|
--- a/libxfs/trans.c
|
||||||
|
+++ b/libxfs/trans.c
|
||||||
|
@@ -415,6 +415,17 @@ xfs_trans_log_inode(
|
||||||
|
tp->t_flags |= XFS_TRANS_DIRTY;
|
||||||
|
set_bit(XFS_LI_DIRTY, &ip->i_itemp->ili_item.li_flags);
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * If we're updating the inode core or the timestamps and it's possible
|
||||||
|
+ * to upgrade this inode to bigtime format, do so now.
|
||||||
|
+ */
|
||||||
|
+ if ((flags & (XFS_ILOG_CORE | XFS_ILOG_TIMESTAMP)) &&
|
||||||
|
+ xfs_sb_version_hasbigtime(&ip->i_mount->m_sb) &&
|
||||||
|
+ !xfs_inode_has_bigtime(ip)) {
|
||||||
|
+ ip->i_d.di_flags2 |= XFS_DIFLAG2_BIGTIME;
|
||||||
|
+ flags |= XFS_ILOG_CORE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Always OR in the bits from the ili_last_fields field.
|
||||||
|
* This is to coordinate with the xfs_iflush() and xfs_iflush_done()
|
||||||
|
diff --git a/libxfs/util.c b/libxfs/util.c
|
||||||
|
index 9383bb8..7a8729f 100644
|
||||||
|
--- a/libxfs/util.c
|
||||||
|
+++ b/libxfs/util.c
|
||||||
|
@@ -222,7 +222,8 @@ xfs_flags2diflags2(
|
||||||
|
unsigned int xflags)
|
||||||
|
{
|
||||||
|
uint64_t di_flags2 =
|
||||||
|
- (ip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK);
|
||||||
|
+ (ip->i_d.di_flags2 & (XFS_DIFLAG2_REFLINK |
|
||||||
|
+ XFS_DIFLAG2_BIGTIME));
|
||||||
|
|
||||||
|
if (xflags & FS_XFLAG_DAX)
|
||||||
|
di_flags2 |= XFS_DIFLAG2_DAX;
|
||||||
|
@@ -317,8 +318,14 @@ libxfs_ialloc(
|
||||||
|
ASSERT(ip->i_d.di_ino == ino);
|
||||||
|
ASSERT(uuid_equal(&ip->i_d.di_uuid, &mp->m_sb.sb_meta_uuid));
|
||||||
|
VFS_I(ip)->i_version = 1;
|
||||||
|
- ip->i_d.di_flags2 = pip ? 0 : xfs_flags2diflags2(ip,
|
||||||
|
- fsx->fsx_xflags);
|
||||||
|
+ if (pip) {
|
||||||
|
+ ip->i_d.di_flags2 = 0;
|
||||||
|
+ if (xfs_sb_version_hasbigtime(&ip->i_mount->m_sb))
|
||||||
|
+ ip->i_d.di_flags2 |= XFS_DIFLAG2_BIGTIME;
|
||||||
|
+ } else {
|
||||||
|
+ ip->i_d.di_flags2 = xfs_flags2diflags2(ip, fsx->fsx_xflags);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
ip->i_d.di_crtime.tv_sec = (int32_t)VFS_I(ip)->i_mtime.tv_sec;
|
||||||
|
ip->i_d.di_crtime.tv_nsec = (int32_t)VFS_I(ip)->i_mtime.tv_nsec;
|
||||||
|
ip->i_d.di_cowextsize = pip ? 0 : fsx->fsx_cowextsize;
|
||||||
|
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
|
||||||
|
index 371f5cd..b1f6219 100644
|
||||||
|
--- a/libxfs/xfs_format.h
|
||||||
|
+++ b/libxfs/xfs_format.h
|
||||||
|
@@ -466,6 +466,7 @@ xfs_sb_has_ro_compat_feature(
|
||||||
|
#define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */
|
||||||
|
#define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */
|
||||||
|
#define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */
|
||||||
|
+#define XFS_SB_FEAT_INCOMPAT_BIGTIME (1 << 3) /* large timestamps */
|
||||||
|
#define XFS_SB_FEAT_INCOMPAT_ALL \
|
||||||
|
(XFS_SB_FEAT_INCOMPAT_FTYPE| \
|
||||||
|
XFS_SB_FEAT_INCOMPAT_SPINODES| \
|
||||||
|
@@ -580,6 +581,12 @@ xfs_is_quota_inode(struct xfs_sb *sbp, xfs_ino_t ino)
|
||||||
|
#define XFS_FSB_TO_DADDR(mp,fsbno) XFS_AGB_TO_DADDR(mp, \
|
||||||
|
XFS_FSB_TO_AGNO(mp,fsbno), XFS_FSB_TO_AGBNO(mp,fsbno))
|
||||||
|
|
||||||
|
+static inline bool xfs_sb_version_hasbigtime(struct xfs_sb *sbp)
|
||||||
|
+{
|
||||||
|
+ return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 &&
|
||||||
|
+ (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_BIGTIME);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* File system sector to basic block conversions.
|
||||||
|
*/
|
||||||
|
@@ -849,6 +856,13 @@ typedef struct xfs_agfl {
|
||||||
|
* Therefore, the ondisk min and max defined here can be used directly to
|
||||||
|
* constrain the incore timestamps on a Unix system. Note that we actually
|
||||||
|
* encode a __be64 value on disk.
|
||||||
|
+ *
|
||||||
|
+ * When the bigtime feature is enabled, ondisk inode timestamps become an
|
||||||
|
+ * unsigned 64-bit nanoseconds counter. This means that the bigtime inode
|
||||||
|
+ * timestamp epoch is the start of the classic timestamp range, which is
|
||||||
|
+ * Dec 31 20:45:52 UTC 1901. Because the epochs are not the same, callers
|
||||||
|
+ * /must/ use the bigtime conversion functions when encoding and decoding raw
|
||||||
|
+ * timestamps.
|
||||||
|
*/
|
||||||
|
typedef __be64 xfs_timestamp_t;
|
||||||
|
|
||||||
|
@@ -870,6 +884,50 @@ struct xfs_legacy_timestamp {
|
||||||
|
*/
|
||||||
|
#define XFS_LEGACY_TIME_MAX ((int64_t)S32_MAX)
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Smallest possible ondisk seconds value with bigtime timestamps. This
|
||||||
|
+ * corresponds (after conversion to a Unix timestamp) with the traditional
|
||||||
|
+ * minimum timestamp of Dec 13 20:45:52 UTC 1901.
|
||||||
|
+ */
|
||||||
|
+#define XFS_BIGTIME_TIME_MIN ((int64_t)0)
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Largest supported ondisk seconds value with bigtime timestamps. This
|
||||||
|
+ * corresponds (after conversion to a Unix timestamp) with an incore timestamp
|
||||||
|
+ * of Jul 2 20:20:24 UTC 2486.
|
||||||
|
+ *
|
||||||
|
+ * We round down the ondisk limit so that the bigtime quota and inode max
|
||||||
|
+ * timestamps will be the same.
|
||||||
|
+ */
|
||||||
|
+#define XFS_BIGTIME_TIME_MAX ((int64_t)((-1ULL / NSEC_PER_SEC) & ~0x3ULL))
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Bigtime epoch is set exactly to the minimum time value that a traditional
|
||||||
|
+ * 32-bit timestamp can represent when using the Unix epoch as a reference.
|
||||||
|
+ * Hence the Unix epoch is at a fixed offset into the supported bigtime
|
||||||
|
+ * timestamp range.
|
||||||
|
+ *
|
||||||
|
+ * The bigtime epoch also matches the minimum value an on-disk 32-bit XFS
|
||||||
|
+ * timestamp can represent so we will not lose any fidelity in converting
|
||||||
|
+ * to/from unix and bigtime timestamps.
|
||||||
|
+ *
|
||||||
|
+ * The following conversion factor converts a seconds counter from the Unix
|
||||||
|
+ * epoch to the bigtime epoch.
|
||||||
|
+ */
|
||||||
|
+#define XFS_BIGTIME_EPOCH_OFFSET (-(int64_t)S32_MIN)
|
||||||
|
+
|
||||||
|
+/* Convert a timestamp from the Unix epoch to the bigtime epoch. */
|
||||||
|
+static inline uint64_t xfs_unix_to_bigtime(time64_t unix_seconds)
|
||||||
|
+{
|
||||||
|
+ return (uint64_t)unix_seconds + XFS_BIGTIME_EPOCH_OFFSET;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Convert a timestamp from the bigtime epoch to the Unix epoch. */
|
||||||
|
+static inline time64_t xfs_bigtime_to_unix(uint64_t ondisk_seconds)
|
||||||
|
+{
|
||||||
|
+ return (time64_t)ondisk_seconds - XFS_BIGTIME_EPOCH_OFFSET;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* On-disk inode structure.
|
||||||
|
*
|
||||||
|
@@ -1096,12 +1154,22 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev)
|
||||||
|
#define XFS_DIFLAG2_DAX_BIT 0 /* use DAX for this inode */
|
||||||
|
#define XFS_DIFLAG2_REFLINK_BIT 1 /* file's blocks may be shared */
|
||||||
|
#define XFS_DIFLAG2_COWEXTSIZE_BIT 2 /* copy on write extent size hint */
|
||||||
|
+#define XFS_DIFLAG2_BIGTIME_BIT 3 /* big timestamps */
|
||||||
|
+
|
||||||
|
#define XFS_DIFLAG2_DAX (1 << XFS_DIFLAG2_DAX_BIT)
|
||||||
|
#define XFS_DIFLAG2_REFLINK (1 << XFS_DIFLAG2_REFLINK_BIT)
|
||||||
|
#define XFS_DIFLAG2_COWEXTSIZE (1 << XFS_DIFLAG2_COWEXTSIZE_BIT)
|
||||||
|
+#define XFS_DIFLAG2_BIGTIME (1 << XFS_DIFLAG2_BIGTIME_BIT)
|
||||||
|
|
||||||
|
#define XFS_DIFLAG2_ANY \
|
||||||
|
- (XFS_DIFLAG2_DAX | XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE)
|
||||||
|
+ (XFS_DIFLAG2_DAX | XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE | \
|
||||||
|
+ XFS_DIFLAG2_BIGTIME)
|
||||||
|
+
|
||||||
|
+static inline bool xfs_dinode_has_bigtime(const struct xfs_dinode *dip)
|
||||||
|
+{
|
||||||
|
+ return dip->di_version >= 3 &&
|
||||||
|
+ (dip->di_flags2 & cpu_to_be64(XFS_DIFLAG2_BIGTIME));
|
||||||
|
+}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Inode number format:
|
||||||
|
diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h
|
||||||
|
index 4fa9852..714dba1 100644
|
||||||
|
--- a/libxfs/xfs_fs.h
|
||||||
|
+++ b/libxfs/xfs_fs.h
|
||||||
|
@@ -231,6 +231,7 @@ typedef struct xfs_fsop_resblks {
|
||||||
|
#define XFS_FSOP_GEOM_FLAGS_SPINODES 0x40000 /* sparse inode chunks */
|
||||||
|
#define XFS_FSOP_GEOM_FLAGS_RMAPBT 0x80000 /* reverse mapping btree */
|
||||||
|
#define XFS_FSOP_GEOM_FLAGS_REFLINK 0x100000 /* files can share blocks */
|
||||||
|
+#define XFS_FSOP_GEOM_FLAGS_BIGTIME 0x200000 /* 64-bit nsec timestamps */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Minimum and maximum sizes need for growth checks.
|
||||||
|
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
|
||||||
|
index d8831a1..8cd16bf 100644
|
||||||
|
--- a/libxfs/xfs_inode_buf.c
|
||||||
|
+++ b/libxfs/xfs_inode_buf.c
|
||||||
|
@@ -195,14 +195,29 @@ xfs_imap_to_bp(
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static inline struct timespec64 xfs_inode_decode_bigtime(uint64_t ts)
|
||||||
|
+{
|
||||||
|
+ struct timespec64 tv;
|
||||||
|
+ uint32_t n;
|
||||||
|
+
|
||||||
|
+ tv.tv_sec = xfs_bigtime_to_unix(div_u64_rem(ts, NSEC_PER_SEC, &n));
|
||||||
|
+ tv.tv_nsec = n;
|
||||||
|
+
|
||||||
|
+ return tv;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Convert an ondisk timestamp to an incore timestamp. */
|
||||||
|
struct timespec64
|
||||||
|
xfs_inode_from_disk_ts(
|
||||||
|
+ struct xfs_dinode *dip,
|
||||||
|
const xfs_timestamp_t ts)
|
||||||
|
{
|
||||||
|
struct timespec64 tv;
|
||||||
|
struct xfs_legacy_timestamp *lts;
|
||||||
|
|
||||||
|
+ if (xfs_dinode_has_bigtime(dip))
|
||||||
|
+ return xfs_inode_decode_bigtime(be64_to_cpu(ts));
|
||||||
|
+
|
||||||
|
lts = (struct xfs_legacy_timestamp *)&ts;
|
||||||
|
tv.tv_sec = (int)be32_to_cpu(lts->t_sec);
|
||||||
|
tv.tv_nsec = (int)be32_to_cpu(lts->t_nsec);
|
||||||
|
@@ -246,9 +261,9 @@ xfs_inode_from_disk(
|
||||||
|
* a time before epoch is converted to a time long after epoch
|
||||||
|
* on 64 bit systems.
|
||||||
|
*/
|
||||||
|
- inode->i_atime = xfs_inode_from_disk_ts(from->di_atime);
|
||||||
|
- inode->i_mtime = xfs_inode_from_disk_ts(from->di_mtime);
|
||||||
|
- inode->i_ctime = xfs_inode_from_disk_ts(from->di_ctime);
|
||||||
|
+ inode->i_atime = xfs_inode_from_disk_ts(from, from->di_atime);
|
||||||
|
+ inode->i_mtime = xfs_inode_from_disk_ts(from, from->di_mtime);
|
||||||
|
+ inode->i_ctime = xfs_inode_from_disk_ts(from, from->di_ctime);
|
||||||
|
|
||||||
|
inode->i_generation = be32_to_cpu(from->di_gen);
|
||||||
|
inode->i_mode = be16_to_cpu(from->di_mode);
|
||||||
|
@@ -267,7 +282,7 @@ xfs_inode_from_disk(
|
||||||
|
if (to->di_version == 3) {
|
||||||
|
inode_set_iversion_queried(inode,
|
||||||
|
be64_to_cpu(from->di_changecount));
|
||||||
|
- to->di_crtime = xfs_inode_from_disk_ts(from->di_crtime);
|
||||||
|
+ to->di_crtime = xfs_inode_from_disk_ts(from, from->di_crtime);
|
||||||
|
to->di_flags2 = be64_to_cpu(from->di_flags2);
|
||||||
|
to->di_cowextsize = be32_to_cpu(from->di_cowextsize);
|
||||||
|
}
|
||||||
|
@@ -276,11 +291,15 @@ xfs_inode_from_disk(
|
||||||
|
/* Convert an incore timestamp to an ondisk timestamp. */
|
||||||
|
static inline xfs_timestamp_t
|
||||||
|
xfs_inode_to_disk_ts(
|
||||||
|
+ struct xfs_inode *ip,
|
||||||
|
const struct timespec64 tv)
|
||||||
|
{
|
||||||
|
struct xfs_legacy_timestamp *lts;
|
||||||
|
xfs_timestamp_t ts;
|
||||||
|
|
||||||
|
+ if (xfs_inode_has_bigtime(ip))
|
||||||
|
+ return cpu_to_be64(xfs_inode_encode_bigtime(tv));
|
||||||
|
+
|
||||||
|
lts = (struct xfs_legacy_timestamp *)&ts;
|
||||||
|
lts->t_sec = cpu_to_be32(tv.tv_sec);
|
||||||
|
lts->t_nsec = cpu_to_be32(tv.tv_nsec);
|
||||||
|
@@ -308,9 +327,9 @@ xfs_inode_to_disk(
|
||||||
|
to->di_projid_hi = cpu_to_be16(from->di_projid_hi);
|
||||||
|
|
||||||
|
memset(to->di_pad, 0, sizeof(to->di_pad));
|
||||||
|
- to->di_atime = xfs_inode_to_disk_ts(inode->i_atime);
|
||||||
|
- to->di_mtime = xfs_inode_to_disk_ts(inode->i_mtime);
|
||||||
|
- to->di_ctime = xfs_inode_to_disk_ts(inode->i_ctime);
|
||||||
|
+ to->di_atime = xfs_inode_to_disk_ts(ip, inode->i_atime);
|
||||||
|
+ to->di_mtime = xfs_inode_to_disk_ts(ip, inode->i_mtime);
|
||||||
|
+ to->di_ctime = xfs_inode_to_disk_ts(ip, inode->i_ctime);
|
||||||
|
to->di_nlink = cpu_to_be32(inode->i_nlink);
|
||||||
|
to->di_gen = cpu_to_be32(inode->i_generation);
|
||||||
|
to->di_mode = cpu_to_be16(inode->i_mode);
|
||||||
|
@@ -328,7 +347,7 @@ xfs_inode_to_disk(
|
||||||
|
|
||||||
|
if (from->di_version == 3) {
|
||||||
|
to->di_changecount = cpu_to_be64(inode_peek_iversion(inode));
|
||||||
|
- to->di_crtime = xfs_inode_to_disk_ts(from->di_crtime);
|
||||||
|
+ to->di_crtime = xfs_inode_to_disk_ts(ip, from->di_crtime);
|
||||||
|
to->di_flags2 = cpu_to_be64(from->di_flags2);
|
||||||
|
to->di_cowextsize = cpu_to_be32(from->di_cowextsize);
|
||||||
|
to->di_ino = cpu_to_be64(ip->i_ino);
|
||||||
|
@@ -547,6 +566,11 @@ xfs_dinode_verify(
|
||||||
|
if (fa)
|
||||||
|
return fa;
|
||||||
|
|
||||||
|
+ /* bigtime iflag can only happen on bigtime filesystems */
|
||||||
|
+ if (xfs_dinode_has_bigtime(dip) &&
|
||||||
|
+ !xfs_sb_version_hasbigtime(&mp->m_sb))
|
||||||
|
+ return __this_address;
|
||||||
|
+
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/libxfs/xfs_inode_buf.h b/libxfs/xfs_inode_buf.h
|
||||||
|
index 6147f42..2b91e60 100644
|
||||||
|
--- a/libxfs/xfs_inode_buf.h
|
||||||
|
+++ b/libxfs/xfs_inode_buf.h
|
||||||
|
@@ -40,6 +40,11 @@ struct xfs_icdinode {
|
||||||
|
struct timespec64 di_crtime; /* time created */
|
||||||
|
};
|
||||||
|
|
||||||
|
+static inline bool xfs_icdinode_has_bigtime(const struct xfs_icdinode *icd)
|
||||||
|
+{
|
||||||
|
+ return icd->di_flags2 & XFS_DIFLAG2_BIGTIME;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Inode location information. Stored in the inode and passed to
|
||||||
|
* xfs_imap_to_bp() to get a buffer and dinode for a given inode.
|
||||||
|
@@ -76,6 +81,12 @@ xfs_failaddr_t xfs_inode_validate_cowextsize(struct xfs_mount *mp,
|
||||||
|
uint32_t cowextsize, uint16_t mode, uint16_t flags,
|
||||||
|
uint64_t flags2);
|
||||||
|
|
||||||
|
-struct timespec64 xfs_inode_from_disk_ts(const xfs_timestamp_t ts);
|
||||||
|
+static inline uint64_t xfs_inode_encode_bigtime(struct timespec64 tv)
|
||||||
|
+{
|
||||||
|
+ return xfs_unix_to_bigtime(tv.tv_sec) * NSEC_PER_SEC + tv.tv_nsec;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+struct timespec64 xfs_inode_from_disk_ts(struct xfs_dinode *dip,
|
||||||
|
+ const xfs_timestamp_t ts);
|
||||||
|
|
||||||
|
#endif /* __XFS_INODE_BUF_H__ */
|
||||||
|
diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c
|
||||||
|
index cee77a6..d11545b 100644
|
||||||
|
--- a/libxfs/xfs_sb.c
|
||||||
|
+++ b/libxfs/xfs_sb.c
|
||||||
|
@@ -1124,6 +1124,8 @@ xfs_fs_geometry(
|
||||||
|
geo->flags |= XFS_FSOP_GEOM_FLAGS_RMAPBT;
|
||||||
|
if (xfs_sb_version_hasreflink(sbp))
|
||||||
|
geo->flags |= XFS_FSOP_GEOM_FLAGS_REFLINK;
|
||||||
|
+ if (xfs_sb_version_hasbigtime(sbp))
|
||||||
|
+ geo->flags |= XFS_FSOP_GEOM_FLAGS_BIGTIME;
|
||||||
|
if (xfs_sb_version_hassector(sbp))
|
||||||
|
geo->logsectsize = sbp->sb_logsectsize;
|
||||||
|
else
|
@ -0,0 +1,170 @@
|
|||||||
|
From 06963ef0d4ff9a6736f699d1ca8ef5a0c194799b Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Thu, 12 Nov 2020 16:49:42 -0500
|
||||||
|
Subject: [PATCH] xfs: widen ondisk quota expiration timestamps to handle
|
||||||
|
y2038+
|
||||||
|
|
||||||
|
Source kernel commit: 4ea1ff3b49681af45a4a8c14baf7f0b3d11aa74a
|
||||||
|
|
||||||
|
Enable the bigtime feature for quota timers. We decrease the accuracy
|
||||||
|
of the timers to ~4s in exchange for being able to set timers up to the
|
||||||
|
bigtime maximum.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
|
||||||
|
Reviewed-by: Dave Chinner <dchinner@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
NOTE: Again, slightly different macro names due to lack of the
|
||||||
|
quota type/flags split.
|
||||||
|
|
||||||
|
diff --git a/include/xfs_mount.h b/include/xfs_mount.h
|
||||||
|
index 8651d6a..beb2328 100644
|
||||||
|
--- a/include/xfs_mount.h
|
||||||
|
+++ b/include/xfs_mount.h
|
||||||
|
@@ -202,4 +202,8 @@ extern xfs_mount_t *libxfs_mount (xfs_mount_t *, xfs_sb_t *,
|
||||||
|
extern void libxfs_umount (xfs_mount_t *);
|
||||||
|
extern void libxfs_rtmount_destroy (xfs_mount_t *);
|
||||||
|
|
||||||
|
+/* Dummy xfs_dquot so that libxfs compiles. */
|
||||||
|
+struct xfs_dquot {
|
||||||
|
+ int q_type;
|
||||||
|
+};
|
||||||
|
#endif /* __XFS_MOUNT_H__ */
|
||||||
|
diff --git a/libxfs/xfs_dquot_buf.c b/libxfs/xfs_dquot_buf.c
|
||||||
|
index 963f8ea..db93dda 100644
|
||||||
|
--- a/libxfs/xfs_dquot_buf.c
|
||||||
|
+++ b/libxfs/xfs_dquot_buf.c
|
||||||
|
@@ -69,6 +69,13 @@ xfs_dquot_verify(
|
||||||
|
ddq_type != XFS_DQ_GROUP)
|
||||||
|
return __this_address;
|
||||||
|
|
||||||
|
+ if ((ddq->d_flags & XFS_DQ_BIGTIME) &&
|
||||||
|
+ !xfs_sb_version_hasbigtime(&mp->m_sb))
|
||||||
|
+ return __this_address;
|
||||||
|
+
|
||||||
|
+ if ((ddq->d_flags & XFS_DQ_BIGTIME) && !ddq->d_id)
|
||||||
|
+ return __this_address;
|
||||||
|
+
|
||||||
|
if (id != -1 && id != be32_to_cpu(ddq->d_id))
|
||||||
|
return __this_address;
|
||||||
|
|
||||||
|
@@ -293,7 +300,12 @@ xfs_dquot_from_disk_ts(
|
||||||
|
struct xfs_disk_dquot *ddq,
|
||||||
|
__be32 dtimer)
|
||||||
|
{
|
||||||
|
- return be32_to_cpu(dtimer);
|
||||||
|
+ uint32_t t = be32_to_cpu(dtimer);
|
||||||
|
+
|
||||||
|
+ if (t != 0 && (ddq->d_flags & XFS_DQ_BIGTIME))
|
||||||
|
+ return xfs_dq_bigtime_to_unix(t);
|
||||||
|
+
|
||||||
|
+ return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert an incore timer value into an on-disk timer value. */
|
||||||
|
@@ -302,5 +314,10 @@ xfs_dquot_to_disk_ts(
|
||||||
|
struct xfs_dquot *dqp,
|
||||||
|
time64_t timer)
|
||||||
|
{
|
||||||
|
- return cpu_to_be32(timer);
|
||||||
|
+ uint32_t t = timer;
|
||||||
|
+
|
||||||
|
+ if (timer != 0 && (dqp->q_type & XFS_DQ_BIGTIME))
|
||||||
|
+ t = xfs_dq_unix_to_bigtime(timer);
|
||||||
|
+
|
||||||
|
+ return cpu_to_be32(t);
|
||||||
|
}
|
||||||
|
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
|
||||||
|
index b1f6219..9ba65e5 100644
|
||||||
|
--- a/libxfs/xfs_format.h
|
||||||
|
+++ b/libxfs/xfs_format.h
|
||||||
|
@@ -1263,6 +1263,10 @@ static inline bool xfs_dinode_has_bigtime(const struct xfs_dinode *dip)
|
||||||
|
* ondisk min and max defined here can be used directly to constrain the incore
|
||||||
|
* quota expiration timestamps on a Unix system.
|
||||||
|
*
|
||||||
|
+ * When bigtime is enabled, we trade two bits of precision to expand the
|
||||||
|
+ * expiration timeout range to match that of big inode timestamps. The min and
|
||||||
|
+ * max recorded here are the on-disk limits, not a Unix timestamp.
|
||||||
|
+ *
|
||||||
|
* The grace period for each quota type is stored in the root dquot (id = 0)
|
||||||
|
* and is applied to a non-root dquot when it exceeds the soft or hard limits.
|
||||||
|
* The length of quota grace periods are unsigned 32-bit quantities measured in
|
||||||
|
@@ -1281,6 +1285,48 @@ static inline bool xfs_dinode_has_bigtime(const struct xfs_dinode *dip)
|
||||||
|
*/
|
||||||
|
#define XFS_DQ_LEGACY_EXPIRY_MAX ((int64_t)U32_MAX)
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Smallest possible ondisk quota expiration value with bigtime timestamps.
|
||||||
|
+ * This corresponds (after conversion to a Unix timestamp) with the incore
|
||||||
|
+ * expiration of Jan 1 00:00:04 UTC 1970.
|
||||||
|
+ */
|
||||||
|
+#define XFS_DQ_BIGTIME_EXPIRY_MIN (XFS_DQ_LEGACY_EXPIRY_MIN)
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Largest supported ondisk quota expiration value with bigtime timestamps.
|
||||||
|
+ * This corresponds (after conversion to a Unix timestamp) with an incore
|
||||||
|
+ * expiration of Jul 2 20:20:24 UTC 2486.
|
||||||
|
+ *
|
||||||
|
+ * The ondisk field supports values up to -1U, which corresponds to an incore
|
||||||
|
+ * expiration in 2514. This is beyond the maximum the bigtime inode timestamp,
|
||||||
|
+ * so we cap the maximum bigtime quota expiration to the max inode timestamp.
|
||||||
|
+ */
|
||||||
|
+#define XFS_DQ_BIGTIME_EXPIRY_MAX ((int64_t)4074815106U)
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * The following conversion factors assist in converting a quota expiration
|
||||||
|
+ * timestamp between the incore and ondisk formats.
|
||||||
|
+ */
|
||||||
|
+#define XFS_DQ_BIGTIME_SHIFT (2)
|
||||||
|
+#define XFS_DQ_BIGTIME_SLACK ((int64_t)(1ULL << XFS_DQ_BIGTIME_SHIFT) - 1)
|
||||||
|
+
|
||||||
|
+/* Convert an incore quota expiration timestamp to an ondisk bigtime value. */
|
||||||
|
+static inline uint32_t xfs_dq_unix_to_bigtime(time64_t unix_seconds)
|
||||||
|
+{
|
||||||
|
+ /*
|
||||||
|
+ * Round the expiration timestamp up to the nearest bigtime timestamp
|
||||||
|
+ * that we can store, to give users the most time to fix problems.
|
||||||
|
+ */
|
||||||
|
+ return ((uint64_t)unix_seconds + XFS_DQ_BIGTIME_SLACK) >>
|
||||||
|
+ XFS_DQ_BIGTIME_SHIFT;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Convert an ondisk bigtime quota expiration value to an incore timestamp. */
|
||||||
|
+static inline time64_t xfs_dq_bigtime_to_unix(uint32_t ondisk_seconds)
|
||||||
|
+{
|
||||||
|
+ return (time64_t)ondisk_seconds << XFS_DQ_BIGTIME_SHIFT;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Default quota grace periods, ranging from zero (use the compiled defaults)
|
||||||
|
* to ~136 years. These are applied to a non-root dquot that has exceeded
|
||||||
|
diff --git a/libxfs/xfs_quota_defs.h b/libxfs/xfs_quota_defs.h
|
||||||
|
index 2f61cd3..70d89cc 100644
|
||||||
|
--- a/libxfs/xfs_quota_defs.h
|
||||||
|
+++ b/libxfs/xfs_quota_defs.h
|
||||||
|
@@ -28,17 +28,20 @@ typedef uint16_t xfs_qwarncnt_t;
|
||||||
|
#define XFS_DQ_GROUP 0x0004 /* a group quota */
|
||||||
|
#define XFS_DQ_DIRTY 0x0008 /* dquot is dirty */
|
||||||
|
#define XFS_DQ_FREEING 0x0010 /* dquot is being torn down */
|
||||||
|
+#define XFS_DQ_BIGTIME 0x0080 /* large expiry timestamps */
|
||||||
|
|
||||||
|
#define XFS_DQ_ALLTYPES (XFS_DQ_USER|XFS_DQ_PROJ|XFS_DQ_GROUP)
|
||||||
|
|
||||||
|
-#define XFS_DQTYPE_ANY (XFS_DQ_ALLTYPES)
|
||||||
|
+#define XFS_DQTYPE_ANY (XFS_DQ_ALLTYPES | \
|
||||||
|
+ XFS_DQ_BIGTIME)
|
||||||
|
|
||||||
|
#define XFS_DQ_FLAGS \
|
||||||
|
{ XFS_DQ_USER, "USER" }, \
|
||||||
|
{ XFS_DQ_PROJ, "PROJ" }, \
|
||||||
|
{ XFS_DQ_GROUP, "GROUP" }, \
|
||||||
|
{ XFS_DQ_DIRTY, "DIRTY" }, \
|
||||||
|
- { XFS_DQ_FREEING, "FREEING" }
|
||||||
|
+ { XFS_DQ_FREEING, "FREEING" }, \
|
||||||
|
+ { XFS_DQ_BIGTIME, "BIGTIME" }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We have the possibility of all three quota types being active at once, and
|
@ -0,0 +1,122 @@
|
|||||||
|
From a9a32fcb9176c82aed6d85f209e7279b76c8b55f Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 20 Nov 2020 17:03:28 -0500
|
||||||
|
Subject: [PATCH] xfs_db: refactor quota timer printing
|
||||||
|
|
||||||
|
Introduce type-specific printing functions to xfs_db to print a quota
|
||||||
|
timer instead of printing a raw int32 value. This is needed to stay
|
||||||
|
ahead of changes that we're going to make to the quota timer format in
|
||||||
|
the following patches.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/db/dquot.c b/db/dquot.c
|
||||||
|
index dd9e83f..5c82456 100644
|
||||||
|
--- a/db/dquot.c
|
||||||
|
+++ b/db/dquot.c
|
||||||
|
@@ -60,8 +60,8 @@ const field_t disk_dquot_flds[] = {
|
||||||
|
TYP_NONE },
|
||||||
|
{ "bcount", FLDT_QCNT, OI(DOFF(bcount)), C1, 0, TYP_NONE },
|
||||||
|
{ "icount", FLDT_QCNT, OI(DOFF(icount)), C1, 0, TYP_NONE },
|
||||||
|
- { "itimer", FLDT_INT32D, OI(DOFF(itimer)), C1, 0, TYP_NONE },
|
||||||
|
- { "btimer", FLDT_INT32D, OI(DOFF(btimer)), C1, 0, TYP_NONE },
|
||||||
|
+ { "itimer", FLDT_QTIMER, OI(DOFF(itimer)), C1, 0, TYP_NONE },
|
||||||
|
+ { "btimer", FLDT_QTIMER, OI(DOFF(btimer)), C1, 0, TYP_NONE },
|
||||||
|
{ "iwarns", FLDT_QWARNCNT, OI(DOFF(iwarns)), C1, 0, TYP_NONE },
|
||||||
|
{ "bwarns", FLDT_QWARNCNT, OI(DOFF(bwarns)), C1, 0, TYP_NONE },
|
||||||
|
{ "pad0", FLDT_UINT32X, OI(DOFF(pad0)), C1, FLD_SKIPALL, TYP_NONE },
|
||||||
|
@@ -70,7 +70,7 @@ const field_t disk_dquot_flds[] = {
|
||||||
|
{ "rtb_softlimit", FLDT_QCNT, OI(DOFF(rtb_softlimit)), C1, 0,
|
||||||
|
TYP_NONE },
|
||||||
|
{ "rtbcount", FLDT_QCNT, OI(DOFF(rtbcount)), C1, 0, TYP_NONE },
|
||||||
|
- { "rtbtimer", FLDT_INT32D, OI(DOFF(rtbtimer)), C1, 0, TYP_NONE },
|
||||||
|
+ { "rtbtimer", FLDT_QTIMER, OI(DOFF(rtbtimer)), C1, 0, TYP_NONE },
|
||||||
|
{ "rtbwarns", FLDT_QWARNCNT, OI(DOFF(rtbwarns)), C1, 0, TYP_NONE },
|
||||||
|
{ "pad", FLDT_UINT16X, OI(DOFF(pad)), C1, FLD_SKIPALL, TYP_NONE },
|
||||||
|
{ NULL }
|
||||||
|
diff --git a/db/field.c b/db/field.c
|
||||||
|
index a187a72..770acda 100644
|
||||||
|
--- a/db/field.c
|
||||||
|
+++ b/db/field.c
|
||||||
|
@@ -351,6 +351,8 @@ const ftattr_t ftattrtab[] = {
|
||||||
|
FTARG_SIGNED, NULL, NULL },
|
||||||
|
{ FLDT_TIMESTAMP, "timestamp", NULL, (char *)timestamp_flds,
|
||||||
|
SI(bitsz(xfs_timestamp_t)), 0, NULL, timestamp_flds },
|
||||||
|
+ { FLDT_QTIMER, "qtimer", fp_qtimer, NULL, SI(bitsz(uint32_t)), 0,
|
||||||
|
+ NULL, NULL },
|
||||||
|
{ FLDT_UINT1, "uint1", fp_num, "%u", SI(1), 0, NULL, NULL },
|
||||||
|
{ FLDT_UINT16D, "uint16d", fp_num, "%u", SI(bitsz(uint16_t)), 0, NULL,
|
||||||
|
NULL },
|
||||||
|
diff --git a/db/field.h b/db/field.h
|
||||||
|
index 1506537..387c189 100644
|
||||||
|
--- a/db/field.h
|
||||||
|
+++ b/db/field.h
|
||||||
|
@@ -170,6 +170,7 @@ typedef enum fldt {
|
||||||
|
|
||||||
|
FLDT_TIME,
|
||||||
|
FLDT_TIMESTAMP,
|
||||||
|
+ FLDT_QTIMER,
|
||||||
|
FLDT_UINT1,
|
||||||
|
FLDT_UINT16D,
|
||||||
|
FLDT_UINT16O,
|
||||||
|
diff --git a/db/fprint.c b/db/fprint.c
|
||||||
|
index 6e72bf0..72ed55f 100644
|
||||||
|
--- a/db/fprint.c
|
||||||
|
+++ b/db/fprint.c
|
||||||
|
@@ -180,6 +180,40 @@ fp_nsec(
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+int
|
||||||
|
+fp_qtimer(
|
||||||
|
+ void *obj,
|
||||||
|
+ int bit,
|
||||||
|
+ int count,
|
||||||
|
+ char *fmtstr,
|
||||||
|
+ int size,
|
||||||
|
+ int arg,
|
||||||
|
+ int base,
|
||||||
|
+ int array)
|
||||||
|
+{
|
||||||
|
+ uint32_t sec;
|
||||||
|
+ __be32 *t;
|
||||||
|
+ int bitpos;
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ ASSERT(bitoffs(bit) == 0);
|
||||||
|
+ for (i = 0, bitpos = bit;
|
||||||
|
+ i < count && !seenint();
|
||||||
|
+ i++, bitpos += size) {
|
||||||
|
+ if (array)
|
||||||
|
+ dbprintf("%d:", i + base);
|
||||||
|
+
|
||||||
|
+ t = obj + byteize(bitpos);
|
||||||
|
+ sec = be32_to_cpu(*t);
|
||||||
|
+
|
||||||
|
+ dbprintf("%u", sec);
|
||||||
|
+
|
||||||
|
+ if (i < count - 1)
|
||||||
|
+ dbprintf(" ");
|
||||||
|
+ }
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*ARGSUSED*/
|
||||||
|
int
|
||||||
|
fp_uuid(
|
||||||
|
diff --git a/db/fprint.h b/db/fprint.h
|
||||||
|
index bfeed15..a1ea935 100644
|
||||||
|
--- a/db/fprint.h
|
||||||
|
+++ b/db/fprint.h
|
||||||
|
@@ -17,6 +17,8 @@ extern int fp_time(void *obj, int bit, int count, char *fmtstr, int size,
|
||||||
|
int arg, int base, int array);
|
||||||
|
extern int fp_nsec(void *obj, int bit, int count, char *fmtstr, int size,
|
||||||
|
int arg, int base, int array);
|
||||||
|
+extern int fp_qtimer(void *obj, int bit, int count, char *fmtstr, int size,
|
||||||
|
+ int arg, int base, int array);
|
||||||
|
extern int fp_uuid(void *obj, int bit, int count, char *fmtstr, int size,
|
||||||
|
int arg, int base, int array);
|
||||||
|
extern int fp_crc(void *obj, int bit, int count, char *fmtstr, int size,
|
@ -0,0 +1,176 @@
|
|||||||
|
From 300422226c423222e78d82d54b09d0ae27c7d4af Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 20 Nov 2020 17:03:27 -0500
|
||||||
|
Subject: [PATCH] xfs_db: refactor timestamp printing
|
||||||
|
|
||||||
|
Introduce type-specific printing functions to xfs_db to print an
|
||||||
|
xfs_timestamp instead of open-coding the timestamp decoding. This is
|
||||||
|
needed to stay ahead of changes that we're going to make to
|
||||||
|
xfs_timestamp_t in the following patches.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/db/field.c b/db/field.c
|
||||||
|
index 4a45c66..a187a72 100644
|
||||||
|
--- a/db/field.c
|
||||||
|
+++ b/db/field.c
|
||||||
|
@@ -334,8 +334,8 @@ const ftattr_t ftattrtab[] = {
|
||||||
|
FTARG_SIGNED, NULL, NULL },
|
||||||
|
{ FLDT_INT8D, "int8d", fp_num, "%d", SI(bitsz(int8_t)), FTARG_SIGNED,
|
||||||
|
NULL, NULL },
|
||||||
|
- { FLDT_NSEC, "nsec", fp_num, "%09d", SI(bitsz(int32_t)), FTARG_SIGNED,
|
||||||
|
- NULL, NULL },
|
||||||
|
+ { FLDT_NSEC, "nsec", fp_nsec, NULL, SI(bitsz(xfs_timestamp_t)),
|
||||||
|
+ FTARG_SIGNED, NULL, NULL },
|
||||||
|
{ FLDT_QCNT, "qcnt", fp_num, "%llu", SI(bitsz(xfs_qcnt_t)), 0, NULL,
|
||||||
|
NULL },
|
||||||
|
{ FLDT_QWARNCNT, "qwarncnt", fp_num, "%u", SI(bitsz(xfs_qwarncnt_t)), 0,
|
||||||
|
@@ -347,10 +347,10 @@ const ftattr_t ftattrtab[] = {
|
||||||
|
{ FLDT_SYMLINK_CRC, "symlink", NULL, (char *)symlink_crc_flds,
|
||||||
|
symlink_size, FTARG_SIZE, NULL, symlink_crc_flds },
|
||||||
|
|
||||||
|
- { FLDT_TIME, "time", fp_time, NULL, SI(bitsz(int32_t)), FTARG_SIGNED,
|
||||||
|
- NULL, NULL },
|
||||||
|
+ { FLDT_TIME, "time", fp_time, NULL, SI(bitsz(xfs_timestamp_t)),
|
||||||
|
+ FTARG_SIGNED, NULL, NULL },
|
||||||
|
{ FLDT_TIMESTAMP, "timestamp", NULL, (char *)timestamp_flds,
|
||||||
|
- SI(bitsz(struct xfs_legacy_timestamp)), 0, NULL, timestamp_flds },
|
||||||
|
+ SI(bitsz(xfs_timestamp_t)), 0, NULL, timestamp_flds },
|
||||||
|
{ FLDT_UINT1, "uint1", fp_num, "%u", SI(1), 0, NULL, NULL },
|
||||||
|
{ FLDT_UINT16D, "uint16d", fp_num, "%u", SI(bitsz(uint16_t)), 0, NULL,
|
||||||
|
NULL },
|
||||||
|
diff --git a/db/fprint.c b/db/fprint.c
|
||||||
|
index c9d07e1..6e72bf0 100644
|
||||||
|
--- a/db/fprint.c
|
||||||
|
+++ b/db/fprint.c
|
||||||
|
@@ -112,22 +112,21 @@ fp_sarray(
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
-/*ARGSUSED*/
|
||||||
|
int
|
||||||
|
fp_time(
|
||||||
|
- void *obj,
|
||||||
|
- int bit,
|
||||||
|
- int count,
|
||||||
|
- char *fmtstr,
|
||||||
|
- int size,
|
||||||
|
- int arg,
|
||||||
|
- int base,
|
||||||
|
- int array)
|
||||||
|
+ void *obj,
|
||||||
|
+ int bit,
|
||||||
|
+ int count,
|
||||||
|
+ char *fmtstr,
|
||||||
|
+ int size,
|
||||||
|
+ int arg,
|
||||||
|
+ int base,
|
||||||
|
+ int array)
|
||||||
|
{
|
||||||
|
- int bitpos;
|
||||||
|
- char *c;
|
||||||
|
- int i;
|
||||||
|
- time_t t;
|
||||||
|
+ struct timespec64 tv;
|
||||||
|
+ xfs_timestamp_t *ts;
|
||||||
|
+ int bitpos;
|
||||||
|
+ int i;
|
||||||
|
|
||||||
|
ASSERT(bitoffs(bit) == 0);
|
||||||
|
for (i = 0, bitpos = bit;
|
||||||
|
@@ -135,10 +134,46 @@ fp_time(
|
||||||
|
i++, bitpos += size) {
|
||||||
|
if (array)
|
||||||
|
dbprintf("%d:", i + base);
|
||||||
|
- t = (time_t)getbitval((char *)obj + byteize(bitpos), 0,
|
||||||
|
- sizeof(int32_t) * 8, BVSIGNED);
|
||||||
|
- c = ctime(&t);
|
||||||
|
- dbprintf("%24.24s", c);
|
||||||
|
+
|
||||||
|
+ ts = obj + byteize(bitpos);
|
||||||
|
+ tv = libxfs_inode_from_disk_ts(obj, *ts);
|
||||||
|
+
|
||||||
|
+ dbprintf("%24.24s", tv.tv_sec);
|
||||||
|
+
|
||||||
|
+ if (i < count - 1)
|
||||||
|
+ dbprintf(" ");
|
||||||
|
+ }
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+fp_nsec(
|
||||||
|
+ void *obj,
|
||||||
|
+ int bit,
|
||||||
|
+ int count,
|
||||||
|
+ char *fmtstr,
|
||||||
|
+ int size,
|
||||||
|
+ int arg,
|
||||||
|
+ int base,
|
||||||
|
+ int array)
|
||||||
|
+{
|
||||||
|
+ struct timespec64 tv;
|
||||||
|
+ xfs_timestamp_t *ts;
|
||||||
|
+ int bitpos;
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ ASSERT(bitoffs(bit) == 0);
|
||||||
|
+ for (i = 0, bitpos = bit;
|
||||||
|
+ i < count && !seenint();
|
||||||
|
+ i++, bitpos += size) {
|
||||||
|
+ if (array)
|
||||||
|
+ dbprintf("%d:", i + base);
|
||||||
|
+
|
||||||
|
+ ts = obj + byteize(bitpos);
|
||||||
|
+ tv = libxfs_inode_from_disk_ts(obj, *ts);
|
||||||
|
+
|
||||||
|
+ dbprintf("%u", tv.tv_nsec);
|
||||||
|
+
|
||||||
|
if (i < count - 1)
|
||||||
|
dbprintf(" ");
|
||||||
|
}
|
||||||
|
diff --git a/db/fprint.h b/db/fprint.h
|
||||||
|
index c958dca..bfeed15 100644
|
||||||
|
--- a/db/fprint.h
|
||||||
|
+++ b/db/fprint.h
|
||||||
|
@@ -15,6 +15,8 @@ extern int fp_sarray(void *obj, int bit, int count, char *fmtstr, int size,
|
||||||
|
int arg, int base, int array);
|
||||||
|
extern int fp_time(void *obj, int bit, int count, char *fmtstr, int size,
|
||||||
|
int arg, int base, int array);
|
||||||
|
+extern int fp_nsec(void *obj, int bit, int count, char *fmtstr, int size,
|
||||||
|
+ int arg, int base, int array);
|
||||||
|
extern int fp_uuid(void *obj, int bit, int count, char *fmtstr, int size,
|
||||||
|
int arg, int base, int array);
|
||||||
|
extern int fp_crc(void *obj, int bit, int count, char *fmtstr, int size,
|
||||||
|
diff --git a/db/inode.c b/db/inode.c
|
||||||
|
index b308538..bbfee74 100644
|
||||||
|
--- a/db/inode.c
|
||||||
|
+++ b/db/inode.c
|
||||||
|
@@ -176,10 +176,9 @@ const field_t inode_v3_flds[] = {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
-#define TOFF(f) bitize(offsetof(struct xfs_legacy_timestamp, t_ ## f))
|
||||||
|
const field_t timestamp_flds[] = {
|
||||||
|
- { "sec", FLDT_TIME, OI(TOFF(sec)), C1, 0, TYP_NONE },
|
||||||
|
- { "nsec", FLDT_NSEC, OI(TOFF(nsec)), C1, 0, TYP_NONE },
|
||||||
|
+ { "sec", FLDT_TIME, OI(0), C1, 0, TYP_NONE },
|
||||||
|
+ { "nsec", FLDT_NSEC, OI(0), C1, 0, TYP_NONE },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
|
||||||
|
index f4f7626..00f367e 100644
|
||||||
|
--- a/libxfs/libxfs_api_defs.h
|
||||||
|
+++ b/libxfs/libxfs_api_defs.h
|
||||||
|
@@ -89,6 +89,7 @@
|
||||||
|
#define xfs_da_get_buf libxfs_da_get_buf
|
||||||
|
|
||||||
|
#define xfs_inode_from_disk libxfs_inode_from_disk
|
||||||
|
+#define xfs_inode_from_disk_ts libxfs_inode_from_disk_ts
|
||||||
|
#define xfs_inode_to_disk libxfs_inode_to_disk
|
||||||
|
#define xfs_dinode_calc_crc libxfs_dinode_calc_crc
|
||||||
|
#define xfs_idata_realloc libxfs_idata_realloc
|
@ -0,0 +1,122 @@
|
|||||||
|
From 344f38a9e5d0f938dae337c8c769853e6368d480 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 20 Nov 2020 17:03:28 -0500
|
||||||
|
Subject: [PATCH] xfs_db: report bigtime format timestamps
|
||||||
|
|
||||||
|
Report the large format timestamps in a human-readable manner if it is
|
||||||
|
possible to do so without loss of information.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/db/fprint.c b/db/fprint.c
|
||||||
|
index 72ed55f..65accfd 100644
|
||||||
|
--- a/db/fprint.c
|
||||||
|
+++ b/db/fprint.c
|
||||||
|
@@ -112,6 +112,35 @@ fp_sarray(
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+fp_time64(
|
||||||
|
+ time64_t sec)
|
||||||
|
+{
|
||||||
|
+ time_t tt = sec;
|
||||||
|
+ time64_t tt_sec = tt;
|
||||||
|
+ char *c;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Stupid time_t shenanigans -- POSIX.1-2017 only requires that this
|
||||||
|
+ * type represent a time in seconds. Since we have no idea if our
|
||||||
|
+ * time64_t filesystem timestamps can actually be represented by the C
|
||||||
|
+ * library, we resort to converting the input value from time64_t to
|
||||||
|
+ * time_t and back to time64_t to check for information loss. If so,
|
||||||
|
+ * we print the raw value; otherwise we print a human-readable value.
|
||||||
|
+ */
|
||||||
|
+ if (tt_sec != sec)
|
||||||
|
+ goto raw;
|
||||||
|
+
|
||||||
|
+ c = ctime(&tt);
|
||||||
|
+ if (!c)
|
||||||
|
+ goto raw;
|
||||||
|
+
|
||||||
|
+ dbprintf("%24.24s", c);
|
||||||
|
+ return;
|
||||||
|
+raw:
|
||||||
|
+ dbprintf("%lld", sec);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int
|
||||||
|
fp_time(
|
||||||
|
void *obj,
|
||||||
|
@@ -138,7 +167,7 @@ fp_time(
|
||||||
|
ts = obj + byteize(bitpos);
|
||||||
|
tv = libxfs_inode_from_disk_ts(obj, *ts);
|
||||||
|
|
||||||
|
- dbprintf("%24.24s", tv.tv_sec);
|
||||||
|
+ fp_time64(tv.tv_sec);
|
||||||
|
|
||||||
|
if (i < count - 1)
|
||||||
|
dbprintf(" ");
|
||||||
|
@@ -191,7 +220,8 @@ fp_qtimer(
|
||||||
|
int base,
|
||||||
|
int array)
|
||||||
|
{
|
||||||
|
- uint32_t sec;
|
||||||
|
+ struct xfs_disk_dquot *ddq = obj;
|
||||||
|
+ time64_t sec;
|
||||||
|
__be32 *t;
|
||||||
|
int bitpos;
|
||||||
|
int i;
|
||||||
|
@@ -204,9 +234,16 @@ fp_qtimer(
|
||||||
|
dbprintf("%d:", i + base);
|
||||||
|
|
||||||
|
t = obj + byteize(bitpos);
|
||||||
|
- sec = be32_to_cpu(*t);
|
||||||
|
+ sec = libxfs_dquot_from_disk_ts(ddq, *t);
|
||||||
|
|
||||||
|
- dbprintf("%u", sec);
|
||||||
|
+ /*
|
||||||
|
+ * Display the raw value if it's the default grace expiration
|
||||||
|
+ * period (root dquot) or if the quota has not expired.
|
||||||
|
+ */
|
||||||
|
+ if (ddq->d_id == 0 || sec == 0)
|
||||||
|
+ dbprintf("%lld", sec);
|
||||||
|
+ else
|
||||||
|
+ fp_time64(sec);
|
||||||
|
|
||||||
|
if (i < count - 1)
|
||||||
|
dbprintf(" ");
|
||||||
|
diff --git a/db/inode.c b/db/inode.c
|
||||||
|
index bbfee74..37c7dc0 100644
|
||||||
|
--- a/db/inode.c
|
||||||
|
+++ b/db/inode.c
|
||||||
|
@@ -172,10 +172,12 @@ const field_t inode_v3_flds[] = {
|
||||||
|
{ "cowextsz", FLDT_UINT1,
|
||||||
|
OI(COFF(flags2) + bitsz(uint64_t) - XFS_DIFLAG2_COWEXTSIZE_BIT-1), C1,
|
||||||
|
0, TYP_NONE },
|
||||||
|
+ { "bigtime", FLDT_UINT1,
|
||||||
|
+ OI(COFF(flags2) + bitsz(uint64_t) - XFS_DIFLAG2_BIGTIME_BIT - 1), C1,
|
||||||
|
+ 0, TYP_NONE },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
-
|
||||||
|
const field_t timestamp_flds[] = {
|
||||||
|
{ "sec", FLDT_TIME, OI(0), C1, 0, TYP_NONE },
|
||||||
|
{ "nsec", FLDT_NSEC, OI(0), C1, 0, TYP_NONE },
|
||||||
|
diff --git a/db/sb.c b/db/sb.c
|
||||||
|
index d63fc71..109fdc3 100644
|
||||||
|
--- a/db/sb.c
|
||||||
|
+++ b/db/sb.c
|
||||||
|
@@ -689,6 +689,8 @@ version_string(
|
||||||
|
strcat(s, ",REFLINK");
|
||||||
|
if (xfs_sb_version_hasinobtcounts(sbp))
|
||||||
|
strcat(s, ",INOBTCNT");
|
||||||
|
+ if (xfs_sb_version_hasbigtime(sbp))
|
||||||
|
+ strcat(s, ",BIGTIME");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
|||||||
|
From 13b8917251601e06660ed6ebe6bdeafa4c431ca3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 20 Nov 2020 17:03:27 -0500
|
||||||
|
Subject: [PATCH] xfs_db: support displaying inode btree block counts in AGI
|
||||||
|
header
|
||||||
|
|
||||||
|
Fix up xfs_db to support displaying the btree block counts.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Brian Foster <bfoster@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/db/agi.c b/db/agi.c
|
||||||
|
index bf21b2d..cfb4f7b 100644
|
||||||
|
--- a/db/agi.c
|
||||||
|
+++ b/db/agi.c
|
||||||
|
@@ -48,6 +48,8 @@ const field_t agi_flds[] = {
|
||||||
|
{ "lsn", FLDT_UINT64X, OI(OFF(lsn)), C1, 0, TYP_NONE },
|
||||||
|
{ "free_root", FLDT_AGBLOCK, OI(OFF(free_root)), C1, 0, TYP_FINOBT },
|
||||||
|
{ "free_level", FLDT_UINT32D, OI(OFF(free_level)), C1, 0, TYP_NONE },
|
||||||
|
+ { "ino_blocks", FLDT_UINT32D, OI(OFF(iblocks)), C1, 0, TYP_NONE },
|
||||||
|
+ { "fino_blocks", FLDT_UINT32D, OI(OFF(fblocks)), C1, 0, TYP_NONE },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
diff --git a/db/sb.c b/db/sb.c
|
||||||
|
index 5059b26..d63fc71 100644
|
||||||
|
--- a/db/sb.c
|
||||||
|
+++ b/db/sb.c
|
||||||
|
@@ -687,6 +687,8 @@ version_string(
|
||||||
|
strcat(s, ",RMAPBT");
|
||||||
|
if (xfs_sb_version_hasreflink(sbp))
|
||||||
|
strcat(s, ",REFLINK");
|
||||||
|
+ if (xfs_sb_version_hasinobtcounts(sbp))
|
||||||
|
+ strcat(s, ",INOBTCNT");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,245 @@
|
|||||||
|
From 4893718570dac172f639cc5e8687e782c4f759ee Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 20 Nov 2020 17:03:28 -0500
|
||||||
|
Subject: [PATCH] xfs_db: support printing time limits
|
||||||
|
|
||||||
|
Support printing the minimum and maxium timestamp limits on this
|
||||||
|
filesystem.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/db/Makefile b/db/Makefile
|
||||||
|
index 8fecfc1..68ab659 100644
|
||||||
|
--- a/db/Makefile
|
||||||
|
+++ b/db/Makefile
|
||||||
|
@@ -14,7 +14,7 @@ HFILES = addr.h agf.h agfl.h agi.h attr.h attrshort.h bit.h block.h bmap.h \
|
||||||
|
io.h logformat.h malloc.h metadump.h output.h print.h quit.h sb.h \
|
||||||
|
sig.h strvec.h text.h type.h write.h attrset.h symlink.h fsmap.h \
|
||||||
|
fuzz.h
|
||||||
|
-CFILES = $(HFILES:.h=.c) btdump.c info.c
|
||||||
|
+CFILES = $(HFILES:.h=.c) btdump.c info.c timelimit.c
|
||||||
|
LSRCFILES = xfs_admin.sh xfs_ncheck.sh xfs_metadump.sh
|
||||||
|
|
||||||
|
LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBFROG) $(LIBUUID) $(LIBRT) $(LIBPTHREAD)
|
||||||
|
diff --git a/db/command.c b/db/command.c
|
||||||
|
index c7c5234..73b06a7 100644
|
||||||
|
--- a/db/command.c
|
||||||
|
+++ b/db/command.c
|
||||||
|
@@ -139,4 +139,5 @@ init_commands(void)
|
||||||
|
write_init();
|
||||||
|
dquot_init();
|
||||||
|
fuzz_init();
|
||||||
|
+ timelimit_init();
|
||||||
|
}
|
||||||
|
diff --git a/db/command.h b/db/command.h
|
||||||
|
index eacfd46..1a9b4d2 100644
|
||||||
|
--- a/db/command.h
|
||||||
|
+++ b/db/command.h
|
||||||
|
@@ -30,3 +30,4 @@ extern void init_commands(void);
|
||||||
|
|
||||||
|
extern void btdump_init(void);
|
||||||
|
extern void info_init(void);
|
||||||
|
+extern void timelimit_init(void);
|
||||||
|
diff --git a/db/timelimit.c b/db/timelimit.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..53a0a39
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/db/timelimit.c
|
||||||
|
@@ -0,0 +1,160 @@
|
||||||
|
+// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
+/*
|
||||||
|
+ * Copyright (C) 2020 Oracle. All Rights Reserved.
|
||||||
|
+ * Author: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
+ */
|
||||||
|
+#include "libxfs.h"
|
||||||
|
+#include "command.h"
|
||||||
|
+#include "output.h"
|
||||||
|
+#include "init.h"
|
||||||
|
+
|
||||||
|
+enum show_what {
|
||||||
|
+ SHOW_AUTO,
|
||||||
|
+ SHOW_CLASSIC,
|
||||||
|
+ SHOW_BIGTIME,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+enum print_how {
|
||||||
|
+ PRINT_RAW,
|
||||||
|
+ PRINT_PRETTY,
|
||||||
|
+ PRINT_COMPACT,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+show_limit(
|
||||||
|
+ const char *tag,
|
||||||
|
+ int64_t limit,
|
||||||
|
+ enum print_how how)
|
||||||
|
+{
|
||||||
|
+ if (how == PRINT_COMPACT) {
|
||||||
|
+ dbprintf("%" PRId64 " ", limit);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (how == PRINT_PRETTY && limit <= LONG_MAX && limit >= LONG_MIN) {
|
||||||
|
+ time_t tt = limit;
|
||||||
|
+ char *c;
|
||||||
|
+
|
||||||
|
+ c = ctime(&tt);
|
||||||
|
+ if (c) {
|
||||||
|
+ dbprintf("%s = %24.24s\n", tag, c);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dbprintf("%s = %" PRId64 "\n", tag, limit);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+show_limits(
|
||||||
|
+ enum show_what whatkind,
|
||||||
|
+ enum print_how how)
|
||||||
|
+{
|
||||||
|
+ enum print_how grace_how = how;
|
||||||
|
+
|
||||||
|
+ switch (whatkind) {
|
||||||
|
+ case SHOW_AUTO:
|
||||||
|
+ /* should never get here */
|
||||||
|
+ break;
|
||||||
|
+ case SHOW_CLASSIC:
|
||||||
|
+ show_limit("time.min", XFS_LEGACY_TIME_MIN, how);
|
||||||
|
+ show_limit("time.max", XFS_LEGACY_TIME_MAX, how);
|
||||||
|
+ show_limit("dqtimer.min", XFS_DQ_LEGACY_EXPIRY_MIN, how);
|
||||||
|
+ show_limit("dqtimer.max", XFS_DQ_LEGACY_EXPIRY_MAX, how);
|
||||||
|
+ break;
|
||||||
|
+ case SHOW_BIGTIME:
|
||||||
|
+ show_limit("time.min",
|
||||||
|
+ xfs_bigtime_to_unix(XFS_BIGTIME_TIME_MIN), how);
|
||||||
|
+ show_limit("time.max",
|
||||||
|
+ xfs_bigtime_to_unix(XFS_BIGTIME_TIME_MAX), how);
|
||||||
|
+ show_limit("dqtimer.min",
|
||||||
|
+ xfs_dq_bigtime_to_unix(XFS_DQ_BIGTIME_EXPIRY_MIN),
|
||||||
|
+ how);
|
||||||
|
+ show_limit("dqtimer.max",
|
||||||
|
+ xfs_dq_bigtime_to_unix(XFS_DQ_BIGTIME_EXPIRY_MAX),
|
||||||
|
+ how);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* grace periods are always integers */
|
||||||
|
+ if (grace_how != PRINT_COMPACT)
|
||||||
|
+ grace_how = PRINT_RAW;
|
||||||
|
+ show_limit("dqgrace.min", XFS_DQ_GRACE_MIN, grace_how);
|
||||||
|
+ show_limit("dqgrace.min", XFS_DQ_GRACE_MAX, grace_how);
|
||||||
|
+
|
||||||
|
+ if (how == PRINT_COMPACT)
|
||||||
|
+ dbprintf("\n");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+timelimit_f(
|
||||||
|
+ int argc,
|
||||||
|
+ char **argv)
|
||||||
|
+{
|
||||||
|
+ enum show_what whatkind = SHOW_AUTO;
|
||||||
|
+ enum print_how how = PRINT_RAW;
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ for (i = 1; i < argc; i++) {
|
||||||
|
+ if (!strcmp("--classic", argv[i]))
|
||||||
|
+ whatkind = SHOW_CLASSIC;
|
||||||
|
+ else if (!strcmp("--bigtime", argv[i]))
|
||||||
|
+ whatkind = SHOW_BIGTIME;
|
||||||
|
+ else if (!strcmp("--pretty", argv[i]))
|
||||||
|
+ how = PRINT_PRETTY;
|
||||||
|
+ else if (!strcmp("--compact", argv[i]))
|
||||||
|
+ how = PRINT_COMPACT;
|
||||||
|
+ else {
|
||||||
|
+ dbprintf(_("%s: bad option for timelimit command\n"),
|
||||||
|
+ argv[i]);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (whatkind == SHOW_AUTO) {
|
||||||
|
+ if (xfs_sb_version_hasbigtime(&mp->m_sb))
|
||||||
|
+ whatkind = SHOW_BIGTIME;
|
||||||
|
+ else
|
||||||
|
+ whatkind = SHOW_CLASSIC;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ show_limits(whatkind, how);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+timelimit_help(void)
|
||||||
|
+{
|
||||||
|
+ dbprintf(_(
|
||||||
|
+"\n"
|
||||||
|
+" Print the minimum and maximum supported values for inode timestamps,\n"
|
||||||
|
+" disk quota expiration timers, and disk quota grace periods supported\n"
|
||||||
|
+" by this filesystem.\n"
|
||||||
|
+"\n"
|
||||||
|
+" Options:\n"
|
||||||
|
+" --classic -- Force printing of the classic time limits.\n"
|
||||||
|
+" --bigtime -- Force printing of the bigtime limits.\n"
|
||||||
|
+" --pretty -- Pretty-print the time limits.\n"
|
||||||
|
+" --compact -- Print the limits in a single line.\n"
|
||||||
|
+"\n"
|
||||||
|
+));
|
||||||
|
+
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const cmdinfo_t timelimit_cmd = {
|
||||||
|
+ .name = "timelimit",
|
||||||
|
+ .cfunc = timelimit_f,
|
||||||
|
+ .argmin = 0,
|
||||||
|
+ .argmax = -1,
|
||||||
|
+ .canpush = 0,
|
||||||
|
+ .args = N_("[--classic|--bigtime] [--pretty]"),
|
||||||
|
+ .oneline = N_("display timestamp limits"),
|
||||||
|
+ .help = timelimit_help,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+timelimit_init(void)
|
||||||
|
+{
|
||||||
|
+ add_command(&timelimit_cmd);
|
||||||
|
+}
|
||||||
|
diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8
|
||||||
|
index a1ee351..f46e936 100644
|
||||||
|
--- a/man/man8/xfs_db.8
|
||||||
|
+++ b/man/man8/xfs_db.8
|
||||||
|
@@ -785,6 +785,29 @@ The possible data types are:
|
||||||
|
.BR rtsummary ", " sb ", " symlink " and " text .
|
||||||
|
See the TYPES section below for more information on these data types.
|
||||||
|
.TP
|
||||||
|
+.BI "timelimit [" OPTIONS ]
|
||||||
|
+Print the minimum and maximum supported values for inode timestamps,
|
||||||
|
+quota expiration timers, and quota grace periods supported by this
|
||||||
|
+filesystem.
|
||||||
|
+Options include:
|
||||||
|
+.RS 1.0i
|
||||||
|
+.TP 0.4i
|
||||||
|
+.B \--bigtime
|
||||||
|
+Print the time limits of an XFS filesystem with the
|
||||||
|
+.B bigtime
|
||||||
|
+feature enabled.
|
||||||
|
+.TP 0.4i
|
||||||
|
+.B \--classic
|
||||||
|
+Print the time limits of a classic XFS filesystem.
|
||||||
|
+.TP 0.4i
|
||||||
|
+.B \--compact
|
||||||
|
+Print all limits as raw values on a single line.
|
||||||
|
+.TP 0.4i
|
||||||
|
+.B \--pretty
|
||||||
|
+Print the timestamps in the current locale's date and time format instead of
|
||||||
|
+raw seconds since the Unix epoch.
|
||||||
|
+.RE
|
||||||
|
+.TP
|
||||||
|
.BI "uuid [" uuid " | " generate " | " rewrite " | " restore ]
|
||||||
|
Set the filesystem universally unique identifier (UUID).
|
||||||
|
The filesystem UUID can be used by
|
@ -0,0 +1,199 @@
|
|||||||
|
From 219285adf56da85171fa90f42714341484750856 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 20 Nov 2020 17:03:27 -0500
|
||||||
|
Subject: [PATCH] xfs_quota: convert time_to_string to use time64_t
|
||||||
|
|
||||||
|
Rework the time_to_string helper to be capable of dealing with 64-bit
|
||||||
|
timestamps.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/quota/quota.c b/quota/quota.c
|
||||||
|
index 9545cc4..8ba0995 100644
|
||||||
|
--- a/quota/quota.c
|
||||||
|
+++ b/quota/quota.c
|
||||||
|
@@ -48,6 +48,7 @@ quota_mount(
|
||||||
|
uint flags)
|
||||||
|
{
|
||||||
|
fs_disk_quota_t d;
|
||||||
|
+ time64_t timer;
|
||||||
|
char *dev = mount->fs_name;
|
||||||
|
char c[8], h[8], s[8];
|
||||||
|
uint qflags;
|
||||||
|
@@ -100,6 +101,7 @@ quota_mount(
|
||||||
|
}
|
||||||
|
|
||||||
|
if (form & XFS_BLOCK_QUOTA) {
|
||||||
|
+ timer = d.d_btimer;
|
||||||
|
qflags = (flags & HUMAN_FLAG);
|
||||||
|
if (d.d_blk_hardlimit && d.d_bcount > d.d_blk_hardlimit)
|
||||||
|
qflags |= LIMIT_FLAG;
|
||||||
|
@@ -111,16 +113,17 @@ quota_mount(
|
||||||
|
bbs_to_string(d.d_blk_softlimit, s, sizeof(s)),
|
||||||
|
bbs_to_string(d.d_blk_hardlimit, h, sizeof(h)),
|
||||||
|
d.d_bwarns,
|
||||||
|
- time_to_string(d.d_btimer, qflags));
|
||||||
|
+ time_to_string(timer, qflags));
|
||||||
|
else
|
||||||
|
fprintf(fp, " %10llu %10llu %10llu %02d %9s ",
|
||||||
|
(unsigned long long)d.d_bcount >> 1,
|
||||||
|
(unsigned long long)d.d_blk_softlimit >> 1,
|
||||||
|
(unsigned long long)d.d_blk_hardlimit >> 1,
|
||||||
|
d.d_bwarns,
|
||||||
|
- time_to_string(d.d_btimer, qflags));
|
||||||
|
+ time_to_string(timer, qflags));
|
||||||
|
}
|
||||||
|
if (form & XFS_INODE_QUOTA) {
|
||||||
|
+ timer = d.d_itimer;
|
||||||
|
qflags = (flags & HUMAN_FLAG);
|
||||||
|
if (d.d_ino_hardlimit && d.d_icount > d.d_ino_hardlimit)
|
||||||
|
qflags |= LIMIT_FLAG;
|
||||||
|
@@ -132,16 +135,17 @@ quota_mount(
|
||||||
|
num_to_string(d.d_ino_softlimit, s, sizeof(s)),
|
||||||
|
num_to_string(d.d_ino_hardlimit, h, sizeof(h)),
|
||||||
|
d.d_iwarns,
|
||||||
|
- time_to_string(d.d_itimer, qflags));
|
||||||
|
+ time_to_string(timer, qflags));
|
||||||
|
else
|
||||||
|
fprintf(fp, " %10llu %10llu %10llu %02d %9s ",
|
||||||
|
(unsigned long long)d.d_icount,
|
||||||
|
(unsigned long long)d.d_ino_softlimit,
|
||||||
|
(unsigned long long)d.d_ino_hardlimit,
|
||||||
|
d.d_iwarns,
|
||||||
|
- time_to_string(d.d_itimer, qflags));
|
||||||
|
+ time_to_string(timer, qflags));
|
||||||
|
}
|
||||||
|
if (form & XFS_RTBLOCK_QUOTA) {
|
||||||
|
+ timer = d.d_rtbtimer;
|
||||||
|
qflags = (flags & HUMAN_FLAG);
|
||||||
|
if (d.d_rtb_hardlimit && d.d_rtbcount > d.d_rtb_hardlimit)
|
||||||
|
qflags |= LIMIT_FLAG;
|
||||||
|
@@ -153,14 +157,14 @@ quota_mount(
|
||||||
|
bbs_to_string(d.d_rtb_softlimit, s, sizeof(s)),
|
||||||
|
bbs_to_string(d.d_rtb_hardlimit, h, sizeof(h)),
|
||||||
|
d.d_rtbwarns,
|
||||||
|
- time_to_string(d.d_rtbtimer, qflags));
|
||||||
|
+ time_to_string(timer, qflags));
|
||||||
|
else
|
||||||
|
fprintf(fp, " %10llu %10llu %10llu %02d %9s ",
|
||||||
|
(unsigned long long)d.d_rtbcount >> 1,
|
||||||
|
(unsigned long long)d.d_rtb_softlimit >> 1,
|
||||||
|
(unsigned long long)d.d_rtb_hardlimit >> 1,
|
||||||
|
d.d_rtbwarns,
|
||||||
|
- time_to_string(d.d_rtbtimer, qflags));
|
||||||
|
+ time_to_string(timer, qflags));
|
||||||
|
}
|
||||||
|
fprintf(fp, "%s\n", mount->fs_dir);
|
||||||
|
return 1;
|
||||||
|
diff --git a/quota/quota.h b/quota/quota.h
|
||||||
|
index b7f259e..13ae450 100644
|
||||||
|
--- a/quota/quota.h
|
||||||
|
+++ b/quota/quota.h
|
||||||
|
@@ -40,7 +40,7 @@ enum {
|
||||||
|
*/
|
||||||
|
extern char *type_to_string(uint __type);
|
||||||
|
extern char *form_to_string(uint __form);
|
||||||
|
-extern char *time_to_string(time_t __time, uint __flags);
|
||||||
|
+extern char *time_to_string(time64_t __time, uint __flags);
|
||||||
|
extern char *bbs_to_string(uint64_t __v, char *__c, uint __size);
|
||||||
|
extern char *num_to_string(uint64_t __v, char *__c, uint __size);
|
||||||
|
extern char *pct_to_string(uint64_t __v, uint64_t __t, char *__c, uint __s);
|
||||||
|
diff --git a/quota/report.c b/quota/report.c
|
||||||
|
index e6def91..2d5024e 100644
|
||||||
|
--- a/quota/report.c
|
||||||
|
+++ b/quota/report.c
|
||||||
|
@@ -330,6 +330,7 @@ report_mount(
|
||||||
|
uint flags)
|
||||||
|
{
|
||||||
|
fs_disk_quota_t d;
|
||||||
|
+ time64_t timer;
|
||||||
|
char *dev = mount->fs_name;
|
||||||
|
char c[8], h[8], s[8];
|
||||||
|
uint qflags;
|
||||||
|
@@ -397,6 +398,7 @@ report_mount(
|
||||||
|
}
|
||||||
|
|
||||||
|
if (form & XFS_BLOCK_QUOTA) {
|
||||||
|
+ timer = d.d_btimer;
|
||||||
|
qflags = (flags & HUMAN_FLAG);
|
||||||
|
if (d.d_blk_hardlimit && d.d_bcount > d.d_blk_hardlimit)
|
||||||
|
qflags |= LIMIT_FLAG;
|
||||||
|
@@ -408,16 +410,17 @@ report_mount(
|
||||||
|
bbs_to_string(d.d_blk_softlimit, s, sizeof(s)),
|
||||||
|
bbs_to_string(d.d_blk_hardlimit, h, sizeof(h)),
|
||||||
|
d.d_bwarns,
|
||||||
|
- time_to_string(d.d_btimer, qflags));
|
||||||
|
+ time_to_string(timer, qflags));
|
||||||
|
else
|
||||||
|
fprintf(fp, " %10llu %10llu %10llu %02d %9s",
|
||||||
|
(unsigned long long)d.d_bcount >> 1,
|
||||||
|
(unsigned long long)d.d_blk_softlimit >> 1,
|
||||||
|
(unsigned long long)d.d_blk_hardlimit >> 1,
|
||||||
|
d.d_bwarns,
|
||||||
|
- time_to_string(d.d_btimer, qflags));
|
||||||
|
+ time_to_string(timer, qflags));
|
||||||
|
}
|
||||||
|
if (form & XFS_INODE_QUOTA) {
|
||||||
|
+ timer = d.d_itimer;
|
||||||
|
qflags = (flags & HUMAN_FLAG);
|
||||||
|
if (d.d_ino_hardlimit && d.d_icount > d.d_ino_hardlimit)
|
||||||
|
qflags |= LIMIT_FLAG;
|
||||||
|
@@ -429,16 +432,17 @@ report_mount(
|
||||||
|
num_to_string(d.d_ino_softlimit, s, sizeof(s)),
|
||||||
|
num_to_string(d.d_ino_hardlimit, h, sizeof(h)),
|
||||||
|
d.d_iwarns,
|
||||||
|
- time_to_string(d.d_itimer, qflags));
|
||||||
|
+ time_to_string(timer, qflags));
|
||||||
|
else
|
||||||
|
fprintf(fp, " %10llu %10llu %10llu %02d %9s",
|
||||||
|
(unsigned long long)d.d_icount,
|
||||||
|
(unsigned long long)d.d_ino_softlimit,
|
||||||
|
(unsigned long long)d.d_ino_hardlimit,
|
||||||
|
d.d_iwarns,
|
||||||
|
- time_to_string(d.d_itimer, qflags));
|
||||||
|
+ time_to_string(timer, qflags));
|
||||||
|
}
|
||||||
|
if (form & XFS_RTBLOCK_QUOTA) {
|
||||||
|
+ timer = d.d_rtbtimer;
|
||||||
|
qflags = (flags & HUMAN_FLAG);
|
||||||
|
if (d.d_rtb_hardlimit && d.d_rtbcount > d.d_rtb_hardlimit)
|
||||||
|
qflags |= LIMIT_FLAG;
|
||||||
|
@@ -450,14 +454,14 @@ report_mount(
|
||||||
|
bbs_to_string(d.d_rtb_softlimit, s, sizeof(s)),
|
||||||
|
bbs_to_string(d.d_rtb_hardlimit, h, sizeof(h)),
|
||||||
|
d.d_rtbwarns,
|
||||||
|
- time_to_string(d.d_rtbtimer, qflags));
|
||||||
|
+ time_to_string(timer, qflags));
|
||||||
|
else
|
||||||
|
fprintf(fp, " %10llu %10llu %10llu %02d %9s",
|
||||||
|
(unsigned long long)d.d_rtbcount >> 1,
|
||||||
|
(unsigned long long)d.d_rtb_softlimit >> 1,
|
||||||
|
(unsigned long long)d.d_rtb_hardlimit >> 1,
|
||||||
|
d.d_rtbwarns,
|
||||||
|
- time_to_string(d.d_rtbtimer, qflags));
|
||||||
|
+ time_to_string(timer, qflags));
|
||||||
|
}
|
||||||
|
fputc('\n', fp);
|
||||||
|
return 1;
|
||||||
|
diff --git a/quota/util.c b/quota/util.c
|
||||||
|
index 50470ab..361d2a8 100644
|
||||||
|
--- a/quota/util.c
|
||||||
|
+++ b/quota/util.c
|
||||||
|
@@ -18,11 +18,12 @@
|
||||||
|
|
||||||
|
char *
|
||||||
|
time_to_string(
|
||||||
|
- time_t origin,
|
||||||
|
+ time64_t origin,
|
||||||
|
uint flags)
|
||||||
|
{
|
||||||
|
static char timestamp[32];
|
||||||
|
- time_t now, timer;
|
||||||
|
+ time64_t timer;
|
||||||
|
+ time_t now;
|
||||||
|
uint days, hours, minutes, seconds;
|
||||||
|
|
||||||
|
if (flags & ABSOLUTE_FLAG) {
|
@ -0,0 +1,35 @@
|
|||||||
|
From 0d7b09ac95e4cde766a534fdb7ea8dd46451ad53 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Date: Fri, 4 Dec 2020 12:17:12 -0500
|
||||||
|
Subject: [PATCH] xfs_quota: document how the default quota is stored
|
||||||
|
|
||||||
|
Nowhere in the man page is the default quota described; what it
|
||||||
|
does or where it is stored. Add some brief information about this.
|
||||||
|
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
man/man8/xfs_quota.8 | 6 ++++++
|
||||||
|
1 file changed, 6 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/man/man8/xfs_quota.8 b/man/man8/xfs_quota.8
|
||||||
|
index dd0479cd..6ead7ee9 100644
|
||||||
|
--- a/man/man8/xfs_quota.8
|
||||||
|
+++ b/man/man8/xfs_quota.8
|
||||||
|
@@ -178,6 +178,12 @@ to a file on
|
||||||
|
where the user's quota has not been exceeded.
|
||||||
|
Then after rectifying the quota situation, the file can be moved back to the
|
||||||
|
filesystem it belongs on.
|
||||||
|
+.SS Default Quotas
|
||||||
|
+The XFS quota subsystem allows a default quota to be enforced
|
||||||
|
+for any user, group or project which does not have a quota limit
|
||||||
|
+explicitly set.
|
||||||
|
+These limits are stored in and displayed as ID 0's limits, although they
|
||||||
|
+do not actually limit ID 0.
|
||||||
|
.SH USER COMMANDS
|
||||||
|
.TP
|
||||||
|
.B print
|
||||||
|
--
|
||||||
|
2.29.2
|
||||||
|
|
@ -0,0 +1,236 @@
|
|||||||
|
From f3eb31d9c005558ce975e2806f8dc73b0ecbd7f7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 20 Nov 2020 17:03:28 -0500
|
||||||
|
Subject: [PATCH] xfs_quota: support editing and reporting quotas with bigtime
|
||||||
|
|
||||||
|
Enhance xfs_quota to detect and report grace period expirations past
|
||||||
|
2038.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/include/xqm.h b/include/xqm.h
|
||||||
|
index 8ab1907..573441d 100644
|
||||||
|
--- a/include/xqm.h
|
||||||
|
+++ b/include/xqm.h
|
||||||
|
@@ -47,7 +47,10 @@ typedef struct fs_disk_quota {
|
||||||
|
__s32 d_btimer; /* similar to above; for disk blocks */
|
||||||
|
__u16 d_iwarns; /* # warnings issued wrt num inodes */
|
||||||
|
__u16 d_bwarns; /* # warnings issued wrt disk blocks */
|
||||||
|
- __s32 d_padding2; /* padding2 - for future use */
|
||||||
|
+ __s8 d_itimer_hi; /* upper 8 bits of timer values */
|
||||||
|
+ __s8 d_btimer_hi;
|
||||||
|
+ __s8 d_rtbtimer_hi;
|
||||||
|
+ __s8 d_padding2; /* padding2 - for future use */
|
||||||
|
__u64 d_rtb_hardlimit;/* absolute limit on realtime blks */
|
||||||
|
__u64 d_rtb_softlimit;/* preferred limit on RT disk blks */
|
||||||
|
__u64 d_rtbcount; /* # realtime blocks owned */
|
||||||
|
@@ -93,6 +96,21 @@ typedef struct fs_disk_quota {
|
||||||
|
#define FS_DQ_RTBWARNS (1<<11)
|
||||||
|
#define FS_DQ_WARNS_MASK (FS_DQ_BWARNS | FS_DQ_IWARNS | FS_DQ_RTBWARNS)
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Accounting values. These can only be set for filesystem with
|
||||||
|
+ * non-transactional quotas that require quotacheck(8) in userspace.
|
||||||
|
+ */
|
||||||
|
+#define FS_DQ_BCOUNT (1<<12)
|
||||||
|
+#define FS_DQ_ICOUNT (1<<13)
|
||||||
|
+#define FS_DQ_RTBCOUNT (1<<14)
|
||||||
|
+#define FS_DQ_ACCT_MASK (FS_DQ_BCOUNT | FS_DQ_ICOUNT | FS_DQ_RTBCOUNT)
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Quota expiration timestamps are 40-bit signed integers, with the upper 8
|
||||||
|
+ * bits encoded in the _hi fields.
|
||||||
|
+ */
|
||||||
|
+#define FS_DQ_BIGTIME (1<<15)
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Various flags related to quotactl(2). Only relevant to XFS filesystems.
|
||||||
|
*/
|
||||||
|
diff --git a/quota/edit.c b/quota/edit.c
|
||||||
|
index b3cad02..1a3b2d9 100644
|
||||||
|
--- a/quota/edit.c
|
||||||
|
+++ b/quota/edit.c
|
||||||
|
@@ -417,6 +417,53 @@ restore_f(
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+time64_t
|
||||||
|
+decode_timer(
|
||||||
|
+ const struct fs_disk_quota *d,
|
||||||
|
+ __s32 timer_lo,
|
||||||
|
+ __s8 timer_hi)
|
||||||
|
+{
|
||||||
|
+ if (d->d_fieldmask & FS_DQ_BIGTIME)
|
||||||
|
+ return (uint32_t)timer_lo | (int64_t)timer_hi << 32;
|
||||||
|
+ return timer_lo;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline void
|
||||||
|
+encode_timer(
|
||||||
|
+ const struct fs_disk_quota *d,
|
||||||
|
+ __s32 *timer_lo,
|
||||||
|
+ __s8 *timer_hi,
|
||||||
|
+ time64_t timer)
|
||||||
|
+{
|
||||||
|
+ *timer_lo = timer;
|
||||||
|
+ if (d->d_fieldmask & FS_DQ_BIGTIME)
|
||||||
|
+ *timer_hi = timer >> 32;
|
||||||
|
+ else
|
||||||
|
+ *timer_hi = 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline bool want_bigtime(time64_t timer)
|
||||||
|
+{
|
||||||
|
+ return timer > INT32_MAX || timer < INT32_MIN;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+encode_timers(
|
||||||
|
+ struct fs_disk_quota *d,
|
||||||
|
+ time64_t btimer,
|
||||||
|
+ time64_t itimer,
|
||||||
|
+ time64_t rtbtimer)
|
||||||
|
+{
|
||||||
|
+ d->d_fieldmask &= ~FS_DQ_BIGTIME;
|
||||||
|
+ if (want_bigtime(btimer) || want_bigtime(itimer) ||
|
||||||
|
+ want_bigtime(rtbtimer))
|
||||||
|
+ d->d_fieldmask |= FS_DQ_BIGTIME;
|
||||||
|
+
|
||||||
|
+ encode_timer(d, &d->d_btimer, &d->d_btimer_hi, btimer);
|
||||||
|
+ encode_timer(d, &d->d_itimer, &d->d_itimer_hi, itimer);
|
||||||
|
+ encode_timer(d, &d->d_rtbtimer, &d->d_rtbtimer_hi, rtbtimer);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
set_timer(
|
||||||
|
uint32_t id,
|
||||||
|
@@ -426,6 +473,7 @@ set_timer(
|
||||||
|
time64_t value)
|
||||||
|
{
|
||||||
|
struct fs_disk_quota d;
|
||||||
|
+ time64_t btimer, itimer, rtbtimer;
|
||||||
|
|
||||||
|
memset(&d, 0, sizeof(d));
|
||||||
|
|
||||||
|
@@ -446,23 +494,28 @@ set_timer(
|
||||||
|
|
||||||
|
time(&now);
|
||||||
|
|
||||||
|
+ btimer = decode_timer(&d, d.d_btimer, d.d_btimer_hi);
|
||||||
|
+ itimer = decode_timer(&d, d.d_itimer, d.d_itimer_hi);
|
||||||
|
+ rtbtimer = decode_timer(&d, d.d_rtbtimer, d.d_rtbtimer_hi);
|
||||||
|
+
|
||||||
|
/* Only set grace time if user is already past soft limit */
|
||||||
|
if (d.d_blk_softlimit && d.d_bcount > d.d_blk_softlimit)
|
||||||
|
- d.d_btimer = now + value;
|
||||||
|
+ btimer = now + value;
|
||||||
|
if (d.d_ino_softlimit && d.d_icount > d.d_ino_softlimit)
|
||||||
|
- d.d_itimer = now + value;
|
||||||
|
+ itimer = now + value;
|
||||||
|
if (d.d_rtb_softlimit && d.d_rtbcount > d.d_rtb_softlimit)
|
||||||
|
- d.d_rtbtimer = now + value;
|
||||||
|
+ rtbtimer = now + value;
|
||||||
|
} else {
|
||||||
|
- d.d_btimer = value;
|
||||||
|
- d.d_itimer = value;
|
||||||
|
- d.d_rtbtimer = value;
|
||||||
|
+ btimer = value;
|
||||||
|
+ itimer = value;
|
||||||
|
+ rtbtimer = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
d.d_version = FS_DQUOT_VERSION;
|
||||||
|
d.d_flags = type;
|
||||||
|
d.d_fieldmask = mask;
|
||||||
|
d.d_id = id;
|
||||||
|
+ encode_timers(&d, btimer, itimer, rtbtimer);
|
||||||
|
|
||||||
|
if (xfsquotactl(XFS_SETQLIM, dev, type, id, (void *)&d) < 0) {
|
||||||
|
exitcode = 1;
|
||||||
|
diff --git a/quota/quota.c b/quota/quota.c
|
||||||
|
index 8ba0995..0747ced 100644
|
||||||
|
--- a/quota/quota.c
|
||||||
|
+++ b/quota/quota.c
|
||||||
|
@@ -101,7 +101,7 @@ quota_mount(
|
||||||
|
}
|
||||||
|
|
||||||
|
if (form & XFS_BLOCK_QUOTA) {
|
||||||
|
- timer = d.d_btimer;
|
||||||
|
+ timer = decode_timer(&d, d.d_btimer, d.d_btimer_hi);
|
||||||
|
qflags = (flags & HUMAN_FLAG);
|
||||||
|
if (d.d_blk_hardlimit && d.d_bcount > d.d_blk_hardlimit)
|
||||||
|
qflags |= LIMIT_FLAG;
|
||||||
|
@@ -123,7 +123,7 @@ quota_mount(
|
||||||
|
time_to_string(timer, qflags));
|
||||||
|
}
|
||||||
|
if (form & XFS_INODE_QUOTA) {
|
||||||
|
- timer = d.d_itimer;
|
||||||
|
+ timer = decode_timer(&d, d.d_itimer, d.d_itimer_hi);
|
||||||
|
qflags = (flags & HUMAN_FLAG);
|
||||||
|
if (d.d_ino_hardlimit && d.d_icount > d.d_ino_hardlimit)
|
||||||
|
qflags |= LIMIT_FLAG;
|
||||||
|
@@ -145,7 +145,7 @@ quota_mount(
|
||||||
|
time_to_string(timer, qflags));
|
||||||
|
}
|
||||||
|
if (form & XFS_RTBLOCK_QUOTA) {
|
||||||
|
- timer = d.d_rtbtimer;
|
||||||
|
+ timer = decode_timer(&d, d.d_rtbtimer, d.d_rtbtimer_hi);
|
||||||
|
qflags = (flags & HUMAN_FLAG);
|
||||||
|
if (d.d_rtb_hardlimit && d.d_rtbcount > d.d_rtb_hardlimit)
|
||||||
|
qflags |= LIMIT_FLAG;
|
||||||
|
diff --git a/quota/quota.h b/quota/quota.h
|
||||||
|
index 13ae450..74eb146 100644
|
||||||
|
--- a/quota/quota.h
|
||||||
|
+++ b/quota/quota.h
|
||||||
|
@@ -3,6 +3,8 @@
|
||||||
|
* Copyright (c) 2005 Silicon Graphics, Inc.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*/
|
||||||
|
+#ifndef XFS_QUOTA_QUOTA_H_
|
||||||
|
+#define XFS_QUOTA_QUOTA_H_
|
||||||
|
|
||||||
|
#include "xqm.h"
|
||||||
|
#include "path.h"
|
||||||
|
@@ -73,3 +75,8 @@ extern char *uid_to_name(uint32_t __uid);
|
||||||
|
extern char *gid_to_name(uint32_t __gid);
|
||||||
|
extern char *prid_to_name(uint32_t __prid);
|
||||||
|
extern bool isdigits_only(const char *);
|
||||||
|
+
|
||||||
|
+time64_t decode_timer(const struct fs_disk_quota *d, __s32 timer_lo,
|
||||||
|
+ __s8 timer_hi);
|
||||||
|
+
|
||||||
|
+#endif /* XFS_QUOTA_QUOTA_H_ */
|
||||||
|
diff --git a/quota/report.c b/quota/report.c
|
||||||
|
index 2d5024e..6ac5549 100644
|
||||||
|
--- a/quota/report.c
|
||||||
|
+++ b/quota/report.c
|
||||||
|
@@ -398,7 +398,7 @@ report_mount(
|
||||||
|
}
|
||||||
|
|
||||||
|
if (form & XFS_BLOCK_QUOTA) {
|
||||||
|
- timer = d.d_btimer;
|
||||||
|
+ timer = decode_timer(&d, d.d_btimer, d.d_btimer_hi);
|
||||||
|
qflags = (flags & HUMAN_FLAG);
|
||||||
|
if (d.d_blk_hardlimit && d.d_bcount > d.d_blk_hardlimit)
|
||||||
|
qflags |= LIMIT_FLAG;
|
||||||
|
@@ -420,7 +420,7 @@ report_mount(
|
||||||
|
time_to_string(timer, qflags));
|
||||||
|
}
|
||||||
|
if (form & XFS_INODE_QUOTA) {
|
||||||
|
- timer = d.d_itimer;
|
||||||
|
+ timer = decode_timer(&d, d.d_itimer, d.d_itimer_hi);
|
||||||
|
qflags = (flags & HUMAN_FLAG);
|
||||||
|
if (d.d_ino_hardlimit && d.d_icount > d.d_ino_hardlimit)
|
||||||
|
qflags |= LIMIT_FLAG;
|
||||||
|
@@ -442,7 +442,7 @@ report_mount(
|
||||||
|
time_to_string(timer, qflags));
|
||||||
|
}
|
||||||
|
if (form & XFS_RTBLOCK_QUOTA) {
|
||||||
|
- timer = d.d_rtbtimer;
|
||||||
|
+ timer = decode_timer(&d, d.d_rtbtimer, d.d_rtbtimer_hi);
|
||||||
|
qflags = (flags & HUMAN_FLAG);
|
||||||
|
if (d.d_rtb_hardlimit && d.d_rtbcount > d.d_rtb_hardlimit)
|
||||||
|
qflags |= LIMIT_FLAG;
|
@ -0,0 +1,92 @@
|
|||||||
|
xfs_repair: Use proper min/max values in compute_level_geometry
|
||||||
|
|
||||||
|
When compute_level_geometry was added it exclusively uses
|
||||||
|
m_alloc_mnr/m_alloc_mxr but the rmap btree should be using
|
||||||
|
m_rmap_mnr/m_rmap_mxr. Pass those in directly to fix the
|
||||||
|
problem.
|
||||||
|
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/repair/phase5.c b/repair/phase5.c
|
||||||
|
index 0b8a55ff..dff342c8 100644
|
||||||
|
--- a/repair/phase5.c
|
||||||
|
+++ b/repair/phase5.c
|
||||||
|
@@ -355,12 +355,12 @@ compute_level_geometry(
|
||||||
|
struct bt_stat_level *lptr,
|
||||||
|
uint64_t nr_this_level,
|
||||||
|
int slack,
|
||||||
|
- bool leaf)
|
||||||
|
+ uint maxrecs,
|
||||||
|
+ uint minrecs)
|
||||||
|
{
|
||||||
|
- unsigned int maxrecs = mp->m_alloc_mxr[!leaf];
|
||||||
|
unsigned int desired_npb;
|
||||||
|
|
||||||
|
- desired_npb = max(mp->m_alloc_mnr[!leaf], maxrecs - slack);
|
||||||
|
+ desired_npb = max(minrecs, maxrecs - slack);
|
||||||
|
lptr->num_recs_tot = nr_this_level;
|
||||||
|
lptr->num_blocks = max(1ULL, nr_this_level / desired_npb);
|
||||||
|
|
||||||
|
@@ -410,7 +410,8 @@ calculate_freespace_cursor(xfs_mount_t *mp, xfs_agnumber_t agno,
|
||||||
|
* of the tree and set up the cursor for the leaf level
|
||||||
|
* (note that the same code is duplicated further down)
|
||||||
|
*/
|
||||||
|
- compute_level_geometry(mp, lptr, num_extents, 2, true);
|
||||||
|
+ compute_level_geometry(mp, lptr, num_extents, 2,
|
||||||
|
+ mp->m_alloc_mxr[0], mp->m_alloc_mnr[0]);
|
||||||
|
level = 1;
|
||||||
|
|
||||||
|
#ifdef XR_BLD_FREE_TRACE
|
||||||
|
@@ -429,7 +430,8 @@ calculate_freespace_cursor(xfs_mount_t *mp, xfs_agnumber_t agno,
|
||||||
|
lptr = &btree_curs->level[level];
|
||||||
|
|
||||||
|
compute_level_geometry(mp, lptr,
|
||||||
|
- p_lptr->num_blocks, 0, false);
|
||||||
|
+ p_lptr->num_blocks, 0,
|
||||||
|
+ mp->m_alloc_mxr[1], mp->m_alloc_mnr[1]);
|
||||||
|
#ifdef XR_BLD_FREE_TRACE
|
||||||
|
fprintf(stderr, "%s %d %d %d %d %d\n", __func__,
|
||||||
|
level,
|
||||||
|
@@ -509,7 +511,8 @@ calculate_freespace_cursor(xfs_mount_t *mp, xfs_agnumber_t agno,
|
||||||
|
* of the number of extents changing
|
||||||
|
*/
|
||||||
|
old_blocks = btree_curs->level[0].num_blocks;
|
||||||
|
- compute_level_geometry(mp, &btree_curs->level[0], num_extents, 2, true);
|
||||||
|
+ compute_level_geometry(mp, &btree_curs->level[0], num_extents, 2,
|
||||||
|
+ mp->m_alloc_mxr[0], mp->m_alloc_mnr[0]);
|
||||||
|
extra_blocks = 0;
|
||||||
|
|
||||||
|
if (old_blocks != btree_curs->level[0].num_blocks) {
|
||||||
|
@@ -578,7 +581,8 @@ calculate_freespace_cursor(xfs_mount_t *mp, xfs_agnumber_t agno,
|
||||||
|
lptr = &btree_curs->level[level++];
|
||||||
|
|
||||||
|
compute_level_geometry(mp, lptr,
|
||||||
|
- p_lptr->num_blocks, 0, false);
|
||||||
|
+ p_lptr->num_blocks, 0,
|
||||||
|
+ mp->m_alloc_mxr[1], mp->m_alloc_mnr[1]);
|
||||||
|
}
|
||||||
|
ASSERT(level < XFS_BTREE_MAXLEVELS);
|
||||||
|
ASSERT(lptr->num_blocks == 1);
|
||||||
|
@@ -1399,7 +1403,8 @@ init_rmapbt_cursor(
|
||||||
|
* metadata AG entries without too many splits.
|
||||||
|
*/
|
||||||
|
compute_level_geometry(mp, lptr, num_recs,
|
||||||
|
- num_recs > mp->m_rmap_mxr[0] ? 10 : 0, true);
|
||||||
|
+ num_recs > mp->m_rmap_mxr[0] ? 10 : 0,
|
||||||
|
+ mp->m_rmap_mxr[0], mp->m_rmap_mnr[0]);
|
||||||
|
blocks_allocated = lptr->num_blocks;
|
||||||
|
level = 1;
|
||||||
|
|
||||||
|
@@ -1408,7 +1413,8 @@ init_rmapbt_cursor(
|
||||||
|
lptr = &btree_curs->level[level++];
|
||||||
|
|
||||||
|
compute_level_geometry(mp, lptr,
|
||||||
|
- p_lptr->num_blocks, 0, false);
|
||||||
|
+ p_lptr->num_blocks, 0,
|
||||||
|
+ mp->m_rmap_mxr[1], mp->m_rmap_mnr[1]);
|
||||||
|
blocks_allocated += lptr->num_blocks;
|
||||||
|
}
|
||||||
|
ASSERT(level < XFS_BTREE_MAXLEVELS);
|
||||||
|
|
||||||
|
|
@ -0,0 +1,98 @@
|
|||||||
|
From 62c713cb0c7791717c0b2a663ff0cc72842fe6c7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 20 Nov 2020 17:03:27 -0500
|
||||||
|
Subject: [PATCH] xfs_repair: check inode btree block counters in AGI
|
||||||
|
|
||||||
|
Make sure that both inode btree block counters in the AGI are correct.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/repair/scan.c b/repair/scan.c
|
||||||
|
index 5b76212..086a3cd 100644
|
||||||
|
--- a/repair/scan.c
|
||||||
|
+++ b/repair/scan.c
|
||||||
|
@@ -1933,6 +1933,12 @@ _("invalid inode count, inode chunk %d/%u, count %d ninodes %d\n"),
|
||||||
|
return suspect;
|
||||||
|
}
|
||||||
|
|
||||||
|
+struct ino_priv {
|
||||||
|
+ struct aghdr_cnts *agcnts;
|
||||||
|
+ uint32_t ino_blocks;
|
||||||
|
+ uint32_t fino_blocks;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* this one walks the inode btrees sucking the info there into
|
||||||
|
* the incore avl tree. We try and rescue corrupted btree records
|
||||||
|
@@ -1961,7 +1967,8 @@ scan_inobt(
|
||||||
|
void *priv,
|
||||||
|
const struct xfs_buf_ops *ops)
|
||||||
|
{
|
||||||
|
- struct aghdr_cnts *agcnts = priv;
|
||||||
|
+ struct ino_priv *ipriv = priv;
|
||||||
|
+ struct aghdr_cnts *agcnts = ipriv->agcnts;
|
||||||
|
char *name;
|
||||||
|
int i;
|
||||||
|
int numrecs;
|
||||||
|
@@ -1977,10 +1984,12 @@ scan_inobt(
|
||||||
|
case XFS_FIBT_MAGIC:
|
||||||
|
case XFS_FIBT_CRC_MAGIC:
|
||||||
|
name = "fino";
|
||||||
|
+ ipriv->fino_blocks++;
|
||||||
|
break;
|
||||||
|
case XFS_IBT_MAGIC:
|
||||||
|
case XFS_IBT_CRC_MAGIC:
|
||||||
|
name = "ino";
|
||||||
|
+ ipriv->ino_blocks++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
name = "(unknown)";
|
||||||
|
@@ -2320,6 +2329,9 @@ validate_agi(
|
||||||
|
xfs_agnumber_t agno,
|
||||||
|
struct aghdr_cnts *agcnts)
|
||||||
|
{
|
||||||
|
+ struct ino_priv priv = {
|
||||||
|
+ .agcnts = agcnts,
|
||||||
|
+ };
|
||||||
|
xfs_agblock_t bno;
|
||||||
|
int i;
|
||||||
|
uint32_t magic;
|
||||||
|
@@ -2329,7 +2341,7 @@ validate_agi(
|
||||||
|
magic = xfs_sb_version_hascrc(&mp->m_sb) ? XFS_IBT_CRC_MAGIC
|
||||||
|
: XFS_IBT_MAGIC;
|
||||||
|
scan_sbtree(bno, be32_to_cpu(agi->agi_level),
|
||||||
|
- agno, 0, scan_inobt, 1, magic, agcnts,
|
||||||
|
+ agno, 0, scan_inobt, 1, magic, &priv,
|
||||||
|
&xfs_inobt_buf_ops);
|
||||||
|
} else {
|
||||||
|
do_warn(_("bad agbno %u for inobt root, agno %d\n"),
|
||||||
|
@@ -2342,7 +2354,7 @@ validate_agi(
|
||||||
|
magic = xfs_sb_version_hascrc(&mp->m_sb) ?
|
||||||
|
XFS_FIBT_CRC_MAGIC : XFS_FIBT_MAGIC;
|
||||||
|
scan_sbtree(bno, be32_to_cpu(agi->agi_free_level),
|
||||||
|
- agno, 0, scan_inobt, 1, magic, agcnts,
|
||||||
|
+ agno, 0, scan_inobt, 1, magic, &priv,
|
||||||
|
&xfs_inobt_buf_ops);
|
||||||
|
} else {
|
||||||
|
do_warn(_("bad agbno %u for finobt root, agno %d\n"),
|
||||||
|
@@ -2350,6 +2362,17 @@ validate_agi(
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (xfs_sb_version_hasinobtcounts(&mp->m_sb)) {
|
||||||
|
+ if (be32_to_cpu(agi->agi_iblocks) != priv.ino_blocks)
|
||||||
|
+ do_warn(_("bad inobt block count %u, saw %u\n"),
|
||||||
|
+ be32_to_cpu(agi->agi_iblocks),
|
||||||
|
+ priv.ino_blocks);
|
||||||
|
+ if (be32_to_cpu(agi->agi_fblocks) != priv.fino_blocks)
|
||||||
|
+ do_warn(_("bad finobt block count %u, saw %u\n"),
|
||||||
|
+ be32_to_cpu(agi->agi_fblocks),
|
||||||
|
+ priv.fino_blocks);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (be32_to_cpu(agi->agi_count) != agcnts->agicount) {
|
||||||
|
do_warn(_("agi_count %u, counted %u in ag %u\n"),
|
||||||
|
be32_to_cpu(agi->agi_count), agcnts->agicount, agno);
|
@ -0,0 +1,177 @@
|
|||||||
|
From a4d94d6c30acac66ff82e740e2dcb95736d7d195 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Date: Tue, 26 May 2020 14:36:04 -0400
|
||||||
|
Subject: [PATCH] xfs_repair: fix progress reporting
|
||||||
|
|
||||||
|
The Fixes: commit tried to avoid a segfault in case the progress timer
|
||||||
|
went off before the first message type had been set up, but this
|
||||||
|
had the net effect of short-circuiting the pthread start routine,
|
||||||
|
and so the timer didn't get set up at all and we lost all fine-grained
|
||||||
|
progress reporting.
|
||||||
|
|
||||||
|
The initial problem occurred when log zeroing took more time than the
|
||||||
|
timer interval.
|
||||||
|
|
||||||
|
So, make a new log zeroing progress item and initialize it when we first
|
||||||
|
set up the timer thread, to be sure that if the timer goes off while we
|
||||||
|
are still zeroing the log, it will be initialized and correct.
|
||||||
|
|
||||||
|
(We can't offer fine-grained status on log zeroing, so it'll go from
|
||||||
|
zero to $LOGBLOCKS with nothing in between, but it's unlikely that log
|
||||||
|
zeroing will take so long that this really matters.)
|
||||||
|
|
||||||
|
Reported-by: Leonardo Vaz <lvaz@redhat.com>
|
||||||
|
Fixes: 7f2d6b811755 ("xfs_repair: avoid segfault if reporting progre...")
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Donald Douwsma <ddouwsma@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
Signed-off-by: Pavel Reichl <preichl@redhat.com>
|
||||||
|
---
|
||||||
|
repair/phase2.c | 6 ++++++
|
||||||
|
repair/progress.c | 35 +++++++++++++++++++----------------
|
||||||
|
repair/progress.h | 31 ++++++++++++++++---------------
|
||||||
|
3 files changed, 41 insertions(+), 31 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/repair/phase2.c b/repair/phase2.c
|
||||||
|
index 40ea2f84..952ac4a5 100644
|
||||||
|
--- a/repair/phase2.c
|
||||||
|
+++ b/repair/phase2.c
|
||||||
|
@@ -120,6 +120,9 @@ zero_log(
|
||||||
|
do_error(_("failed to clear log"));
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* And we are now magically complete! */
|
||||||
|
+ PROG_RPT_INC(prog_rpt_done[0], mp->m_sb.sb_logblocks);
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Finally, seed the max LSN from the current state of the log if this
|
||||||
|
* is a v5 filesystem.
|
||||||
|
@@ -160,7 +163,10 @@ phase2(
|
||||||
|
|
||||||
|
/* Zero log if applicable */
|
||||||
|
do_log(_(" - zero log...\n"));
|
||||||
|
+
|
||||||
|
+ set_progress_msg(PROG_FMT_ZERO_LOG, (uint64_t)mp->m_sb.sb_logblocks);
|
||||||
|
zero_log(mp);
|
||||||
|
+ print_final_rpt();
|
||||||
|
|
||||||
|
do_log(_(" - scan filesystem freespace and inode maps...\n"));
|
||||||
|
|
||||||
|
diff --git a/repair/progress.c b/repair/progress.c
|
||||||
|
index 5ee08229..e5a9c1ef 100644
|
||||||
|
--- a/repair/progress.c
|
||||||
|
+++ b/repair/progress.c
|
||||||
|
@@ -49,35 +49,37 @@ typedef struct progress_rpt_s {
|
||||||
|
|
||||||
|
static
|
||||||
|
progress_rpt_t progress_rpt_reports[] = {
|
||||||
|
-{FMT1, N_("scanning filesystem freespace"), /* 0 */
|
||||||
|
+{FMT1, N_("zeroing log"), /* 0 */
|
||||||
|
+ &rpt_fmts[FMT1], &rpt_types[TYPE_BLOCK]},
|
||||||
|
+{FMT1, N_("scanning filesystem freespace"), /* 1 */
|
||||||
|
&rpt_fmts[FMT1], &rpt_types[TYPE_AG]},
|
||||||
|
-{FMT1, N_("scanning agi unlinked lists"), /* 1 */
|
||||||
|
+{FMT1, N_("scanning agi unlinked lists"), /* 2 */
|
||||||
|
&rpt_fmts[FMT1], &rpt_types[TYPE_AG]},
|
||||||
|
-{FMT2, N_("check uncertain AG inodes"), /* 2 */
|
||||||
|
+{FMT2, N_("check uncertain AG inodes"), /* 3 */
|
||||||
|
&rpt_fmts[FMT2], &rpt_types[TYPE_AGI_BUCKET]},
|
||||||
|
-{FMT1, N_("process known inodes and inode discovery"), /* 3 */
|
||||||
|
+{FMT1, N_("process known inodes and inode discovery"), /* 4 */
|
||||||
|
&rpt_fmts[FMT1], &rpt_types[TYPE_INODE]},
|
||||||
|
-{FMT1, N_("process newly discovered inodes"), /* 4 */
|
||||||
|
+{FMT1, N_("process newly discovered inodes"), /* 5 */
|
||||||
|
&rpt_fmts[FMT1], &rpt_types[TYPE_AG]},
|
||||||
|
-{FMT1, N_("setting up duplicate extent list"), /* 5 */
|
||||||
|
+{FMT1, N_("setting up duplicate extent list"), /* 6 */
|
||||||
|
&rpt_fmts[FMT1], &rpt_types[TYPE_AG]},
|
||||||
|
-{FMT1, N_("initialize realtime bitmap"), /* 6 */
|
||||||
|
+{FMT1, N_("initialize realtime bitmap"), /* 7 */
|
||||||
|
&rpt_fmts[FMT1], &rpt_types[TYPE_BLOCK]},
|
||||||
|
-{FMT1, N_("reset realtime bitmaps"), /* 7 */
|
||||||
|
+{FMT1, N_("reset realtime bitmaps"), /* 8 */
|
||||||
|
&rpt_fmts[FMT1], &rpt_types[TYPE_AG]},
|
||||||
|
-{FMT1, N_("check for inodes claiming duplicate blocks"), /* 8 */
|
||||||
|
+{FMT1, N_("check for inodes claiming duplicate blocks"), /* 9 */
|
||||||
|
&rpt_fmts[FMT1], &rpt_types[TYPE_INODE]},
|
||||||
|
-{FMT1, N_("rebuild AG headers and trees"), /* 9 */
|
||||||
|
+{FMT1, N_("rebuild AG headers and trees"), /* 10 */
|
||||||
|
&rpt_fmts[FMT1], &rpt_types[TYPE_AG]},
|
||||||
|
-{FMT1, N_("traversing filesystem"), /* 10 */
|
||||||
|
+{FMT1, N_("traversing filesystem"), /* 12 */
|
||||||
|
&rpt_fmts[FMT1], &rpt_types[TYPE_AG]},
|
||||||
|
-{FMT2, N_("traversing all unattached subtrees"), /* 11 */
|
||||||
|
+{FMT2, N_("traversing all unattached subtrees"), /* 12 */
|
||||||
|
&rpt_fmts[FMT2], &rpt_types[TYPE_DIR]},
|
||||||
|
-{FMT2, N_("moving disconnected inodes to lost+found"), /* 12 */
|
||||||
|
+{FMT2, N_("moving disconnected inodes to lost+found"), /* 13 */
|
||||||
|
&rpt_fmts[FMT2], &rpt_types[TYPE_INODE]},
|
||||||
|
-{FMT1, N_("verify and correct link counts"), /* 13 */
|
||||||
|
+{FMT1, N_("verify and correct link counts"), /* 14 */
|
||||||
|
&rpt_fmts[FMT1], &rpt_types[TYPE_AG]},
|
||||||
|
-{FMT1, N_("verify link counts"), /* 14 */
|
||||||
|
+{FMT1, N_("verify link counts"), /* 15 */
|
||||||
|
&rpt_fmts[FMT1], &rpt_types[TYPE_AG]}
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -125,7 +127,8 @@ init_progress_rpt (void)
|
||||||
|
*/
|
||||||
|
|
||||||
|
pthread_mutex_init(&global_msgs.mutex, NULL);
|
||||||
|
- global_msgs.format = NULL;
|
||||||
|
+ /* Make sure the format is set to the first phase and not NULL */
|
||||||
|
+ global_msgs.format = &progress_rpt_reports[PROG_FMT_ZERO_LOG];
|
||||||
|
global_msgs.count = glob_agcount;
|
||||||
|
global_msgs.interval = report_interval;
|
||||||
|
global_msgs.done = prog_rpt_done;
|
||||||
|
diff --git a/repair/progress.h b/repair/progress.h
|
||||||
|
index 9de9eb72..2c1690db 100644
|
||||||
|
--- a/repair/progress.h
|
||||||
|
+++ b/repair/progress.h
|
||||||
|
@@ -8,26 +8,27 @@
|
||||||
|
#define PHASE_END 1
|
||||||
|
|
||||||
|
|
||||||
|
-#define PROG_FMT_SCAN_AG 0 /* Phase 2 */
|
||||||
|
+#define PROG_FMT_ZERO_LOG 0 /* Phase 2 */
|
||||||
|
+#define PROG_FMT_SCAN_AG 1
|
||||||
|
|
||||||
|
-#define PROG_FMT_AGI_UNLINKED 1 /* Phase 3 */
|
||||||
|
-#define PROG_FMT_UNCERTAIN 2
|
||||||
|
-#define PROG_FMT_PROCESS_INO 3
|
||||||
|
-#define PROG_FMT_NEW_INODES 4
|
||||||
|
+#define PROG_FMT_AGI_UNLINKED 2 /* Phase 3 */
|
||||||
|
+#define PROG_FMT_UNCERTAIN 3
|
||||||
|
+#define PROG_FMT_PROCESS_INO 4
|
||||||
|
+#define PROG_FMT_NEW_INODES 5
|
||||||
|
|
||||||
|
-#define PROG_FMT_DUP_EXTENT 5 /* Phase 4 */
|
||||||
|
-#define PROG_FMT_INIT_RTEXT 6
|
||||||
|
-#define PROG_FMT_RESET_RTBM 7
|
||||||
|
-#define PROG_FMT_DUP_BLOCKS 8
|
||||||
|
+#define PROG_FMT_DUP_EXTENT 6 /* Phase 4 */
|
||||||
|
+#define PROG_FMT_INIT_RTEXT 7
|
||||||
|
+#define PROG_FMT_RESET_RTBM 8
|
||||||
|
+#define PROG_FMT_DUP_BLOCKS 9
|
||||||
|
|
||||||
|
-#define PROG_FMT_REBUILD_AG 9 /* Phase 5 */
|
||||||
|
+#define PROG_FMT_REBUILD_AG 10 /* Phase 5 */
|
||||||
|
|
||||||
|
-#define PROG_FMT_TRAVERSAL 10 /* Phase 6 */
|
||||||
|
-#define PROG_FMT_TRAVERSSUB 11
|
||||||
|
-#define PROG_FMT_DISCONINODE 12
|
||||||
|
+#define PROG_FMT_TRAVERSAL 11 /* Phase 6 */
|
||||||
|
+#define PROG_FMT_TRAVERSSUB 12
|
||||||
|
+#define PROG_FMT_DISCONINODE 13
|
||||||
|
|
||||||
|
-#define PROGRESS_FMT_CORR_LINK 13 /* Phase 7 */
|
||||||
|
-#define PROGRESS_FMT_VRFY_LINK 14
|
||||||
|
+#define PROGRESS_FMT_CORR_LINK 14 /* Phase 7 */
|
||||||
|
+#define PROGRESS_FMT_VRFY_LINK 15
|
||||||
|
|
||||||
|
#define DURATION_BUF_SIZE 512
|
||||||
|
|
||||||
|
--
|
||||||
|
2.40.1
|
||||||
|
|
@ -0,0 +1,29 @@
|
|||||||
|
From 086250dc5707ee6fcfb1ee8499e7af092904a7a6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 20 Nov 2020 17:03:27 -0500
|
||||||
|
Subject: [PATCH] xfs_repair: regenerate inode btree block counters in AGI
|
||||||
|
|
||||||
|
Reset both inode btree block counters in the AGI when rebuilding the
|
||||||
|
metadata indexes.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Brian Foster <bfoster@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/repair/phase5.c b/repair/phase5.c
|
||||||
|
index ad9394d..a37d672 100644
|
||||||
|
--- a/repair/phase5.c
|
||||||
|
+++ b/repair/phase5.c
|
||||||
|
@@ -1126,6 +1126,11 @@ build_agi(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs,
|
||||||
|
agi->agi_free_level = cpu_to_be32(finobt_curs->num_levels);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (xfs_sb_version_hasinobtcounts(&mp->m_sb)) {
|
||||||
|
+ agi->agi_iblocks = cpu_to_be32(btree_curs->num_tot_blocks);
|
||||||
|
+ agi->agi_fblocks = cpu_to_be32(finobt_curs->num_tot_blocks);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
libxfs_writebuf(agi_buf, 0);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,81 @@
|
|||||||
|
From 37c7dda1c20bfd2cc73679275bab2dd43e0ad9b8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 20 Nov 2020 17:03:28 -0500
|
||||||
|
Subject: [PATCH] xfs_repair: support bigtime timestamp checking
|
||||||
|
|
||||||
|
Make sure that inodes don't have the bigtime flag set when the feature
|
||||||
|
is disabled, and don't check for overflows in the nanoseconds when
|
||||||
|
bigtime is enabled because that is no longer possible. Also make sure
|
||||||
|
that quotas don't have bigtime set erroneously.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
NOTE: we do not have quota repair in this version of xfsprogs
|
||||||
|
|
||||||
|
diff --git a/repair/dinode.c b/repair/dinode.c
|
||||||
|
index 0c40f2a..561603b 100644
|
||||||
|
--- a/repair/dinode.c
|
||||||
|
+++ b/repair/dinode.c
|
||||||
|
@@ -2213,11 +2213,15 @@ static void
|
||||||
|
check_nsec(
|
||||||
|
const char *name,
|
||||||
|
xfs_ino_t lino,
|
||||||
|
+ struct xfs_dinode *dip,
|
||||||
|
xfs_timestamp_t *ts,
|
||||||
|
int *dirty)
|
||||||
|
{
|
||||||
|
struct xfs_legacy_timestamp *t;
|
||||||
|
|
||||||
|
+ if (xfs_dinode_has_bigtime(dip))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
t = (struct xfs_legacy_timestamp *)ts;
|
||||||
|
if (be32_to_cpu(t->t_nsec) < NSEC_PER_SEC)
|
||||||
|
return;
|
||||||
|
@@ -2625,6 +2629,27 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"),
|
||||||
|
flags2 &= ~XFS_DIFLAG2_COWEXTSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (xfs_dinode_has_bigtime(dino) &&
|
||||||
|
+ !xfs_sb_version_hasbigtime(&mp->m_sb)) {
|
||||||
|
+ if (!uncertain) {
|
||||||
|
+ do_warn(
|
||||||
|
+ _("inode %" PRIu64 " is marked bigtime but file system does not support large timestamps\n"),
|
||||||
|
+ lino);
|
||||||
|
+ }
|
||||||
|
+ flags2 &= ~XFS_DIFLAG2_BIGTIME;
|
||||||
|
+
|
||||||
|
+ if (no_modify) {
|
||||||
|
+ do_warn(_("would zero timestamps.\n"));
|
||||||
|
+ } else {
|
||||||
|
+ do_warn(_("zeroing timestamps.\n"));
|
||||||
|
+ dino->di_atime = 0;
|
||||||
|
+ dino->di_mtime = 0;
|
||||||
|
+ dino->di_ctime = 0;
|
||||||
|
+ dino->di_crtime = 0;
|
||||||
|
+ *dirty = 1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (!verify_mode && flags2 != be64_to_cpu(dino->di_flags2)) {
|
||||||
|
if (!no_modify) {
|
||||||
|
do_warn(_("fixing bad flags2.\n"));
|
||||||
|
@@ -2752,11 +2777,11 @@ _("Bad CoW extent size %u on inode %" PRIu64 ", "),
|
||||||
|
}
|
||||||
|
|
||||||
|
/* nsec fields cannot be larger than 1 billion */
|
||||||
|
- check_nsec("atime", lino, &dino->di_atime, dirty);
|
||||||
|
- check_nsec("mtime", lino, &dino->di_mtime, dirty);
|
||||||
|
- check_nsec("ctime", lino, &dino->di_ctime, dirty);
|
||||||
|
+ check_nsec("atime", lino, dino, &dino->di_atime, dirty);
|
||||||
|
+ check_nsec("mtime", lino, dino, &dino->di_mtime, dirty);
|
||||||
|
+ check_nsec("ctime", lino, dino, &dino->di_ctime, dirty);
|
||||||
|
if (dino->di_version >= 3)
|
||||||
|
- check_nsec("crtime", lino, &dino->di_crtime, dirty);
|
||||||
|
+ check_nsec("crtime", lino, dino, &dino->di_crtime, dirty);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* general size/consistency checks:
|
@ -0,0 +1,38 @@
|
|||||||
|
From 2c40c5a72b3cd0c4599bc84a7a8b09a496d46db3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Zorro Lang <zlang@redhat.com>
|
||||||
|
Date: Fri, 12 Feb 2021 17:23:05 -0500
|
||||||
|
Subject: [PATCH] mkfs: fix wrong inobtcount usage error output
|
||||||
|
|
||||||
|
When mkfs fails, it shows:
|
||||||
|
...
|
||||||
|
/* metadata */ [-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1,\n\
|
||||||
|
inobtcnt=0|1,bigtime=0|1]\n\
|
||||||
|
...
|
||||||
|
|
||||||
|
The "inobtcnt=0|1" is wrong usage, it must be inobtcount, there's not
|
||||||
|
an alias. To avoid misadvice, fix it.
|
||||||
|
|
||||||
|
Signed-off-by: Zorro Lang <zlang@redhat.com>
|
||||||
|
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
mkfs/xfs_mkfs.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
|
||||||
|
index 0c66255a..964299d3 100644
|
||||||
|
--- a/mkfs/xfs_mkfs.c
|
||||||
|
+++ b/mkfs/xfs_mkfs.c
|
||||||
|
@@ -928,7 +928,7 @@ usage( void )
|
||||||
|
fprintf(stderr, _("Usage: %s\n\
|
||||||
|
/* blocksize */ [-b size=num]\n\
|
||||||
|
/* metadata */ [-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1,\n\
|
||||||
|
- inobtcnt=0|1,bigtime=0|1]\n\
|
||||||
|
+ inobtcount=0|1,bigtime=0|1]\n\
|
||||||
|
/* data subvol */ [-d agcount=n,agsize=n,file,name=xxx,size=num,\n\
|
||||||
|
(sunit=value,swidth=value|su=num,sw=num|noalign),\n\
|
||||||
|
sectsize=num\n\
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
@ -1,15 +0,0 @@
|
|||||||
--- a/man/man8/mkfs.xfs.8.in 2021-12-01 20:48:09.241170607 +0100
|
|
||||||
+++ b/man/man8/mkfs.xfs.8.in 2021-12-03 15:34:32.382616819 +0100
|
|
||||||
@@ -1091,6 +1091,12 @@
|
|
||||||
.HP
|
|
||||||
.PD
|
|
||||||
.PP
|
|
||||||
+.SH Example Of Backward Compatible Configuration Files
|
|
||||||
+An example of a configuration file that facilitates creation of Red Hat
|
|
||||||
+Enterprise Linux 8 compatible XFS filesystems while running on Red Hat
|
|
||||||
+Enterprise Linux 9 can be found at:
|
|
||||||
+/usr/share/xfsprogs/mkfs/rhel8.0.conf
|
|
||||||
+.PP
|
|
||||||
.SH SEE ALSO
|
|
||||||
.BR xfs (5),
|
|
||||||
.BR mkfs (8),
|
|
@ -0,0 +1,53 @@
|
|||||||
|
From dcad5c60c59bfcdf4e27dc552b94591eced0a452 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <djwong@kernel.org>
|
||||||
|
Date: Thu, 15 Apr 2021 15:44:10 -0400
|
||||||
|
Subject: [PATCH] libfrog: report inobtcount in geometry
|
||||||
|
|
||||||
|
Report the inode btree counter feature in fs feature reports.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
libfrog/fsgeom.c | 6 ++++--
|
||||||
|
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libfrog/fsgeom.c b/libfrog/fsgeom.c
|
||||||
|
index 14507668..4f1a1842 100644
|
||||||
|
--- a/libfrog/fsgeom.c
|
||||||
|
+++ b/libfrog/fsgeom.c
|
||||||
|
@@ -29,6 +29,7 @@ xfs_report_geom(
|
||||||
|
int rmapbt_enabled;
|
||||||
|
int reflink_enabled;
|
||||||
|
int bigtime_enabled;
|
||||||
|
+ int inobtcount;
|
||||||
|
|
||||||
|
isint = geo->logstart > 0;
|
||||||
|
lazycount = geo->flags & XFS_FSOP_GEOM_FLAGS_LAZYSB ? 1 : 0;
|
||||||
|
@@ -45,12 +46,13 @@ xfs_report_geom(
|
||||||
|
rmapbt_enabled = geo->flags & XFS_FSOP_GEOM_FLAGS_RMAPBT ? 1 : 0;
|
||||||
|
reflink_enabled = geo->flags & XFS_FSOP_GEOM_FLAGS_REFLINK ? 1 : 0;
|
||||||
|
bigtime_enabled = geo->flags & XFS_FSOP_GEOM_FLAGS_BIGTIME ? 1 : 0;
|
||||||
|
+ inobtcount = geo->flags & XFS_FSOP_GEOM_FLAGS_INOBTCNT ? 1 : 0;
|
||||||
|
|
||||||
|
printf(_(
|
||||||
|
"meta-data=%-22s isize=%-6d agcount=%u, agsize=%u blks\n"
|
||||||
|
" =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n"
|
||||||
|
" =%-22s crc=%-8u finobt=%u, sparse=%u, rmapbt=%u\n"
|
||||||
|
-" =%-22s reflink=%-4u bigtime=%u\n"
|
||||||
|
+" =%-22s reflink=%-4u bigtime=%u inobtcount=%u\n"
|
||||||
|
"data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n"
|
||||||
|
" =%-22s sunit=%-6u swidth=%u blks\n"
|
||||||
|
"naming =version %-14u bsize=%-6u ascii-ci=%d, ftype=%d\n"
|
||||||
|
@@ -60,7 +62,7 @@ xfs_report_geom(
|
||||||
|
mntpoint, geo->inodesize, geo->agcount, geo->agblocks,
|
||||||
|
"", geo->sectsize, attrversion, projid32bit,
|
||||||
|
"", crcs_enabled, finobt_enabled, spinodes, rmapbt_enabled,
|
||||||
|
- "", reflink_enabled, bigtime_enabled,
|
||||||
|
+ "", reflink_enabled, bigtime_enabled, inobtcount,
|
||||||
|
"", geo->blocksize, (unsigned long long)geo->datablocks,
|
||||||
|
geo->imaxpct,
|
||||||
|
"", geo->sunit, geo->swidth,
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
@ -0,0 +1,29 @@
|
|||||||
|
From d625f74125863304d111f5c6a0817a115f8e502d Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <djwong@kernel.org>
|
||||||
|
Date: Fri, 7 May 2021 10:42:17 -0400
|
||||||
|
Subject: [PATCH] libxfs: copy crtime correctly now that it's timespec64
|
||||||
|
|
||||||
|
The incore i_mtime and di_crtime are both timespec64 now, which means
|
||||||
|
that tv_sec is a 64-bit value. Don't cast that to int32_t when we're
|
||||||
|
creating an inode, because we'll end up truncating the creation time
|
||||||
|
incorrectly, should an xfsprogs of this vintage make it to 2039. :P
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/libxfs/util.c b/libxfs/util.c
|
||||||
|
index 7a8729f..fd4906f 100644
|
||||||
|
--- a/libxfs/util.c
|
||||||
|
+++ b/libxfs/util.c
|
||||||
|
@@ -326,8 +326,7 @@ libxfs_ialloc(
|
||||||
|
ip->i_d.di_flags2 = xfs_flags2diflags2(ip, fsx->fsx_xflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
- ip->i_d.di_crtime.tv_sec = (int32_t)VFS_I(ip)->i_mtime.tv_sec;
|
||||||
|
- ip->i_d.di_crtime.tv_nsec = (int32_t)VFS_I(ip)->i_mtime.tv_nsec;
|
||||||
|
+ ip->i_d.di_crtime = VFS_I(ip)->i_mtime; /* struct copy */
|
||||||
|
ip->i_d.di_cowextsize = pip ? 0 : fsx->fsx_cowextsize;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
|||||||
|
From bdeb014153934e1d98787a9609a7532baf6a5c37 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Zorro Lang <zlang@redhat.com>
|
||||||
|
Date: Tue, 6 Apr 2021 16:56:32 -0400
|
||||||
|
Subject: [PATCH] libxfs: expose inobtcount in xfs geometry
|
||||||
|
|
||||||
|
Source kernel commit: bc41fa5321f93ecbabec177f888451cfc17ad66d
|
||||||
|
|
||||||
|
As xfs supports the feature of inode btree block counters now, expose
|
||||||
|
this feature flag in xfs geometry, for userspace can check if the
|
||||||
|
inobtcnt is enabled or not.
|
||||||
|
|
||||||
|
Signed-off-by: Zorro Lang <zlang@redhat.com>
|
||||||
|
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
|
||||||
|
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h
|
||||||
|
index 714dba1..4e4a22e 100644
|
||||||
|
--- a/libxfs/xfs_fs.h
|
||||||
|
+++ b/libxfs/xfs_fs.h
|
||||||
|
@@ -232,6 +232,7 @@ typedef struct xfs_fsop_resblks {
|
||||||
|
#define XFS_FSOP_GEOM_FLAGS_RMAPBT 0x80000 /* reverse mapping btree */
|
||||||
|
#define XFS_FSOP_GEOM_FLAGS_REFLINK 0x100000 /* files can share blocks */
|
||||||
|
#define XFS_FSOP_GEOM_FLAGS_BIGTIME 0x200000 /* 64-bit nsec timestamps */
|
||||||
|
+#define XFS_FSOP_GEOM_FLAGS_INOBTCNT 0x400000 /* inobt btree counter */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Minimum and maximum sizes need for growth checks.
|
||||||
|
diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c
|
||||||
|
index d11545b..6249e9a 100644
|
||||||
|
--- a/libxfs/xfs_sb.c
|
||||||
|
+++ b/libxfs/xfs_sb.c
|
||||||
|
@@ -1126,6 +1126,8 @@ xfs_fs_geometry(
|
||||||
|
geo->flags |= XFS_FSOP_GEOM_FLAGS_REFLINK;
|
||||||
|
if (xfs_sb_version_hasbigtime(sbp))
|
||||||
|
geo->flags |= XFS_FSOP_GEOM_FLAGS_BIGTIME;
|
||||||
|
+ if (xfs_sb_version_hasinobtcounts(sbp))
|
||||||
|
+ geo->flags |= XFS_FSOP_GEOM_FLAGS_INOBTCNT;
|
||||||
|
if (xfs_sb_version_hassector(sbp))
|
||||||
|
geo->logsectsize = sbp->sb_logsectsize;
|
||||||
|
else
|
@ -0,0 +1,29 @@
|
|||||||
|
From 5b9782c9317b7ac0ff942dffb667bad8502f0932 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christoph Hellwig <hch@lst.de>
|
||||||
|
Date: Wed, 30 Jun 2021 18:29:41 -0400
|
||||||
|
Subject: [PATCH] xfs: remove the unused xfs_icdinode_has_bigtime helper
|
||||||
|
|
||||||
|
Source kernel commit: 55f773380e922d3b975a7acb24331c76611cce30
|
||||||
|
|
||||||
|
Signed-off-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
|
||||||
|
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/libxfs/xfs_inode_buf.h b/libxfs/xfs_inode_buf.h
|
||||||
|
index 2b91e60..8d6737b 100644
|
||||||
|
--- a/libxfs/xfs_inode_buf.h
|
||||||
|
+++ b/libxfs/xfs_inode_buf.h
|
||||||
|
@@ -40,11 +40,6 @@ struct xfs_icdinode {
|
||||||
|
struct timespec64 di_crtime; /* time created */
|
||||||
|
};
|
||||||
|
|
||||||
|
-static inline bool xfs_icdinode_has_bigtime(const struct xfs_icdinode *icd)
|
||||||
|
-{
|
||||||
|
- return icd->di_flags2 & XFS_DIFLAG2_BIGTIME;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
/*
|
||||||
|
* Inode location information. Stored in the inode and passed to
|
||||||
|
* xfs_imap_to_bp() to get a buffer and dinode for a given inode.
|
@ -0,0 +1,46 @@
|
|||||||
|
From 59301887102cc0415c8350a5e9562fe4beb083b6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christoph Hellwig <hch@lst.de>
|
||||||
|
Date: Wed, 30 Jun 2021 18:38:58 -0400
|
||||||
|
Subject: [PATCH] xfs: rename struct xfs_legacy_ictimestamp
|
||||||
|
|
||||||
|
Source kernel commit: 732de7dbdbd30df40a6d260a8da6fc5262039439
|
||||||
|
|
||||||
|
Rename struct xfs_legacy_ictimestamp to struct xfs_log_legacy_timestamp
|
||||||
|
as it is a type used for logging timestamps with no relationship to the
|
||||||
|
in-core inode.
|
||||||
|
|
||||||
|
Signed-off-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
|
||||||
|
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/libxfs/xfs_log_format.h b/libxfs/xfs_log_format.h
|
||||||
|
index 85ac52c..bc26894 100644
|
||||||
|
--- a/libxfs/xfs_log_format.h
|
||||||
|
+++ b/libxfs/xfs_log_format.h
|
||||||
|
@@ -371,7 +371,7 @@ static inline int xfs_ilog_fdata(int w)
|
||||||
|
typedef uint64_t xfs_log_timestamp_t;
|
||||||
|
|
||||||
|
/* Legacy timestamp encoding format. */
|
||||||
|
-struct xfs_legacy_ictimestamp {
|
||||||
|
+struct xfs_log_legacy_timestamp {
|
||||||
|
int32_t t_sec; /* timestamp seconds */
|
||||||
|
int32_t t_nsec; /* timestamp nanoseconds */
|
||||||
|
};
|
||||||
|
diff --git a/logprint/log_misc.c b/logprint/log_misc.c
|
||||||
|
index f4fd7a8..4889e65 100644
|
||||||
|
--- a/logprint/log_misc.c
|
||||||
|
+++ b/logprint/log_misc.c
|
||||||
|
@@ -745,9 +745,9 @@ time64_t
|
||||||
|
xlog_extract_dinode_ts(
|
||||||
|
const xfs_log_timestamp_t its)
|
||||||
|
{
|
||||||
|
- struct xfs_legacy_ictimestamp *lits;
|
||||||
|
+ struct xfs_log_legacy_timestamp *lits;
|
||||||
|
|
||||||
|
- lits = (struct xfs_legacy_ictimestamp *)&its;
|
||||||
|
+ lits = (struct xfs_log_legacy_timestamp *)&its;
|
||||||
|
return (time64_t)lits->t_sec;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,77 @@
|
|||||||
|
From 27bb0efa5e615a9162f5bc3e228bdb7c337faa4c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christoph Hellwig <hch@lst.de>
|
||||||
|
Date: Wed, 30 Jun 2021 18:38:58 -0400
|
||||||
|
Subject: [PATCH] xfs: rename xfs_ictimestamp_t
|
||||||
|
|
||||||
|
Source kernel commit: 6fc277c7c935c7e1fdee23e82da988d9d3cb6bef
|
||||||
|
|
||||||
|
Rename xfs_ictimestamp_t to xfs_log_timestamp_t as it is a type used
|
||||||
|
for logging timestamps with no relationship to the in-core inode.
|
||||||
|
|
||||||
|
Signed-off-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
|
||||||
|
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/libxfs/xfs_log_format.h b/libxfs/xfs_log_format.h
|
||||||
|
index 8dc0df0..85ac52c 100644
|
||||||
|
--- a/libxfs/xfs_log_format.h
|
||||||
|
+++ b/libxfs/xfs_log_format.h
|
||||||
|
@@ -368,7 +368,7 @@ static inline int xfs_ilog_fdata(int w)
|
||||||
|
* directly mirrors the xfs_dinode structure as it must contain all the same
|
||||||
|
* information.
|
||||||
|
*/
|
||||||
|
-typedef uint64_t xfs_ictimestamp_t;
|
||||||
|
+typedef uint64_t xfs_log_timestamp_t;
|
||||||
|
|
||||||
|
/* Legacy timestamp encoding format. */
|
||||||
|
struct xfs_legacy_ictimestamp {
|
||||||
|
@@ -393,9 +393,9 @@ struct xfs_log_dinode {
|
||||||
|
uint16_t di_projid_hi; /* higher part of owner's project id */
|
||||||
|
uint8_t di_pad[6]; /* unused, zeroed space */
|
||||||
|
uint16_t di_flushiter; /* incremented on flush */
|
||||||
|
- xfs_ictimestamp_t di_atime; /* time last accessed */
|
||||||
|
- xfs_ictimestamp_t di_mtime; /* time last modified */
|
||||||
|
- xfs_ictimestamp_t di_ctime; /* time created/inode modified */
|
||||||
|
+ xfs_log_timestamp_t di_atime; /* time last accessed */
|
||||||
|
+ xfs_log_timestamp_t di_mtime; /* time last modified */
|
||||||
|
+ xfs_log_timestamp_t di_ctime; /* time created/inode modified */
|
||||||
|
xfs_fsize_t di_size; /* number of bytes in file */
|
||||||
|
xfs_rfsblock_t di_nblocks; /* # of direct & btree blocks used */
|
||||||
|
xfs_extlen_t di_extsize; /* basic/minimum extent size for file */
|
||||||
|
@@ -420,7 +420,7 @@ struct xfs_log_dinode {
|
||||||
|
uint8_t di_pad2[12]; /* more padding for future expansion */
|
||||||
|
|
||||||
|
/* fields only written to during inode creation */
|
||||||
|
- xfs_ictimestamp_t di_crtime; /* time created */
|
||||||
|
+ xfs_log_timestamp_t di_crtime; /* time created */
|
||||||
|
xfs_ino_t di_ino; /* inode number */
|
||||||
|
uuid_t di_uuid; /* UUID of the filesystem */
|
||||||
|
|
||||||
|
diff --git a/logprint/log_misc.c b/logprint/log_misc.c
|
||||||
|
index 4fad82b..f4fd7a8 100644
|
||||||
|
--- a/logprint/log_misc.c
|
||||||
|
+++ b/logprint/log_misc.c
|
||||||
|
@@ -743,7 +743,7 @@ xlog_print_trans_icreate(
|
||||||
|
|
||||||
|
time64_t
|
||||||
|
xlog_extract_dinode_ts(
|
||||||
|
- const xfs_ictimestamp_t its)
|
||||||
|
+ const xfs_log_timestamp_t its)
|
||||||
|
{
|
||||||
|
struct xfs_legacy_ictimestamp *lits;
|
||||||
|
|
||||||
|
diff --git a/logprint/logprint.h b/logprint/logprint.h
|
||||||
|
index 0061d5a..fe3831d 100644
|
||||||
|
--- a/logprint/logprint.h
|
||||||
|
+++ b/logprint/logprint.h
|
||||||
|
@@ -18,7 +18,7 @@ extern int print_no_data;
|
||||||
|
extern int print_no_print;
|
||||||
|
|
||||||
|
/* exports */
|
||||||
|
-extern time64_t xlog_extract_dinode_ts(const xfs_ictimestamp_t);
|
||||||
|
+extern time64_t xlog_extract_dinode_ts(const xfs_log_timestamp_t);
|
||||||
|
extern void xlog_print_lseek(struct xlog *, int, xfs_daddr_t, int);
|
||||||
|
|
||||||
|
extern void xfs_log_copy(struct xlog *, int, char *);
|
@ -1,52 +0,0 @@
|
|||||||
--- a/mkfs/xfs_mkfs.c.orig 2022-08-12 20:38:21.000000000 +0200
|
|
||||||
+++ b/mkfs/xfs_mkfs.c 2023-01-25 11:06:01.863076713 +0100
|
|
||||||
@@ -13,6 +13,8 @@
|
|
||||||
#include "libfrog/crc32cselftest.h"
|
|
||||||
#include "proto.h"
|
|
||||||
#include <ini.h>
|
|
||||||
+#include <linux/version.h>
|
|
||||||
+#include <sys/utsname.h>
|
|
||||||
|
|
||||||
#define TERABYTES(count, blog) ((uint64_t)(count) << (40 - (blog)))
|
|
||||||
#define GIGABYTES(count, blog) ((uint64_t)(count) << (30 - (blog)))
|
|
||||||
@@ -3998,6 +4000,23 @@
|
|
||||||
cli->cfgfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
+static unsigned int get_system_kver(void)
|
|
||||||
+{
|
|
||||||
+ const char *kver = getenv("KVER");
|
|
||||||
+ struct utsname utsname;
|
|
||||||
+ int a, b, c;
|
|
||||||
+
|
|
||||||
+ if (!kver) {
|
|
||||||
+ uname(&utsname);
|
|
||||||
+ kver = utsname.release;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (sscanf(kver, "%d.%d.%d", &a, &b, &c) != 3)
|
|
||||||
+ return LINUX_VERSION_CODE;
|
|
||||||
+
|
|
||||||
+ return KERNEL_VERSION(a,b,c);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
int
|
|
||||||
main(
|
|
||||||
int argc,
|
|
||||||
@@ -4077,8 +4096,16 @@
|
|
||||||
};
|
|
||||||
|
|
||||||
struct list_head buffer_list;
|
|
||||||
+ unsigned int kver;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
+ /* turn bigtime & inobtcnt back off if running under older kernels */
|
|
||||||
+ kver = get_system_kver();
|
|
||||||
+ if (kver < KERNEL_VERSION(5,10,0)) {
|
|
||||||
+ dft.sb_feat.inobtcnt = false;
|
|
||||||
+ dft.sb_feat.bigtime = false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
platform_uuid_generate(&cli.uuid);
|
|
||||||
progname = basename(argv[0]);
|
|
||||||
setlocale(LC_ALL, "");
|
|
@ -0,0 +1,112 @@
|
|||||||
|
From 50dba8189b1f628073eb61d824ae8a8a1b43cefb Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <djwong@kernel.org>
|
||||||
|
Date: Wed, 13 Jul 2022 20:58:28 -0500
|
||||||
|
Subject: [PATCH] mkfs: terminate getsubopt arrays properly
|
||||||
|
|
||||||
|
Having not drank any (or maybe too much) coffee this morning, I typed:
|
||||||
|
|
||||||
|
$ mkfs.xfs -d agcount=3 -d nrext64=0
|
||||||
|
Segmentation fault
|
||||||
|
|
||||||
|
I traced this down to getsubopt walking off the end of the dopts.subopts
|
||||||
|
array. The manpage says you're supposed to terminate the suboptions
|
||||||
|
string array with a NULL entry, but the structure definition uses
|
||||||
|
MAX_SUBOPTS/D_MAX_OPTS directly, which means there is no terminator.
|
||||||
|
|
||||||
|
Explicitly terminate each suboption array with a NULL entry after
|
||||||
|
making room for it.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
|
||||||
|
[sandeen: explicitly add NULL terminators & clarify comment]
|
||||||
|
Reviewed-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
Signed-off-by: Pavel Reichl <preichl@redhat.com>
|
||||||
|
---
|
||||||
|
mkfs/xfs_mkfs.c | 16 ++++++++++++++--
|
||||||
|
1 file changed, 14 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
|
||||||
|
index db322b3a..b140b815 100644
|
||||||
|
--- a/mkfs/xfs_mkfs.c
|
||||||
|
+++ b/mkfs/xfs_mkfs.c
|
||||||
|
@@ -140,8 +140,11 @@ enum {
|
||||||
|
M_MAX_OPTS,
|
||||||
|
};
|
||||||
|
|
||||||
|
-/* Just define the max options array size manually right now */
|
||||||
|
-#define MAX_SUBOPTS D_MAX_OPTS
|
||||||
|
+/*
|
||||||
|
+ * Just define the max options array size manually to the largest
|
||||||
|
+ * enum right now, leaving room for a NULL terminator at the end
|
||||||
|
+ */
|
||||||
|
+#define MAX_SUBOPTS (D_MAX_OPTS + 1)
|
||||||
|
|
||||||
|
#define SUBOPT_NEEDS_VAL (-1LL)
|
||||||
|
#define MAX_CONFLICTS 8
|
||||||
|
@@ -251,6 +254,7 @@ static struct opt_params bopts = {
|
||||||
|
.name = 'b',
|
||||||
|
.subopts = {
|
||||||
|
[B_SIZE] = "size",
|
||||||
|
+ [B_MAX_OPTS] = NULL,
|
||||||
|
},
|
||||||
|
.subopt_params = {
|
||||||
|
{ .index = B_SIZE,
|
||||||
|
@@ -306,6 +311,7 @@ static struct opt_params dopts = {
|
||||||
|
[D_PROJINHERIT] = "projinherit",
|
||||||
|
[D_EXTSZINHERIT] = "extszinherit",
|
||||||
|
[D_COWEXTSIZE] = "cowextsize",
|
||||||
|
+ [D_MAX_OPTS] = NULL,
|
||||||
|
},
|
||||||
|
.subopt_params = {
|
||||||
|
{ .index = D_AGCOUNT,
|
||||||
|
@@ -443,6 +449,7 @@ static struct opt_params iopts = {
|
||||||
|
[I_ATTR] = "attr",
|
||||||
|
[I_PROJID32BIT] = "projid32bit",
|
||||||
|
[I_SPINODES] = "sparse",
|
||||||
|
+ [I_MAX_OPTS] = NULL,
|
||||||
|
},
|
||||||
|
.subopt_params = {
|
||||||
|
{ .index = I_ALIGN,
|
||||||
|
@@ -515,6 +522,7 @@ static struct opt_params lopts = {
|
||||||
|
[L_FILE] = "file",
|
||||||
|
[L_NAME] = "name",
|
||||||
|
[L_LAZYSBCNTR] = "lazy-count",
|
||||||
|
+ [L_MAX_OPTS] = NULL,
|
||||||
|
},
|
||||||
|
.subopt_params = {
|
||||||
|
{ .index = L_AGNUM,
|
||||||
|
@@ -607,6 +615,7 @@ static struct opt_params nopts = {
|
||||||
|
[N_SIZE] = "size",
|
||||||
|
[N_VERSION] = "version",
|
||||||
|
[N_FTYPE] = "ftype",
|
||||||
|
+ [N_MAX_OPTS] = NULL,
|
||||||
|
},
|
||||||
|
.subopt_params = {
|
||||||
|
{ .index = N_SIZE,
|
||||||
|
@@ -642,6 +651,7 @@ static struct opt_params ropts = {
|
||||||
|
[R_FILE] = "file",
|
||||||
|
[R_NAME] = "name",
|
||||||
|
[R_NOALIGN] = "noalign",
|
||||||
|
+ [R_MAX_OPTS] = NULL,
|
||||||
|
},
|
||||||
|
.subopt_params = {
|
||||||
|
{ .index = R_EXTSIZE,
|
||||||
|
@@ -689,6 +699,7 @@ static struct opt_params sopts = {
|
||||||
|
.subopts = {
|
||||||
|
[S_SIZE] = "size",
|
||||||
|
[S_SECTSIZE] = "sectsize",
|
||||||
|
+ [S_MAX_OPTS] = NULL,
|
||||||
|
},
|
||||||
|
.subopt_params = {
|
||||||
|
{ .index = S_SIZE,
|
||||||
|
@@ -725,6 +736,7 @@ static struct opt_params mopts = {
|
||||||
|
[M_REFLINK] = "reflink",
|
||||||
|
[M_INOBTCNT] = "inobtcount",
|
||||||
|
[M_BIGTIME] = "bigtime",
|
||||||
|
+ [M_MAX_OPTS] = NULL,
|
||||||
|
},
|
||||||
|
.subopt_params = {
|
||||||
|
{ .index = M_CRC,
|
||||||
|
--
|
||||||
|
2.40.1
|
||||||
|
|
@ -1,91 +0,0 @@
|
|||||||
From 17b691400e8ce0755bb1d7a33490fbc014067e5e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Pavel Reichl <preichl@redhat.com>
|
|
||||||
Date: Fri, 27 Jan 2023 06:30:20 +0100
|
|
||||||
Subject: [PATCH] mkfs: tolerate tiny filesystems
|
|
||||||
|
|
||||||
Signed-off-by: Pavel Reichl <preichl@redhat.com>
|
|
||||||
---
|
|
||||||
man/man8/mkfs.xfs.8.in | 4 ++--
|
|
||||||
mkfs/xfs_mkfs.c | 23 ++++++++++++++---------
|
|
||||||
2 files changed, 16 insertions(+), 11 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/man/man8/mkfs.xfs.8.in b/man/man8/mkfs.xfs.8.in
|
|
||||||
index 211e7b0c..03f0fda8 100644
|
|
||||||
--- a/man/man8/mkfs.xfs.8.in
|
|
||||||
+++ b/man/man8/mkfs.xfs.8.in
|
|
||||||
@@ -405,7 +405,7 @@ is required if
|
|
||||||
is given. Otherwise, it is only needed if the filesystem should occupy
|
|
||||||
less space than the size of the special file.
|
|
||||||
|
|
||||||
-The data section must be at least 300MB in size.
|
|
||||||
+The data section should be at least 300MB in size.
|
|
||||||
.TP
|
|
||||||
.BI sunit= value
|
|
||||||
This is used to specify the stripe unit for a RAID device or a
|
|
||||||
@@ -705,7 +705,7 @@ described above. The overriding minimum value for size is 512 blocks.
|
|
||||||
With some combinations of filesystem block size, inode size,
|
|
||||||
and directory block size, the minimum log size is larger than 512 blocks.
|
|
||||||
|
|
||||||
-The log must be at least 64MB in size.
|
|
||||||
+The log should be at least 64MB in size.
|
|
||||||
The log cannot be more than 2GB in size.
|
|
||||||
.TP
|
|
||||||
.BI version= value
|
|
||||||
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
|
|
||||||
index 9dd0e79c..72c906d6 100644
|
|
||||||
--- a/mkfs/xfs_mkfs.c
|
|
||||||
+++ b/mkfs/xfs_mkfs.c
|
|
||||||
@@ -2503,6 +2503,8 @@ validate_supported(
|
|
||||||
struct xfs_mount *mp,
|
|
||||||
struct cli_params *cli)
|
|
||||||
{
|
|
||||||
+ bool deprecated = false;
|
|
||||||
+
|
|
||||||
/* Undocumented option to enable unsupported tiny filesystems. */
|
|
||||||
if (!cli->is_supported) {
|
|
||||||
printf(
|
|
||||||
@@ -2532,9 +2534,8 @@ validate_supported(
|
|
||||||
* 64MB * (8 / 7) * 4 = 293MB
|
|
||||||
*/
|
|
||||||
if (mp->m_sb.sb_dblocks < MEGABYTES(300, mp->m_sb.sb_blocklog)) {
|
|
||||||
- fprintf(stderr,
|
|
||||||
- _("Filesystem must be larger than 300MB.\n"));
|
|
||||||
- usage();
|
|
||||||
+ printf(_("Filesystem should be larger than 300MB.\n"));
|
|
||||||
+ deprecated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ -2543,9 +2544,8 @@ validate_supported(
|
|
||||||
*/
|
|
||||||
if (mp->m_sb.sb_logblocks <
|
|
||||||
XFS_MIN_REALISTIC_LOG_BLOCKS(mp->m_sb.sb_blocklog)) {
|
|
||||||
- fprintf(stderr,
|
|
||||||
- _("Log size must be at least 64MB.\n"));
|
|
||||||
- usage();
|
|
||||||
+ printf( _("Log size should be at least 64MB.\n"));
|
|
||||||
+ deprecated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ -2553,9 +2553,14 @@ validate_supported(
|
|
||||||
* have redundant superblocks.
|
|
||||||
*/
|
|
||||||
if (mp->m_sb.sb_agcount < 2) {
|
|
||||||
- fprintf(stderr,
|
|
||||||
- _("Filesystem must have at least 2 superblocks for redundancy!\n"));
|
|
||||||
- usage();
|
|
||||||
+ printf(
|
|
||||||
+ _("Filesystem should have at least 2 superblocks for redundancy!\n"));
|
|
||||||
+ deprecated = true;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (deprecated) {
|
|
||||||
+ printf(
|
|
||||||
+_("Support for filesystems like this one is deprecated and they will not be supported in future releases.\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.39.1
|
|
||||||
|
|
@ -1,113 +0,0 @@
|
|||||||
From b445624f0882badf00da739c52e58a85c18ae002 Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Darrick J. Wong" <djwong@kernel.org>
|
|
||||||
Date: Wed, 15 Mar 2023 15:56:35 +0100
|
|
||||||
Subject: [PATCH] xfs: estimate post-merge refcounts correctly
|
|
||||||
|
|
||||||
Source kernel commit: b25d1984aa884fc91a73a5a407b9ac976d441e9b
|
|
||||||
|
|
||||||
Upon enabling fsdax + reflink for XFS, xfs/179 began to report refcount
|
|
||||||
metadata corruptions after being run. Specifically, xfs_repair noticed
|
|
||||||
single-block refcount records that could be combined but had not been.
|
|
||||||
|
|
||||||
The root cause of this is improper MAXREFCOUNT edge case handling in
|
|
||||||
xfs_refcount_merge_extents. When we're trying to find candidates for a
|
|
||||||
refcount btree record merge, we compute the refcount attribute of the
|
|
||||||
merged record, but we fail to account for the fact that once a record
|
|
||||||
hits rc_refcount == MAXREFCOUNT, it is pinned that way forever. Hence
|
|
||||||
the computed refcount is wrong, and we fail to merge the extents.
|
|
||||||
|
|
||||||
Fix this by adjusting the merge predicates to compute the adjusted
|
|
||||||
refcount correctly.
|
|
||||||
|
|
||||||
Fixes: 3172725814f9 ("xfs: adjust refcount of an extent of blocks in refcount btree")
|
|
||||||
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
|
|
||||||
Reviewed-by: Dave Chinner <dchinner@redhat.com>
|
|
||||||
Reviewed-by: Xiao Yang <yangx.jy@fujitsu.com>
|
|
||||||
Signed-off-by: Carlos Maiolino <cem@kernel.org>
|
|
||||||
Signed-off-by: Pavel Reichl <preichl@redhat.com>
|
|
||||||
---
|
|
||||||
libxfs/xfs_refcount.c | 25 +++++++++++++++++++++----
|
|
||||||
1 file changed, 21 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/libxfs/xfs_refcount.c b/libxfs/xfs_refcount.c
|
|
||||||
index f6167c5f..29258bdd 100644
|
|
||||||
--- a/libxfs/xfs_refcount.c
|
|
||||||
+++ b/libxfs/xfs_refcount.c
|
|
||||||
@@ -819,6 +819,17 @@ xfs_refc_valid(
|
|
||||||
return rc->rc_startblock != NULLAGBLOCK;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static inline xfs_nlink_t
|
|
||||||
+xfs_refc_merge_refcount(
|
|
||||||
+ const struct xfs_refcount_irec *irec,
|
|
||||||
+ enum xfs_refc_adjust_op adjust)
|
|
||||||
+{
|
|
||||||
+ /* Once a record hits MAXREFCOUNT, it is pinned there forever */
|
|
||||||
+ if (irec->rc_refcount == MAXREFCOUNT)
|
|
||||||
+ return MAXREFCOUNT;
|
|
||||||
+ return irec->rc_refcount + adjust;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static inline bool
|
|
||||||
xfs_refc_want_merge_center(
|
|
||||||
const struct xfs_refcount_irec *left,
|
|
||||||
@@ -830,6 +841,7 @@ xfs_refc_want_merge_center(
|
|
||||||
unsigned long long *ulenp)
|
|
||||||
{
|
|
||||||
unsigned long long ulen = left->rc_blockcount;
|
|
||||||
+ xfs_nlink_t new_refcount;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* To merge with a center record, both shoulder records must be
|
|
||||||
@@ -845,9 +857,10 @@ xfs_refc_want_merge_center(
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* The shoulder record refcounts must match the new refcount. */
|
|
||||||
- if (left->rc_refcount != cleft->rc_refcount + adjust)
|
|
||||||
+ new_refcount = xfs_refc_merge_refcount(cleft, adjust);
|
|
||||||
+ if (left->rc_refcount != new_refcount)
|
|
||||||
return false;
|
|
||||||
- if (right->rc_refcount != cleft->rc_refcount + adjust)
|
|
||||||
+ if (right->rc_refcount != new_refcount)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ -870,6 +883,7 @@ xfs_refc_want_merge_left(
|
|
||||||
enum xfs_refc_adjust_op adjust)
|
|
||||||
{
|
|
||||||
unsigned long long ulen = left->rc_blockcount;
|
|
||||||
+ xfs_nlink_t new_refcount;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For a left merge, the left shoulder record must be adjacent to the
|
|
||||||
@@ -880,7 +894,8 @@ xfs_refc_want_merge_left(
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* Left shoulder record refcount must match the new refcount. */
|
|
||||||
- if (left->rc_refcount != cleft->rc_refcount + adjust)
|
|
||||||
+ new_refcount = xfs_refc_merge_refcount(cleft, adjust);
|
|
||||||
+ if (left->rc_refcount != new_refcount)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ -902,6 +917,7 @@ xfs_refc_want_merge_right(
|
|
||||||
enum xfs_refc_adjust_op adjust)
|
|
||||||
{
|
|
||||||
unsigned long long ulen = right->rc_blockcount;
|
|
||||||
+ xfs_nlink_t new_refcount;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For a right merge, the right shoulder record must be adjacent to the
|
|
||||||
@@ -912,7 +928,8 @@ xfs_refc_want_merge_right(
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* Right shoulder record refcount must match the new refcount. */
|
|
||||||
- if (right->rc_refcount != cright->rc_refcount + adjust)
|
|
||||||
+ new_refcount = xfs_refc_merge_refcount(cright, adjust);
|
|
||||||
+ if (right->rc_refcount != new_refcount)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/*
|
|
||||||
--
|
|
||||||
2.40.0
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
|||||||
From a68dabd45f3591456ecf7e35f6a6077db79f6bc6 Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Darrick J. Wong" <djwong@kernel.org>
|
|
||||||
Date: Wed, 15 Mar 2023 15:59:35 +0100
|
|
||||||
Subject: [PATCH] xfs: fix off-by-one error in xfs_btree_space_to_height
|
|
||||||
|
|
||||||
Source kernel commit: c0f399ff51495ac8d30367418f4f6292ecd61fbe
|
|
||||||
|
|
||||||
Lately I've been stress-testing extreme-sized rmap btrees by using the
|
|
||||||
(new) xfs_db bmap_inflate command to clone bmbt mappings billions of
|
|
||||||
times and then using xfs_repair to build new rmap and refcount btrees.
|
|
||||||
This of course is /much/ faster than actually FICLONEing a file billions
|
|
||||||
of times.
|
|
||||||
|
|
||||||
Unfortunately, xfs_repair fails in xfs_btree_bload_compute_geometry with
|
|
||||||
EOVERFLOW, which indicates that xfs_mount.m_rmap_maxlevels is not
|
|
||||||
sufficiently large for the test scenario. For a 1TB filesystem (~67
|
|
||||||
million AG blocks, 4 AGs) the btheight command reports:
|
|
||||||
|
|
||||||
$ xfs_db -c 'btheight -n 4400801200 -w min rmapbt' /dev/sda
|
|
||||||
rmapbt: worst case per 4096-byte block: 84 records (leaf) / 45 keyptrs (node)
|
|
||||||
level 0: 4400801200 records, 52390491 blocks
|
|
||||||
level 1: 52390491 records, 1164234 blocks
|
|
||||||
level 2: 1164234 records, 25872 blocks
|
|
||||||
level 3: 25872 records, 575 blocks
|
|
||||||
level 4: 575 records, 13 blocks
|
|
||||||
level 5: 13 records, 1 block
|
|
||||||
6 levels, 53581186 blocks total
|
|
||||||
|
|
||||||
The AG is sufficiently large to build this rmap btree. Unfortunately,
|
|
||||||
m_rmap_maxlevels is 5. Augmenting the loop in the space->height
|
|
||||||
function to report height, node blocks, and blocks remaining produces
|
|
||||||
this:
|
|
||||||
|
|
||||||
ht 1 node_blocks 45 blockleft 67108863
|
|
||||||
ht 2 node_blocks 2025 blockleft 67108818
|
|
||||||
ht 3 node_blocks 91125 blockleft 67106793
|
|
||||||
ht 4 node_blocks 4100625 blockleft 67015668
|
|
||||||
final height: 5
|
|
||||||
|
|
||||||
The goal of this function is to compute the maximum height btree that
|
|
||||||
can be stored in the given number of ondisk fsblocks. Starting with the
|
|
||||||
top level of the tree, each iteration through the loop adds the fanout
|
|
||||||
factor of the next level down until we run out of blocks. IOWs, maximum
|
|
||||||
height is achieved by using the smallest fanout factor that can apply
|
|
||||||
to that level.
|
|
||||||
|
|
||||||
However, the loop setup is not correct. Top level btree blocks are
|
|
||||||
allowed to contain fewer than minrecs items, so the computation is
|
|
||||||
incorrect because the first time through the loop it should be using a
|
|
||||||
fanout factor of 2. With this corrected, the above becomes:
|
|
||||||
|
|
||||||
ht 1 node_blocks 2 blockleft 67108863
|
|
||||||
ht 2 node_blocks 90 blockleft 67108861
|
|
||||||
ht 3 node_blocks 4050 blockleft 67108771
|
|
||||||
ht 4 node_blocks 182250 blockleft 67104721
|
|
||||||
ht 5 node_blocks 8201250 blockleft 66922471
|
|
||||||
final height: 6
|
|
||||||
|
|
||||||
Fixes: 9ec691205e7d ("xfs: compute the maximum height of the rmap btree when reflink enabled")
|
|
||||||
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
|
|
||||||
Reviewed-by: Dave Chinner <dchinner@redhat.com>
|
|
||||||
Signed-off-by: Carlos Maiolino <cem@kernel.org>
|
|
||||||
Signed-off-by: Pavel Reichl <preichl@redhat.com>
|
|
||||||
---
|
|
||||||
libxfs/xfs_btree.c | 7 ++++++-
|
|
||||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c
|
|
||||||
index 65d38637..38a3092d 100644
|
|
||||||
--- a/libxfs/xfs_btree.c
|
|
||||||
+++ b/libxfs/xfs_btree.c
|
|
||||||
@@ -4663,7 +4663,12 @@ xfs_btree_space_to_height(
|
|
||||||
const unsigned int *limits,
|
|
||||||
unsigned long long leaf_blocks)
|
|
||||||
{
|
|
||||||
- unsigned long long node_blocks = limits[1];
|
|
||||||
+ /*
|
|
||||||
+ * The root btree block can have fewer than minrecs pointers in it
|
|
||||||
+ * because the tree might not be big enough to require that amount of
|
|
||||||
+ * fanout. Hence it has a minimum size of 2 pointers, not limits[1].
|
|
||||||
+ */
|
|
||||||
+ unsigned long long node_blocks = 2;
|
|
||||||
unsigned long long blocks_left = leaf_blocks - 1;
|
|
||||||
unsigned int height = 1;
|
|
||||||
|
|
||||||
--
|
|
||||||
2.40.0
|
|
||||||
|
|
@ -1,119 +0,0 @@
|
|||||||
From b827e2318ea2bb3eabca13a965c2535a1d7289e5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Long Li <leo.lilong@huawei.com>
|
|
||||||
Date: Fri, 18 Nov 2022 12:23:57 +0100
|
|
||||||
Subject: [PATCH] xfs: fix sb write verify for lazysbcount
|
|
||||||
|
|
||||||
Source kernel commit: 7cecd500d90164419add650e26cc1de03a7a66cb
|
|
||||||
|
|
||||||
When lazysbcount is enabled, fsstress and loop mount/unmount test report
|
|
||||||
the following problems:
|
|
||||||
|
|
||||||
XFS (loop0): SB summary counter sanity check failed
|
|
||||||
XFS (loop0): Metadata corruption detected at xfs_sb_write_verify+0x13b/0x460,
|
|
||||||
xfs_sb block 0x0
|
|
||||||
XFS (loop0): Unmount and run xfs_repair
|
|
||||||
XFS (loop0): First 128 bytes of corrupted metadata buffer:
|
|
||||||
00000000: 58 46 53 42 00 00 10 00 00 00 00 00 00 28 00 00 XFSB.........(..
|
|
||||||
00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
|
|
||||||
00000020: 69 fb 7c cd 5f dc 44 af 85 74 e0 cc d4 e3 34 5a i.|._.D..t....4Z
|
|
||||||
00000030: 00 00 00 00 00 20 00 06 00 00 00 00 00 00 00 80 ..... ..........
|
|
||||||
00000040: 00 00 00 00 00 00 00 81 00 00 00 00 00 00 00 82 ................
|
|
||||||
00000050: 00 00 00 01 00 0a 00 00 00 00 00 04 00 00 00 00 ................
|
|
||||||
00000060: 00 00 0a 00 b4 b5 02 00 02 00 00 08 00 00 00 00 ................
|
|
||||||
00000070: 00 00 00 00 00 00 00 00 0c 09 09 03 14 00 00 19 ................
|
|
||||||
XFS (loop0): Corruption of in-memory data (0x8) detected at _xfs_buf_ioapply
|
|
||||||
+0xe1e/0x10e0 (fs/xfs/xfs_buf.c:1580). Shutting down filesystem.
|
|
||||||
XFS (loop0): Please unmount the filesystem and rectify the problem(s)
|
|
||||||
XFS (loop0): log mount/recovery failed: error -117
|
|
||||||
XFS (loop0): log mount failed
|
|
||||||
|
|
||||||
This corruption will shutdown the file system and the file system will
|
|
||||||
no longer be mountable. The following script can reproduce the problem,
|
|
||||||
but it may take a long time.
|
|
||||||
|
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
device=/dev/sda
|
|
||||||
testdir=/mnt/test
|
|
||||||
round=0
|
|
||||||
|
|
||||||
function fail()
|
|
||||||
{
|
|
||||||
echo "$*"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
mkdir -p $testdir
|
|
||||||
while [ $round -lt 10000 ]
|
|
||||||
do
|
|
||||||
echo "******* round $round ********"
|
|
||||||
mkfs.xfs -f $device
|
|
||||||
mount $device $testdir || fail "mount failed!"
|
|
||||||
fsstress -d $testdir -l 0 -n 10000 -p 4 >/dev/null &
|
|
||||||
sleep 4
|
|
||||||
killall -w fsstress
|
|
||||||
umount $testdir
|
|
||||||
xfs_repair -e $device > /dev/null
|
|
||||||
if [ $? -eq 2 ];then
|
|
||||||
echo "ERR CODE 2: Dirty log exception during repair."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
round=$(($round+1))
|
|
||||||
done
|
|
||||||
|
|
||||||
With lazysbcount is enabled, There is no additional lock protection for
|
|
||||||
reading m_ifree and m_icount in xfs_log_sb(), if other cpu modifies the
|
|
||||||
m_ifree, this will make the m_ifree greater than m_icount. For example,
|
|
||||||
consider the following sequence and ifreedelta is postive:
|
|
||||||
|
|
||||||
CPU0 CPU1
|
|
||||||
xfs_log_sb xfs_trans_unreserve_and_mod_sb
|
|
||||||
---------- ------------------------------
|
|
||||||
percpu_counter_sum(&mp->m_icount)
|
|
||||||
percpu_counter_add_batch(&mp->m_icount,
|
|
||||||
idelta, XFS_ICOUNT_BATCH)
|
|
||||||
percpu_counter_add(&mp->m_ifree, ifreedelta);
|
|
||||||
percpu_counter_sum(&mp->m_ifree)
|
|
||||||
|
|
||||||
After this, incorrect inode count (sb_ifree > sb_icount) will be writen to
|
|
||||||
the log. In the subsequent writing of sb, incorrect inode count (sb_ifree >
|
|
||||||
sb_icount) will fail to pass the boundary check in xfs_validate_sb_write()
|
|
||||||
that cause the file system shutdown.
|
|
||||||
|
|
||||||
When lazysbcount is enabled, we don't need to guarantee that Lazy sb
|
|
||||||
counters are completely correct, but we do need to guarantee that sb_ifree
|
|
||||||
<= sb_icount. On the other hand, the constraint that m_ifree <= m_icount
|
|
||||||
must be satisfied any time that there /cannot/ be other threads allocating
|
|
||||||
or freeing inode chunks. If the constraint is violated under these
|
|
||||||
circumstances, sb_i{count,free} (the ondisk superblock inode counters)
|
|
||||||
maybe incorrect and need to be marked sick at unmount, the count will
|
|
||||||
be rebuilt on the next mount.
|
|
||||||
|
|
||||||
Fixes: 8756a5af1819 ("libxfs: add more bounds checking to sb sanity checks")
|
|
||||||
Signed-off-by: Long Li <leo.lilong@huawei.com>
|
|
||||||
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
|
|
||||||
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
|
|
||||||
Signed-off-by: Carlos Maiolino <cem@kernel.org>
|
|
||||||
Signed-off-by: Pavel Reichl <preichl@redhat.com>
|
|
||||||
---
|
|
||||||
libxfs/xfs_sb.c | 4 +++-
|
|
||||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c
|
|
||||||
index fc33dc4a..d05f0e6e 100644
|
|
||||||
--- a/libxfs/xfs_sb.c
|
|
||||||
+++ b/libxfs/xfs_sb.c
|
|
||||||
@@ -970,7 +970,9 @@ xfs_log_sb(
|
|
||||||
*/
|
|
||||||
if (xfs_has_lazysbcount(mp)) {
|
|
||||||
mp->m_sb.sb_icount = percpu_counter_sum(&mp->m_icount);
|
|
||||||
- mp->m_sb.sb_ifree = percpu_counter_sum(&mp->m_ifree);
|
|
||||||
+ mp->m_sb.sb_ifree = min_t(uint64_t,
|
|
||||||
+ percpu_counter_sum(&mp->m_ifree),
|
|
||||||
+ mp->m_sb.sb_icount);
|
|
||||||
mp->m_sb.sb_fdblocks = percpu_counter_sum(&mp->m_fdblocks);
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.40.0
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
|||||||
From f5ef812888a81be534466fa34df747c16bb65b7f Mon Sep 17 00:00:00 2001
|
|
||||||
From: Guo Xuenan <guoxuenan@huawei.com>
|
|
||||||
Date: Wed, 15 Mar 2023 15:57:35 +0100
|
|
||||||
Subject: [PATCH] xfs: get rid of assert from xfs_btree_islastblock
|
|
||||||
|
|
||||||
Source kernel commit: 8c25febf23963431686f04874b96321288504127
|
|
||||||
|
|
||||||
xfs_btree_check_block contains debugging knobs. With XFS_DEBUG setting up,
|
|
||||||
turn on the debugging knob can trigger the assert of xfs_btree_islastblock,
|
|
||||||
test script as follows:
|
|
||||||
|
|
||||||
while true
|
|
||||||
do
|
|
||||||
mount $disk $mountpoint
|
|
||||||
fsstress -d $testdir -l 0 -n 10000 -p 4 >/dev/null
|
|
||||||
echo 1 > /sys/fs/xfs/sda/errortag/btree_chk_sblk
|
|
||||||
sleep 10
|
|
||||||
umount $mountpoint
|
|
||||||
done
|
|
||||||
|
|
||||||
Kick off fsstress and only *then* turn on the debugging knob. If it
|
|
||||||
happens that the knob gets turned on after the cntbt lookup succeeds
|
|
||||||
but before the call to xfs_btree_islastblock, then we *can* end up in
|
|
||||||
the situation where a previously checked btree block suddenly starts
|
|
||||||
returning EFSCORRUPTED from xfs_btree_check_block. Kaboom.
|
|
||||||
|
|
||||||
Darrick give a very detailed explanation as follows:
|
|
||||||
Looking back at commit 27d9ee577dcce, I think the point of all this was
|
|
||||||
to make sure that the cursor has actually performed a lookup, and that
|
|
||||||
the btree block at whatever level we're asking about is ok.
|
|
||||||
|
|
||||||
If the caller hasn't ever done a lookup, the bc_levels array will be
|
|
||||||
empty, so cur->bc_levels[level].bp pointer will be NULL. The call to
|
|
||||||
xfs_btree_get_block will crash anyway, so the "ASSERT(block);" part is
|
|
||||||
pointless.
|
|
||||||
|
|
||||||
If the caller did a lookup but the lookup failed due to block
|
|
||||||
corruption, the corresponding cur->bc_levels[level].bp pointer will also
|
|
||||||
be NULL, and we'll still crash. The "ASSERT(xfs_btree_check_block);"
|
|
||||||
logic is also unnecessary.
|
|
||||||
|
|
||||||
If the cursor level points to an inode root, the block buffer will be
|
|
||||||
incore, so it had better always be consistent.
|
|
||||||
|
|
||||||
If the caller ignores a failed lookup after a successful one and calls
|
|
||||||
this function, the cursor state is garbage and the assert wouldn't have
|
|
||||||
tripped anyway. So get rid of the assert.
|
|
||||||
|
|
||||||
Fixes: 27d9ee577dcc ("xfs: actually check xfs_btree_check_block return in xfs_btree_islastblock")
|
|
||||||
Signed-off-by: Guo Xuenan <guoxuenan@huawei.com>
|
|
||||||
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
|
|
||||||
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
|
|
||||||
Signed-off-by: Carlos Maiolino <cem@kernel.org>
|
|
||||||
Signed-off-by: Pavel Reichl <preichl@redhat.com>
|
|
||||||
---
|
|
||||||
libxfs/xfs_btree.h | 1 -
|
|
||||||
1 file changed, 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h
|
|
||||||
index eef27858..29c4b4cc 100644
|
|
||||||
--- a/libxfs/xfs_btree.h
|
|
||||||
+++ b/libxfs/xfs_btree.h
|
|
||||||
@@ -556,7 +556,6 @@ xfs_btree_islastblock(
|
|
||||||
struct xfs_buf *bp;
|
|
||||||
|
|
||||||
block = xfs_btree_get_block(cur, level, &bp);
|
|
||||||
- ASSERT(block && xfs_btree_check_block(cur, block, level, bp) == 0);
|
|
||||||
|
|
||||||
if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
|
|
||||||
return block->bb_u.l.bb_rightsib == cpu_to_be64(NULLFSBLOCK);
|
|
||||||
--
|
|
||||||
2.40.0
|
|
||||||
|
|
@ -1,187 +0,0 @@
|
|||||||
From d1dca9f6b365e439878e550ed0c801bbfb6d347b Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Darrick J. Wong" <djwong@kernel.org>
|
|
||||||
Date: Wed, 15 Mar 2023 15:55:35 +0100
|
|
||||||
Subject: [PATCH] xfs: hoist refcount record merge predicates
|
|
||||||
|
|
||||||
Source kernel commit: 9d720a5a658f5135861773f26e927449bef93d61
|
|
||||||
|
|
||||||
Hoist these multiline conditionals into separate static inline helpers
|
|
||||||
to improve readability and set the stage for corruption fixes that will
|
|
||||||
be introduced in the next patch.
|
|
||||||
|
|
||||||
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
|
|
||||||
Reviewed-by: Dave Chinner <dchinner@redhat.com>
|
|
||||||
Reviewed-by: Xiao Yang <yangx.jy@fujitsu.com>
|
|
||||||
Signed-off-by: Carlos Maiolino <cem@kernel.org>
|
|
||||||
Signed-off-by: Pavel Reichl <preichl@redhat.com>
|
|
||||||
---
|
|
||||||
libxfs/xfs_refcount.c | 129 ++++++++++++++++++++++++++++++++++++------
|
|
||||||
1 file changed, 113 insertions(+), 16 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/libxfs/xfs_refcount.c b/libxfs/xfs_refcount.c
|
|
||||||
index 64e66861..f6167c5f 100644
|
|
||||||
--- a/libxfs/xfs_refcount.c
|
|
||||||
+++ b/libxfs/xfs_refcount.c
|
|
||||||
@@ -814,11 +814,119 @@ out_error:
|
|
||||||
/* Is this extent valid? */
|
|
||||||
static inline bool
|
|
||||||
xfs_refc_valid(
|
|
||||||
- struct xfs_refcount_irec *rc)
|
|
||||||
+ const struct xfs_refcount_irec *rc)
|
|
||||||
{
|
|
||||||
return rc->rc_startblock != NULLAGBLOCK;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static inline bool
|
|
||||||
+xfs_refc_want_merge_center(
|
|
||||||
+ const struct xfs_refcount_irec *left,
|
|
||||||
+ const struct xfs_refcount_irec *cleft,
|
|
||||||
+ const struct xfs_refcount_irec *cright,
|
|
||||||
+ const struct xfs_refcount_irec *right,
|
|
||||||
+ bool cleft_is_cright,
|
|
||||||
+ enum xfs_refc_adjust_op adjust,
|
|
||||||
+ unsigned long long *ulenp)
|
|
||||||
+{
|
|
||||||
+ unsigned long long ulen = left->rc_blockcount;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * To merge with a center record, both shoulder records must be
|
|
||||||
+ * adjacent to the record we want to adjust. This is only true if
|
|
||||||
+ * find_left and find_right made all four records valid.
|
|
||||||
+ */
|
|
||||||
+ if (!xfs_refc_valid(left) || !xfs_refc_valid(right) ||
|
|
||||||
+ !xfs_refc_valid(cleft) || !xfs_refc_valid(cright))
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ /* There must only be one record for the entire range. */
|
|
||||||
+ if (!cleft_is_cright)
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ /* The shoulder record refcounts must match the new refcount. */
|
|
||||||
+ if (left->rc_refcount != cleft->rc_refcount + adjust)
|
|
||||||
+ return false;
|
|
||||||
+ if (right->rc_refcount != cleft->rc_refcount + adjust)
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * The new record cannot exceed the max length. ulen is a ULL as the
|
|
||||||
+ * individual record block counts can be up to (u32 - 1) in length
|
|
||||||
+ * hence we need to catch u32 addition overflows here.
|
|
||||||
+ */
|
|
||||||
+ ulen += cleft->rc_blockcount + right->rc_blockcount;
|
|
||||||
+ if (ulen >= MAXREFCEXTLEN)
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ *ulenp = ulen;
|
|
||||||
+ return true;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline bool
|
|
||||||
+xfs_refc_want_merge_left(
|
|
||||||
+ const struct xfs_refcount_irec *left,
|
|
||||||
+ const struct xfs_refcount_irec *cleft,
|
|
||||||
+ enum xfs_refc_adjust_op adjust)
|
|
||||||
+{
|
|
||||||
+ unsigned long long ulen = left->rc_blockcount;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * For a left merge, the left shoulder record must be adjacent to the
|
|
||||||
+ * start of the range. If this is true, find_left made left and cleft
|
|
||||||
+ * contain valid contents.
|
|
||||||
+ */
|
|
||||||
+ if (!xfs_refc_valid(left) || !xfs_refc_valid(cleft))
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ /* Left shoulder record refcount must match the new refcount. */
|
|
||||||
+ if (left->rc_refcount != cleft->rc_refcount + adjust)
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * The new record cannot exceed the max length. ulen is a ULL as the
|
|
||||||
+ * individual record block counts can be up to (u32 - 1) in length
|
|
||||||
+ * hence we need to catch u32 addition overflows here.
|
|
||||||
+ */
|
|
||||||
+ ulen += cleft->rc_blockcount;
|
|
||||||
+ if (ulen >= MAXREFCEXTLEN)
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ return true;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline bool
|
|
||||||
+xfs_refc_want_merge_right(
|
|
||||||
+ const struct xfs_refcount_irec *cright,
|
|
||||||
+ const struct xfs_refcount_irec *right,
|
|
||||||
+ enum xfs_refc_adjust_op adjust)
|
|
||||||
+{
|
|
||||||
+ unsigned long long ulen = right->rc_blockcount;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * For a right merge, the right shoulder record must be adjacent to the
|
|
||||||
+ * end of the range. If this is true, find_right made cright and right
|
|
||||||
+ * contain valid contents.
|
|
||||||
+ */
|
|
||||||
+ if (!xfs_refc_valid(right) || !xfs_refc_valid(cright))
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ /* Right shoulder record refcount must match the new refcount. */
|
|
||||||
+ if (right->rc_refcount != cright->rc_refcount + adjust)
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * The new record cannot exceed the max length. ulen is a ULL as the
|
|
||||||
+ * individual record block counts can be up to (u32 - 1) in length
|
|
||||||
+ * hence we need to catch u32 addition overflows here.
|
|
||||||
+ */
|
|
||||||
+ ulen += cright->rc_blockcount;
|
|
||||||
+ if (ulen >= MAXREFCEXTLEN)
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ return true;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* Try to merge with any extents on the boundaries of the adjustment range.
|
|
||||||
*/
|
|
||||||
@@ -860,23 +968,15 @@ xfs_refcount_merge_extents(
|
|
||||||
(cleft.rc_blockcount == cright.rc_blockcount);
|
|
||||||
|
|
||||||
/* Try to merge left, cleft, and right. cleft must == cright. */
|
|
||||||
- ulen = (unsigned long long)left.rc_blockcount + cleft.rc_blockcount +
|
|
||||||
- right.rc_blockcount;
|
|
||||||
- if (xfs_refc_valid(&left) && xfs_refc_valid(&right) &&
|
|
||||||
- xfs_refc_valid(&cleft) && xfs_refc_valid(&cright) && cequal &&
|
|
||||||
- left.rc_refcount == cleft.rc_refcount + adjust &&
|
|
||||||
- right.rc_refcount == cleft.rc_refcount + adjust &&
|
|
||||||
- ulen < MAXREFCEXTLEN) {
|
|
||||||
+ if (xfs_refc_want_merge_center(&left, &cleft, &cright, &right, cequal,
|
|
||||||
+ adjust, &ulen)) {
|
|
||||||
*shape_changed = true;
|
|
||||||
return xfs_refcount_merge_center_extents(cur, &left, &cleft,
|
|
||||||
&right, ulen, aglen);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Try to merge left and cleft. */
|
|
||||||
- ulen = (unsigned long long)left.rc_blockcount + cleft.rc_blockcount;
|
|
||||||
- if (xfs_refc_valid(&left) && xfs_refc_valid(&cleft) &&
|
|
||||||
- left.rc_refcount == cleft.rc_refcount + adjust &&
|
|
||||||
- ulen < MAXREFCEXTLEN) {
|
|
||||||
+ if (xfs_refc_want_merge_left(&left, &cleft, adjust)) {
|
|
||||||
*shape_changed = true;
|
|
||||||
error = xfs_refcount_merge_left_extent(cur, &left, &cleft,
|
|
||||||
agbno, aglen);
|
|
||||||
@@ -892,10 +992,7 @@ xfs_refcount_merge_extents(
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Try to merge cright and right. */
|
|
||||||
- ulen = (unsigned long long)right.rc_blockcount + cright.rc_blockcount;
|
|
||||||
- if (xfs_refc_valid(&right) && xfs_refc_valid(&cright) &&
|
|
||||||
- right.rc_refcount == cright.rc_refcount + adjust &&
|
|
||||||
- ulen < MAXREFCEXTLEN) {
|
|
||||||
+ if (xfs_refc_want_merge_right(&cright, &right, adjust)) {
|
|
||||||
*shape_changed = true;
|
|
||||||
return xfs_refcount_merge_right_extent(cur, &right, &cright,
|
|
||||||
aglen);
|
|
||||||
--
|
|
||||||
2.40.0
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
|||||||
From 798d43495df2c8a09a73b8e868a71d8f2fd81d5e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Andrey Strachuk <strochuk@ispras.ru>
|
|
||||||
Date: Wed, 24 Aug 2022 10:24:01 +0200
|
|
||||||
Subject: [PATCH] xfs: removed useless condition in function xfs_attr_node_get
|
|
||||||
|
|
||||||
Source kernel commit: 0f38063d7a38015a47ca1488406bf21e0effe80e
|
|
||||||
|
|
||||||
At line 1561, variable "state" is being compared
|
|
||||||
with NULL every loop iteration.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
|
||||||
1561 for (i = 0; state != NULL && i < state->path.active; i++) {
|
|
||||||
1562 xfs_trans_brelse(args->trans, state->path.blk[i].bp);
|
|
||||||
1563 state->path.blk[i].bp = NULL;
|
|
||||||
1564 }
|
|
||||||
-------------------------------------------------------------------
|
|
||||||
|
|
||||||
However, it cannot be NULL.
|
|
||||||
|
|
||||||
----------------------------------------
|
|
||||||
1546 state = xfs_da_state_alloc(args);
|
|
||||||
----------------------------------------
|
|
||||||
|
|
||||||
xfs_da_state_alloc calls kmem_cache_zalloc. kmem_cache_zalloc is
|
|
||||||
called with __GFP_NOFAIL flag and, therefore, it cannot return NULL.
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
struct xfs_da_state *
|
|
||||||
xfs_da_state_alloc(
|
|
||||||
struct xfs_da_args *args)
|
|
||||||
{
|
|
||||||
struct xfs_da_state *state;
|
|
||||||
|
|
||||||
state = kmem_cache_zalloc(xfs_da_state_cache, GFP_NOFS | __GFP_NOFAIL);
|
|
||||||
state->args = args;
|
|
||||||
state->mp = args->dp->i_mount;
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Found by Linux Verification Center (linuxtesting.org) with SVACE.
|
|
||||||
|
|
||||||
Signed-off-by: Andrey Strachuk <strochuk@ispras.ru>
|
|
||||||
|
|
||||||
Fixes: 4d0cdd2bb8f0 ("xfs: clean up xfs_attr_node_hasname")
|
|
||||||
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
|
|
||||||
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
|
|
||||||
Signed-off-by: Carlos Maiolino <cem@kernel.org>
|
|
||||||
Signed-off-by: Pavel Reichl <preichl@redhat.com>
|
|
||||||
---
|
|
||||||
libxfs/xfs_attr.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
|
|
||||||
index 08973934..b451fcdb 100644
|
|
||||||
--- a/libxfs/xfs_attr.c
|
|
||||||
+++ b/libxfs/xfs_attr.c
|
|
||||||
@@ -1556,7 +1556,7 @@ xfs_attr_node_get(
|
|
||||||
* If not in a transaction, we have to release all the buffers.
|
|
||||||
*/
|
|
||||||
out_release:
|
|
||||||
- for (i = 0; state != NULL && i < state->path.active; i++) {
|
|
||||||
+ for (i = 0; i < state->path.active; i++) {
|
|
||||||
xfs_trans_brelse(args->trans, state->path.blk[i].bp);
|
|
||||||
state->path.blk[i].bp = NULL;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.40.0
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
|||||||
From 7374f58bfeb38467bab6552a47a5cd6bbe3c2e2e Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Darrick J. Wong" <djwong@kernel.org>
|
|
||||||
Date: Tue, 20 Dec 2022 16:53:34 -0800
|
|
||||||
Subject: [PATCH] xfs_db: fix dir3 block magic check
|
|
||||||
|
|
||||||
Fix this broken check, which (amazingly) went unnoticed until I cranked
|
|
||||||
up the warning level /and/ built the system for s390x.
|
|
||||||
|
|
||||||
Fixes: e96864ff4d4 ("xfs_db: enable blockget for v5 filesystems")
|
|
||||||
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
|
|
||||||
Reviewed-by: Dave Chinner <dchinner@redhat.com>
|
|
||||||
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
|
|
||||||
Signed-off-by: Carlos Maiolino <cem@kernel.org>
|
|
||||||
Signed-off-by: Pavel Reichl <preichl@redhat.com>
|
|
||||||
---
|
|
||||||
db/check.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/db/check.c b/db/check.c
|
|
||||||
index bb27ce58..964756d0 100644
|
|
||||||
--- a/db/check.c
|
|
||||||
+++ b/db/check.c
|
|
||||||
@@ -2578,7 +2578,7 @@ process_data_dir_v2(
|
|
||||||
error++;
|
|
||||||
}
|
|
||||||
if ((be32_to_cpu(data->magic) == XFS_DIR2_BLOCK_MAGIC ||
|
|
||||||
- be32_to_cpu(data->magic) == XFS_DIR2_BLOCK_MAGIC) &&
|
|
||||||
+ be32_to_cpu(data->magic) == XFS_DIR3_BLOCK_MAGIC) &&
|
|
||||||
stale != be32_to_cpu(btp->stale)) {
|
|
||||||
if (!sflag || v)
|
|
||||||
dbprintf(_("dir %lld block %d bad stale tail count %d\n"),
|
|
||||||
--
|
|
||||||
2.40.0
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
|||||||
|
From f50d3462c654acc484ab3ea68e75e8252b77e262 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <djwong@kernel.org>
|
||||||
|
Date: Wed, 13 Jul 2022 20:58:25 -0500
|
||||||
|
Subject: [PATCH] xfs_repair: ignore empty xattr leaf blocks
|
||||||
|
|
||||||
|
As detailed in the commit:
|
||||||
|
|
||||||
|
5e572d1a xfs: empty xattr leaf header blocks are not corruption
|
||||||
|
|
||||||
|
empty xattr leaf blocks can be the benign byproduct of the system
|
||||||
|
going down during the multi-step process of adding a large xattr
|
||||||
|
to a file that has no xattrs. If we find one at attr fork offset 0,
|
||||||
|
we should clear it, but this isn't a corruption.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
|
||||||
|
Reviewed-by: Dave Chinner <dchinner@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
Signed-off-by: Pavel Reichl <preichl@redhat.com>
|
||||||
|
---
|
||||||
|
repair/attr_repair.c | 20 ++++++++++++++++++++
|
||||||
|
1 file changed, 20 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/repair/attr_repair.c b/repair/attr_repair.c
|
||||||
|
index 2055d96e..c3a6d502 100644
|
||||||
|
--- a/repair/attr_repair.c
|
||||||
|
+++ b/repair/attr_repair.c
|
||||||
|
@@ -579,6 +579,26 @@ process_leaf_attr_block(
|
||||||
|
firstb = mp->m_sb.sb_blocksize;
|
||||||
|
stop = xfs_attr3_leaf_hdr_size(leaf);
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * Empty leaf blocks at offset zero can occur as a race between
|
||||||
|
+ * setxattr and the system going down, so we only take action if we're
|
||||||
|
+ * running in modify mode. See xfs_attr3_leaf_verify for details of
|
||||||
|
+ * how we've screwed this up many times.
|
||||||
|
+ */
|
||||||
|
+ if (!leafhdr.count && da_bno == 0) {
|
||||||
|
+ if (no_modify) {
|
||||||
|
+ do_log(
|
||||||
|
+ _("would clear empty leaf attr block 0, inode %" PRIu64 "\n"),
|
||||||
|
+ ino);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ do_warn(
|
||||||
|
+ _("will clear empty leaf attr block 0, inode %" PRIu64 "\n"),
|
||||||
|
+ ino);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* does the count look sorta valid? */
|
||||||
|
if (!leafhdr.count ||
|
||||||
|
leafhdr.count * sizeof(xfs_attr_leaf_entry_t) + stop >
|
||||||
|
--
|
||||||
|
2.40.1
|
||||||
|
|
@ -1,266 +0,0 @@
|
|||||||
From 945c7341dedab44ae5daed83377e6366c3fb8fee Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Darrick J. Wong" <djwong@kernel.org>
|
|
||||||
Date: Wed, 23 Nov 2022 09:09:33 -0800
|
|
||||||
Subject: [PATCH] xfs_repair: retain superblock buffer to avoid write hook
|
|
||||||
deadlock
|
|
||||||
|
|
||||||
Every now and then I experience the following deadlock in xfs_repair
|
|
||||||
when I'm running the offline repair fuzz tests:
|
|
||||||
|
|
||||||
#0 futex_wait (private=0, expected=2, futex_word=0x55555566df70) at ../sysdeps/nptl/futex-internal.h:146
|
|
||||||
#1 __GI___lll_lock_wait (futex=futex@entry=0x55555566df70, private=0) at ./nptl/lowlevellock.c:49
|
|
||||||
#2 lll_mutex_lock_optimized (mutex=0x55555566df70) at ./nptl/pthread_mutex_lock.c:48
|
|
||||||
#3 ___pthread_mutex_lock (mutex=mutex@entry=0x55555566df70) at ./nptl/pthread_mutex_lock.c:93
|
|
||||||
#4 cache_shake (cache=cache@entry=0x55555566de60, priority=priority@entry=2, purge=purge@entry=false) at cache.c:231
|
|
||||||
#5 cache_node_get (cache=cache@entry=0x55555566de60, key=key@entry=0x7fffe55e01b0, nodep=nodep@entry=0x7fffe55e0168) at cache.c:452
|
|
||||||
#6 __cache_lookup (key=key@entry=0x7fffe55e01b0, flags=0, bpp=bpp@entry=0x7fffe55e0228) at rdwr.c:405
|
|
||||||
#7 libxfs_getbuf_flags (btp=0x55555566de00, blkno=0, len=<optimized out>, flags=<optimized out>, bpp=0x7fffe55e0228) at rdwr.c:457
|
|
||||||
#8 libxfs_buf_read_map (btp=0x55555566de00, map=map@entry=0x7fffe55e0280, nmaps=nmaps@entry=1, flags=flags@entry=0, bpp=bpp@entry=0x7fffe55e0278, ops=0x5555556233e0 <xfs_sb_buf_ops>)
|
|
||||||
at rdwr.c:704
|
|
||||||
#9 libxfs_buf_read (ops=<optimized out>, bpp=0x7fffe55e0278, flags=0, numblks=<optimized out>, blkno=0, target=<optimized out>)
|
|
||||||
at /storage/home/djwong/cdev/work/xfsprogs/build-x86_64/libxfs/libxfs_io.h:195
|
|
||||||
#10 libxfs_getsb (mp=mp@entry=0x7fffffffd690) at rdwr.c:162
|
|
||||||
#11 force_needsrepair (mp=0x7fffffffd690) at xfs_repair.c:924
|
|
||||||
#12 repair_capture_writeback (bp=<optimized out>) at xfs_repair.c:1000
|
|
||||||
#13 libxfs_bwrite (bp=0x7fffe011e530) at rdwr.c:869
|
|
||||||
#14 cache_shake (cache=cache@entry=0x55555566de60, priority=priority@entry=2, purge=purge@entry=false) at cache.c:240
|
|
||||||
#15 cache_node_get (cache=cache@entry=0x55555566de60, key=key@entry=0x7fffe55e0470, nodep=nodep@entry=0x7fffe55e0428) at cache.c:452
|
|
||||||
#16 __cache_lookup (key=key@entry=0x7fffe55e0470, flags=1, bpp=bpp@entry=0x7fffe55e0538) at rdwr.c:405
|
|
||||||
#17 libxfs_getbuf_flags (btp=0x55555566de00, blkno=12736, len=<optimized out>, flags=<optimized out>, bpp=0x7fffe55e0538) at rdwr.c:457
|
|
||||||
#18 __libxfs_buf_get_map (btp=<optimized out>, map=map@entry=0x7fffe55e05b0, nmaps=<optimized out>, flags=flags@entry=1, bpp=bpp@entry=0x7fffe55e0538) at rdwr.c:501
|
|
||||||
#19 libxfs_buf_get_map (btp=<optimized out>, map=map@entry=0x7fffe55e05b0, nmaps=<optimized out>, flags=flags@entry=1, bpp=bpp@entry=0x7fffe55e0538) at rdwr.c:525
|
|
||||||
#20 pf_queue_io (args=args@entry=0x5555556722c0, map=map@entry=0x7fffe55e05b0, nmaps=<optimized out>, flag=flag@entry=11) at prefetch.c:124
|
|
||||||
#21 pf_read_bmbt_reclist (args=0x5555556722c0, rp=<optimized out>, numrecs=78) at prefetch.c:220
|
|
||||||
#22 pf_scan_lbtree (dbno=dbno@entry=1211, level=level@entry=1, isadir=isadir@entry=1, args=args@entry=0x5555556722c0, func=0x55555557f240 <pf_scanfunc_bmap>) at prefetch.c:298
|
|
||||||
#23 pf_read_btinode (isadir=1, dino=<optimized out>, args=0x5555556722c0) at prefetch.c:385
|
|
||||||
#24 pf_read_inode_dirs (args=args@entry=0x5555556722c0, bp=bp@entry=0x7fffdc023790) at prefetch.c:459
|
|
||||||
#25 pf_read_inode_dirs (bp=<optimized out>, args=0x5555556722c0) at prefetch.c:411
|
|
||||||
#26 pf_batch_read (args=args@entry=0x5555556722c0, which=which@entry=PF_PRIMARY, buf=buf@entry=0x7fffd001d000) at prefetch.c:609
|
|
||||||
#27 pf_io_worker (param=0x5555556722c0) at prefetch.c:673
|
|
||||||
#28 start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
|
|
||||||
#29 clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
|
|
||||||
|
|
||||||
>From this stack trace, we see that xfs_repair's prefetch module is
|
|
||||||
getting some xfs_buf objects ahead of initiating a read (#19). The
|
|
||||||
buffer cache has hit its limit, so it calls cache_shake (#14) to free
|
|
||||||
some unused xfs_bufs. The buffer it finds is a dirty buffer, so it
|
|
||||||
calls libxfs_bwrite to flush it out to disk, which in turn invokes the
|
|
||||||
buffer write hook that xfs_repair set up in 3b7667cb to mark the ondisk
|
|
||||||
filesystem's superblock as NEEDSREPAIR until repair actually completes.
|
|
||||||
|
|
||||||
Unfortunately, the NEEDSREPAIR handler itself needs to grab the
|
|
||||||
superblock buffer, so it makes another call into the buffer cache (#9),
|
|
||||||
which sees that the cache is full and tries to shake it(#4). Hence we
|
|
||||||
deadlock on cm_mutex because shaking is not reentrant.
|
|
||||||
|
|
||||||
Fix this by retaining a reference to the superblock buffer when possible
|
|
||||||
so that the writeback hook doesn't have to access the buffer cache to
|
|
||||||
set NEEDSREPAIR.
|
|
||||||
|
|
||||||
Fixes: 3b7667cb ("xfs_repair: set NEEDSREPAIR the first time we write to a filesystem")
|
|
||||||
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
|
|
||||||
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
|
|
||||||
Signed-off-by: Carlos Maiolino <cem@kernel.org>
|
|
||||||
Signed-off-by: Pavel Reichl <preichl@redhat.com>
|
|
||||||
---
|
|
||||||
libxfs/libxfs_api_defs.h | 2 ++
|
|
||||||
libxfs/libxfs_io.h | 1 +
|
|
||||||
libxfs/rdwr.c | 8 +++++
|
|
||||||
repair/phase2.c | 8 +++++
|
|
||||||
repair/protos.h | 1 +
|
|
||||||
repair/xfs_repair.c | 75 +++++++++++++++++++++++++++++++++++-----
|
|
||||||
6 files changed, 86 insertions(+), 9 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
|
|
||||||
index 2716a731..f8efcce7 100644
|
|
||||||
--- a/libxfs/libxfs_api_defs.h
|
|
||||||
+++ b/libxfs/libxfs_api_defs.h
|
|
||||||
@@ -53,9 +53,11 @@
|
|
||||||
#define xfs_buf_delwri_submit libxfs_buf_delwri_submit
|
|
||||||
#define xfs_buf_get libxfs_buf_get
|
|
||||||
#define xfs_buf_get_uncached libxfs_buf_get_uncached
|
|
||||||
+#define xfs_buf_lock libxfs_buf_lock
|
|
||||||
#define xfs_buf_read libxfs_buf_read
|
|
||||||
#define xfs_buf_read_uncached libxfs_buf_read_uncached
|
|
||||||
#define xfs_buf_relse libxfs_buf_relse
|
|
||||||
+#define xfs_buf_unlock libxfs_buf_unlock
|
|
||||||
#define xfs_bunmapi libxfs_bunmapi
|
|
||||||
#define xfs_bwrite libxfs_bwrite
|
|
||||||
#define xfs_calc_dquots_per_chunk libxfs_calc_dquots_per_chunk
|
|
||||||
diff --git a/libxfs/libxfs_io.h b/libxfs/libxfs_io.h
|
|
||||||
index 9c0e2704..fae86427 100644
|
|
||||||
--- a/libxfs/libxfs_io.h
|
|
||||||
+++ b/libxfs/libxfs_io.h
|
|
||||||
@@ -226,6 +226,7 @@ xfs_buf_hold(struct xfs_buf *bp)
|
|
||||||
}
|
|
||||||
|
|
||||||
void xfs_buf_lock(struct xfs_buf *bp);
|
|
||||||
+void xfs_buf_unlock(struct xfs_buf *bp);
|
|
||||||
|
|
||||||
int libxfs_buf_get_uncached(struct xfs_buftarg *targ, size_t bblen, int flags,
|
|
||||||
struct xfs_buf **bpp);
|
|
||||||
diff --git a/libxfs/rdwr.c b/libxfs/rdwr.c
|
|
||||||
index 20e0793c..d5aad3ea 100644
|
|
||||||
--- a/libxfs/rdwr.c
|
|
||||||
+++ b/libxfs/rdwr.c
|
|
||||||
@@ -384,6 +384,14 @@ xfs_buf_lock(
|
|
||||||
pthread_mutex_lock(&bp->b_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
+void
|
|
||||||
+xfs_buf_unlock(
|
|
||||||
+ struct xfs_buf *bp)
|
|
||||||
+{
|
|
||||||
+ if (use_xfs_buf_lock)
|
|
||||||
+ pthread_mutex_unlock(&bp->b_lock);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static int
|
|
||||||
__cache_lookup(
|
|
||||||
struct xfs_bufkey *key,
|
|
||||||
diff --git a/repair/phase2.c b/repair/phase2.c
|
|
||||||
index 56a39bb4..2ada95ae 100644
|
|
||||||
--- a/repair/phase2.c
|
|
||||||
+++ b/repair/phase2.c
|
|
||||||
@@ -370,6 +370,14 @@ phase2(
|
|
||||||
} else
|
|
||||||
do_log(_("Phase 2 - using internal log\n"));
|
|
||||||
|
|
||||||
+ /*
|
|
||||||
+ * Now that we've set up the buffer cache the way we want it, try to
|
|
||||||
+ * grab our own reference to the primary sb so that the hooks will not
|
|
||||||
+ * have to call out to the buffer cache.
|
|
||||||
+ */
|
|
||||||
+ if (mp->m_buf_writeback_fn)
|
|
||||||
+ retain_primary_sb(mp);
|
|
||||||
+
|
|
||||||
/* Zero log if applicable */
|
|
||||||
do_log(_(" - zero log...\n"));
|
|
||||||
|
|
||||||
diff --git a/repair/protos.h b/repair/protos.h
|
|
||||||
index 03ebae14..83e471ff 100644
|
|
||||||
--- a/repair/protos.h
|
|
||||||
+++ b/repair/protos.h
|
|
||||||
@@ -16,6 +16,7 @@ int get_sb(xfs_sb_t *sbp,
|
|
||||||
xfs_off_t off,
|
|
||||||
int size,
|
|
||||||
xfs_agnumber_t agno);
|
|
||||||
+int retain_primary_sb(struct xfs_mount *mp);
|
|
||||||
void write_primary_sb(xfs_sb_t *sbp,
|
|
||||||
int size);
|
|
||||||
|
|
||||||
diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c
|
|
||||||
index 871b428d..ff29bea9 100644
|
|
||||||
--- a/repair/xfs_repair.c
|
|
||||||
+++ b/repair/xfs_repair.c
|
|
||||||
@@ -749,6 +749,63 @@ check_fs_vs_host_sectsize(
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+/*
|
|
||||||
+ * If we set up a writeback function to set NEEDSREPAIR while the filesystem is
|
|
||||||
+ * dirty, there's a chance that calling libxfs_getsb could deadlock the buffer
|
|
||||||
+ * cache while trying to get the primary sb buffer if the first non-sb write to
|
|
||||||
+ * the filesystem is the result of a cache shake. Retain a reference to the
|
|
||||||
+ * primary sb buffer to avoid all that.
|
|
||||||
+ */
|
|
||||||
+static struct xfs_buf *primary_sb_bp; /* buffer for superblock */
|
|
||||||
+
|
|
||||||
+int
|
|
||||||
+retain_primary_sb(
|
|
||||||
+ struct xfs_mount *mp)
|
|
||||||
+{
|
|
||||||
+ int error;
|
|
||||||
+
|
|
||||||
+ error = -libxfs_buf_read(mp->m_ddev_targp, XFS_SB_DADDR,
|
|
||||||
+ XFS_FSS_TO_BB(mp, 1), 0, &primary_sb_bp,
|
|
||||||
+ &xfs_sb_buf_ops);
|
|
||||||
+ if (error)
|
|
||||||
+ return error;
|
|
||||||
+
|
|
||||||
+ libxfs_buf_unlock(primary_sb_bp);
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+drop_primary_sb(void)
|
|
||||||
+{
|
|
||||||
+ if (!primary_sb_bp)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ libxfs_buf_lock(primary_sb_bp);
|
|
||||||
+ libxfs_buf_relse(primary_sb_bp);
|
|
||||||
+ primary_sb_bp = NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+get_primary_sb(
|
|
||||||
+ struct xfs_mount *mp,
|
|
||||||
+ struct xfs_buf **bpp)
|
|
||||||
+{
|
|
||||||
+ int error;
|
|
||||||
+
|
|
||||||
+ *bpp = NULL;
|
|
||||||
+
|
|
||||||
+ if (!primary_sb_bp) {
|
|
||||||
+ error = retain_primary_sb(mp);
|
|
||||||
+ if (error)
|
|
||||||
+ return error;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ libxfs_buf_lock(primary_sb_bp);
|
|
||||||
+ xfs_buf_hold(primary_sb_bp);
|
|
||||||
+ *bpp = primary_sb_bp;
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/* Clear needsrepair after a successful repair run. */
|
|
||||||
void
|
|
||||||
clear_needsrepair(
|
|
||||||
@@ -769,15 +826,14 @@ clear_needsrepair(
|
|
||||||
do_warn(
|
|
||||||
_("Cannot clear needsrepair due to flush failure, err=%d.\n"),
|
|
||||||
error);
|
|
||||||
- return;
|
|
||||||
+ goto drop;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear needsrepair from the superblock. */
|
|
||||||
- bp = libxfs_getsb(mp);
|
|
||||||
- if (!bp || bp->b_error) {
|
|
||||||
+ error = get_primary_sb(mp, &bp);
|
|
||||||
+ if (error) {
|
|
||||||
do_warn(
|
|
||||||
- _("Cannot clear needsrepair from primary super, err=%d.\n"),
|
|
||||||
- bp ? bp->b_error : ENOMEM);
|
|
||||||
+ _("Cannot clear needsrepair from primary super, err=%d.\n"), error);
|
|
||||||
} else {
|
|
||||||
mp->m_sb.sb_features_incompat &=
|
|
||||||
~XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR;
|
|
||||||
@@ -786,6 +842,8 @@ clear_needsrepair(
|
|
||||||
}
|
|
||||||
if (bp)
|
|
||||||
libxfs_buf_relse(bp);
|
|
||||||
+drop:
|
|
||||||
+ drop_primary_sb();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
@@ -808,11 +866,10 @@ force_needsrepair(
|
|
||||||
xfs_sb_version_needsrepair(&mp->m_sb))
|
|
||||||
return;
|
|
||||||
|
|
||||||
- bp = libxfs_getsb(mp);
|
|
||||||
- if (!bp || bp->b_error) {
|
|
||||||
+ error = get_primary_sb(mp, &bp);
|
|
||||||
+ if (error) {
|
|
||||||
do_log(
|
|
||||||
- _("couldn't get superblock to set needsrepair, err=%d\n"),
|
|
||||||
- bp ? bp->b_error : ENOMEM);
|
|
||||||
+ _("couldn't get superblock to set needsrepair, err=%d\n"), error);
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* It's possible that we need to set NEEDSREPAIR before we've
|
|
||||||
--
|
|
||||||
2.40.0
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
|||||||
-----BEGIN PGP SIGNATURE-----
|
|
||||||
|
|
||||||
iQJIBAABCAAyFiEEK4GFkZ6NJImBhp3tIK4WkuE93uAFAmL2oA0UHHNhbmRlZW5A
|
|
||||||
c2FuZGVlbi5uZXQACgkQIK4WkuE93uCKsxAAxhIfv5fSmuy7Qh+b8w3a4khG8r5V
|
|
||||||
BtaNAqbKE+Zz1Rl8z3TGlYKXcI/Ruola5UKUjXzGeHBbXcOGWDpWoaMp5kDnloUP
|
|
||||||
SovsR+qpBUijPO4bff/7aR9+4tHS2UvEv0yDuG8gd6VyOGxPXDgwFSCEse4bWf61
|
|
||||||
l5UZN3dPXOMmm+G4ZITWuq1Us+3/uz12WwSuftCbPsghcCIDhnEQSA40yqyU2yJH
|
|
||||||
WTkLBb9/ROFN2iLjJ2HWeCEdZ62+mT767tZrmaQHlzFbK+rrl3CA7S+RjWHFA0qz
|
|
||||||
tDBLJLDMBdAExmR+sG+48pZTbgd1s8aXmMjCt80q5OzB5dKTfoYlqljkZxyIM0E2
|
|
||||||
y2Kq716s4rBHV/Na/lhqYMPAPY3hG9iDOLKAVSJWbI7i/j5t5+Uin697Ha79cupO
|
|
||||||
3bD7tJBr4JpL+tu9Q9khQhekGgSGqfQG/a9aJA0H8DoPsmOuuUrJBKs10npvVu18
|
|
||||||
Cx5WHwNeadK3rr0DLgik0X1POUex0fD+xjYXMWCHSJZhoC2wCbyvgg1xwYgEg16n
|
|
||||||
iyh+yxYSOlNgTZsseP/AmgsfKDO0hH/k4PiXrd4vT4+jDcVzBEQ62j8QJ629/qyC
|
|
||||||
mChjhcbzrJosAseLDMbm5gM2M79nqavrdvBhJ9JMEIjq/5m8VaQrmZE12w48lh92
|
|
||||||
WIngBgst2MrB8mE=
|
|
||||||
=KQvs
|
|
||||||
-----END PGP SIGNATURE-----
|
|
@ -0,0 +1,70 @@
|
|||||||
|
From 7e8275f8939988f18f9a4a596381ca215fde2270 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Date: Mon, 4 Nov 2019 15:35:49 -0500
|
||||||
|
Subject: [PATCH] xfs_growfs: allow mounted device node as argument
|
||||||
|
|
||||||
|
Up until:
|
||||||
|
|
||||||
|
b97815a0 xfs_growfs: ensure target path is an active xfs mountpoint
|
||||||
|
|
||||||
|
xfs_growfs actually accepted a mounted block device name as the
|
||||||
|
primary argument, because it could be found in the mount table.
|
||||||
|
|
||||||
|
It turns out that Ansible was making use of this undocumented behavior,
|
||||||
|
and it's trivial to allow it, so put it back in place and document
|
||||||
|
it this time.
|
||||||
|
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
growfs/xfs_growfs.c | 3 +++
|
||||||
|
man/man8/xfs_growfs.8 | 10 +++++++++-
|
||||||
|
2 files changed, 12 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/growfs/xfs_growfs.c b/growfs/xfs_growfs.c
|
||||||
|
index eab15984..6c62833b 100644
|
||||||
|
--- a/growfs/xfs_growfs.c
|
||||||
|
+++ b/growfs/xfs_growfs.c
|
||||||
|
@@ -141,6 +141,9 @@ main(int argc, char **argv)
|
||||||
|
}
|
||||||
|
|
||||||
|
fs = fs_table_lookup_mount(rpath);
|
||||||
|
+ if (!fs)
|
||||||
|
+ fs = fs_table_lookup_blkdev(rpath);
|
||||||
|
+
|
||||||
|
if (!fs) {
|
||||||
|
fprintf(stderr, _("%s: %s is not a mounted XFS filesystem\n"),
|
||||||
|
progname, argv[optind]);
|
||||||
|
diff --git a/man/man8/xfs_growfs.8 b/man/man8/xfs_growfs.8
|
||||||
|
index 7e6a387c..60a88189 100644
|
||||||
|
--- a/man/man8/xfs_growfs.8
|
||||||
|
+++ b/man/man8/xfs_growfs.8
|
||||||
|
@@ -35,7 +35,12 @@ xfs_growfs \- expand an XFS filesystem
|
||||||
|
.B \-R
|
||||||
|
.I size
|
||||||
|
]
|
||||||
|
+[
|
||||||
|
.I mount-point
|
||||||
|
+|
|
||||||
|
+.I block-device
|
||||||
|
+]
|
||||||
|
+
|
||||||
|
.br
|
||||||
|
.B xfs_growfs \-V
|
||||||
|
.SH DESCRIPTION
|
||||||
|
@@ -45,7 +50,10 @@ expands an existing XFS filesystem (see
|
||||||
|
The
|
||||||
|
.I mount-point
|
||||||
|
argument is the pathname of the directory where the filesystem
|
||||||
|
-is mounted. The filesystem must be mounted to be grown (see
|
||||||
|
+is mounted. The
|
||||||
|
+.I block-device
|
||||||
|
+argument is the device name of a mounted XFS filesystem.
|
||||||
|
+The filesystem must be mounted to be grown (see
|
||||||
|
.BR mount (8)).
|
||||||
|
The existing contents of the filesystem are undisturbed, and the added space
|
||||||
|
becomes available for additional file storage.
|
||||||
|
--
|
||||||
|
2.17.0
|
||||||
|
|
@ -0,0 +1,56 @@
|
|||||||
|
From 2383d7c5cf20efcff75cb29ca3e02cfbe1bf2209 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Date: Tue, 17 Dec 2019 16:52:39 -0500
|
||||||
|
Subject: [PATCH] mkfs: tidy up discard notifications
|
||||||
|
|
||||||
|
Only notify user of discard operations if the first one succeeds,
|
||||||
|
and be sure to print a trailing newline if we stop early.
|
||||||
|
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
mkfs/xfs_mkfs.c | 16 ++++++++++------
|
||||||
|
1 file changed, 10 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
|
||||||
|
index 4bfdebf6..606f79da 100644
|
||||||
|
--- a/mkfs/xfs_mkfs.c
|
||||||
|
+++ b/mkfs/xfs_mkfs.c
|
||||||
|
@@ -1251,10 +1251,6 @@ discard_blocks(dev_t dev, uint64_t nsectors, int quiet)
|
||||||
|
fd = libxfs_device_to_fd(dev);
|
||||||
|
if (fd <= 0)
|
||||||
|
return;
|
||||||
|
- if (!quiet) {
|
||||||
|
- printf("Discarding blocks...");
|
||||||
|
- fflush(stdout);
|
||||||
|
- }
|
||||||
|
|
||||||
|
/* The block discarding happens in smaller batches so it can be
|
||||||
|
* interrupted prematurely
|
||||||
|
@@ -1267,12 +1263,20 @@ discard_blocks(dev_t dev, uint64_t nsectors, int quiet)
|
||||||
|
* not necessary for the mkfs functionality but just an
|
||||||
|
* optimization. However we should stop on error.
|
||||||
|
*/
|
||||||
|
- if (platform_discard_blocks(fd, offset, tmp_step))
|
||||||
|
+ if (platform_discard_blocks(fd, offset, tmp_step) == 0) {
|
||||||
|
+ if (offset == 0 && !quiet) {
|
||||||
|
+ printf("Discarding blocks...");
|
||||||
|
+ fflush(stdout);
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ if (offset > 0 && !quiet)
|
||||||
|
+ printf("\n");
|
||||||
|
return;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
offset += tmp_step;
|
||||||
|
}
|
||||||
|
- if (!quiet)
|
||||||
|
+ if (offset > 0 && !quiet)
|
||||||
|
printf("Done.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.17.0
|
||||||
|
|
@ -0,0 +1,112 @@
|
|||||||
|
From 9d6023a856a1c4f84415dff59b0d5459cc8768db Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Date: Thu, 27 Feb 2020 15:05:48 -0500
|
||||||
|
Subject: [PATCH] libxfs: use FALLOC_FL_ZERO_RANGE in libxfs_device_zero
|
||||||
|
|
||||||
|
I had a request from someone who cared about mkfs speed over
|
||||||
|
a slower network block device to look into using faster zeroing
|
||||||
|
methods, particularly for the log, during mkfs.
|
||||||
|
|
||||||
|
Using FALLOC_FL_ZERO_RANGE is faster in this case than writing
|
||||||
|
a bunch of zeros across a wire.
|
||||||
|
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
include/builddefs.in | 3 +++
|
||||||
|
include/linux.h | 22 ++++++++++++++++++++++
|
||||||
|
libxfs/rdwr.c | 15 +++++++++++----
|
||||||
|
3 files changed, 36 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/include/builddefs.in b/include/builddefs.in
|
||||||
|
index 4700b52..1dd27f7 100644
|
||||||
|
--- a/include/builddefs.in
|
||||||
|
+++ b/include/builddefs.in
|
||||||
|
@@ -144,6 +144,9 @@ endif
|
||||||
|
ifeq ($(HAVE_GETFSMAP),yes)
|
||||||
|
PCFLAGS+= -DHAVE_GETFSMAP
|
||||||
|
endif
|
||||||
|
+ifeq ($(HAVE_FALLOCATE),yes)
|
||||||
|
+PCFLAGS += -DHAVE_FALLOCATE
|
||||||
|
+endif
|
||||||
|
|
||||||
|
LIBICU_LIBS = @libicu_LIBS@
|
||||||
|
LIBICU_CFLAGS = @libicu_CFLAGS@
|
||||||
|
diff --git a/include/linux.h b/include/linux.h
|
||||||
|
index 8f3c32b..57726bb 100644
|
||||||
|
--- a/include/linux.h
|
||||||
|
+++ b/include/linux.h
|
||||||
|
@@ -20,6 +20,10 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <asm/types.h>
|
||||||
|
#include <mntent.h>
|
||||||
|
+#include <fcntl.h>
|
||||||
|
+#if defined(HAVE_FALLOCATE)
|
||||||
|
+#include <linux/falloc.h>
|
||||||
|
+#endif
|
||||||
|
#ifdef OVERRIDE_SYSTEM_FSXATTR
|
||||||
|
# define fsxattr sys_fsxattr
|
||||||
|
#endif
|
||||||
|
@@ -164,6 +168,24 @@ static inline void platform_mntent_close(struct mntent_cursor * cursor)
|
||||||
|
endmntent(cursor->mtabp);
|
||||||
|
}
|
||||||
|
|
||||||
|
+#if defined(FALLOC_FL_ZERO_RANGE)
|
||||||
|
+static inline int
|
||||||
|
+platform_zero_range(
|
||||||
|
+ int fd,
|
||||||
|
+ xfs_off_t start,
|
||||||
|
+ size_t len)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = fallocate(fd, FALLOC_FL_ZERO_RANGE, start, len);
|
||||||
|
+ if (!ret)
|
||||||
|
+ return 0;
|
||||||
|
+ return -errno;
|
||||||
|
+}
|
||||||
|
+#else
|
||||||
|
+#define platform_zero_range(fd, s, l) (-EOPNOTSUPP)
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Check whether we have to define FS_IOC_FS[GS]ETXATTR ourselves. These
|
||||||
|
* are a copy of the definitions moved to linux/uapi/fs.h in the 4.5 kernel,
|
||||||
|
diff --git a/libxfs/rdwr.c b/libxfs/rdwr.c
|
||||||
|
index 0d9d720..e2d9d79 100644
|
||||||
|
--- a/libxfs/rdwr.c
|
||||||
|
+++ b/libxfs/rdwr.c
|
||||||
|
@@ -61,8 +61,18 @@ libxfs_device_zero(struct xfs_buftarg *btp, xfs_daddr_t start, uint len)
|
||||||
|
{
|
||||||
|
xfs_off_t start_offset, end_offset, offset;
|
||||||
|
ssize_t zsize, bytes;
|
||||||
|
+ size_t len_bytes;
|
||||||
|
char *z;
|
||||||
|
- int fd;
|
||||||
|
+ int error, fd;
|
||||||
|
+
|
||||||
|
+ fd = libxfs_device_to_fd(btp->dev);
|
||||||
|
+ start_offset = LIBXFS_BBTOOFF64(start);
|
||||||
|
+
|
||||||
|
+ /* try to use special zeroing methods, fall back to writes if needed */
|
||||||
|
+ len_bytes = LIBXFS_BBTOOFF64(len);
|
||||||
|
+ error = platform_zero_range(fd, start_offset, len_bytes);
|
||||||
|
+ if (!error)
|
||||||
|
+ return 0;
|
||||||
|
|
||||||
|
zsize = min(BDSTRAT_SIZE, BBTOB(len));
|
||||||
|
if ((z = memalign(libxfs_device_alignment(), zsize)) == NULL) {
|
||||||
|
@@ -73,9 +83,6 @@ libxfs_device_zero(struct xfs_buftarg *btp, xfs_daddr_t start, uint len)
|
||||||
|
}
|
||||||
|
memset(z, 0, zsize);
|
||||||
|
|
||||||
|
- fd = libxfs_device_to_fd(btp->dev);
|
||||||
|
- start_offset = LIBXFS_BBTOOFF64(start);
|
||||||
|
-
|
||||||
|
if ((lseek(fd, start_offset, SEEK_SET)) < 0) {
|
||||||
|
fprintf(stderr, _("%s: %s seek to offset %llu failed: %s\n"),
|
||||||
|
progname, __FUNCTION__,
|
||||||
|
--
|
||||||
|
2.9.5
|
||||||
|
|
@ -0,0 +1,123 @@
|
|||||||
|
From cb49e9a41477791af390a397c97da28da31fb81d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christoph Hellwig <hch@lst.de>
|
||||||
|
Date: Wed, 22 Jan 2020 11:29:44 -0500
|
||||||
|
Subject: [PATCH] xfs: use a struct timespec64 for the in-core crtime
|
||||||
|
|
||||||
|
Source kernel commit: 8d2d878db897d7501aaa2f72e10bb28295bb5498
|
||||||
|
|
||||||
|
struct xfs_icdinode is purely an in-memory data structure, so don't use
|
||||||
|
a log on-disk structure for it. This simplifies the code a bit, and
|
||||||
|
also reduces our include hell slightly.
|
||||||
|
|
||||||
|
Signed-off-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
[darrick: fix a minor indenting problem in xfs_trans_ichgtime]
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/include/libxfs.h b/include/libxfs.h
|
||||||
|
index 2bdef70..731561c 100644
|
||||||
|
--- a/include/libxfs.h
|
||||||
|
+++ b/include/libxfs.h
|
||||||
|
@@ -36,6 +36,8 @@ extern uint32_t crc32c_le(uint32_t crc, unsigned char const *p, size_t len);
|
||||||
|
|
||||||
|
#include "xfs_cksum.h"
|
||||||
|
|
||||||
|
+#define timespec64 timespec
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* This mirrors the kernel include for xfs_buf.h - it's implicitly included in
|
||||||
|
* every files via a similar include in the kernel xfs_linux.h.
|
||||||
|
diff --git a/include/xfs_inode.h b/include/xfs_inode.h
|
||||||
|
index 76f9ac7..e03d1cb 100644
|
||||||
|
--- a/include/xfs_inode.h
|
||||||
|
+++ b/include/xfs_inode.h
|
||||||
|
@@ -161,7 +161,6 @@ extern void libxfs_trans_ichgtime(struct xfs_trans *,
|
||||||
|
struct xfs_inode *, int);
|
||||||
|
extern int libxfs_iflush_int (struct xfs_inode *, struct xfs_buf *);
|
||||||
|
|
||||||
|
-#define timespec64 timespec
|
||||||
|
extern struct timespec64 current_time(struct inode *inode);
|
||||||
|
|
||||||
|
/* Inode Cache Interfaces */
|
||||||
|
diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h
|
||||||
|
index b45d07e..8232f89 100644
|
||||||
|
--- a/libxfs/libxfs_priv.h
|
||||||
|
+++ b/libxfs/libxfs_priv.h
|
||||||
|
@@ -62,6 +62,8 @@ extern kmem_zone_t *xfs_buf_zone;
|
||||||
|
extern kmem_zone_t *xfs_inode_zone;
|
||||||
|
extern kmem_zone_t *xfs_trans_zone;
|
||||||
|
|
||||||
|
+#define timespec64 timespec
|
||||||
|
+
|
||||||
|
/* CRC stuff, buffer API dependent on it */
|
||||||
|
#define crc32c(c,p,l) crc32c_le((c),(unsigned char const *)(p),(l))
|
||||||
|
|
||||||
|
diff --git a/libxfs/util.c b/libxfs/util.c
|
||||||
|
index 951f7cf..9383bb8 100644
|
||||||
|
--- a/libxfs/util.c
|
||||||
|
+++ b/libxfs/util.c
|
||||||
|
@@ -170,10 +170,8 @@ libxfs_trans_ichgtime(
|
||||||
|
VFS_I(ip)->i_mtime = tv;
|
||||||
|
if (flags & XFS_ICHGTIME_CHG)
|
||||||
|
VFS_I(ip)->i_ctime = tv;
|
||||||
|
- if (flags & XFS_ICHGTIME_CREATE) {
|
||||||
|
- ip->i_d.di_crtime.t_sec = (int32_t)tv.tv_sec;
|
||||||
|
- ip->i_d.di_crtime.t_nsec = (int32_t)tv.tv_nsec;
|
||||||
|
- }
|
||||||
|
+ if (flags & XFS_ICHGTIME_CREATE)
|
||||||
|
+ ip->i_d.di_crtime = tv;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC uint16_t
|
||||||
|
@@ -321,8 +319,8 @@ libxfs_ialloc(
|
||||||
|
VFS_I(ip)->i_version = 1;
|
||||||
|
ip->i_d.di_flags2 = pip ? 0 : xfs_flags2diflags2(ip,
|
||||||
|
fsx->fsx_xflags);
|
||||||
|
- ip->i_d.di_crtime.t_sec = (int32_t)VFS_I(ip)->i_mtime.tv_sec;
|
||||||
|
- ip->i_d.di_crtime.t_nsec = (int32_t)VFS_I(ip)->i_mtime.tv_nsec;
|
||||||
|
+ ip->i_d.di_crtime.tv_sec = (int32_t)VFS_I(ip)->i_mtime.tv_sec;
|
||||||
|
+ ip->i_d.di_crtime.tv_nsec = (int32_t)VFS_I(ip)->i_mtime.tv_nsec;
|
||||||
|
ip->i_d.di_cowextsize = pip ? 0 : fsx->fsx_cowextsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
|
||||||
|
index 503990f..975f097 100644
|
||||||
|
--- a/libxfs/xfs_inode_buf.c
|
||||||
|
+++ b/libxfs/xfs_inode_buf.c
|
||||||
|
@@ -254,8 +254,8 @@ xfs_inode_from_disk(
|
||||||
|
if (to->di_version == 3) {
|
||||||
|
inode_set_iversion_queried(inode,
|
||||||
|
be64_to_cpu(from->di_changecount));
|
||||||
|
- to->di_crtime.t_sec = be32_to_cpu(from->di_crtime.t_sec);
|
||||||
|
- to->di_crtime.t_nsec = be32_to_cpu(from->di_crtime.t_nsec);
|
||||||
|
+ to->di_crtime.tv_sec = be32_to_cpu(from->di_crtime.t_sec);
|
||||||
|
+ to->di_crtime.tv_nsec = be32_to_cpu(from->di_crtime.t_nsec);
|
||||||
|
to->di_flags2 = be64_to_cpu(from->di_flags2);
|
||||||
|
to->di_cowextsize = be32_to_cpu(from->di_cowextsize);
|
||||||
|
}
|
||||||
|
@@ -304,8 +304,8 @@ xfs_inode_to_disk(
|
||||||
|
|
||||||
|
if (from->di_version == 3) {
|
||||||
|
to->di_changecount = cpu_to_be64(inode_peek_iversion(inode));
|
||||||
|
- to->di_crtime.t_sec = cpu_to_be32(from->di_crtime.t_sec);
|
||||||
|
- to->di_crtime.t_nsec = cpu_to_be32(from->di_crtime.t_nsec);
|
||||||
|
+ to->di_crtime.t_sec = cpu_to_be32(from->di_crtime.tv_sec);
|
||||||
|
+ to->di_crtime.t_nsec = cpu_to_be32(from->di_crtime.tv_nsec);
|
||||||
|
to->di_flags2 = cpu_to_be64(from->di_flags2);
|
||||||
|
to->di_cowextsize = cpu_to_be32(from->di_cowextsize);
|
||||||
|
to->di_ino = cpu_to_be64(ip->i_ino);
|
||||||
|
diff --git a/libxfs/xfs_inode_buf.h b/libxfs/xfs_inode_buf.h
|
||||||
|
index ab0f841..c9ac69c 100644
|
||||||
|
--- a/libxfs/xfs_inode_buf.h
|
||||||
|
+++ b/libxfs/xfs_inode_buf.h
|
||||||
|
@@ -37,7 +37,7 @@ struct xfs_icdinode {
|
||||||
|
uint64_t di_flags2; /* more random flags */
|
||||||
|
uint32_t di_cowextsize; /* basic cow extent size for file */
|
||||||
|
|
||||||
|
- xfs_ictimestamp_t di_crtime; /* time created */
|
||||||
|
+ struct timespec64 di_crtime; /* time created */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
@ -0,0 +1,227 @@
|
|||||||
|
From 36dc471cc9bb17868b79cf8dea8151b207387539 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Date: Tue, 26 May 2020 14:36:26 -0400
|
||||||
|
Subject: [PATCH] xfs_quota: allow individual timer extension
|
||||||
|
|
||||||
|
The only grace period which can be set via xfs_quota today is for id 0,
|
||||||
|
i.e. the default grace period for all users. However, setting an
|
||||||
|
individual grace period is useful; for example:
|
||||||
|
|
||||||
|
Alice has a soft quota of 100 inodes, and a hard quota of 200 inodes
|
||||||
|
Alice uses 150 inodes, and enters a short grace period
|
||||||
|
Alice really needs to use those 150 inodes past the grace period
|
||||||
|
The administrator extends Alice's grace period until next Monday
|
||||||
|
|
||||||
|
vfs quota users such as ext4 can do this today, with setquota -T
|
||||||
|
|
||||||
|
xfs_quota can now accept an optional user id or name (symmetric with
|
||||||
|
how warn limits are specified), in which case that user's grace period
|
||||||
|
is extended to expire the given amount of time from now().
|
||||||
|
|
||||||
|
To maintain compatibility with old command lines, if none of
|
||||||
|
[-d|id|name] are specified, default limits are set as before.
|
||||||
|
|
||||||
|
(kernelspace requires updates to enable all this as well.)
|
||||||
|
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
man/man8/xfs_quota.8 | 36 +++++++++++++++++--
|
||||||
|
quota/edit.c | 83 +++++++++++++++++++++++++++++++++++++-------
|
||||||
|
2 files changed, 104 insertions(+), 15 deletions(-)
|
||||||
|
|
||||||
|
Index: xfsprogs-5.0.0/man/man8/xfs_quota.8
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/man/man8/xfs_quota.8
|
||||||
|
+++ xfsprogs-5.0.0/man/man8/xfs_quota.8
|
||||||
|
@@ -460,14 +460,46 @@ must be specified.
|
||||||
|
.B \-bir
|
||||||
|
]
|
||||||
|
.I value
|
||||||
|
+[
|
||||||
|
+.B -d
|
||||||
|
+|
|
||||||
|
+.I id
|
||||||
|
+|
|
||||||
|
+.I name
|
||||||
|
+]
|
||||||
|
.br
|
||||||
|
Allows the quota enforcement timeout (i.e. the amount of time allowed
|
||||||
|
to pass before the soft limits are enforced as the hard limits) to
|
||||||
|
be modified. The current timeout setting can be displayed using the
|
||||||
|
.B state
|
||||||
|
-command. The value argument is a number of seconds, but units of
|
||||||
|
-\&'minutes', 'hours', 'days', and 'weeks' are also understood
|
||||||
|
+command.
|
||||||
|
+.br
|
||||||
|
+When setting the default timer via the
|
||||||
|
+.B \-d
|
||||||
|
+option, or for
|
||||||
|
+.B id
|
||||||
|
+0, or if no argument is given after
|
||||||
|
+.I value
|
||||||
|
+the
|
||||||
|
+.I value
|
||||||
|
+argument is a number of seconds indicating the relative amount of time after
|
||||||
|
+soft limits are exceeded, before hard limits are enforced.
|
||||||
|
+.br
|
||||||
|
+When setting any other individual timer by
|
||||||
|
+.I id
|
||||||
|
+or
|
||||||
|
+.I name,
|
||||||
|
+the
|
||||||
|
+.I value
|
||||||
|
+is the number of seconds from now, at which time the hard limits will be enforced.
|
||||||
|
+This allows extending the grace time of an individual user who has exceeded soft
|
||||||
|
+limits.
|
||||||
|
+.br
|
||||||
|
+For
|
||||||
|
+.I value,
|
||||||
|
+units of \&'minutes', 'hours', 'days', and 'weeks' are also understood
|
||||||
|
(as are their abbreviations 'm', 'h', 'd', and 'w').
|
||||||
|
+.br
|
||||||
|
.HP
|
||||||
|
.B warn
|
||||||
|
[
|
||||||
|
Index: xfsprogs-5.0.0/quota/edit.c
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/quota/edit.c
|
||||||
|
+++ xfsprogs-5.0.0/quota/edit.c
|
||||||
|
@@ -419,6 +419,7 @@ restore_f(
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_timer(
|
||||||
|
+ uint32_t id,
|
||||||
|
uint type,
|
||||||
|
uint mask,
|
||||||
|
char *dev,
|
||||||
|
@@ -427,14 +428,43 @@ set_timer(
|
||||||
|
fs_disk_quota_t d;
|
||||||
|
|
||||||
|
memset(&d, 0, sizeof(d));
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * If id is specified we are extending grace time by value
|
||||||
|
+ * Otherwise we are setting the default grace time
|
||||||
|
+ */
|
||||||
|
+ if (id) {
|
||||||
|
+ time_t now;
|
||||||
|
+
|
||||||
|
+ /* Get quota to find out whether user is past soft limits */
|
||||||
|
+ if (xfsquotactl(XFS_GETQUOTA, dev, type, id, (void *)&d) < 0) {
|
||||||
|
+ exitcode = 1;
|
||||||
|
+ fprintf(stderr, _("%s: cannot get quota: %s\n"),
|
||||||
|
+ progname, strerror(errno));
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ time(&now);
|
||||||
|
+
|
||||||
|
+ /* Only set grace time if user is already past soft limit */
|
||||||
|
+ if (d.d_blk_softlimit && d.d_bcount > d.d_blk_softlimit)
|
||||||
|
+ d.d_btimer = now + value;
|
||||||
|
+ if (d.d_ino_softlimit && d.d_icount > d.d_ino_softlimit)
|
||||||
|
+ d.d_itimer = now + value;
|
||||||
|
+ if (d.d_rtb_softlimit && d.d_rtbcount > d.d_rtb_softlimit)
|
||||||
|
+ d.d_rtbtimer = now + value;
|
||||||
|
+ } else {
|
||||||
|
+ d.d_btimer = value;
|
||||||
|
+ d.d_itimer = value;
|
||||||
|
+ d.d_rtbtimer = value;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
d.d_version = FS_DQUOT_VERSION;
|
||||||
|
d.d_flags = type;
|
||||||
|
d.d_fieldmask = mask;
|
||||||
|
- d.d_itimer = value;
|
||||||
|
- d.d_btimer = value;
|
||||||
|
- d.d_rtbtimer = value;
|
||||||
|
+ d.d_id = id;
|
||||||
|
|
||||||
|
- if (xfsquotactl(XFS_SETQLIM, dev, type, 0, (void *)&d) < 0) {
|
||||||
|
+ if (xfsquotactl(XFS_SETQLIM, dev, type, id, (void *)&d) < 0) {
|
||||||
|
exitcode = 1;
|
||||||
|
fprintf(stderr, _("%s: cannot set timer: %s\n"),
|
||||||
|
progname, strerror(errno));
|
||||||
|
@@ -447,10 +477,15 @@ timer_f(
|
||||||
|
char **argv)
|
||||||
|
{
|
||||||
|
uint value;
|
||||||
|
- int c, type = 0, mask = 0;
|
||||||
|
+ char *name = NULL;
|
||||||
|
+ uint32_t id = 0;
|
||||||
|
+ int c, flags = 0, type = 0, mask = 0;
|
||||||
|
|
||||||
|
- while ((c = getopt(argc, argv, "bgipru")) != EOF) {
|
||||||
|
+ while ((c = getopt(argc, argv, "bdgipru")) != EOF) {
|
||||||
|
switch (c) {
|
||||||
|
+ case 'd':
|
||||||
|
+ flags |= DEFAULTS_FLAG;
|
||||||
|
+ break;
|
||||||
|
case 'b':
|
||||||
|
mask |= FS_DQ_BTIMER;
|
||||||
|
break;
|
||||||
|
@@ -474,23 +509,45 @@ timer_f(
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (argc != optind + 1)
|
||||||
|
+ /*
|
||||||
|
+ * Older versions of the command did not accept -d|id|name,
|
||||||
|
+ * so in that case we assume we're setting default timer,
|
||||||
|
+ * and the last arg is the timer value.
|
||||||
|
+ *
|
||||||
|
+ * Otherwise, if the defaults flag is set, we expect 1 more arg for
|
||||||
|
+ * timer value ; if not, 2 more args: 1 for value, one for id/name.
|
||||||
|
+ */
|
||||||
|
+ if (!(flags & DEFAULTS_FLAG) && (argc == optind + 1)) {
|
||||||
|
+ value = cvttime(argv[optind++]);
|
||||||
|
+ } else if (flags & DEFAULTS_FLAG) {
|
||||||
|
+ if (argc != optind + 1)
|
||||||
|
+ return command_usage(&timer_cmd);
|
||||||
|
+ value = cvttime(argv[optind++]);
|
||||||
|
+ } else if (argc == optind + 2) {
|
||||||
|
+ value = cvttime(argv[optind++]);
|
||||||
|
+ name = (flags & DEFAULTS_FLAG) ? "0" : argv[optind++];
|
||||||
|
+ } else
|
||||||
|
return command_usage(&timer_cmd);
|
||||||
|
|
||||||
|
- value = cvttime(argv[optind++]);
|
||||||
|
|
||||||
|
+ /* if none of -bir specified, set them all */
|
||||||
|
if (!mask)
|
||||||
|
mask = FS_DQ_TIMER_MASK;
|
||||||
|
|
||||||
|
if (!type) {
|
||||||
|
type = XFS_USER_QUOTA;
|
||||||
|
} else if (type != XFS_GROUP_QUOTA &&
|
||||||
|
- type != XFS_PROJ_QUOTA &&
|
||||||
|
- type != XFS_USER_QUOTA) {
|
||||||
|
+ type != XFS_PROJ_QUOTA &&
|
||||||
|
+ type != XFS_USER_QUOTA) {
|
||||||
|
return command_usage(&timer_cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
- set_timer(type, mask, fs_path->fs_name, value);
|
||||||
|
+ if (name)
|
||||||
|
+ id = id_from_string(name, type);
|
||||||
|
+
|
||||||
|
+ if (id >= 0)
|
||||||
|
+ set_timer(id, type, mask, fs_path->fs_name, value);
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -616,9 +673,9 @@ edit_init(void)
|
||||||
|
|
||||||
|
timer_cmd.name = "timer";
|
||||||
|
timer_cmd.cfunc = timer_f;
|
||||||
|
- timer_cmd.argmin = 2;
|
||||||
|
+ timer_cmd.argmin = 1;
|
||||||
|
timer_cmd.argmax = -1;
|
||||||
|
- timer_cmd.args = _("[-bir] [-g|-p|-u] value");
|
||||||
|
+ timer_cmd.args = _("[-bir] [-g|-p|-u] value [-d|id|name]");
|
||||||
|
timer_cmd.oneline = _("set quota enforcement timeouts");
|
||||||
|
timer_cmd.help = timer_help;
|
||||||
|
timer_cmd.flags = CMD_FLAG_FOREIGN_OK;
|
@ -0,0 +1,69 @@
|
|||||||
|
From eaa5b0b79bcf2eb36f7a5e1a5b7171ad5ced7bac Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 10 Jul 2020 15:33:36 -0400
|
||||||
|
Subject: [PATCH] xfs_quota: fix unsigned int id comparisons
|
||||||
|
|
||||||
|
Fix compiler warnings about unsigned int comparisons by replacing them
|
||||||
|
with an explicit check for the one possible invalid value (-1U).
|
||||||
|
id_from_string sets exitcode to nonzero when it sees this value, so the
|
||||||
|
call sites don't have to do that.
|
||||||
|
|
||||||
|
Coverity-id: 1463855, 1463856, 1463857
|
||||||
|
Fixes: 67a73d6139d0 ("xfs_quota: refactor code to generate id from name")
|
||||||
|
Fixes: 36dc471cc9bb ("xfs_quota: allow individual timer extension")
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
quota/edit.c | 22 +++++++++++-----------
|
||||||
|
1 file changed, 11 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
|
Index: xfsprogs-5.0.0/quota/edit.c
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/quota/edit.c
|
||||||
|
+++ xfsprogs-5.0.0/quota/edit.c
|
||||||
|
@@ -307,11 +307,11 @@ limit_f(
|
||||||
|
|
||||||
|
|
||||||
|
id = id_from_string(name, type);
|
||||||
|
- if (id >= 0)
|
||||||
|
- set_limits(id, type, mask, fs_path->fs_name,
|
||||||
|
- &bsoft, &bhard, &isoft, &ihard, &rtbsoft, &rtbhard);
|
||||||
|
- else
|
||||||
|
- exitcode = -1;
|
||||||
|
+ if (id == -1)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ set_limits(id, type, mask, fs_path->fs_name,
|
||||||
|
+ &bsoft, &bhard, &isoft, &ihard, &rtbsoft, &rtbhard);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -545,9 +545,10 @@ timer_f(
|
||||||
|
if (name)
|
||||||
|
id = id_from_string(name, type);
|
||||||
|
|
||||||
|
- if (id >= 0)
|
||||||
|
- set_timer(id, type, mask, fs_path->fs_name, value);
|
||||||
|
+ if (id == -1)
|
||||||
|
+ return 0;
|
||||||
|
|
||||||
|
+ set_timer(id, type, mask, fs_path->fs_name, value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -642,11 +643,10 @@ warn_f(
|
||||||
|
}
|
||||||
|
|
||||||
|
id = id_from_string(name, type);
|
||||||
|
- if (id >= 0)
|
||||||
|
- set_warnings(id, type, mask, fs_path->fs_name, value);
|
||||||
|
- else
|
||||||
|
- exitcode = -1;
|
||||||
|
+ if (id == -1)
|
||||||
|
+ return 0;
|
||||||
|
|
||||||
|
+ set_warnings(id, type, mask, fs_path->fs_name, value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,271 @@
|
|||||||
|
From 67a73d6139d0336eb7ced05bd78a26b57f408187 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Date: Tue, 26 May 2020 14:36:04 -0400
|
||||||
|
Subject: [PATCH] xfs_quota: refactor code to generate id from name
|
||||||
|
|
||||||
|
There's boilerplate for setting limits and warnings, where we have
|
||||||
|
a case statement for each of the 3 quota types, and from there call
|
||||||
|
3 different functions to configure each of the 3 types, each of which
|
||||||
|
calls its own version of id to string function...
|
||||||
|
|
||||||
|
Refactor this so that the main function can call a generic id to string
|
||||||
|
conversion routine, and then call a common action. This save a lot of
|
||||||
|
LOC.
|
||||||
|
|
||||||
|
I was looking at allowing xfs to bump out individual grace periods like
|
||||||
|
setquota can do, and this refactoring allows us to add new actions like
|
||||||
|
that without copying all the boilerplate again.
|
||||||
|
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
quota/edit.c | 194 +++++++++++++--------------------------------------
|
||||||
|
1 file changed, 49 insertions(+), 145 deletions(-)
|
||||||
|
|
||||||
|
Index: xfsprogs-5.0.0/quota/edit.c
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/quota/edit.c
|
||||||
|
+++ xfsprogs-5.0.0/quota/edit.c
|
||||||
|
@@ -101,6 +101,40 @@ warn_help(void)
|
||||||
|
"\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
+static uint32_t
|
||||||
|
+id_from_string(
|
||||||
|
+ char *name,
|
||||||
|
+ int type)
|
||||||
|
+{
|
||||||
|
+ uint32_t id = -1;
|
||||||
|
+ const char *type_name = "unknown type";
|
||||||
|
+
|
||||||
|
+ switch (type) {
|
||||||
|
+ case XFS_USER_QUOTA:
|
||||||
|
+ type_name = "user";
|
||||||
|
+ id = uid_from_string(name);
|
||||||
|
+ break;
|
||||||
|
+ case XFS_GROUP_QUOTA:
|
||||||
|
+ type_name = "group";
|
||||||
|
+ id = gid_from_string(name);
|
||||||
|
+ break;
|
||||||
|
+ case XFS_PROJ_QUOTA:
|
||||||
|
+ type_name = "project";
|
||||||
|
+ id = prid_from_string(name);
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ ASSERT(0);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (id == -1) {
|
||||||
|
+ fprintf(stderr, _("%s: invalid %s name: %s\n"),
|
||||||
|
+ type_name, progname, name);
|
||||||
|
+ exitcode = 1;
|
||||||
|
+ }
|
||||||
|
+ return id;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
set_limits(
|
||||||
|
uint32_t id,
|
||||||
|
@@ -135,75 +169,6 @@ set_limits(
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void
|
||||||
|
-set_user_limits(
|
||||||
|
- char *name,
|
||||||
|
- uint type,
|
||||||
|
- uint mask,
|
||||||
|
- uint64_t *bsoft,
|
||||||
|
- uint64_t *bhard,
|
||||||
|
- uint64_t *isoft,
|
||||||
|
- uint64_t *ihard,
|
||||||
|
- uint64_t *rtbsoft,
|
||||||
|
- uint64_t *rtbhard)
|
||||||
|
-{
|
||||||
|
- uid_t uid = uid_from_string(name);
|
||||||
|
-
|
||||||
|
- if (uid == -1) {
|
||||||
|
- exitcode = 1;
|
||||||
|
- fprintf(stderr, _("%s: invalid user name: %s\n"),
|
||||||
|
- progname, name);
|
||||||
|
- } else
|
||||||
|
- set_limits(uid, type, mask, fs_path->fs_name,
|
||||||
|
- bsoft, bhard, isoft, ihard, rtbsoft, rtbhard);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void
|
||||||
|
-set_group_limits(
|
||||||
|
- char *name,
|
||||||
|
- uint type,
|
||||||
|
- uint mask,
|
||||||
|
- uint64_t *bsoft,
|
||||||
|
- uint64_t *bhard,
|
||||||
|
- uint64_t *isoft,
|
||||||
|
- uint64_t *ihard,
|
||||||
|
- uint64_t *rtbsoft,
|
||||||
|
- uint64_t *rtbhard)
|
||||||
|
-{
|
||||||
|
- gid_t gid = gid_from_string(name);
|
||||||
|
-
|
||||||
|
- if (gid == -1) {
|
||||||
|
- exitcode = 1;
|
||||||
|
- fprintf(stderr, _("%s: invalid group name: %s\n"),
|
||||||
|
- progname, name);
|
||||||
|
- } else
|
||||||
|
- set_limits(gid, type, mask, fs_path->fs_name,
|
||||||
|
- bsoft, bhard, isoft, ihard, rtbsoft, rtbhard);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void
|
||||||
|
-set_project_limits(
|
||||||
|
- char *name,
|
||||||
|
- uint type,
|
||||||
|
- uint mask,
|
||||||
|
- uint64_t *bsoft,
|
||||||
|
- uint64_t *bhard,
|
||||||
|
- uint64_t *isoft,
|
||||||
|
- uint64_t *ihard,
|
||||||
|
- uint64_t *rtbsoft,
|
||||||
|
- uint64_t *rtbhard)
|
||||||
|
-{
|
||||||
|
- prid_t prid = prid_from_string(name);
|
||||||
|
-
|
||||||
|
- if (prid == -1) {
|
||||||
|
- exitcode = 1;
|
||||||
|
- fprintf(stderr, _("%s: invalid project name: %s\n"),
|
||||||
|
- progname, name);
|
||||||
|
- } else
|
||||||
|
- set_limits(prid, type, mask, fs_path->fs_name,
|
||||||
|
- bsoft, bhard, isoft, ihard, rtbsoft, rtbhard);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
/* extract number of blocks from an ascii string */
|
||||||
|
static int
|
||||||
|
extractb(
|
||||||
|
@@ -258,6 +223,7 @@ limit_f(
|
||||||
|
char **argv)
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
+ uint32_t id;
|
||||||
|
uint64_t bsoft, bhard, isoft, ihard, rtbsoft, rtbhard;
|
||||||
|
int c, type = 0, mask = 0, flags = 0;
|
||||||
|
uint bsize, ssize, endoptions;
|
||||||
|
@@ -339,20 +305,13 @@ limit_f(
|
||||||
|
return command_usage(&limit_cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
- switch (type) {
|
||||||
|
- case XFS_USER_QUOTA:
|
||||||
|
- set_user_limits(name, type, mask,
|
||||||
|
- &bsoft, &bhard, &isoft, &ihard, &rtbsoft, &rtbhard);
|
||||||
|
- break;
|
||||||
|
- case XFS_GROUP_QUOTA:
|
||||||
|
- set_group_limits(name, type, mask,
|
||||||
|
- &bsoft, &bhard, &isoft, &ihard, &rtbsoft, &rtbhard);
|
||||||
|
- break;
|
||||||
|
- case XFS_PROJ_QUOTA:
|
||||||
|
- set_project_limits(name, type, mask,
|
||||||
|
- &bsoft, &bhard, &isoft, &ihard, &rtbsoft, &rtbhard);
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
+
|
||||||
|
+ id = id_from_string(name, type);
|
||||||
|
+ if (id >= 0)
|
||||||
|
+ set_limits(id, type, mask, fs_path->fs_name,
|
||||||
|
+ &bsoft, &bhard, &isoft, &ihard, &rtbsoft, &rtbhard);
|
||||||
|
+ else
|
||||||
|
+ exitcode = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -561,63 +520,13 @@ set_warnings(
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void
|
||||||
|
-set_user_warnings(
|
||||||
|
- char *name,
|
||||||
|
- uint type,
|
||||||
|
- uint mask,
|
||||||
|
- uint value)
|
||||||
|
-{
|
||||||
|
- uid_t uid = uid_from_string(name);
|
||||||
|
-
|
||||||
|
- if (uid == -1) {
|
||||||
|
- exitcode = 1;
|
||||||
|
- fprintf(stderr, _("%s: invalid user name: %s\n"),
|
||||||
|
- progname, name);
|
||||||
|
- } else
|
||||||
|
- set_warnings(uid, type, mask, fs_path->fs_name, value);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void
|
||||||
|
-set_group_warnings(
|
||||||
|
- char *name,
|
||||||
|
- uint type,
|
||||||
|
- uint mask,
|
||||||
|
- uint value)
|
||||||
|
-{
|
||||||
|
- gid_t gid = gid_from_string(name);
|
||||||
|
-
|
||||||
|
- if (gid == -1) {
|
||||||
|
- exitcode = 1;
|
||||||
|
- fprintf(stderr, _("%s: invalid group name: %s\n"),
|
||||||
|
- progname, name);
|
||||||
|
- } else
|
||||||
|
- set_warnings(gid, type, mask, fs_path->fs_name, value);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void
|
||||||
|
-set_project_warnings(
|
||||||
|
- char *name,
|
||||||
|
- uint type,
|
||||||
|
- uint mask,
|
||||||
|
- uint value)
|
||||||
|
-{
|
||||||
|
- prid_t prid = prid_from_string(name);
|
||||||
|
-
|
||||||
|
- if (prid == -1) {
|
||||||
|
- exitcode = 1;
|
||||||
|
- fprintf(stderr, _("%s: invalid project name: %s\n"),
|
||||||
|
- progname, name);
|
||||||
|
- } else
|
||||||
|
- set_warnings(prid, type, mask, fs_path->fs_name, value);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static int
|
||||||
|
warn_f(
|
||||||
|
int argc,
|
||||||
|
char **argv)
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
+ uint32_t id;
|
||||||
|
uint value;
|
||||||
|
int c, flags = 0, type = 0, mask = 0;
|
||||||
|
|
||||||
|
@@ -675,17 +584,12 @@ warn_f(
|
||||||
|
return command_usage(&warn_cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
- switch (type) {
|
||||||
|
- case XFS_USER_QUOTA:
|
||||||
|
- set_user_warnings(name, type, mask, value);
|
||||||
|
- break;
|
||||||
|
- case XFS_GROUP_QUOTA:
|
||||||
|
- set_group_warnings(name, type, mask, value);
|
||||||
|
- break;
|
||||||
|
- case XFS_PROJ_QUOTA:
|
||||||
|
- set_project_warnings(name, type, mask, value);
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
+ id = id_from_string(name, type);
|
||||||
|
+ if (id >= 0)
|
||||||
|
+ set_warnings(id, type, mask, fs_path->fs_name, value);
|
||||||
|
+ else
|
||||||
|
+ exitcode = -1;
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,54 @@
|
|||||||
|
From cae4fd291266c32441c6a7fcca49929fe11c391c Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 10 Jul 2020 15:35:44 -0400
|
||||||
|
Subject: [PATCH] xfs_repair: check for AG btree records that would wrap around
|
||||||
|
|
||||||
|
For AG btree types, make sure that each record's length is not so huge
|
||||||
|
that integer wraparound would happen.
|
||||||
|
|
||||||
|
Found via xfs/358 fuzzing recs[1].blockcount = ones.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
repair/scan.c | 9 ++++++---
|
||||||
|
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/repair/scan.c b/repair/scan.c
|
||||||
|
index 5c8d8b23..1ddb5763 100644
|
||||||
|
--- a/repair/scan.c
|
||||||
|
+++ b/repair/scan.c
|
||||||
|
@@ -684,7 +684,8 @@ _("%s freespace btree block claimed (state %d), agno %d, bno %d, suspect %d\n"),
|
||||||
|
b, i, name, agno, bno);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
- if (len == 0 || !verify_agbno(mp, agno, end - 1)) {
|
||||||
|
+ if (len == 0 || end <= b ||
|
||||||
|
+ !verify_agbno(mp, agno, end - 1)) {
|
||||||
|
do_warn(
|
||||||
|
_("invalid length %u in record %u of %s btree block %u/%u\n"),
|
||||||
|
len, i, name, agno, bno);
|
||||||
|
@@ -1066,7 +1067,8 @@ _("%s rmap btree block claimed (state %d), agno %d, bno %d, suspect %d\n"),
|
||||||
|
b, i, name, agno, bno);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
- if (len == 0 || !verify_agbno(mp, agno, end - 1)) {
|
||||||
|
+ if (len == 0 || end <= b ||
|
||||||
|
+ !verify_agbno(mp, agno, end - 1)) {
|
||||||
|
do_warn(
|
||||||
|
_("invalid length %u in record %u of %s btree block %u/%u\n"),
|
||||||
|
len, i, name, agno, bno);
|
||||||
|
@@ -1353,7 +1355,8 @@ _("leftover CoW extent has invalid startblock in record %u of %s btree block %u/
|
||||||
|
b, i, name, agno, bno);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
- if (len == 0 || !verify_agbno(mp, agno, end - 1)) {
|
||||||
|
+ if (len == 0 || end <= agb ||
|
||||||
|
+ !verify_agbno(mp, agno, end - 1)) {
|
||||||
|
do_warn(
|
||||||
|
_("invalid length %u in record %u of %s btree block %u/%u\n"),
|
||||||
|
len, i, name, agno, bno);
|
||||||
|
--
|
||||||
|
2.29.2
|
||||||
|
|
@ -0,0 +1,124 @@
|
|||||||
|
From 320cc3b263542e692c4978fb327efa591892ab37 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 10 Jul 2020 15:35:45 -0400
|
||||||
|
Subject: [PATCH] xfs_repair: complain about bad interior btree pointers
|
||||||
|
|
||||||
|
Actually complain about garbage btree node pointers, don't just silently
|
||||||
|
ignore them.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
libxfs/libxfs_api_defs.h | 1 +
|
||||||
|
repair/scan.c | 55 +++++++++++++++++++++++++++++-----------
|
||||||
|
2 files changed, 41 insertions(+), 15 deletions(-)
|
||||||
|
|
||||||
|
Index: xfsprogs-5.0.0/libxfs/libxfs_api_defs.h
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/libxfs/libxfs_api_defs.h
|
||||||
|
+++ xfsprogs-5.0.0/libxfs/libxfs_api_defs.h
|
||||||
|
@@ -118,6 +118,7 @@
|
||||||
|
#define xfs_symlink_blocks libxfs_symlink_blocks
|
||||||
|
#define xfs_symlink_hdr_ok libxfs_symlink_hdr_ok
|
||||||
|
|
||||||
|
+#define xfs_verify_agbno libxfs_verify_agbno
|
||||||
|
#define xfs_verify_cksum libxfs_verify_cksum
|
||||||
|
#define xfs_dinode_verify libxfs_dinode_verify
|
||||||
|
|
||||||
|
Index: xfsprogs-5.0.0/repair/scan.c
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/repair/scan.c
|
||||||
|
+++ xfsprogs-5.0.0/repair/scan.c
|
||||||
|
@@ -743,6 +743,14 @@ _("%s freespace btree block claimed (sta
|
||||||
|
for (i = 0; i < numrecs; i++) {
|
||||||
|
xfs_agblock_t agbno = be32_to_cpu(pp[i]);
|
||||||
|
|
||||||
|
+ if (!libxfs_verify_agbno(mp, agno, agbno)) {
|
||||||
|
+ do_warn(
|
||||||
|
+ _("bad btree pointer (%u) in %sbt block %u/%u\n"),
|
||||||
|
+ agbno, name, agno, bno);
|
||||||
|
+ suspect++;
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* XXX - put sibling detection right here.
|
||||||
|
* we know our sibling chain is good. So as we go,
|
||||||
|
@@ -752,10 +760,8 @@ _("%s freespace btree block claimed (sta
|
||||||
|
* pointer mismatch, try and extract as much data
|
||||||
|
* as possible.
|
||||||
|
*/
|
||||||
|
- if (agbno != 0 && verify_agbno(mp, agno, agbno)) {
|
||||||
|
- scan_sbtree(agbno, level, agno, suspect, scan_allocbt,
|
||||||
|
- 0, magic, priv, ops);
|
||||||
|
- }
|
||||||
|
+ scan_sbtree(agbno, level, agno, suspect, scan_allocbt, 0,
|
||||||
|
+ magic, priv, ops);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1196,10 +1202,16 @@ advance:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (agbno != 0 && verify_agbno(mp, agno, agbno)) {
|
||||||
|
- scan_sbtree(agbno, level, agno, suspect, scan_rmapbt, 0,
|
||||||
|
- magic, priv, ops);
|
||||||
|
+ if (!libxfs_verify_agbno(mp, agno, agbno)) {
|
||||||
|
+ do_warn(
|
||||||
|
+ _("bad btree pointer (%u) in %sbt block %u/%u\n"),
|
||||||
|
+ agbno, name, agno, bno);
|
||||||
|
+ suspect++;
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ scan_sbtree(agbno, level, agno, suspect, scan_rmapbt, 0, magic,
|
||||||
|
+ priv, ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
@@ -1416,10 +1428,16 @@ _("extent (%u/%u) len %u claimed, state
|
||||||
|
for (i = 0; i < numrecs; i++) {
|
||||||
|
xfs_agblock_t agbno = be32_to_cpu(pp[i]);
|
||||||
|
|
||||||
|
- if (agbno != 0 && verify_agbno(mp, agno, agbno)) {
|
||||||
|
- scan_sbtree(agbno, level, agno, suspect, scan_refcbt, 0,
|
||||||
|
- magic, priv, ops);
|
||||||
|
+ if (!libxfs_verify_agbno(mp, agno, agbno)) {
|
||||||
|
+ do_warn(
|
||||||
|
+ _("bad btree pointer (%u) in %sbt block %u/%u\n"),
|
||||||
|
+ agbno, name, agno, bno);
|
||||||
|
+ suspect++;
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ scan_sbtree(agbno, level, agno, suspect, scan_refcbt, 0, magic,
|
||||||
|
+ priv, ops);
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
if (suspect)
|
||||||
|
@@ -2083,11 +2101,18 @@ _("inode btree block claimed (state %d),
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < numrecs; i++) {
|
||||||
|
- if (be32_to_cpu(pp[i]) != 0 && verify_agbno(mp, agno,
|
||||||
|
- be32_to_cpu(pp[i])))
|
||||||
|
- scan_sbtree(be32_to_cpu(pp[i]), level, agno,
|
||||||
|
- suspect, scan_inobt, 0, magic, priv,
|
||||||
|
- ops);
|
||||||
|
+ xfs_agblock_t agbno = be32_to_cpu(pp[i]);
|
||||||
|
+
|
||||||
|
+ if (!libxfs_verify_agbno(mp, agno, agbno)) {
|
||||||
|
+ do_warn(
|
||||||
|
+ _("bad btree pointer (%u) in %sbt block %u/%u\n"),
|
||||||
|
+ agbno, name, agno, bno);
|
||||||
|
+ suspect++;
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ scan_sbtree(be32_to_cpu(pp[i]), level, agno, suspect,
|
||||||
|
+ scan_inobt, 0, magic, priv, ops);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,209 @@
|
|||||||
|
From dcd6c2e1490ba5c59c14ca8ea843ca36048888b8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 10 Jul 2020 15:35:45 -0400
|
||||||
|
Subject: [PATCH] xfs_repair: convert to libxfs_verify_agbno
|
||||||
|
|
||||||
|
Convert the homegrown verify_agbno callers to use the libxfs function,
|
||||||
|
as needed. In some places we drop the "bno != 0" checks because those
|
||||||
|
conditionals are checking btree roots; btree roots should never be
|
||||||
|
zero if the corresponding feature bit is set; and repair skips the if
|
||||||
|
clause entirely if the feature bit is disabled.
|
||||||
|
|
||||||
|
In effect, this strengthens repair to validate that AG btree pointers
|
||||||
|
neither point to the AG headers nor past the end of the AG.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
libxfs/libxfs_api_defs.h | 1 +
|
||||||
|
repair/dinode.c | 11 -----------
|
||||||
|
repair/dinode.h | 5 -----
|
||||||
|
repair/scan.c | 36 +++++++++++++++++++++++-------------
|
||||||
|
4 files changed, 24 insertions(+), 29 deletions(-)
|
||||||
|
|
||||||
|
Index: xfsprogs-5.0.0/libxfs/libxfs_api_defs.h
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/libxfs/libxfs_api_defs.h
|
||||||
|
+++ xfsprogs-5.0.0/libxfs/libxfs_api_defs.h
|
||||||
|
@@ -121,6 +121,7 @@
|
||||||
|
#define xfs_verify_agbno libxfs_verify_agbno
|
||||||
|
#define xfs_verify_cksum libxfs_verify_cksum
|
||||||
|
#define xfs_dinode_verify libxfs_dinode_verify
|
||||||
|
+#define xfs_ag_block_count libxfs_ag_block_count
|
||||||
|
|
||||||
|
#define xfs_alloc_ag_max_usable libxfs_alloc_ag_max_usable
|
||||||
|
#define xfs_allocbt_maxrecs libxfs_allocbt_maxrecs
|
||||||
|
Index: xfsprogs-5.0.0/repair/dinode.c
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/repair/dinode.c
|
||||||
|
+++ xfsprogs-5.0.0/repair/dinode.c
|
||||||
|
@@ -284,17 +284,6 @@ verify_dfsbno_range(xfs_mount_t *mp,
|
||||||
|
return (XR_DFSBNORANGE_VALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
-int
|
||||||
|
-verify_agbno(xfs_mount_t *mp,
|
||||||
|
- xfs_agnumber_t agno,
|
||||||
|
- xfs_agblock_t agbno)
|
||||||
|
-{
|
||||||
|
- xfs_sb_t *sbp = &mp->m_sb;;
|
||||||
|
-
|
||||||
|
- /* range check ag #, ag block. range-checking offset is pointless */
|
||||||
|
- return verify_ag_bno(sbp, agno, agbno) == 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static int
|
||||||
|
process_rt_rec(
|
||||||
|
xfs_mount_t *mp,
|
||||||
|
Index: xfsprogs-5.0.0/repair/dinode.h
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/repair/dinode.h
|
||||||
|
+++ xfsprogs-5.0.0/repair/dinode.h
|
||||||
|
@@ -10,11 +10,6 @@ struct blkmap;
|
||||||
|
struct prefetch_args;
|
||||||
|
|
||||||
|
int
|
||||||
|
-verify_agbno(xfs_mount_t *mp,
|
||||||
|
- xfs_agnumber_t agno,
|
||||||
|
- xfs_agblock_t agbno);
|
||||||
|
-
|
||||||
|
-int
|
||||||
|
verify_dfsbno(xfs_mount_t *mp,
|
||||||
|
xfs_fsblock_t fsbno);
|
||||||
|
|
||||||
|
Index: xfsprogs-5.0.0/repair/scan.c
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/repair/scan.c
|
||||||
|
+++ xfsprogs-5.0.0/repair/scan.c
|
||||||
|
@@ -642,14 +642,14 @@ _("%s freespace btree block claimed (sta
|
||||||
|
len = be32_to_cpu(rp[i].ar_blockcount);
|
||||||
|
end = b + len;
|
||||||
|
|
||||||
|
- if (b == 0 || !verify_agbno(mp, agno, b)) {
|
||||||
|
+ if (!libxfs_verify_agbno(mp, agno, b)) {
|
||||||
|
do_warn(
|
||||||
|
_("invalid start block %u in record %u of %s btree block %u/%u\n"),
|
||||||
|
b, i, name, agno, bno);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (len == 0 || end <= b ||
|
||||||
|
- !verify_agbno(mp, agno, end - 1)) {
|
||||||
|
+ !libxfs_verify_agbno(mp, agno, end - 1)) {
|
||||||
|
do_warn(
|
||||||
|
_("invalid length %u in record %u of %s btree block %u/%u\n"),
|
||||||
|
len, i, name, agno, bno);
|
||||||
|
@@ -914,6 +914,16 @@ rmap_in_order(
|
||||||
|
return offset > lastoffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static inline bool
|
||||||
|
+verify_rmap_agbno(
|
||||||
|
+ struct xfs_mount *mp,
|
||||||
|
+ xfs_agnumber_t agno,
|
||||||
|
+ xfs_agblock_t agbno)
|
||||||
|
+{
|
||||||
|
+ return agbno < libxfs_ag_block_count(mp, agno);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
scan_rmapbt(
|
||||||
|
struct xfs_btree_block *block,
|
||||||
|
@@ -1031,14 +1041,14 @@ _("%s rmap btree block claimed (state %d
|
||||||
|
end = key.rm_startblock + key.rm_blockcount;
|
||||||
|
|
||||||
|
/* Make sure agbno & len make sense. */
|
||||||
|
- if (!verify_agbno(mp, agno, b)) {
|
||||||
|
+ if (!verify_rmap_agbno(mp, agno, b)) {
|
||||||
|
do_warn(
|
||||||
|
_("invalid start block %u in record %u of %s btree block %u/%u\n"),
|
||||||
|
b, i, name, agno, bno);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (len == 0 || end <= b ||
|
||||||
|
- !verify_agbno(mp, agno, end - 1)) {
|
||||||
|
+ !verify_rmap_agbno(mp, agno, end - 1)) {
|
||||||
|
do_warn(
|
||||||
|
_("invalid length %u in record %u of %s btree block %u/%u\n"),
|
||||||
|
len, i, name, agno, bno);
|
||||||
|
@@ -1325,14 +1335,14 @@ _("leftover CoW extent has invalid start
|
||||||
|
}
|
||||||
|
end = agb + len;
|
||||||
|
|
||||||
|
- if (!verify_agbno(mp, agno, agb)) {
|
||||||
|
+ if (!libxfs_verify_agbno(mp, agno, agb)) {
|
||||||
|
do_warn(
|
||||||
|
_("invalid start block %u in record %u of %s btree block %u/%u\n"),
|
||||||
|
b, i, name, agno, bno);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (len == 0 || end <= agb ||
|
||||||
|
- !verify_agbno(mp, agno, end - 1)) {
|
||||||
|
+ !libxfs_verify_agbno(mp, agno, end - 1)) {
|
||||||
|
do_warn(
|
||||||
|
_("invalid length %u in record %u of %s btree block %u/%u\n"),
|
||||||
|
len, i, name, agno, bno);
|
||||||
|
@@ -2145,7 +2155,7 @@ scan_agfl(
|
||||||
|
{
|
||||||
|
struct agfl_state *as = priv;
|
||||||
|
|
||||||
|
- if (verify_agbno(mp, as->agno, bno))
|
||||||
|
+ if (libxfs_verify_agbno(mp, as->agno, bno))
|
||||||
|
set_bmap(as->agno, bno, XR_E_FREE);
|
||||||
|
else
|
||||||
|
do_warn(_("bad agbno %u in agfl, agno %d\n"),
|
||||||
|
@@ -2217,7 +2227,7 @@ validate_agf(
|
||||||
|
uint32_t magic;
|
||||||
|
|
||||||
|
bno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]);
|
||||||
|
- if (bno != 0 && verify_agbno(mp, agno, bno)) {
|
||||||
|
+ if (libxfs_verify_agbno(mp, agno, bno)) {
|
||||||
|
magic = xfs_sb_version_hascrc(&mp->m_sb) ? XFS_ABTB_CRC_MAGIC
|
||||||
|
: XFS_ABTB_MAGIC;
|
||||||
|
scan_sbtree(bno, be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]),
|
||||||
|
@@ -2229,7 +2239,7 @@ validate_agf(
|
||||||
|
}
|
||||||
|
|
||||||
|
bno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]);
|
||||||
|
- if (bno != 0 && verify_agbno(mp, agno, bno)) {
|
||||||
|
+ if (libxfs_verify_agbno(mp, agno, bno)) {
|
||||||
|
magic = xfs_sb_version_hascrc(&mp->m_sb) ? XFS_ABTC_CRC_MAGIC
|
||||||
|
: XFS_ABTC_MAGIC;
|
||||||
|
scan_sbtree(bno, be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]),
|
||||||
|
@@ -2249,7 +2259,7 @@ validate_agf(
|
||||||
|
priv.last_rec.rm_owner = XFS_RMAP_OWN_UNKNOWN;
|
||||||
|
priv.nr_blocks = 0;
|
||||||
|
bno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_RMAP]);
|
||||||
|
- if (bno != 0 && verify_agbno(mp, agno, bno)) {
|
||||||
|
+ if (libxfs_verify_agbno(mp, agno, bno)) {
|
||||||
|
scan_sbtree(bno,
|
||||||
|
be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]),
|
||||||
|
agno, 0, scan_rmapbt, 1, XFS_RMAP_CRC_MAGIC,
|
||||||
|
@@ -2267,7 +2277,7 @@ validate_agf(
|
||||||
|
|
||||||
|
if (xfs_sb_version_hasreflink(&mp->m_sb)) {
|
||||||
|
bno = be32_to_cpu(agf->agf_refcount_root);
|
||||||
|
- if (bno != 0 && verify_agbno(mp, agno, bno)) {
|
||||||
|
+ if (libxfs_verify_agbno(mp, agno, bno)) {
|
||||||
|
struct refc_priv priv;
|
||||||
|
|
||||||
|
memset(&priv, 0, sizeof(priv));
|
||||||
|
@@ -2315,7 +2325,7 @@ validate_agi(
|
||||||
|
uint32_t magic;
|
||||||
|
|
||||||
|
bno = be32_to_cpu(agi->agi_root);
|
||||||
|
- if (bno != 0 && verify_agbno(mp, agno, bno)) {
|
||||||
|
+ if (libxfs_verify_agbno(mp, agno, bno)) {
|
||||||
|
magic = xfs_sb_version_hascrc(&mp->m_sb) ? XFS_IBT_CRC_MAGIC
|
||||||
|
: XFS_IBT_MAGIC;
|
||||||
|
scan_sbtree(bno, be32_to_cpu(agi->agi_level),
|
||||||
|
@@ -2328,7 +2338,7 @@ validate_agi(
|
||||||
|
|
||||||
|
if (xfs_sb_version_hasfinobt(&mp->m_sb)) {
|
||||||
|
bno = be32_to_cpu(agi->agi_free_root);
|
||||||
|
- if (bno != 0 && verify_agbno(mp, agno, bno)) {
|
||||||
|
+ if (libxfs_verify_agbno(mp, agno, bno)) {
|
||||||
|
magic = xfs_sb_version_hascrc(&mp->m_sb) ?
|
||||||
|
XFS_FIBT_CRC_MAGIC : XFS_FIBT_MAGIC;
|
||||||
|
scan_sbtree(bno, be32_to_cpu(agi->agi_free_level),
|
@ -0,0 +1,290 @@
|
|||||||
|
From 6df28d12d7760701c9d11e659e374665c5ffd0b9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Gao Xiang <hsiangkao@redhat.com>
|
||||||
|
Date: Fri, 10 Jul 2020 15:32:36 -0400
|
||||||
|
Subject: [PATCH] xfs_repair: fix rebuilding btree block less than minrecs
|
||||||
|
|
||||||
|
In production, we found that sometimes xfs_repair phase 5
|
||||||
|
rebuilds freespace node block with pointers less than minrecs
|
||||||
|
and if we trigger xfs_repair again it would report such
|
||||||
|
the following message:
|
||||||
|
|
||||||
|
bad btree nrecs (39, min=40, max=80) in btbno block 0/7882
|
||||||
|
|
||||||
|
The background is that xfs_repair starts to rebuild AGFL
|
||||||
|
after the freespace btree is settled in phase 5 so we may
|
||||||
|
need to leave necessary room in advance for each btree
|
||||||
|
leaves in order to avoid freespace btree split and then
|
||||||
|
result in AGFL rebuild fails. The old mathematics uses
|
||||||
|
ceil(num_extents / maxrecs) to decide the number of node
|
||||||
|
blocks. That would be fine without leaving extra space
|
||||||
|
since minrecs = maxrecs / 2 but if some slack was decreased
|
||||||
|
from maxrecs, the result would be larger than what is
|
||||||
|
expected and cause num_recs_pb less than minrecs, i.e:
|
||||||
|
|
||||||
|
num_extents = 79, adj_maxrecs = 80 - 2 (slack) = 78
|
||||||
|
|
||||||
|
so we'd get
|
||||||
|
|
||||||
|
num_blocks = ceil(79 / 78) = 2,
|
||||||
|
num_recs_pb = 79 / 2 = 39, which is less than
|
||||||
|
minrecs = 80 / 2 = 40
|
||||||
|
|
||||||
|
OTOH, btree bulk loading code behaves in a different way.
|
||||||
|
As in xfs_btree_bload_level_geometry it wrote
|
||||||
|
|
||||||
|
num_blocks = floor(num_extents / maxrecs)
|
||||||
|
|
||||||
|
which will never go below minrecs. And when it goes above
|
||||||
|
maxrecs, just increment num_blocks and recalculate so we
|
||||||
|
can get the reasonable results.
|
||||||
|
|
||||||
|
Later, btree bulk loader will replace the current repair code.
|
||||||
|
But we may still want to look for a backportable solution
|
||||||
|
for stable versions. Hence, keep the same logic to avoid
|
||||||
|
the freespace as well as rmap btree minrecs underflow for now.
|
||||||
|
|
||||||
|
Cc: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Cc: Dave Chinner <dchinner@redhat.com>
|
||||||
|
Cc: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
Fixes: 9851fd79bfb1 ("repair: AGFL rebuild fails if btree split required")
|
||||||
|
Signed-off-by: Gao Xiang <hsiangkao@redhat.com>
|
||||||
|
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
repair/phase5.c | 152 ++++++++++++++++++++----------------------------
|
||||||
|
1 file changed, 63 insertions(+), 89 deletions(-)
|
||||||
|
|
||||||
|
Index: xfsprogs-5.0.0/repair/phase5.c
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/repair/phase5.c
|
||||||
|
+++ xfsprogs-5.0.0/repair/phase5.c
|
||||||
|
@@ -346,11 +346,32 @@ finish_cursor(bt_status_t *curs)
|
||||||
|
* failure at runtime. Hence leave a couple of records slack space in
|
||||||
|
* each block to allow immediate modification of the tree without
|
||||||
|
* requiring splits to be done.
|
||||||
|
- *
|
||||||
|
- * XXX(hch): any reason we don't just look at mp->m_alloc_mxr?
|
||||||
|
*/
|
||||||
|
-#define XR_ALLOC_BLOCK_MAXRECS(mp, level) \
|
||||||
|
- (libxfs_allocbt_maxrecs((mp), (mp)->m_sb.sb_blocksize, (level) == 0) - 2)
|
||||||
|
+static void
|
||||||
|
+compute_level_geometry(
|
||||||
|
+ struct xfs_mount *mp,
|
||||||
|
+ struct bt_stat_level *lptr,
|
||||||
|
+ uint64_t nr_this_level,
|
||||||
|
+ int slack,
|
||||||
|
+ bool leaf)
|
||||||
|
+{
|
||||||
|
+ unsigned int maxrecs = mp->m_alloc_mxr[!leaf];
|
||||||
|
+ unsigned int desired_npb;
|
||||||
|
+
|
||||||
|
+ desired_npb = max(mp->m_alloc_mnr[!leaf], maxrecs - slack);
|
||||||
|
+ lptr->num_recs_tot = nr_this_level;
|
||||||
|
+ lptr->num_blocks = max(1ULL, nr_this_level / desired_npb);
|
||||||
|
+
|
||||||
|
+ lptr->num_recs_pb = nr_this_level / lptr->num_blocks;
|
||||||
|
+ lptr->modulo = nr_this_level % lptr->num_blocks;
|
||||||
|
+ if (lptr->num_recs_pb > maxrecs ||
|
||||||
|
+ (lptr->num_recs_pb == maxrecs && lptr->modulo)) {
|
||||||
|
+ lptr->num_blocks++;
|
||||||
|
+
|
||||||
|
+ lptr->num_recs_pb = nr_this_level / lptr->num_blocks;
|
||||||
|
+ lptr->modulo = nr_this_level % lptr->num_blocks;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this calculates a freespace cursor for an ag.
|
||||||
|
@@ -368,6 +389,7 @@ calculate_freespace_cursor(xfs_mount_t *
|
||||||
|
int i;
|
||||||
|
int extents_used;
|
||||||
|
int extra_blocks;
|
||||||
|
+ uint64_t old_blocks;
|
||||||
|
bt_stat_level_t *lptr;
|
||||||
|
bt_stat_level_t *p_lptr;
|
||||||
|
extent_tree_node_t *ext_ptr;
|
||||||
|
@@ -386,10 +408,7 @@ calculate_freespace_cursor(xfs_mount_t *
|
||||||
|
* of the tree and set up the cursor for the leaf level
|
||||||
|
* (note that the same code is duplicated further down)
|
||||||
|
*/
|
||||||
|
- lptr->num_blocks = howmany(num_extents, XR_ALLOC_BLOCK_MAXRECS(mp, 0));
|
||||||
|
- lptr->num_recs_pb = num_extents / lptr->num_blocks;
|
||||||
|
- lptr->modulo = num_extents % lptr->num_blocks;
|
||||||
|
- lptr->num_recs_tot = num_extents;
|
||||||
|
+ compute_level_geometry(mp, lptr, num_extents, 2, true);
|
||||||
|
level = 1;
|
||||||
|
|
||||||
|
#ifdef XR_BLD_FREE_TRACE
|
||||||
|
@@ -403,30 +422,23 @@ calculate_freespace_cursor(xfs_mount_t *
|
||||||
|
* if we need more levels, set them up. # of records
|
||||||
|
* per level is the # of blocks in the level below it
|
||||||
|
*/
|
||||||
|
- if (lptr->num_blocks > 1) {
|
||||||
|
- for (; btree_curs->level[level - 1].num_blocks > 1
|
||||||
|
- && level < XFS_BTREE_MAXLEVELS;
|
||||||
|
- level++) {
|
||||||
|
- lptr = &btree_curs->level[level];
|
||||||
|
- p_lptr = &btree_curs->level[level - 1];
|
||||||
|
- lptr->num_blocks = howmany(p_lptr->num_blocks,
|
||||||
|
- XR_ALLOC_BLOCK_MAXRECS(mp, level));
|
||||||
|
- lptr->modulo = p_lptr->num_blocks
|
||||||
|
- % lptr->num_blocks;
|
||||||
|
- lptr->num_recs_pb = p_lptr->num_blocks
|
||||||
|
- / lptr->num_blocks;
|
||||||
|
- lptr->num_recs_tot = p_lptr->num_blocks;
|
||||||
|
+ while (lptr->num_blocks > 1) {
|
||||||
|
+ p_lptr = lptr;
|
||||||
|
+ lptr = &btree_curs->level[level];
|
||||||
|
+
|
||||||
|
+ compute_level_geometry(mp, lptr,
|
||||||
|
+ p_lptr->num_blocks, 0, false);
|
||||||
|
#ifdef XR_BLD_FREE_TRACE
|
||||||
|
- fprintf(stderr, "%s %d %d %d %d %d\n", __func__,
|
||||||
|
- level,
|
||||||
|
- lptr->num_blocks,
|
||||||
|
- lptr->num_recs_pb,
|
||||||
|
- lptr->modulo,
|
||||||
|
- lptr->num_recs_tot);
|
||||||
|
+ fprintf(stderr, "%s %d %d %d %d %d\n", __func__,
|
||||||
|
+ level,
|
||||||
|
+ lptr->num_blocks,
|
||||||
|
+ lptr->num_recs_pb,
|
||||||
|
+ lptr->modulo,
|
||||||
|
+ lptr->num_recs_tot);
|
||||||
|
#endif
|
||||||
|
- }
|
||||||
|
+ level++;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
+ ASSERT(level < XFS_BTREE_MAXLEVELS);
|
||||||
|
ASSERT(lptr->num_blocks == 1);
|
||||||
|
btree_curs->num_levels = level;
|
||||||
|
|
||||||
|
@@ -494,8 +506,11 @@ calculate_freespace_cursor(xfs_mount_t *
|
||||||
|
* see if the number of leaf blocks will change as a result
|
||||||
|
* of the number of extents changing
|
||||||
|
*/
|
||||||
|
- if (howmany(num_extents, XR_ALLOC_BLOCK_MAXRECS(mp, 0))
|
||||||
|
- != btree_curs->level[0].num_blocks) {
|
||||||
|
+ old_blocks = btree_curs->level[0].num_blocks;
|
||||||
|
+ compute_level_geometry(mp, &btree_curs->level[0], num_extents, 2, true);
|
||||||
|
+ extra_blocks = 0;
|
||||||
|
+
|
||||||
|
+ if (old_blocks != btree_curs->level[0].num_blocks) {
|
||||||
|
/*
|
||||||
|
* yes -- recalculate the cursor. If the number of
|
||||||
|
* excess (overallocated) blocks is < xfs_agfl_size/2, we're ok.
|
||||||
|
@@ -551,31 +566,19 @@ calculate_freespace_cursor(xfs_mount_t *
|
||||||
|
}
|
||||||
|
|
||||||
|
lptr = &btree_curs->level[0];
|
||||||
|
- lptr->num_blocks = howmany(num_extents,
|
||||||
|
- XR_ALLOC_BLOCK_MAXRECS(mp, 0));
|
||||||
|
- lptr->num_recs_pb = num_extents / lptr->num_blocks;
|
||||||
|
- lptr->modulo = num_extents % lptr->num_blocks;
|
||||||
|
- lptr->num_recs_tot = num_extents;
|
||||||
|
level = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if we need more levels, set them up
|
||||||
|
*/
|
||||||
|
- if (lptr->num_blocks > 1) {
|
||||||
|
- for (level = 1; btree_curs->level[level-1].num_blocks
|
||||||
|
- > 1 && level < XFS_BTREE_MAXLEVELS;
|
||||||
|
- level++) {
|
||||||
|
- lptr = &btree_curs->level[level];
|
||||||
|
- p_lptr = &btree_curs->level[level-1];
|
||||||
|
- lptr->num_blocks = howmany(p_lptr->num_blocks,
|
||||||
|
- XR_ALLOC_BLOCK_MAXRECS(mp, level));
|
||||||
|
- lptr->modulo = p_lptr->num_blocks
|
||||||
|
- % lptr->num_blocks;
|
||||||
|
- lptr->num_recs_pb = p_lptr->num_blocks
|
||||||
|
- / lptr->num_blocks;
|
||||||
|
- lptr->num_recs_tot = p_lptr->num_blocks;
|
||||||
|
- }
|
||||||
|
+ while (lptr->num_blocks > 1) {
|
||||||
|
+ p_lptr = lptr;
|
||||||
|
+ lptr = &btree_curs->level[level++];
|
||||||
|
+
|
||||||
|
+ compute_level_geometry(mp, lptr,
|
||||||
|
+ p_lptr->num_blocks, 0, false);
|
||||||
|
}
|
||||||
|
+ ASSERT(level < XFS_BTREE_MAXLEVELS);
|
||||||
|
ASSERT(lptr->num_blocks == 1);
|
||||||
|
btree_curs->num_levels = level;
|
||||||
|
|
||||||
|
@@ -589,22 +592,6 @@ calculate_freespace_cursor(xfs_mount_t *
|
||||||
|
|
||||||
|
ASSERT(blocks_allocated_total >= blocks_needed);
|
||||||
|
extra_blocks = blocks_allocated_total - blocks_needed;
|
||||||
|
- } else {
|
||||||
|
- if (extents_used > 0) {
|
||||||
|
- /*
|
||||||
|
- * reset the leaf level geometry to account
|
||||||
|
- * for consumed extents. we can leave the
|
||||||
|
- * rest of the cursor alone since the number
|
||||||
|
- * of leaf blocks hasn't changed.
|
||||||
|
- */
|
||||||
|
- lptr = &btree_curs->level[0];
|
||||||
|
-
|
||||||
|
- lptr->num_recs_pb = num_extents / lptr->num_blocks;
|
||||||
|
- lptr->modulo = num_extents % lptr->num_blocks;
|
||||||
|
- lptr->num_recs_tot = num_extents;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- extra_blocks = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
btree_curs->num_tot_blocks = blocks_allocated_pt;
|
||||||
|
@@ -1335,7 +1322,6 @@ init_rmapbt_cursor(
|
||||||
|
struct bt_stat_level *lptr;
|
||||||
|
struct bt_stat_level *p_lptr;
|
||||||
|
xfs_extlen_t blocks_allocated;
|
||||||
|
- int maxrecs;
|
||||||
|
|
||||||
|
if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) {
|
||||||
|
memset(btree_curs, 0, sizeof(struct bt_status));
|
||||||
|
@@ -1371,32 +1357,20 @@ init_rmapbt_cursor(
|
||||||
|
* Leave enough slack in the rmapbt that we can insert the
|
||||||
|
* metadata AG entries without too many splits.
|
||||||
|
*/
|
||||||
|
- maxrecs = mp->m_rmap_mxr[0];
|
||||||
|
- if (num_recs > maxrecs)
|
||||||
|
- maxrecs -= 10;
|
||||||
|
- blocks_allocated = lptr->num_blocks = howmany(num_recs, maxrecs);
|
||||||
|
-
|
||||||
|
- lptr->modulo = num_recs % lptr->num_blocks;
|
||||||
|
- lptr->num_recs_pb = num_recs / lptr->num_blocks;
|
||||||
|
- lptr->num_recs_tot = num_recs;
|
||||||
|
+ compute_level_geometry(mp, lptr, num_recs,
|
||||||
|
+ num_recs > mp->m_rmap_mxr[0] ? 10 : 0, true);
|
||||||
|
+ blocks_allocated = lptr->num_blocks;
|
||||||
|
level = 1;
|
||||||
|
|
||||||
|
- if (lptr->num_blocks > 1) {
|
||||||
|
- for (; btree_curs->level[level-1].num_blocks > 1
|
||||||
|
- && level < XFS_BTREE_MAXLEVELS;
|
||||||
|
- level++) {
|
||||||
|
- lptr = &btree_curs->level[level];
|
||||||
|
- p_lptr = &btree_curs->level[level - 1];
|
||||||
|
- lptr->num_blocks = howmany(p_lptr->num_blocks,
|
||||||
|
- mp->m_rmap_mxr[1]);
|
||||||
|
- lptr->modulo = p_lptr->num_blocks % lptr->num_blocks;
|
||||||
|
- lptr->num_recs_pb = p_lptr->num_blocks
|
||||||
|
- / lptr->num_blocks;
|
||||||
|
- lptr->num_recs_tot = p_lptr->num_blocks;
|
||||||
|
-
|
||||||
|
- blocks_allocated += lptr->num_blocks;
|
||||||
|
- }
|
||||||
|
+ while (lptr->num_blocks > 1) {
|
||||||
|
+ p_lptr = lptr;
|
||||||
|
+ lptr = &btree_curs->level[level++];
|
||||||
|
+
|
||||||
|
+ compute_level_geometry(mp, lptr,
|
||||||
|
+ p_lptr->num_blocks, 0, false);
|
||||||
|
+ blocks_allocated += lptr->num_blocks;
|
||||||
|
}
|
||||||
|
+ ASSERT(level < XFS_BTREE_MAXLEVELS);
|
||||||
|
ASSERT(lptr->num_blocks == 1);
|
||||||
|
btree_curs->num_levels = level;
|
||||||
|
|
@ -0,0 +1,88 @@
|
|||||||
|
From 08280b4b6efd317c673c6718a27d77e702d0480d Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 10 Jul 2020 15:35:45 -0400
|
||||||
|
Subject: [PATCH] xfs_repair: tag inobt vs finobt errors properly
|
||||||
|
|
||||||
|
Amend the generic inode btree block scanner function to tag correctly
|
||||||
|
which tree it's complaining about. Previously, dubious finobt headers
|
||||||
|
would be attributed to the "inode btree", which is at best ambiguous
|
||||||
|
and misleading at worst.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
repair/scan.c | 36 ++++++++++++++++++++++++++----------
|
||||||
|
1 file changed, 26 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
Index: xfsprogs-5.0.0/repair/scan.c
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/repair/scan.c
|
||||||
|
+++ xfsprogs-5.0.0/repair/scan.c
|
||||||
|
@@ -1934,6 +1934,7 @@ scan_inobt(
|
||||||
|
const struct xfs_buf_ops *ops)
|
||||||
|
{
|
||||||
|
struct aghdr_cnts *agcnts = priv;
|
||||||
|
+ char *name;
|
||||||
|
int i;
|
||||||
|
int numrecs;
|
||||||
|
int state;
|
||||||
|
@@ -1944,17 +1945,32 @@ scan_inobt(
|
||||||
|
|
||||||
|
hdr_errors = 0;
|
||||||
|
|
||||||
|
+ switch (magic) {
|
||||||
|
+ case XFS_FIBT_MAGIC:
|
||||||
|
+ case XFS_FIBT_CRC_MAGIC:
|
||||||
|
+ name = "fino";
|
||||||
|
+ break;
|
||||||
|
+ case XFS_IBT_MAGIC:
|
||||||
|
+ case XFS_IBT_CRC_MAGIC:
|
||||||
|
+ name = "ino";
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ name = "(unknown)";
|
||||||
|
+ assert(0);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (be32_to_cpu(block->bb_magic) != magic) {
|
||||||
|
- do_warn(_("bad magic # %#x in inobt block %d/%d\n"),
|
||||||
|
- be32_to_cpu(block->bb_magic), agno, bno);
|
||||||
|
+ do_warn(_("bad magic # %#x in %sbt block %d/%d\n"),
|
||||||
|
+ be32_to_cpu(block->bb_magic), name, agno, bno);
|
||||||
|
hdr_errors++;
|
||||||
|
bad_ino_btree = 1;
|
||||||
|
if (suspect)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (be16_to_cpu(block->bb_level) != level) {
|
||||||
|
- do_warn(_("expected level %d got %d in inobt block %d/%d\n"),
|
||||||
|
- level, be16_to_cpu(block->bb_level), agno, bno);
|
||||||
|
+ do_warn(_("expected level %d got %d in %sbt block %d/%d\n"),
|
||||||
|
+ level, be16_to_cpu(block->bb_level), name, agno, bno);
|
||||||
|
hdr_errors++;
|
||||||
|
bad_ino_btree = 1;
|
||||||
|
if (suspect)
|
||||||
|
@@ -1976,8 +1992,8 @@ scan_inobt(
|
||||||
|
default:
|
||||||
|
set_bmap(agno, bno, XR_E_MULT);
|
||||||
|
do_warn(
|
||||||
|
-_("inode btree block claimed (state %d), agno %d, bno %d, suspect %d\n"),
|
||||||
|
- state, agno, bno, suspect);
|
||||||
|
+_("%sbt btree block claimed (state %d), agno %d, bno %d, suspect %d\n"),
|
||||||
|
+ name, state, agno, bno, suspect);
|
||||||
|
}
|
||||||
|
|
||||||
|
numrecs = be16_to_cpu(block->bb_numrecs);
|
||||||
|
@@ -1999,8 +2015,8 @@ _("inode btree block claimed (state %d),
|
||||||
|
|
||||||
|
if (hdr_errors) {
|
||||||
|
bad_ino_btree = 1;
|
||||||
|
- do_warn(_("dubious inode btree block header %d/%d\n"),
|
||||||
|
- agno, bno);
|
||||||
|
+ do_warn(_("dubious %sbt btree block header %d/%d\n"),
|
||||||
|
+ name, agno, bno);
|
||||||
|
suspect++;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
|||||||
|
From 7b4a7b3f6bce91be45b54fc68e169cb756dc8c74 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Date: Mon, 24 Aug 2020 12:47:47 -0400
|
||||||
|
Subject: [PATCH] xfs_db: short circuit type_f if type is unchanged
|
||||||
|
|
||||||
|
There's no reason to go through the type change code if the
|
||||||
|
type has not been changed.
|
||||||
|
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
db/type.c | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/db/type.c b/db/type.c
|
||||||
|
index 3cb1e868..572ac6d6 100644
|
||||||
|
--- a/db/type.c
|
||||||
|
+++ b/db/type.c
|
||||||
|
@@ -216,6 +216,8 @@ type_f(
|
||||||
|
tt = findtyp(argv[1]);
|
||||||
|
if (tt == NULL) {
|
||||||
|
dbprintf(_("no such type %s\n"), argv[1]);
|
||||||
|
+ } else if (iocur_top->typ == tt) {
|
||||||
|
+ return 0;
|
||||||
|
} else {
|
||||||
|
if (iocur_top->typ == NULL)
|
||||||
|
dbprintf(_("no current object\n"));
|
||||||
|
--
|
||||||
|
2.29.2
|
||||||
|
|
@ -0,0 +1,76 @@
|
|||||||
|
From ca42fa70929e88781e7daeee4cf4588adb834661 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bill O'Donnell <billodo@redhat.com>
|
||||||
|
Date: Mon, 24 Aug 2020 13:23:23 -0400
|
||||||
|
Subject: [PATCH] xfs_quota: command error message improvement
|
||||||
|
|
||||||
|
Make the error messages for rudimentary xfs_quota commands
|
||||||
|
(off, enable, disable) more user friendly, instead of the
|
||||||
|
terse sys error outputs.
|
||||||
|
|
||||||
|
Signed-off-by: Bill O'Donnell <billodo@redhat.com>
|
||||||
|
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
quota/state.c | 32 ++++++++++++++++++++++++++------
|
||||||
|
1 file changed, 26 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/quota/state.c b/quota/state.c
|
||||||
|
index 8f9718f1..7a595fc6 100644
|
||||||
|
--- a/quota/state.c
|
||||||
|
+++ b/quota/state.c
|
||||||
|
@@ -306,8 +306,16 @@ enable_enforcement(
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dir = mount->fs_name;
|
||||||
|
- if (xfsquotactl(XFS_QUOTAON, dir, type, 0, (void *)&qflags) < 0)
|
||||||
|
- perror("XFS_QUOTAON");
|
||||||
|
+ if (xfsquotactl(XFS_QUOTAON, dir, type, 0, (void *)&qflags) < 0) {
|
||||||
|
+ if (errno == EEXIST)
|
||||||
|
+ fprintf(stderr,
|
||||||
|
+ _("Quota enforcement already enabled.\n"));
|
||||||
|
+ else if (errno == EINVAL || errno == ENOSYS)
|
||||||
|
+ fprintf(stderr,
|
||||||
|
+ _("Can't enable enforcement when quota off.\n"));
|
||||||
|
+ else
|
||||||
|
+ perror("XFS_QUOTAON");
|
||||||
|
+ }
|
||||||
|
else if (flags & VERBOSE_FLAG)
|
||||||
|
state_quotafile_mount(stdout, type, mount, flags);
|
||||||
|
}
|
||||||
|
@@ -328,8 +336,16 @@ disable_enforcement(
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dir = mount->fs_name;
|
||||||
|
- if (xfsquotactl(XFS_QUOTAOFF, dir, type, 0, (void *)&qflags) < 0)
|
||||||
|
- perror("XFS_QUOTAOFF");
|
||||||
|
+ if (xfsquotactl(XFS_QUOTAOFF, dir, type, 0, (void *)&qflags) < 0) {
|
||||||
|
+ if (errno == EEXIST)
|
||||||
|
+ fprintf(stderr,
|
||||||
|
+ _("Quota enforcement already disabled.\n"));
|
||||||
|
+ else if (errno == EINVAL || errno == ENOSYS)
|
||||||
|
+ fprintf(stderr,
|
||||||
|
+ _("Can't disable enforcement when quota off.\n"));
|
||||||
|
+ else
|
||||||
|
+ perror("XFS_QUOTAOFF");
|
||||||
|
+ }
|
||||||
|
else if (flags & VERBOSE_FLAG)
|
||||||
|
state_quotafile_mount(stdout, type, mount, flags);
|
||||||
|
}
|
||||||
|
@@ -350,8 +366,12 @@ quotaoff(
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dir = mount->fs_name;
|
||||||
|
- if (xfsquotactl(XFS_QUOTAOFF, dir, type, 0, (void *)&qflags) < 0)
|
||||||
|
- perror("XFS_QUOTAOFF");
|
||||||
|
+ if (xfsquotactl(XFS_QUOTAOFF, dir, type, 0, (void *)&qflags) < 0) {
|
||||||
|
+ if (errno == EEXIST || errno == ENOSYS)
|
||||||
|
+ fprintf(stderr, _("Quota already off.\n"));
|
||||||
|
+ else
|
||||||
|
+ perror("XFS_QUOTAOFF");
|
||||||
|
+ }
|
||||||
|
else if (flags & VERBOSE_FLAG)
|
||||||
|
state_quotafile_mount(stdout, type, mount, flags);
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.31.1
|
||||||
|
|
@ -0,0 +1,52 @@
|
|||||||
|
From 387a96e12a937c1b2ee29a0f2c52245d6a283078 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Mon, 24 Aug 2020 13:23:32 -0400
|
||||||
|
Subject: [PATCH] xfs_quota: display warning limits when printing quota type
|
||||||
|
information
|
||||||
|
|
||||||
|
We should dump the default warning limits when we're printing quota
|
||||||
|
information.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
quota/state.c | 14 ++++++++++++++
|
||||||
|
1 file changed, 14 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/quota/state.c b/quota/state.c
|
||||||
|
index 7a595fc6..1627181d 100644
|
||||||
|
--- a/quota/state.c
|
||||||
|
+++ b/quota/state.c
|
||||||
|
@@ -130,6 +130,16 @@ state_timelimit(
|
||||||
|
time_to_string(timelimit, VERBOSE_FLAG | ABSOLUTE_FLAG));
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+state_warnlimit(
|
||||||
|
+ FILE *fp,
|
||||||
|
+ uint form,
|
||||||
|
+ uint16_t warnlimit)
|
||||||
|
+{
|
||||||
|
+ fprintf(fp, _("%s max warnings: %u\n"),
|
||||||
|
+ form_to_string(form), warnlimit);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* fs_quota_stat holds a subset of fs_quota_statv; this copies
|
||||||
|
* the smaller into the larger, leaving any not-present fields
|
||||||
|
@@ -218,7 +228,11 @@ state_quotafile_mount(
|
||||||
|
sv.qs_flags & XFS_QUOTA_PDQ_ENFD);
|
||||||
|
|
||||||
|
state_timelimit(fp, XFS_BLOCK_QUOTA, sv.qs_btimelimit);
|
||||||
|
+ state_warnlimit(fp, XFS_BLOCK_QUOTA, sv.qs_bwarnlimit);
|
||||||
|
+
|
||||||
|
state_timelimit(fp, XFS_INODE_QUOTA, sv.qs_itimelimit);
|
||||||
|
+ state_warnlimit(fp, XFS_INODE_QUOTA, sv.qs_iwarnlimit);
|
||||||
|
+
|
||||||
|
state_timelimit(fp, XFS_RTBLOCK_QUOTA, sv.qs_rtbtimelimit);
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.31.1
|
||||||
|
|
@ -0,0 +1,141 @@
|
|||||||
|
From d8a9454608ff97e98fb7de0da28f8d40804d2296 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bill O'Donnell <billodo@redhat.com>
|
||||||
|
Date: Mon, 24 Aug 2020 13:23:43 -0400
|
||||||
|
Subject: [PATCH] xfs_quota: state command should report ugp grace times
|
||||||
|
|
||||||
|
Since grace periods are now supported for three quota types (ugp),
|
||||||
|
modify xfs_quota state command to report times for all three.
|
||||||
|
Add a helper function for stat reporting.
|
||||||
|
|
||||||
|
Signed-off-by: Bill O'Donnell <billodo@redhat.com>
|
||||||
|
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
quota/state.c | 96 +++++++++++++++++++++++++++++++++++----------------
|
||||||
|
1 file changed, 67 insertions(+), 29 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/quota/state.c b/quota/state.c
|
||||||
|
index 1627181d..19d34ed0 100644
|
||||||
|
--- a/quota/state.c
|
||||||
|
+++ b/quota/state.c
|
||||||
|
@@ -191,49 +191,87 @@ state_stat_to_statv(
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
-state_quotafile_mount(
|
||||||
|
+state_quotafile_stat(
|
||||||
|
FILE *fp,
|
||||||
|
uint type,
|
||||||
|
- struct fs_path *mount,
|
||||||
|
+ struct fs_path *mount,
|
||||||
|
+ struct fs_quota_statv *sv,
|
||||||
|
+ struct fs_quota_stat *s,
|
||||||
|
uint flags)
|
||||||
|
{
|
||||||
|
- struct fs_quota_stat s;
|
||||||
|
- struct fs_quota_statv sv;
|
||||||
|
+ bool accounting, enforcing;
|
||||||
|
+ struct fs_qfilestatv *qsv;
|
||||||
|
char *dev = mount->fs_name;
|
||||||
|
|
||||||
|
- sv.qs_version = FS_QSTATV_VERSION1;
|
||||||
|
-
|
||||||
|
- if (xfsquotactl(XFS_GETQSTATV, dev, type, 0, (void *)&sv) < 0) {
|
||||||
|
- if (xfsquotactl(XFS_GETQSTAT, dev, type, 0, (void *)&s) < 0) {
|
||||||
|
+ if (xfsquotactl(XFS_GETQSTATV, dev, type, 0, (void *)sv) < 0) {
|
||||||
|
+ if (xfsquotactl(XFS_GETQSTAT, dev, type, 0, (void *)s) < 0) {
|
||||||
|
if (flags & VERBOSE_FLAG)
|
||||||
|
fprintf(fp,
|
||||||
|
_("%s quota are not enabled on %s\n"),
|
||||||
|
type_to_string(type), dev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
- state_stat_to_statv(&s, &sv);
|
||||||
|
+ state_stat_to_statv(s, sv);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ switch(type) {
|
||||||
|
+ case XFS_USER_QUOTA:
|
||||||
|
+ qsv = &sv->qs_uquota;
|
||||||
|
+ accounting = sv->qs_flags & XFS_QUOTA_UDQ_ACCT;
|
||||||
|
+ enforcing = sv->qs_flags & XFS_QUOTA_UDQ_ENFD;
|
||||||
|
+ break;
|
||||||
|
+ case XFS_GROUP_QUOTA:
|
||||||
|
+ qsv = &sv->qs_gquota;
|
||||||
|
+ accounting = sv->qs_flags & XFS_QUOTA_GDQ_ACCT;
|
||||||
|
+ enforcing = sv->qs_flags & XFS_QUOTA_GDQ_ENFD;
|
||||||
|
+ break;
|
||||||
|
+ case XFS_PROJ_QUOTA:
|
||||||
|
+ qsv = &sv->qs_pquota;
|
||||||
|
+ accounting = sv->qs_flags & XFS_QUOTA_PDQ_ACCT;
|
||||||
|
+ enforcing = sv->qs_flags & XFS_QUOTA_PDQ_ENFD;
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (type & XFS_USER_QUOTA)
|
||||||
|
- state_qfilestat(fp, mount, XFS_USER_QUOTA, &sv.qs_uquota,
|
||||||
|
- sv.qs_flags & XFS_QUOTA_UDQ_ACCT,
|
||||||
|
- sv.qs_flags & XFS_QUOTA_UDQ_ENFD);
|
||||||
|
- if (type & XFS_GROUP_QUOTA)
|
||||||
|
- state_qfilestat(fp, mount, XFS_GROUP_QUOTA, &sv.qs_gquota,
|
||||||
|
- sv.qs_flags & XFS_QUOTA_GDQ_ACCT,
|
||||||
|
- sv.qs_flags & XFS_QUOTA_GDQ_ENFD);
|
||||||
|
- if (type & XFS_PROJ_QUOTA)
|
||||||
|
- state_qfilestat(fp, mount, XFS_PROJ_QUOTA, &sv.qs_pquota,
|
||||||
|
- sv.qs_flags & XFS_QUOTA_PDQ_ACCT,
|
||||||
|
- sv.qs_flags & XFS_QUOTA_PDQ_ENFD);
|
||||||
|
-
|
||||||
|
- state_timelimit(fp, XFS_BLOCK_QUOTA, sv.qs_btimelimit);
|
||||||
|
- state_warnlimit(fp, XFS_BLOCK_QUOTA, sv.qs_bwarnlimit);
|
||||||
|
-
|
||||||
|
- state_timelimit(fp, XFS_INODE_QUOTA, sv.qs_itimelimit);
|
||||||
|
- state_warnlimit(fp, XFS_INODE_QUOTA, sv.qs_iwarnlimit);
|
||||||
|
-
|
||||||
|
- state_timelimit(fp, XFS_RTBLOCK_QUOTA, sv.qs_rtbtimelimit);
|
||||||
|
+
|
||||||
|
+ state_qfilestat(fp, mount, type, qsv, accounting, enforcing);
|
||||||
|
+
|
||||||
|
+ state_timelimit(fp, XFS_BLOCK_QUOTA, sv->qs_btimelimit);
|
||||||
|
+ state_warnlimit(fp, XFS_BLOCK_QUOTA, sv->qs_bwarnlimit);
|
||||||
|
+
|
||||||
|
+ state_timelimit(fp, XFS_INODE_QUOTA, sv->qs_itimelimit);
|
||||||
|
+ state_warnlimit(fp, XFS_INODE_QUOTA, sv->qs_iwarnlimit);
|
||||||
|
+
|
||||||
|
+ state_timelimit(fp, XFS_RTBLOCK_QUOTA, sv->qs_rtbtimelimit);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+state_quotafile_mount(
|
||||||
|
+ FILE *fp,
|
||||||
|
+ uint type,
|
||||||
|
+ struct fs_path *mount,
|
||||||
|
+ uint flags)
|
||||||
|
+{
|
||||||
|
+ struct fs_quota_stat s;
|
||||||
|
+ struct fs_quota_statv sv;
|
||||||
|
+
|
||||||
|
+ sv.qs_version = FS_QSTATV_VERSION1;
|
||||||
|
+
|
||||||
|
+ if (type & XFS_USER_QUOTA) {
|
||||||
|
+ state_quotafile_stat(fp, XFS_USER_QUOTA, mount,
|
||||||
|
+ &sv, &s, flags);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (type & XFS_GROUP_QUOTA) {
|
||||||
|
+ state_quotafile_stat(fp, XFS_GROUP_QUOTA, mount,
|
||||||
|
+ &sv, &s, flags);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (type & XFS_PROJ_QUOTA) {
|
||||||
|
+ state_quotafile_stat(fp, XFS_PROJ_QUOTA, mount,
|
||||||
|
+ &sv, &s, flags);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
--
|
||||||
|
2.31.1
|
||||||
|
|
@ -0,0 +1,76 @@
|
|||||||
|
From 97a4059660b27a9b0e3d8cdde5dbef8712685865 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pavel Reichl <preichl@redhat.com>
|
||||||
|
Date: Mon, 28 Sep 2020 17:31:18 -0400
|
||||||
|
Subject: [PATCH] mkfs.xfs: fix ASSERT on too-small device with stripe geometry
|
||||||
|
|
||||||
|
When a too-small device is created with stripe geometry, we hit an
|
||||||
|
assert in align_ag_geometry():
|
||||||
|
|
||||||
|
mkfs.xfs: xfs_mkfs.c:2834: align_ag_geometry: Assertion `cfg->agcount != 0' failed.
|
||||||
|
|
||||||
|
This is because align_ag_geometry() finds that the size of the last
|
||||||
|
(only) AG is too small, and attempts to trim it off. Obviously 0
|
||||||
|
AGs is invalid, and we hit the ASSERT.
|
||||||
|
|
||||||
|
Reported-by: Zdenek Kabelac <zkabelac@redhat.com>
|
||||||
|
Suggested-by: Dave Chinner <dchinner@redhat.com>
|
||||||
|
Signed-off-by: Pavel Reichl <preichl@redhat.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
include/xfs_multidisk.h | 14 +++++++-------
|
||||||
|
mkfs/xfs_mkfs.c | 6 +++---
|
||||||
|
2 files changed, 10 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
Index: xfsprogs-5.0.0/include/xfs_multidisk.h
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/include/xfs_multidisk.h
|
||||||
|
+++ xfsprogs-5.0.0/include/xfs_multidisk.h
|
||||||
|
@@ -14,7 +14,6 @@
|
||||||
|
#define XFS_DFL_BLOCKSIZE_LOG 12 /* 4096 byte blocks */
|
||||||
|
#define XFS_DINODE_DFL_LOG 8 /* 256 byte inodes */
|
||||||
|
#define XFS_DINODE_DFL_CRC_LOG 9 /* 512 byte inodes for CRCs */
|
||||||
|
-#define XFS_MIN_DATA_BLOCKS 100
|
||||||
|
#define XFS_MIN_INODE_PERBLOCK 2 /* min inodes per block */
|
||||||
|
#define XFS_DFL_IMAXIMUM_PCT 25 /* max % of space for inodes */
|
||||||
|
#define XFS_MIN_REC_DIRSIZE 12 /* 4096 byte dirblocks (V2) */
|
||||||
|
@@ -25,13 +24,14 @@
|
||||||
|
* accept w/o warnings
|
||||||
|
*/
|
||||||
|
|
||||||
|
-#define XFS_AG_BYTES(bblog) ((long long)BBSIZE << (bblog))
|
||||||
|
-#define XFS_AG_MIN_BYTES ((XFS_AG_BYTES(15))) /* 16 MB */
|
||||||
|
-#define XFS_AG_MAX_BYTES ((XFS_AG_BYTES(31))) /* 1 TB */
|
||||||
|
-#define XFS_AG_MIN_BLOCKS(blog) (XFS_AG_MIN_BYTES >> (blog))
|
||||||
|
-#define XFS_AG_MAX_BLOCKS(blog) ((XFS_AG_MAX_BYTES - 1) >> (blog))
|
||||||
|
+#define XFS_AG_BYTES(bblog) ((long long)BBSIZE << (bblog))
|
||||||
|
+#define XFS_MIN_DATA_BLOCKS(cfg) (XFS_AG_MIN_BLOCKS((cfg)->blocklog))
|
||||||
|
+#define XFS_AG_MIN_BYTES ((XFS_AG_BYTES(15))) /* 16 MB */
|
||||||
|
+#define XFS_AG_MAX_BYTES ((XFS_AG_BYTES(31))) /* 1 TB */
|
||||||
|
+#define XFS_AG_MIN_BLOCKS(blog) (XFS_AG_MIN_BYTES >> (blog))
|
||||||
|
+#define XFS_AG_MAX_BLOCKS(blog) ((XFS_AG_MAX_BYTES - 1) >> (blog))
|
||||||
|
|
||||||
|
-#define XFS_MAX_AGNUMBER ((xfs_agnumber_t)(NULLAGNUMBER - 1))
|
||||||
|
+#define XFS_MAX_AGNUMBER ((xfs_agnumber_t)(NULLAGNUMBER - 1))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These values define what we consider a "multi-disk" filesystem. That is, a
|
||||||
|
Index: xfsprogs-5.0.0/mkfs/xfs_mkfs.c
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/mkfs/xfs_mkfs.c
|
||||||
|
+++ xfsprogs-5.0.0/mkfs/xfs_mkfs.c
|
||||||
|
@@ -2581,10 +2581,10 @@ _("size %s specified for data subvolume
|
||||||
|
cfg->dblocks = DTOBT(xi->dsize, cfg->blocklog);
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (cfg->dblocks < XFS_MIN_DATA_BLOCKS) {
|
||||||
|
+ if (cfg->dblocks < XFS_MIN_DATA_BLOCKS(cfg)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
-_("size %lld of data subvolume is too small, minimum %d blocks\n"),
|
||||||
|
- (long long)cfg->dblocks, XFS_MIN_DATA_BLOCKS);
|
||||||
|
+_("size %lld of data subvolume is too small, minimum %lld blocks\n"),
|
||||||
|
+ (long long)cfg->dblocks, XFS_MIN_DATA_BLOCKS(cfg));
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,101 @@
|
|||||||
|
From bce109af5ea0b0d6547d8cd0500560f32532e6bd Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 4 Sep 2020 16:05:20 -0400
|
||||||
|
Subject: [PATCH] xfs: drop the type parameter from xfs_dquot_verify
|
||||||
|
|
||||||
|
Source kernel commit: f9751c4ad3d17fa93773c187732f10c8a49940e3
|
||||||
|
|
||||||
|
xfs_qm_reset_dqcounts (aka quotacheck) is the only xfs_dqblk_verify
|
||||||
|
caller that actually knows the specific quota type that it's looking
|
||||||
|
for. Since everything else just pass in type==0 (including the buffer
|
||||||
|
verifier), drop the parameter and open-code the check like
|
||||||
|
xfs_dquot_from_disk already does.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Dave Chinner <dchinner@redhat.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/libxfs/xfs_dquot_buf.c b/libxfs/xfs_dquot_buf.c
|
||||||
|
index 5e31938..a3e8ba1 100644
|
||||||
|
--- a/libxfs/xfs_dquot_buf.c
|
||||||
|
+++ b/libxfs/xfs_dquot_buf.c
|
||||||
|
@@ -37,8 +37,7 @@ xfs_failaddr_t
|
||||||
|
xfs_dquot_verify(
|
||||||
|
struct xfs_mount *mp,
|
||||||
|
xfs_disk_dquot_t *ddq,
|
||||||
|
- xfs_dqid_t id,
|
||||||
|
- uint type) /* used only during quotacheck */
|
||||||
|
+ xfs_dqid_t id) /* used only during quotacheck */
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We can encounter an uninitialized dquot buffer for 2 reasons:
|
||||||
|
@@ -60,8 +59,6 @@ xfs_dquot_verify(
|
||||||
|
if (ddq->d_version != XFS_DQUOT_VERSION)
|
||||||
|
return __this_address;
|
||||||
|
|
||||||
|
- if (type && ddq->d_flags != type)
|
||||||
|
- return __this_address;
|
||||||
|
if (ddq->d_flags != XFS_DQ_USER &&
|
||||||
|
ddq->d_flags != XFS_DQ_PROJ &&
|
||||||
|
ddq->d_flags != XFS_DQ_GROUP)
|
||||||
|
@@ -95,14 +92,13 @@ xfs_failaddr_t
|
||||||
|
xfs_dqblk_verify(
|
||||||
|
struct xfs_mount *mp,
|
||||||
|
struct xfs_dqblk *dqb,
|
||||||
|
- xfs_dqid_t id,
|
||||||
|
- uint type) /* used only during quotacheck */
|
||||||
|
+ xfs_dqid_t id) /* used only during quotacheck */
|
||||||
|
{
|
||||||
|
if (xfs_sb_version_hascrc(&mp->m_sb) &&
|
||||||
|
!uuid_equal(&dqb->dd_uuid, &mp->m_sb.sb_meta_uuid))
|
||||||
|
return __this_address;
|
||||||
|
|
||||||
|
- return xfs_dquot_verify(mp, &dqb->dd_diskdq, id, type);
|
||||||
|
+ return xfs_dquot_verify(mp, &dqb->dd_diskdq, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -207,7 +203,7 @@ xfs_dquot_buf_verify(
|
||||||
|
if (i == 0)
|
||||||
|
id = be32_to_cpu(ddq->d_id);
|
||||||
|
|
||||||
|
- fa = xfs_dqblk_verify(mp, &dqb[i], id + i, 0);
|
||||||
|
+ fa = xfs_dqblk_verify(mp, &dqb[i], id + i);
|
||||||
|
if (fa) {
|
||||||
|
if (!readahead)
|
||||||
|
xfs_buf_verifier_error(bp, -EFSCORRUPTED,
|
||||||
|
diff --git a/libxfs/xfs_quota_defs.h b/libxfs/xfs_quota_defs.h
|
||||||
|
index d3f2977..afe1ea0 100644
|
||||||
|
--- a/libxfs/xfs_quota_defs.h
|
||||||
|
+++ b/libxfs/xfs_quota_defs.h
|
||||||
|
@@ -140,9 +140,9 @@ typedef uint16_t xfs_qwarncnt_t;
|
||||||
|
#define XFS_QMOPT_RESBLK_MASK (XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_RES_RTBLKS)
|
||||||
|
|
||||||
|
extern xfs_failaddr_t xfs_dquot_verify(struct xfs_mount *mp,
|
||||||
|
- struct xfs_disk_dquot *ddq, xfs_dqid_t id, uint type);
|
||||||
|
+ struct xfs_disk_dquot *ddq, xfs_dqid_t id);
|
||||||
|
extern xfs_failaddr_t xfs_dqblk_verify(struct xfs_mount *mp,
|
||||||
|
- struct xfs_dqblk *dqb, xfs_dqid_t id, uint type);
|
||||||
|
+ struct xfs_dqblk *dqb, xfs_dqid_t id);
|
||||||
|
extern int xfs_calc_dquots_per_chunk(unsigned int nbblks);
|
||||||
|
extern int xfs_dqblk_repair(struct xfs_mount *mp, struct xfs_dqblk *dqb,
|
||||||
|
xfs_dqid_t id, uint type);
|
||||||
|
diff --git a/repair/dinode.c b/repair/dinode.c
|
||||||
|
index 04c2dd5..77f78f1 100644
|
||||||
|
--- a/repair/dinode.c
|
||||||
|
+++ b/repair/dinode.c
|
||||||
|
@@ -1233,8 +1233,10 @@ _("cannot read inode %" PRIu64 ", file block %" PRIu64 ", disk block %" PRIu64 "
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- if (libxfs_dquot_verify(mp, &dqb->dd_diskdq, dqid,
|
||||||
|
- quota_type) != NULL) {
|
||||||
|
+ if (libxfs_dquot_verify(mp, &dqb->dd_diskdq, dqid)
|
||||||
|
+ != NULL ||
|
||||||
|
+ (dqb->dd_diskdq.d_flags & XFS_DQ_ALLTYPES)
|
||||||
|
+ != quota_type) {
|
||||||
|
do_warn(_("%s: Corrupt quota for id %u. "),
|
||||||
|
quota_string, dqid);
|
||||||
|
bad_dqb = 1;
|
@ -0,0 +1,78 @@
|
|||||||
|
From 5ca4d781d36946de197ed2d4196c84c8f6b4522f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ian Kent <raven@themaw.net>
|
||||||
|
Date: Mon, 12 Oct 2020 15:40:01 -0400
|
||||||
|
Subject: [PATCH] xfsprogs: ignore autofs mount table entries
|
||||||
|
|
||||||
|
Some of the xfsprogs utilities read the mount table via. getmntent(3).
|
||||||
|
|
||||||
|
The mount table may contain (almost always these days since /etc/mtab is
|
||||||
|
symlinked to /proc/self/mounts) autofs mount entries. During processing
|
||||||
|
of the mount table entries statfs(2) can be called on mount point paths
|
||||||
|
which will trigger an automount if those entries are direct or offset
|
||||||
|
autofs mount triggers (indirect autofs mounts aren't affected).
|
||||||
|
|
||||||
|
This can be a problem when there are a lot of autofs direct or offset
|
||||||
|
mounts because real mounts will be triggered when statfs(2) is called.
|
||||||
|
This can be particularly bad if the triggered mounts are NFS mounts and
|
||||||
|
the server is unavailable leading to lengthy boot times or worse.
|
||||||
|
|
||||||
|
Simply ignoring autofs mount entries during getmentent(3) traversals
|
||||||
|
avoids the statfs() call that triggers these mounts. If there are
|
||||||
|
automounted mounts (real mounts) at the time of reading the mount table
|
||||||
|
these will still be seen in the list so they will be included if that
|
||||||
|
actually matters to the reader.
|
||||||
|
|
||||||
|
Recent glibc getmntent(3) can ignore autofs mounts but that requires the
|
||||||
|
autofs user to configure autofs to use the "ignore" pseudo mount option
|
||||||
|
for autofs mounts. But this isn't yet the autofs default (to prevent
|
||||||
|
unexpected side effects) so that can't be used.
|
||||||
|
|
||||||
|
The autofs direct and offset automount triggers are pseudo file system
|
||||||
|
mounts and are more or less useless in terms on file system information
|
||||||
|
so excluding them doesn't sacrifice useful file system information
|
||||||
|
either.
|
||||||
|
|
||||||
|
Consequently excluding autofs mounts shouldn't have any adverse side
|
||||||
|
effects.
|
||||||
|
|
||||||
|
Changes since v1:
|
||||||
|
- drop hunk from fsr/xfs_fsr.c.
|
||||||
|
|
||||||
|
Signed-off-by: Ian Kent <raven@themaw.net>
|
||||||
|
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
Signed-off-by: Pavel Reichl <preichl@redhat.com>
|
||||||
|
---
|
||||||
|
libfrog/linux.c | 2 ++
|
||||||
|
libfrog/paths.c | 2 ++
|
||||||
|
2 files changed, 4 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/libfrog/linux.c b/libfrog/linux.c
|
||||||
|
index 40a839d1..a45d99ab 100644
|
||||||
|
--- a/libfrog/linux.c
|
||||||
|
+++ b/libfrog/linux.c
|
||||||
|
@@ -73,6 +73,8 @@ platform_check_mount(char *name, char *block, struct stat *s, int flags)
|
||||||
|
* servers. So first, a simple check: does the "dev" start with "/" ?
|
||||||
|
*/
|
||||||
|
while ((mnt = getmntent(f)) != NULL) {
|
||||||
|
+ if (!strcmp(mnt->mnt_type, "autofs"))
|
||||||
|
+ continue;
|
||||||
|
if (mnt->mnt_fsname[0] != '/')
|
||||||
|
continue;
|
||||||
|
if (stat(mnt->mnt_dir, &mst) < 0)
|
||||||
|
diff --git a/libfrog/paths.c b/libfrog/paths.c
|
||||||
|
index 32737223..d6793764 100644
|
||||||
|
--- a/libfrog/paths.c
|
||||||
|
+++ b/libfrog/paths.c
|
||||||
|
@@ -389,6 +389,8 @@ fs_table_initialise_mounts(
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
while ((mnt = getmntent(mtp)) != NULL) {
|
||||||
|
+ if (!strcmp(mnt->mnt_type, "autofs"))
|
||||||
|
+ continue;
|
||||||
|
if (!realpath(mnt->mnt_dir, rmnt_dir))
|
||||||
|
continue;
|
||||||
|
if (!realpath(mnt->mnt_fsname, rmnt_fsname))
|
||||||
|
--
|
||||||
|
2.40.1
|
||||||
|
|
@ -0,0 +1,98 @@
|
|||||||
|
From 28518f7782310951019d6d28f2a6e9f9fc6e4a1c Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Tue, 15 Sep 2020 15:50:35 -0400
|
||||||
|
Subject: [PATCH] xfs: improve ondisk dquot flags checking
|
||||||
|
|
||||||
|
Source kernel commit: a990f7a84edc9941956ea3c1dfb89733c80f9ad0
|
||||||
|
|
||||||
|
Create an XFS_DQTYPE_ANY mask for ondisk dquots flags, and use that to
|
||||||
|
ensure that we never accept any garbage flags when we're loading dquots.
|
||||||
|
While we're at it, restructure the quota type flag checking to use the
|
||||||
|
proper masking.
|
||||||
|
|
||||||
|
Note that I plan to add y2038 support soon, which will require a new
|
||||||
|
xfs_dqtype_t flag for extended timestamp support, hence all the work to
|
||||||
|
make the type masking work correctly.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Dave Chinner <dchinner@redhat.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
|
||||||
|
NOTES: I did not backport the type-vs-flags split, so some of the
|
||||||
|
naming convenstions are different here.
|
||||||
|
|
||||||
|
diff --git a/db/check.c b/db/check.c
|
||||||
|
index c3dae20..27f6639 100644
|
||||||
|
--- a/db/check.c
|
||||||
|
+++ b/db/check.c
|
||||||
|
@@ -3452,7 +3452,7 @@ process_quota(
|
||||||
|
error++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
- if (dqb->dd_diskdq.d_flags != exp_flags) {
|
||||||
|
+ if (dqb->dd_diskdq.d_flags & ~XFS_DQTYPE_ANY) {
|
||||||
|
if (scicb)
|
||||||
|
dbprintf(_("bad flags %#x for %s dqblk "
|
||||||
|
"%lld entry %d id %u\n"),
|
||||||
|
@@ -3461,6 +3461,17 @@ process_quota(
|
||||||
|
error++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
+ if ((dqb->dd_diskdq.d_flags & XFS_DQ_ALLTYPES)
|
||||||
|
+ != exp_flags) {
|
||||||
|
+ if (scicb)
|
||||||
|
+ dbprintf(_("wrong type %#x for %s dqblk "
|
||||||
|
+ "%lld entry %d id %u\n"),
|
||||||
|
+ dqb->dd_diskdq.d_flags &
|
||||||
|
+ XFS_DQ_ALLTYPES, s,
|
||||||
|
+ (xfs_fileoff_t)qbno, i, dqid);
|
||||||
|
+ error++;
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
if (be32_to_cpu(dqb->dd_diskdq.d_id) != dqid) {
|
||||||
|
if (scicb)
|
||||||
|
dbprintf(_("bad id %u for %s dqblk %lld "
|
||||||
|
diff --git a/libxfs/xfs_dquot_buf.c b/libxfs/xfs_dquot_buf.c
|
||||||
|
index a3e8ba1..324f528 100644
|
||||||
|
--- a/libxfs/xfs_dquot_buf.c
|
||||||
|
+++ b/libxfs/xfs_dquot_buf.c
|
||||||
|
@@ -39,6 +39,8 @@ xfs_dquot_verify(
|
||||||
|
xfs_disk_dquot_t *ddq,
|
||||||
|
xfs_dqid_t id) /* used only during quotacheck */
|
||||||
|
{
|
||||||
|
+ __u8 ddq_type;
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* We can encounter an uninitialized dquot buffer for 2 reasons:
|
||||||
|
* 1. If we crash while deleting the quotainode(s), and those blks got
|
||||||
|
@@ -59,9 +61,12 @@ xfs_dquot_verify(
|
||||||
|
if (ddq->d_version != XFS_DQUOT_VERSION)
|
||||||
|
return __this_address;
|
||||||
|
|
||||||
|
- if (ddq->d_flags != XFS_DQ_USER &&
|
||||||
|
- ddq->d_flags != XFS_DQ_PROJ &&
|
||||||
|
- ddq->d_flags != XFS_DQ_GROUP)
|
||||||
|
+ if (ddq->d_flags & ~XFS_DQTYPE_ANY)
|
||||||
|
+ return __this_address;
|
||||||
|
+ ddq_type = ddq->d_flags & XFS_DQ_ALLTYPES;
|
||||||
|
+ if (ddq_type != XFS_DQ_USER &&
|
||||||
|
+ ddq_type != XFS_DQ_PROJ &&
|
||||||
|
+ ddq_type != XFS_DQ_GROUP)
|
||||||
|
return __this_address;
|
||||||
|
|
||||||
|
if (id != -1 && id != be32_to_cpu(ddq->d_id))
|
||||||
|
diff --git a/libxfs/xfs_quota_defs.h b/libxfs/xfs_quota_defs.h
|
||||||
|
index afe1ea0..c69dba4 100644
|
||||||
|
--- a/libxfs/xfs_quota_defs.h
|
||||||
|
+++ b/libxfs/xfs_quota_defs.h
|
||||||
|
@@ -31,6 +31,8 @@ typedef uint16_t xfs_qwarncnt_t;
|
||||||
|
|
||||||
|
#define XFS_DQ_ALLTYPES (XFS_DQ_USER|XFS_DQ_PROJ|XFS_DQ_GROUP)
|
||||||
|
|
||||||
|
+#define XFS_DQTYPE_ANY (XFS_DQ_ALLTYPES)
|
||||||
|
+
|
||||||
|
#define XFS_DQ_FLAGS \
|
||||||
|
{ XFS_DQ_USER, "USER" }, \
|
||||||
|
{ XFS_DQ_PROJ, "PROJ" }, \
|
@ -1,39 +0,0 @@
|
|||||||
From 780e93c5103d3c19d53c36ab7f4794d14912f3a5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Bill O'Donnell <bodonnel@redhat.com>
|
|
||||||
Date: Fri, 28 Jul 2023 17:20:17 -0500
|
|
||||||
Subject: [PATCH] mkfs.xfs.8: correction on mkfs.xfs manpage since reflink and
|
|
||||||
dax are compatible
|
|
||||||
|
|
||||||
Merged early in 2023: Commit 480017957d638 xfs: remove restrictions for fsdax
|
|
||||||
and reflink. There needs to be a corresponding change to the mkfs.xfs manpage
|
|
||||||
to remove the incompatiblity statement.
|
|
||||||
|
|
||||||
Signed-off-by: Bill O'Donnell <bodonnel@redhat.com>
|
|
||||||
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
|
|
||||||
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
|
|
||||||
Signed-off-by: Pavel Reichl <preichl@redhat.com>
|
|
||||||
---
|
|
||||||
man/man8/mkfs.xfs.8.in | 7 -------
|
|
||||||
1 file changed, 7 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/man/man8/mkfs.xfs.8.in b/man/man8/mkfs.xfs.8.in
|
|
||||||
index ce6f1e2d..08bb92f6 100644
|
|
||||||
--- a/man/man8/mkfs.xfs.8.in
|
|
||||||
+++ b/man/man8/mkfs.xfs.8.in
|
|
||||||
@@ -323,13 +323,6 @@ option set. When the option
|
|
||||||
.B \-m crc=0
|
|
||||||
is used, the reference count btree feature is not supported and reflink is
|
|
||||||
disabled.
|
|
||||||
-.IP
|
|
||||||
-Note: the filesystem DAX mount option (
|
|
||||||
-.B \-o dax
|
|
||||||
-) is incompatible with
|
|
||||||
-reflink-enabled XFS filesystems. To use filesystem DAX with XFS, specify the
|
|
||||||
-.B \-m reflink=0
|
|
||||||
-option to mkfs.xfs to disable the reflink feature.
|
|
||||||
.RE
|
|
||||||
.PP
|
|
||||||
.PD 0
|
|
||||||
--
|
|
||||||
2.41.0
|
|
||||||
|
|
@ -1,128 +0,0 @@
|
|||||||
From 8e698ee72c4ecbbf18264568eb310875839fd601 Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Darrick J. Wong" <djwong@kernel.org>
|
|
||||||
Date: Tue, 2 May 2023 09:14:36 +1000
|
|
||||||
Subject: [PATCH] xfs: set bnobt/cntbt numrecs correctly when formatting new
|
|
||||||
AGs
|
|
||||||
|
|
||||||
Through generic/300, I discovered that mkfs.xfs creates corrupt
|
|
||||||
filesystems when given these parameters:
|
|
||||||
|
|
||||||
# mkfs.xfs -d size=512M /dev/sda -f -d su=128k,sw=4 --unsupported
|
|
||||||
Filesystems formatted with --unsupported are not supported!!
|
|
||||||
meta-data=/dev/sda isize=512 agcount=8, agsize=16352 blks
|
|
||||||
= sectsz=512 attr=2, projid32bit=1
|
|
||||||
= crc=1 finobt=1, sparse=1, rmapbt=1
|
|
||||||
= reflink=1 bigtime=1 inobtcount=1 nrext64=1
|
|
||||||
data = bsize=4096 blocks=130816, imaxpct=25
|
|
||||||
= sunit=32 swidth=128 blks
|
|
||||||
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
|
|
||||||
log =internal log bsize=4096 blocks=8192, version=2
|
|
||||||
= sectsz=512 sunit=32 blks, lazy-count=1
|
|
||||||
realtime =none extsz=4096 blocks=0, rtextents=0
|
|
||||||
= rgcount=0 rgsize=0 blks
|
|
||||||
Discarding blocks...Done.
|
|
||||||
# xfs_repair -n /dev/sda
|
|
||||||
Phase 1 - find and verify superblock...
|
|
||||||
- reporting progress in intervals of 15 minutes
|
|
||||||
Phase 2 - using internal log
|
|
||||||
- zero log...
|
|
||||||
- 16:30:50: zeroing log - 16320 of 16320 blocks done
|
|
||||||
- scan filesystem freespace and inode maps...
|
|
||||||
agf_freeblks 25, counted 0 in ag 4
|
|
||||||
sb_fdblocks 8823, counted 8798
|
|
||||||
|
|
||||||
The root cause of this problem is the numrecs handling in
|
|
||||||
xfs_freesp_init_recs, which is used to initialize a new AG. Prior to
|
|
||||||
calling the function, we set up the new bnobt block with numrecs == 1
|
|
||||||
and rely on _freesp_init_recs to format that new record. If the last
|
|
||||||
record created has a blockcount of zero, then it sets numrecs = 0.
|
|
||||||
|
|
||||||
That last bit isn't correct if the AG contains the log, the start of the
|
|
||||||
log is not immediately after the initial blocks due to stripe alignment,
|
|
||||||
and the end of the log is perfectly aligned with the end of the AG. For
|
|
||||||
this case, we actually formatted a single bnobt record to handle the
|
|
||||||
free space before the start of the (stripe aligned) log, and incremented
|
|
||||||
arec to try to format a second record. That second record turned out to
|
|
||||||
be unnecessary, so what we really want is to leave numrecs at 1.
|
|
||||||
|
|
||||||
The numrecs handling itself is overly complicated because a different
|
|
||||||
function sets numrecs == 1. Change the bnobt creation code to start
|
|
||||||
with numrecs set to zero and only increment it after successfully
|
|
||||||
formatting a free space extent into the btree block.
|
|
||||||
|
|
||||||
Fixes: f327a00745ff ("xfs: account for log space when formatting new AGs")
|
|
||||||
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
|
|
||||||
Reviewed-by: Dave Chinner <dchinner@redhat.com>
|
|
||||||
Signed-off-by: Dave Chinner <david@fromorbit.com>
|
|
||||||
Signed-off-by: Pavel Reichl <preichl@redhat.com>
|
|
||||||
---
|
|
||||||
fs/xfs/libxfs/xfs_ag.c | 19 +++++++++----------
|
|
||||||
1 file changed, 9 insertions(+), 10 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/fs/xfs/libxfs/xfs_ag.c b/fs/xfs/libxfs/xfs_ag.c
|
|
||||||
index 1b078bbbf225..9b373a0c7aaf 100644
|
|
||||||
--- a//libxfs/xfs_ag.c
|
|
||||||
+++ b//libxfs/xfs_ag.c
|
|
||||||
@@ -495,10 +495,12 @@ xfs_freesp_init_recs(
|
|
||||||
ASSERT(start >= mp->m_ag_prealloc_blocks);
|
|
||||||
if (start != mp->m_ag_prealloc_blocks) {
|
|
||||||
/*
|
|
||||||
- * Modify first record to pad stripe align of log
|
|
||||||
+ * Modify first record to pad stripe align of log and
|
|
||||||
+ * bump the record count.
|
|
||||||
*/
|
|
||||||
arec->ar_blockcount = cpu_to_be32(start -
|
|
||||||
mp->m_ag_prealloc_blocks);
|
|
||||||
+ be16_add_cpu(&block->bb_numrecs, 1);
|
|
||||||
nrec = arec + 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ -509,7 +511,6 @@ xfs_freesp_init_recs(
|
|
||||||
be32_to_cpu(arec->ar_startblock) +
|
|
||||||
be32_to_cpu(arec->ar_blockcount));
|
|
||||||
arec = nrec;
|
|
||||||
- be16_add_cpu(&block->bb_numrecs, 1);
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Change record start to after the internal log
|
|
||||||
@@ -518,15 +519,13 @@ xfs_freesp_init_recs(
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
- * Calculate the record block count and check for the case where
|
|
||||||
- * the log might have consumed all available space in the AG. If
|
|
||||||
- * so, reset the record count to 0 to avoid exposure of an invalid
|
|
||||||
- * record start block.
|
|
||||||
+ * Calculate the block count of this record; if it is nonzero,
|
|
||||||
+ * increment the record count.
|
|
||||||
*/
|
|
||||||
arec->ar_blockcount = cpu_to_be32(id->agsize -
|
|
||||||
be32_to_cpu(arec->ar_startblock));
|
|
||||||
- if (!arec->ar_blockcount)
|
|
||||||
- block->bb_numrecs = 0;
|
|
||||||
+ if (arec->ar_blockcount)
|
|
||||||
+ be16_add_cpu(&block->bb_numrecs, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ -538,7 +537,7 @@ xfs_bnoroot_init(
|
|
||||||
struct xfs_buf *bp,
|
|
||||||
struct aghdr_init_data *id)
|
|
||||||
{
|
|
||||||
- xfs_btree_init_block(mp, bp, XFS_BTNUM_BNO, 0, 1, id->agno);
|
|
||||||
+ xfs_btree_init_block(mp, bp, XFS_BTNUM_BNO, 0, 0, id->agno);
|
|
||||||
xfs_freesp_init_recs(mp, bp, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -548,7 +547,7 @@ xfs_cntroot_init(
|
|
||||||
struct xfs_buf *bp,
|
|
||||||
struct aghdr_init_data *id)
|
|
||||||
{
|
|
||||||
- xfs_btree_init_block(mp, bp, XFS_BTNUM_CNT, 0, 1, id->agno);
|
|
||||||
+ xfs_btree_init_block(mp, bp, XFS_BTNUM_CNT, 0, 0, id->agno);
|
|
||||||
xfs_freesp_init_recs(mp, bp, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.40.1
|
|
||||||
|
|
Loading…
Reference in new issue