XRootD
Loading...
Searching...
No Matches
XrdOssArcFSMon.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d O s s A r c F S M o n . c c */
4/* */
5/* (c) 2024 by the Board of Trustees of the Leland Stanford, Jr., University */
6/* All Rights Reserved */
7/* Produced by Andrew Hanushevsky for Stanford University under contract */
8/* DE-AC02-76-SFO0515 with the Department of Energy */
9/* */
10/* This file is part of the XRootD software suite. */
11/* */
12/* XRootD is free software: you can redistribute it and/or modify it under */
13/* the terms of the GNU Lesser General Public License as published by the */
14/* Free Software Foundation, either version 3 of the License, or (at your */
15/* option) any later version. */
16/* */
17/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
18/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
19/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
20/* License for more details. */
21/* */
22/* You should have received a copy of the GNU Lesser General Public License */
23/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
24/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
25/* */
26/* The copyright holder's institutional names and contributor's names may not */
27/* be used to endorse or promote products derived from this software without */
28/* specific prior written permission of the institution or contributor. */
29/******************************************************************************/
30
31/******************************************************************************/
32/* P l a t f o r m D e p e n d e n t D e f i n i t i o n s */
33/******************************************************************************/
34
35// This should really be part of XrdSysPlatform.hh (see XrdOssCache.hh).
36//
37#if defined(__linux__) || defined(__GNU__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
38#include <sys/vfs.h>
39#define FS_Stat(a,b) statfs(a,b)
40#define STATFS_t struct statfs
41#define FS_BLKSZ f_bsize
42#define FS_FFREE f_ffree
43#endif
44#if defined(__APPLE__) || defined(__FreeBSD__)
45#include <sys/param.h>
46#include <sys/mount.h>
47#define STATFS_t struct statfs
48#define FS_Stat(a,b) statfs(a,b)
49#define FS_BLKSZ f_bsize
50#define FS_FFREE f_ffree
51#endif
52
53/******************************************************************************/
54/* I n c l u d e s */
55/******************************************************************************/
56
57#include <stdio.h>
58
59#include "Xrd/XrdScheduler.hh"
60
64
65#include "XrdOuc/XrdOucUtils.hh"
66
67#include "XrdSys/XrdSysError.hh"
68
69/******************************************************************************/
70/* G l o b a l O b j e c t s */
71/******************************************************************************/
72
73namespace XrdOssArcGlobals
74{
75extern XrdScheduler* schedP;
76
77extern XrdSysError Elog;
78
79extern XrdSysTrace ArcTrace;
80}
81using namespace XrdOssArcGlobals;
82
83/******************************************************************************/
84/* L o c a l O b j e c t s & D e f i n i t i o n s */
85/******************************************************************************/
86
87#define HSZ(x,y) XrdOucUtils::HSize(x, y, (int)sizeof(y))
88
89/******************************************************************************/
90/* D o I t */
91/******************************************************************************/
92
94{
95 TraceInfo("FSMon", 0);
96 XrdSysMutexHelper rmHelp(rmMutex);
97 size_t tmpSize, tmpFree;
98
99// Update file system statistics
100//
101 if (!(tmpSize = getFSpace(tmpFree, fs_Path)))
102 Elog.Emsg("FSMon", errno, "filesystem info for", fs_Path);
103 else {fs_Size = tmpSize;
104 fs_Free = tmpFree;
105 fs_MaxUsed = fs_Size - fs_MinFree;
106 fs_inUse = fs_Size - fs_Free;
107 }
108
109// Perform some debugging
110//
111 DEBUG("FS info: Size="<<fs_Size<<" Free="<<fs_Free<<" Used="<<fs_inUse<<
112 " Commit="<<fs_inBkp<<" Avail="<<
113 (fs_Free <= fs_inBkp ? 0 : fs_Free - fs_inBkp));
114
115// reschedule ourselves
116//
117 schedP->Schedule(this, time(0)+fs_Updt);
118}
119
120/******************************************************************************/
121/* Private: g e t F S p a c e */
122/******************************************************************************/
123
124size_t XrdOssArcFSMon::getFSpace(size_t &Free, const char *path)
125{
126 STATFS_t fsbuff;
127
128// Get space information for the requested filesystem
129//
130 if (FS_Stat(path, &fsbuff)) return 0;
131 Free = static_cast<size_t>(fsbuff.f_bavail)
132 * static_cast<size_t>(fsbuff.FS_BLKSZ);
133 return static_cast<size_t>(fsbuff.f_blocks)
134 * static_cast<size_t>(fsbuff.FS_BLKSZ);
135}
136
137/******************************************************************************/
138/* I n i t */
139/******************************************************************************/
140
141bool XrdOssArcFSMon::Init(const char* path, long long fVal, int fsupdt)
142{
143 char buff[1024], HSb1[16], HSb2[16], HSb3[16];
144
145// Save the update frequescy
146//
147 fs_Updt = fsupdt;
148
149// The first step is to get the relevant filesystem statistics we need
150//
151 if (!(fs_Size = getFSpace(fs_Free, path)))
152 {Elog.Emsg("FSMon", errno, "filesystem info for", path);
153 return false;
154 }
155
156// Calculate the minimum free space allowed (if fval < 0 -> percentage)
157//
158 if (fVal < 0) fs_MinFree = fs_Size*(static_cast<size_t>(-fVal))/100;
159 else {fs_MinFree = static_cast<size_t>(fVal);
160 if (fs_MinFree >= fs_Size)
161 {snprintf(buff, sizeof(buff), "Minimum free space allowed (%s) "
162 ">= size of filesystem (%s) at",
163 HSZ(fs_MinFree, HSb1), HSZ(fs_Size, HSb2));
164 Elog.Emsg("FSMon", buff, path);
165 return false;
166 }
167 }
168
169// Calculate the maximum amount of usage and set the filesystem path
170//
171 fs_MaxUsed = fs_Size - fs_MinFree;
172 fs_inUse = fs_Size - fs_Free;
173 fs_Path = path;
174
175// Check if we don't have enough free space at startup time
176//
177 if (fs_Free < fs_MinFree)
178 {snprintf(buff, sizeof(buff), "Filesystme free space (%s) < minimum "
179 "allowed (%s) at ",
180 HSZ(fs_Free, HSb1), HSZ(fs_MinFree, HSb2));
181 Elog.Say("Config warning: ", buff, path);
182 } else {
183 snprintf(buff, sizeof(buff), "Filesystme free space: %s; "
184 "minimum allowed: %s; remaining: %s at ",
185 HSZ(fs_Free, HSb1), HSZ(fs_MinFree,HSb2),
186 HSZ(fs_Free-fs_MinFree, HSb3));
187 Elog.Say("Config outcome: ", buff, path);
188 }
189
190// Start automatic filesystem updates
191//
192 schedP->Schedule(this, time(0)+fs_Updt);
193
194// All done
195//
196 return true;
197}
198
199/******************************************************************************/
200/* P e r m i t */
201/******************************************************************************/
202
204{
205// Check if we can permit this request or the caller will need to wait
206//
207 rmMutex.Lock();
208 if ((fs_inUse + fs_inBkp + btP->numBytes) <= fs_MaxUsed)
209 {fs_inBkp += btP->numBytes;
210 btP->relSpace = true;
211 rmMutex.UnLock();
212 return true;
213 }
214
215// There is not enough space to permit the request. Place it on the re-drive
216// queue and tell the call to wait.
217//
218 btWaitQ.push_back(btP);
219 rmMutex.UnLock();
220 return false;
221}
222
223/******************************************************************************/
224/* R e l e a s e */
225/******************************************************************************/
226
227void XrdOssArcFSMon::Release(size_t bytes)
228{
229 XrdSysMutexHelper mHelp(rmMutex);
230 size_t tmpSize, tmpFree;
231 int n;
232
233// Release the number of bytes previously reserved
234//
235 if (bytes >= fs_inBkp) fs_inBkp = 0;
236 else fs_inBkp -= bytes;
237
238// Update file system statistics
239//
240 if (!(tmpSize = getFSpace(tmpFree, fs_Path)))
241 Elog.Emsg("FSMon", errno, "filesystem info for", fs_Path);
242 else {fs_Size = tmpSize;
243 fs_Free = tmpFree;
244 fs_MaxUsed = fs_Size - fs_MinFree;
245 fs_inUse = fs_Size - fs_Free;
246 }
247
248// If a backup is waiting for space, see if it can proceed
249//
250 size_t nTot = 0;
251 while(!btWaitQ.empty())
252 {XrdOssArcBackupTask* btP = btWaitQ.front();
253 if ((fs_inUse + fs_inBkp + btP->numBytes + nTot) <= fs_MaxUsed)
254 {nTot += btP->numBytes;
255 btP->btSem.Post();
256 btWaitQ.pop_front();
257 } else break;
258 }
259
260// Issue message if there are still queued backups
261//
262 if ((n = btWaitQ.size()))
263 {char buff[1024], HSb1[16], HSb2[16];
264 size_t free = (fs_Free <= fs_inBkp ? 0 : fs_Free - fs_inBkp);
265 snprintf(buff, sizeof(buff), "Insufficient free space (%s < %s); "
266 "%d backup(s) still pending!",
267 HSZ(free, HSb1), HSZ(fs_MinFree, HSb2), n);
268 Elog.Emsg("FSMon", buff);
269 }
270}
#define DEBUG(x)
#define HSZ(x, y)
#define TraceInfo(x, y)
XrdSysSemaphore btSem
void Release(size_t bytes)
bool Permit(XrdOssArcBackupTask *btP)
void DoIt() override
bool Init(const char *path, long long fVal, int fsupdt)
XrdSysTrace ArcTrace("OssArc")
XrdScheduler * schedP
Definition XrdOssArc.cc:66
XrdSysError Elog(0, "OssArc_")