Compare commits

...

No commits in common. 'c9' and 'i8c' have entirely different histories.
c9 ... i8c

2
.gitignore vendored

@ -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,109 @@
From 7e8a6edb4d1ba0079152eb477abbbc1dfb1ebb7e Mon Sep 17 00:00:00 2001
From: Pavel Reichl <preichl@redhat.com>
Date: Fri, 13 Dec 2019 16:21:26 -0500
Subject: [PATCH] mkfs: Break block discard into chunks of 2 GB
Some users are not happy about the BLKDISCARD taking too long and at the
same time not being informed about that - so they think that the command
actually hung.
This commit changes code so that progress reporting is possible and also
typing the ^C will cancel the ongoing BLKDISCARD.
Signed-off-by: Pavel Reichl <preichl@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
---
mkfs/xfs_mkfs.c | 50 ++++++++++++++++++++++++++++++++++++-------------
1 file changed, 37 insertions(+), 13 deletions(-)
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 18338a61..4bfdebf6 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -1240,17 +1240,40 @@ done:
}
static void
-discard_blocks(dev_t dev, uint64_t nsectors)
+discard_blocks(dev_t dev, uint64_t nsectors, int quiet)
{
- int fd;
+ int fd;
+ uint64_t offset = 0;
+ /* Discard the device 2G at a time */
+ const uint64_t step = 2ULL << 30;
+ const uint64_t count = BBTOB(nsectors);
- /*
- * We intentionally ignore errors from the discard ioctl. It is
- * not necessary for the mkfs functionality but just an optimization.
- */
fd = libxfs_device_to_fd(dev);
- if (fd > 0)
- platform_discard_blocks(fd, 0, nsectors << 9);
+ if (fd <= 0)
+ return;
+ if (!quiet) {
+ printf("Discarding blocks...");
+ fflush(stdout);
+ }
+
+ /* The block discarding happens in smaller batches so it can be
+ * interrupted prematurely
+ */
+ while (offset < count) {
+ uint64_t tmp_step = min(step, count - offset);
+
+ /*
+ * We intentionally ignore errors from the discard ioctl. It is
+ * not necessary for the mkfs functionality but just an
+ * optimization. However we should stop on error.
+ */
+ if (platform_discard_blocks(fd, offset, tmp_step))
+ return;
+
+ offset += tmp_step;
+ }
+ if (!quiet)
+ printf("Done.\n");
}
static __attribute__((noreturn)) void
@@ -2507,18 +2530,19 @@ open_devices(
static void
discard_devices(
- struct libxfs_xinit *xi)
+ struct libxfs_xinit *xi,
+ int quiet)
{
/*
* This function has to be called after libxfs has been initialized.
*/
if (!xi->disfile)
- discard_blocks(xi->ddev, xi->dsize);
+ discard_blocks(xi->ddev, xi->dsize, quiet);
if (xi->rtdev && !xi->risfile)
- discard_blocks(xi->rtdev, xi->rtsize);
+ discard_blocks(xi->rtdev, xi->rtsize, quiet);
if (xi->logdev && xi->logdev != xi->ddev && !xi->lisfile)
- discard_blocks(xi->logdev, xi->logBBsize);
+ discard_blocks(xi->logdev, xi->logBBsize, quiet);
}
static void
@@ -3749,7 +3773,7 @@ main(
* All values have been validated, discard the old device layout.
*/
if (discard && !dry_run)
- discard_devices(&xi);
+ discard_devices(&xi, quiet);
/*
* we need the libxfs buffer cache from here on in.
--
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

@ -7,13 +7,13 @@ Fixes: 9cf846b51 ("mkfs: enable sparse inodes by default")
Suggested-by: Lukas Herbolt <lukas@herbolt.com>
Signed-off-by: Pavel Reichl <preichl@redhat.com>
---
man/man8/mkfs.xfs.8.in | 2 +-
man/man8/mkfs.xfs.8 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/man/man8/mkfs.xfs.8.in b/man/man8/mkfs.xfs.8.in
diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8
index 49e64d47a..48e26ece7 100644
--- a/man/man8/mkfs.xfs.8.in
+++ b/man/man8/mkfs.xfs.8.in
--- a/man/man8/mkfs.xfs.8
+++ b/man/man8/mkfs.xfs.8
@@ -631,7 +631,7 @@ Enable sparse inode chunk allocation. The
.I value
is either 0 or 1, with 1 signifying that sparse allocation is enabled.

@ -1,42 +1,90 @@
Summary: Utilities for managing the XFS filesystem
Name: xfsprogs
Version: 5.19.0
Release: 4%{?dist}
Version: 5.0.0
Release: 12%{?dist}
License: GPL+ and LGPLv2+
Group: System Environment/Base
URL: https://xfs.wiki.kernel.org
Source0: http://kernel.org/pub/linux/utils/fs/xfs/xfsprogs/%{name}-%{version}.tar.xz
Source1: http://kernel.org/pub/linux/utils/fs/xfs/xfsprogs/%{name}-%{version}.tar.sign
Source2: https://git.kernel.org/pub/scm/docs/kernel/pgpkeys.git/plain/keys/20AE1692E13DDEE0.asc
Source3: rhel8.0.conf
Requires: util-linux
BuildRequires: make
BuildRequires: gcc
BuildRequires: libtool, gettext, libattr-devel, libuuid-devel
BuildRequires: libedit-devel, libblkid-devel >= 2.17-0.1.git5e51568
Buildrequires: lvm2-devel, libicu-devel >= 4.6
BuildRequires: gnupg2, xz, inih-devel
BuildRequires: userspace-rcu-devel
BuildRequires: readline-devel, libblkid-devel >= 2.17-0.1.git5e51568
BuildRequires: lvm2-devel, libicu-devel >= 4.6
Provides: xfs-cmds
Obsoletes: xfs-cmds <= %{version}
Provides: xfsprogs-qa-devel
Obsoletes: xfsprogs-qa-devel <= %{version}
Conflicts: xfsdump < 3.0.1
Suggests: xfsprogs-xfs_scrub
Patch0: xfsprogs-5.19.0-disable-old-kernel-bigtime-inobtcnt-on.patch
Patch1: xfsprogs-5.12.0-example-conf.patch
Patch2: xfsprogs-5.19.0-mkfs-tolerate-tiny-filesystems.patch
Patch3: xfsprogs-5.19.0-xfs-hoist-refcount-record-merge-predicates.patch
Patch4: xfsprogs-5.19.0-xfs_db-fix-dir3-block-magic-check.patch
Patch5: xfsprogs-5.19.0-xfs-estimate-post-merge-refcounts-correctly.patch
Patch7: xfsprogs-5.19.0-xfs-fix-off-by-one-error-in-xfs_btree_space_to_heigh.patch
Patch8: xfsprogs-5.19.0-xfs-fix-sb-write-verify-for-lazysbcount.patch
Patch9: xfsprogs-5.19.0-xfs-get-rid-of-assert-from-xfs_btree_islastblock.patch
Patch10: xfsprogs-5.19.0-xfs-removed-useless-condition-in-function-xfs_attr_n.patch
Patch11: xfsprogs-5.19.0-xfs_repair-retain-superblock-buffer-to-avoid-write-h.patch
Patch12: xfsprogs-kernel-xfs-set-bnobt-cntbt-numrecs-correctly-when-formattin.patch
Patch13: xfsprogs-rhelonly-mkfs-fix-man-s-default-value-for-sparse-option.patch
Patch14: xfsprogs-6.5.0-mkfs.xfs.8-correction-on-mkfs.xfs-manpage-since-refl.patch
# reflink is not yet default upstream, but we enabled it as such
Patch0: xfsprogs-4.17.0-reflink-default.patch
Patch1: xfsprogs-5.1.0-mkfs-validate-start-and-end-of-aligned-logs.patch
Patch2: xfsprogs-5.1.0-mkfs-don-t-use-xfs_verify_fsbno-before-m_sb-is-fully.patch
Patch3: xfsprogs-5.1.0-xfsprogs-Fix-uninitialized-cfg-lsunit.patch
Patch4: xfsprogs-5.3.0-xfs_growfs-allow-mounted-device-node-as-argument.patch
Patch5: xfsprogs-5.5.0-libxfs-use-FALLOC_FL_ZERO_RANGE-in-libxfs_device_zer.patch
Patch6: xfsprogs-5.4.0-mkfs-Break-block-discard-into-chunks-of-2-GB.patch
Patch7: xfsprogs-5.4.0-mkfs-tidy-up-discard-notifications.patch
Patch8: xfsprogs-5.7.0-xfs_quota-refactor-code-to-generate-id-from-name.patch
Patch9: xfsprogs-5.7.0-xfs_quota-allow-individual-timer-extension.patch
Patch10: xfsprogs-5.7.0-xfs_quota-fix-unsigned-int-id-comparisons.patch
Patch11: xfsprogs-5.7.0-xfs_repair-check-for-AG-btree-records-that-would-wra.patch
Patch12: xfsprogs-5.7.0-xfs_repair-tag-inobt-vs-finobt-errors-properly.patch
Patch13: xfsprogs-5.7.0-xfs_repair-complain-about-bad-interior-btree-pointer.patch
Patch14: xfsprogs-5.7.0-xfs_repair-convert-to-libxfs_verify_agbno.patch
Patch15: xfsprogs-5.9.0-mkfs.xfs-fix-ASSERT-on-too-small-device-with-stripe.patch
Patch16: xfsprogs-5.7.0-xfs_repair-fix-rebuilding-btree-block-less-than-minr.patch
Patch17: xfsprogs-5.10.0-xfs_quota-document-how-the-default-quota-is-stored.patch
Patch18: xfsprogs-5.8.0-xfs_db-short-circuit-type_f-if-type-is-unchanged.patch
Patch19: xfsprogs-5.10.0-xfs_repair-Use-proper-min-max-values-in-compute_level_geometry.patch
Patch20: xfsprogs-5.8.0-xfs_quota-command-error-message-improvement.patch
Patch21: xfsprogs-5.8.0-xfs_quota-display-warning-limits-when-printing-quota.patch
Patch22: xfsprogs-5.8.0-xfs_quota-state-command-should-report-ugp-grace-time.patch
Patch23: xfsprogs-5.1.0-libxfs-create-current_time-helper-and-sync-xfs_trans.patch
Patch24: xfsprogs-5.5.0-xfs-use-a-struct-timespec64-for-the-in-core-crtime.patch
Patch25: xfsprogs-5.9.0-xfs-drop-the-type-parameter-from-xfs_dquot_verify.patch
Patch26: xfsprogs-5.9.0-xfs-improve-ondisk-dquot-flags-checking.patch
Patch27: xfsprogs-5.10.0-libxfs-create-a-real-struct-timespec64.patch
Patch28: xfsprogs-5.10.0-libxfs-refactor-NSEC_PER_SEC.patch
Patch29: xfsprogs-5.10.0-xfs-store-inode-btree-block-counts-in-AGI-header.patch
Patch30: xfsprogs-5.10.0-xfs-use-the-finobt-block-counts-to-speed-up-mount-ti.patch
Patch31: xfsprogs-5.10.0-xfs-explicitly-define-inode-timestamp-range.patch
Patch32: xfsprogs-5.10.0-xfs-refactor-quota-expiration-timer-modification.patch
Patch33: xfsprogs-5.10.0-xfs-refactor-default-quota-grace-period-setting-code.patch
Patch34: xfsprogs-5.10.0-xfs-refactor-quota-timestamp-coding.patch
Patch35: xfsprogs-5.10.0-xfs-move-xfs_log_dinode_to_disk-to-the-log-recovery-.patch
Patch36: xfsprogs-5.10.0-xfs-redefine-xfs_timestamp_t.patch
Patch37: xfsprogs-5.10.0-xfs-redefine-xfs_ictimestamp_t.patch
Patch38: xfsprogs-5.10.0-xfs-widen-ondisk-inode-timestamps-to-deal-with-y2038.patch
Patch39: xfsprogs-5.10.0-xfs-widen-ondisk-quota-expiration-timestamps-to-hand.patch
Patch40: xfsprogs-5.10.0-xfs_db-support-displaying-inode-btree-block-counts-i.patch
Patch41: xfsprogs-5.10.0-xfs_repair-check-inode-btree-block-counters-in-AGI.patch
Patch42: xfsprogs-5.10.0-xfs_repair-regenerate-inode-btree-block-counters-in-.patch
Patch43: xfsprogs-5.10.0-xfs-enable-new-inode-btree-counters-feature.patch
Patch44: xfsprogs-5.10.0-mkfs-enable-the-inode-btree-counter-feature.patch
Patch45: xfsprogs-5.10.0-libfrog-convert-cvttime-to-return-time64_t.patch
Patch46: xfsprogs-5.10.0-xfs_quota-convert-time_to_string-to-use-time64_t.patch
Patch47: xfsprogs-5.10.0-xfs_db-refactor-timestamp-printing.patch
Patch48: xfsprogs-5.10.0-xfs_db-refactor-quota-timer-printing.patch
Patch49: xfsprogs-5.10.0-libfrog-list-the-bigtime-feature-when-reporting-geom.patch
Patch50: xfsprogs-5.10.0-xfs_db-report-bigtime-format-timestamps.patch
Patch51: xfsprogs-5.10.0-xfs_db-support-printing-time-limits.patch
Patch52: xfsprogs-5.10.0-xfs_quota-support-editing-and-reporting-quotas-with-.patch
Patch53: xfsprogs-5.10.0-xfs_repair-support-bigtime-timestamp-checking.patch
Patch54: xfsprogs-5.10.0-xfs-enable-big-timestamps.patch
Patch55: xfsprogs-5.10.0-mkfs-format-bigtime-filesystems.patch
Patch56: xfsprogs-5.12.0-libxfs-copy-crtime-correctly-now-that-it-s-timespec6.patch
Patch57: xfsprogs-5.13.0-xfs-remove-the-unused-xfs_icdinode_has_bigtime-helpe.patch
Patch58: xfsprogs-5.13.0-xfs-rename-xfs_ictimestamp_t.patch
Patch59: xfsprogs-5.13.0-xfs-rename-struct-xfs_legacy_ictimestamp.patch
Patch60: xfsprogs-5.11.0-mkfs-fix-wrong-inobtcount-usage-error-output.patch
Patch61: xfsprogs-5.12.0-libxfs-expose-inobtcount-in-xfs-geometry.patch
Patch62: xfsprogs-5.12.0-libfrog-report-inobtcount-in-geometry.patch
Patch63: xfsprogs-5.19.0-xfs_repair-ignore-empty-xattr-leaf-blocks.patch
Patch64: xfsprogs-5.19.0-mkfs-terminate-getsubopt-arrays-properly.patch
Patch65: xfsprogs-5.9.0-xfs-ignore-autofs-mount-table-entries.patch
Patch66: xfsprogs-5.10.0-xfs_repair-fix-progress-reporting.patch
Patch67: xfsprogs-rhelonly-mkfs-fix-man-s-default-value-for-sparse-option.patch
%description
A set of commands to use the XFS filesystem, including mkfs.xfs.
@ -53,6 +101,7 @@ of XFS.
%package devel
Summary: XFS filesystem-specific headers
Group: Development/Libraries
Requires: xfsprogs = %{version}-%{release}, libuuid-devel
%description devel
@ -63,28 +112,90 @@ You should install xfsprogs-devel if you want to develop XFS
filesystem-specific programs, If you install xfsprogs-devel, you'll
also want to install xfsprogs.
%package xfs_scrub
Summary: XFS filesystem online scrubbing utilities
Requires: xfsprogs = %{version}-%{release}, python3
%description xfs_scrub
xfs_scrub attempts to check and repair all metadata in a mounted XFS filesystem.
WARNING! This program is EXPERIMENTAL, which means that its behavior and
interface could change at any time!
%prep
xzcat '%{SOURCE0}' | %{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data=-
%autosetup -p1
%setup -q
%patch0 -p1
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
%patch14 -p1
%patch15 -p1
%patch16 -p1
%patch17 -p1
%patch18 -p1
%patch19 -p1
%patch20 -p1
%patch21 -p1
%patch22 -p1
%patch23 -p1
%patch24 -p1
%patch25 -p1
%patch26 -p1
%patch27 -p1
%patch28 -p1
%patch29 -p1
%patch30 -p1
%patch31 -p1
%patch32 -p1
%patch33 -p1
%patch34 -p1
%patch35 -p1
%patch36 -p1
%patch37 -p1
%patch38 -p1
%patch39 -p1
%patch40 -p1
%patch41 -p1
%patch42 -p1
%patch43 -p1
%patch44 -p1
%patch45 -p1
%patch46 -p1
%patch47 -p1
%patch48 -p1
%patch49 -p1
%patch50 -p1
%patch51 -p1
%patch52 -p1
%patch53 -p1
%patch54 -p1
%patch55 -p1
%patch56 -p1
%patch57 -p1
%patch58 -p1
%patch59 -p1
%patch60 -p1
%patch61 -p1
%patch62 -p1
%patch63 -p1
%patch64 -p1
%patch65 -p1
%patch66 -p1
%patch67 -p1
%build
export tagname=CC
%configure \
--enable-editline=yes \
--enable-readline=yes \
--enable-blkid=yes \
--enable-lto=no
--enable-lto=no \
--enable-scrub=no
%make_build
# NOTE scrub manpages manually removed below as well
make V=1 %{?_smp_mflags}
%install
make DIST_ROOT=$RPM_BUILD_ROOT install install-dev \
@ -96,37 +207,21 @@ rm -f $RPM_BUILD_ROOT/{%{_lib}/*.{la,a,so},%{_libdir}/*.{la,a}}
# remove non-versioned docs location
rm -rf $RPM_BUILD_ROOT/%{_datadir}/doc/xfsprogs/
# add backward compatible configure file for mkfs
%global mkfsdir %{_datadir}/xfsprogs/mkfs
install -m 0755 -d %{buildroot}%{mkfsdir}
install -m 0644 %{SOURCE3} %{buildroot}%{mkfsdir}
# Remove scrub manpages
rm -rf $RPM_BUILD_ROOT/%{_mandir}/man8/xfs_scrub*
%find_lang %{name}
%ldconfig_scriptlets
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%files -f %{name}.lang
%doc doc/CHANGES README
%{_libdir}/*.so.*
%dir %{_usr}/%{_lib}/xfsprogs
%{_usr}/%{_lib}/xfsprogs/*
%{_mandir}/man5/*
%{_mandir}/man8/*
%{_sbindir}/*
%{_unitdir}/*
%{mkfsdir}
%exclude %{_sbindir}/xfs_scrub*
%exclude %{_mandir}/man8/xfs_scrub*
%exclude %{_usr}/%{_lib}/xfsprogs/xfs_scrub*
%exclude %{_mandir}/man8/xfs_scrub_all*
%exclude %{_unitdir}/xfs_scrub*
%files xfs_scrub
%{_sbindir}/xfs_scrub*
%{_mandir}/man8/xfs_scrub*
%{_usr}/%{_lib}/xfsprogs/xfs_scrub*
%{_mandir}/man8/xfs_scrub_all*
%{_unitdir}/xfs_scrub*
%files devel
%{_mandir}/man2/*
@ -138,7 +233,6 @@ install -m 0644 %{SOURCE3} %{buildroot}%{mkfsdir}
%{_includedir}/xfs/xfs.h
%{_includedir}/xfs/xfs_arch.h
%{_includedir}/xfs/xfs_fs.h
%{_includedir}/xfs/xfs_fs_compat.h
%{_includedir}/xfs/xfs_types.h
%{_includedir}/xfs/xfs_format.h
%{_includedir}/xfs/xfs_da_format.h
@ -148,148 +242,88 @@ install -m 0644 %{SOURCE3} %{buildroot}%{mkfsdir}
%{_libdir}/*.so
%changelog
* Wed Aug 02 2023 Pavel Reichl <preichl@redhat.com> - 5.19.0-4
- Fix man page, mkfs.xfs(8): Update section on dax+reflink
- compatibility (#2226900)
* Tue Jun 20 2023 Pavel Reichl <preichl@redhat.com> - 5.19.0-3
- Fix man page default for sparse mkfs option (#2216118)
* Fri May 26 2023 Pavel Reichl <preichl@redhat.com> - 5.19.0-2
- Fix xfs corrupted when AG size is a multiple of stripe width
- Related: rhbz#2192982
* Tue Jan 10 2023 Pavel Reichl <preichl@redhat.com> - 5.19.0-1
- New upstream release
- Tolerate tiny (<300MB) filesystems
- Rename xfsprogs-5.12.0-default-bigtime-inobtcnt-on.patch to
xfsprogs-5.19.0-disable-old-kernel-bigtime-inobtcnt-on.patch
and amend it to reflect upstream changes
- Backport all "Fixing" patches relevant to 5.19
Related: rhbz#2142910
* Fri Jan 21 2022 Pavel Reichl <preichl@redhat.com> - 5.14.2-1
- New upstream release
Related: rhbz#2041525
* Wed Dec 01 2021 Pavel Reichl <preichl@redhat.com> - 5.12.0-5
- Add an example of backward compatible conf. file for mkfs
Related: rhbz#2026002
* Wed Jul 26 2023 MSVSphere Packaging Team <packager@msvsphere.ru> - 5.0.0-12
- Rebuilt for MSVSphere 8.8
* Tue Aug 10 2021 Mohan Boddu <mboddu@redhat.com> - 5.12.0-4
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
* Thu Jun 08 2023 Pavel Reichl <preichl@redhat.com> - 5.0.0-12
- Fix xfs_repair progress reporting is not working (#2183398)
- Fix man page default for sparse mkfs option (#2118564)
* Wed Jun 16 2021 Eric Sandeen <sandeen@redhat.com> 5.12.0-3
- Local change to default bigtime & inobtcnt to off under older kernels
* Tue May 02 2023 Pavel Reichl <preichl@redhat.com> - 5.0.0-11
- Fix xfstest fails with error "missing xfsprogs fix patch"(#2161936,#2160746)
- Fix ignore autofs mount table entries (#2182361)
* Thu Jun 03 2021 Eric Sandeen <sandeen@redhat.com> 5.12.0-2
- Turn on bigtime (y2038) and inobtcnt features by default
* Thu Dec 09 2021 Bill O'Donnell <bodonnel@redhat.com> 5.0.0-10
- xfsprogs: enable bigtime and inode btree counter features in RHEL8 (#2024201))
* Thu Jun 03 2021 Eric Sandeen <sandeen@redhat.com> 5.12.0-1
- New upstream release
* Thu Jul 08 2021 Bill O'Donnell <bodonnel@redhat.com> 5.0.0-9
- xfs_quota: state command should report ugp grace time (#1949743)
* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 5.10.0-3
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
* Thu Jan 07 2021 Bill O'Donnell <billodo@redhat.com> 5.0.0-8
- xfs_repair: Use proper min/max values in compute_level_geometry (#1910384)
* Thu Jan 28 2021 Fedora Release Engineering <releng@fedoraproject.org> - 5.10.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
* Mon Dec 14 2020 Bill O'Donnell <billodo@redhat.com> 5.0.0-7
- xfs_quota: document how the default quota is stored (#1850188)
- xfs_db: skip type change if type_f unchanged (#1867474)
* Fri Dec 11 2020 Eric Sandeen <sandeen@redhat.com> 5.10.0-1
- New upstream release
- New mkfs config file feature
- Y2038+ format support
* Wed Dec 09 2020 Bill O'Donnell <billodo@redhat.com> 5.0.0-6
- xfs_repair: improve AG btree ptr validation (libxfs_verify_agbno) (#1887288)
- mkfs.xfs: fix ASSERT on too-small device with stripe geometry (#1887401)
- xfs_repair: fix rebuilding btree block less than minrecs (#1759452)
* Tue Oct 20 2020 Eric Sandeen <sandeen@redhat.com> 5.9.0-1
- New upstream release
* Wed Dec 02 2020 Bill O'Donnell <billodo@redhat.com> 5.0.0-5
- xfs_quota: allow individual timer extension (#1899204)
* Fri Sep 04 2020 Eric Sandeen <sandeen@redhat.com> 5.8.0-1
- New upstream release
* Wed Jun 03 2020 Eric Sandeen <sandeen@redhat.com> 5.0.0-4
- mkfs.xfs: inform user about discard, and make interruptable (#1836414)
* Fri Jul 24 2020 Eric Sandeen <sandeen@redhat.com> 5.7.0-1
- New upstream release
- Replace libreadline with libedit
- Add tarball signature checking
* Mon Apr 20 2020 Eric Sandeen <sandeen@redhat.com> 5.0.0-3
- mkfs.xfs: use faster log zeroing on supported devices (#1755046)
* Tue Jul 14 2020 Tom Stellard <tstellar@redhat.com> - 5.6.0-3
- Use make macros
- https://fedoraproject.org/wiki/Changes/UseMakeBuildInstallMacro
* Sat Dec 14 2019 Eric Sandeen <sandeen@redhat.com> 5.0.0-2
- mkfs.xfs: validate log stripe unit alignment (#1632596)
- xfs_growfs: allow mounted device node as argument (#1765217)
* Sat May 16 2020 Pete Walter <pwalter@fedoraproject.org> - 5.6.0-2
- Rebuild for ICU 67
* Tue May 21 2019 Eric Sandeen <sandeen@redhat.com> 5.0.0-1
- New upstream version (#1712147)
- mkfs.xfs: validate extent size hint parameters (#1683007)
- mkfs.xfs: null-terminate symlinks created via protofile (#1640503)
- xfs_repair: allow '/' in attribute names (#1667354)
- xfs_info: allow device name as parameter (#1679840)
- xfs_quota: fix project inheritance flag handling (#1664105)
- xfs_metadump: handle symlinks correctly (#1693074)
- xfs_db: fix finobt record decoding with sparse inodes (#1690245)
* Tue Apr 14 2020 Eric Sandeen <sandeen@redhat.com> 5.6.0-1
- New upstream release
* Mon Feb 04 2019 Eric Sandeen <sandeen@redhat.com> 4.19.0-2
- xfs_repair: initialize non-leaf finobt blocks with correct magic (#1670153)
* Fri Mar 13 2020 Eric Sandeen <sandeen@redhat.com> 5.5.0-1
- New upstream release
* Tue Nov 27 2018 Eric Sandeen <sandeen@redhat.com> 4.19.0-1
- New upstream release (#1652248)
- Note reflink default in mkfs.xfs manpage (#1641698)
- Fix xfs_db sign extension in agi freecount (#1640090)
- Fix xfs_repair hang on large filesystem (#1630674)
* Fri Jan 31 2020 Eric Sandeen <sandeen@redhat.com> 5.4.0-3
- Fix global redefinitions for gcc10 build
* Tue Sep 25 2018 Eric Sandeen <sandeen@redhat.com> 4.18.0-3
- Remove experimental xfs_scrub utility (#1623301)
* Fri Jan 31 2020 Fedora Release Engineering <releng@fedoraproject.org> - 5.4.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Wed Sep 19 2018 Eric Sandeen <sandeen@redhat.com> 4.18.0-2
- Fix annobin checks (#1630641)
* Fri Jan 17 2020 Eric Sandeen <sandeen@redhat.com> 5.4.0-1
- New upstream release
* Tue Aug 28 2018 Eric Sandeen <sandeen@redhat.com> 4.18.0-1
- New upstream release (#1623695)
* Fri Nov 15 2019 Eric Sandeen <sandeen@redhat.com> 5.3.0-1
- New upstream release
* Mon Aug 13 2018 Eric Sandeen <sandeen@redhat.com> 4.17.0-4
- Disable reflink automatically if crcs are disabled (#1600610)
* Fri Nov 01 2019 Pete Walter <pwalter@fedoraproject.org> - 5.2.1-2
- Rebuild for ICU 65
* Wed Aug 01 2018 Charalampos Stratakis <cstratak@redhat.com> - 4.17.0-3
- Rebuild for platform-python
* Wed Aug 21 2019 Eric Sandeen <sandeen@redhat.com> 5.2.1-1
- New upstream release
* Fri Aug 16 2019 Eric Sandeen <sandeen@redhat.com> 5.2.0-1
- New upstream release
* Sat Jul 27 2019 Fedora Release Engineering <releng@fedoraproject.org> - 5.1.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Fri Jul 19 2019 Eric Sandeen <sandeen@redhat.com> 5.1.0-1
- New upstream release
* Wed May 08 2019 Eric Sandeen <sandeen@redhat.com> 5.0.0-2
- Create new xfs_scrub subpackage (#1666839)
* Fri May 03 2019 Eric Sandeen <sandeen@redhat.com> 5.0.0-1
- New upstream release
* Fri Feb 22 2019 Eric Sandeen <sandeen@redhat.com> 4.20.0-1
- New upstream release
* Sun Feb 17 2019 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 4.19.0-4
- Rebuild for readline 8.0
* Sun Feb 03 2019 Fedora Release Engineering <releng@fedoraproject.org> - 4.19.0-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Wed Jan 23 2019 Pete Walter <pwalter@fedoraproject.org> - 4.19.0-2
- Rebuild for ICU 63
* Tue Nov 13 2018 Eric Sandeen <sandeen@redhat.com> 4.19.0-1
- New upstream release
* Fri Aug 24 2018 Eric Sandeen <sandeen@redhat.com> 4.18.0-1
- New upstream release
* Sat Jul 14 2018 Fedora Release Engineering <releng@fedoraproject.org> - 4.17.0-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
* Tue Jul 10 2018 Pete Walter <pwalter@fedoraproject.org> - 4.17.0-2
- Rebuild for ICU 62
* Thu Jun 28 2018 Eric Sandeen <sandeen@redhat.com> 4.17.0-2
- Default mkfs to reflink enabled (#1494028)
* Thu Jun 28 2018 Eric Sandeen <sandeen@redhat.com> 4.17.0-1
- New upstream release
* Mon Apr 30 2018 Pete Walter <pwalter@fedoraproject.org> - 4.16.0-2
- Rebuild for ICU 61.1
* Thu Apr 26 2018 Eric Sandeen <sandeen@redhat.com> 4.16.0-1
- New upstream release
- Clean up specfile
- Clean up spec file
* Mon Feb 26 2018 Eric Sandeen <sandeen@redhat.com> 4.15.1-1
- New upstream release

Loading…
Cancel
Save