XRootD
XrdFfsPosix.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* XrdFfsPosix.cc C wrapper to some of the Xrootd Posix library functions */
3 /* */
4 /* (c) 2010 by the Board of Trustees of the Leland Stanford, Jr., University */
5 /* All Rights Reserved */
6 /* Author: Wei Yang (SLAC National Accelerator Laboratory, 2009) */
7 /* Contract DE-AC02-76-SFO0515 with the Department of Energy */
8 /* */
9 /* This file is part of the XRootD software suite. */
10 /* */
11 /* XRootD is free software: you can redistribute it and/or modify it under */
12 /* the terms of the GNU Lesser General Public License as published by the */
13 /* Free Software Foundation, either version 3 of the License, or (at your */
14 /* option) any later version. */
15 /* */
16 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19 /* License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24 /* */
25 /* The copyright holder's institutional names and contributor's names may not */
26 /* be used to endorse or promote products derived from this software without */
27 /* specific prior written permission of the institution or contributor. */
28 /******************************************************************************/
29 
30 #define _FILE_OFFSET_BITS 64
31 #include <cerrno>
32 #include <cstdio>
33 #include <cstring>
34 #include <sys/types.h>
35 
36 #if !defined(__solaris__) && !defined(__FreeBSD__)
37 #include <sys/xattr.h>
38 #endif
39 
40 #ifndef ENOATTR
41  #define ENOATTR ENODATA
42 #endif
43 
44 #include <iostream>
45 #include <libgen.h>
46 #include <unistd.h>
47 #include <cstdlib>
48 #include <syslog.h>
49 #include "XrdFfs/XrdFfsPosix.hh"
51 #include "XrdFfs/XrdFfsMisc.hh"
52 #include "XrdFfs/XrdFfsDent.hh"
53 #include "XrdFfs/XrdFfsQueue.hh"
54 
55 #include "XrdCl/XrdClFileSystem.hh"
56 #include "XrdCl/XrdClFile.hh"
57 #include "XrdCl/XrdClURL.hh"
59 
60 #ifdef __cplusplus
61  extern "C" {
62 #endif
63 
64 #define MAXROOTURLLEN 1024 // this is also defined in other files
65 
66 int XrdFfsPosix_stat(const char *path, struct stat *buf)
67 {
68  int rc;
69  errno = 0;
70  rc = XrdPosixXrootd::Stat(path, buf);
71  if (rc == 0 && S_ISBLK(buf->st_mode)) /* If 'buf' come from HPSS, xrootd will return it as a block device! */
72  { /* So we re-mark it to a regular file */
73  buf->st_mode &= 0007777;
74  if ( buf->st_mode & S_IXUSR )
75  buf->st_mode |= 0040000; /* a directory */
76  else
77  buf->st_mode |= 0100000; /* a file */
78  }
79  return rc;
80 }
81 
82 DIR *XrdFfsPosix_opendir(const char *path)
83 {
84  return XrdPosixXrootd::Opendir(path);
85 }
86 
87 struct dirent *XrdFfsPosix_readdir(DIR *dirp)
88 {
89  return XrdPosixXrootd::Readdir(dirp);
90 }
91 
92 int XrdFfsPosix_closedir(DIR *dirp)
93 {
94  return XrdPosixXrootd::Closedir(dirp);
95 }
96 
97 int XrdFfsPosix_mkdir(const char *path, mode_t mode)
98 {
99  XrdCl::URL url(path);
100  std::string dir = url.GetPath();
101  XrdCl::LocationInfo *info = nullptr;
102  XrdCl::FileSystem fs(path);
103 
105  std::unique_ptr<XrdCl::LocationInfo> ptr( info );
106 
107  if( !st.IsOK() )
108  {
109  errno = ENOENT;
110  return -1;
111  }
112  std::string nodeUrl = "root://" + info->At(0).GetAddress() + "/" + dir;
113 
114  return XrdPosixXrootd::Mkdir(nodeUrl.c_str(), mode);
115 }
116 
117 int XrdFfsPosix_rmdir(const char *path)
118 {
119  return XrdPosixXrootd::Rmdir(path);
120 }
121 
122 int XrdFfsPosix_open(const char *path, int oflags, mode_t mode)
123 {
124  return XrdPosixXrootd::Open(path, oflags, mode);
125 }
126 
127 int XrdFfsPosix_close(int fildes)
128 {
129  return XrdPosixXrootd::Close(fildes);
130 }
131 
132 off_t XrdFfsPosix_lseek(int fildes, off_t offset, int whence)
133 {
134  return XrdPosixXrootd::Lseek(fildes, (long long)offset, whence);
135 }
136 
137 ssize_t XrdFfsPosix_read(int fildes, void *buf, size_t nbyte)
138 {
139  return XrdPosixXrootd::Read(fildes, buf, nbyte);
140 }
141 
142 ssize_t XrdFfsPosix_pread(int fildes, void *buf, size_t nbyte, off_t offset)
143 {
144  return XrdPosixXrootd::Pread(fildes, buf, nbyte, (long long)offset);
145 }
146 
147 ssize_t XrdFfsPosix_write(int fildes, const void *buf, size_t nbyte)
148 {
149  return XrdPosixXrootd::Write(fildes, buf, nbyte);
150 }
151 
152 ssize_t XrdFfsPosix_pwrite(int fildes, const void *buf, size_t nbyte, off_t offset)
153 {
154  return XrdPosixXrootd::Pwrite(fildes, buf, nbyte, (long long) offset);
155 }
156 
157 int XrdFfsPosix_fsync(int fildes)
158 {
159  return XrdPosixXrootd::Fsync(fildes);
160 }
161 
162 int XrdFfsPosix_unlink(const char *path)
163 {
164  return XrdPosixXrootd::Unlink(path);
165 }
166 
167 int XrdFfsPosix_rename(const char *oldpath, const char *newpath)
168 {
169  return XrdPosixXrootd::Rename(oldpath, newpath);
170 }
171 
172 int XrdFfsPosix_ftruncate(int fildes, off_t offset)
173 {
174  return XrdPosixXrootd::Ftruncate(fildes, offset);
175 }
176 int XrdFfsPosix_truncate(const char *path, off_t Size)
177 {
178  return XrdPosixXrootd::Truncate(path, Size);
179 }
180 
181 long long XrdFfsPosix_getxattr(const char *path, const char *name, void *value, unsigned long long size)
182 {
183  int bufsize;
184  char xattrbuf[1024], nameclass[128], *namesubclass;
185  char *token, *key, *val;
186  char *lasts_xattr[256], *lasts_tokens[128];
187 
188 /*
189  Xrootd only support two names: xroot.space and xroot.xattr. We add support of xroot.space.*
190  such as xroot.space.oss.cgroup etc.
191  */
192  strncpy(nameclass, name, 11);
193  nameclass[11] = '\0';
194 
195  if (strcmp(nameclass, "xroot.space") != 0 &&
196  strcmp(nameclass, "xroot.xattr") != 0 &&
197  strcmp(nameclass, "xroot.cksum") != 0)
198  {
199  errno = ENOATTR;
200  return -1;
201  }
202 
203  bufsize = XrdPosixXrootd::Getxattr(path, nameclass, xattrbuf, size);
204  if (bufsize == -1) return -1;
205 
206  if (strlen(name) > 11)
207  {
208  strcpy(nameclass, name);
209  namesubclass = &nameclass[12];
210  }
211  else /* xroot.space or xroot.xattr or xroot.cksum is provided. */
212  {
213  strcpy((char*)value, xattrbuf);
214  return bufsize;
215  }
216 
217  token = strtok_r(xattrbuf, "&", lasts_xattr);
218  while ( token != NULL )
219  {
220  key = strtok_r(token, "=", lasts_tokens);
221  val = strtok_r(NULL, "=", lasts_tokens);
222  if (! strcmp(key, namesubclass))
223  {
224  strcpy((char*)value, val);
225  return strlen(val);
226  }
227  token = strtok_r(NULL, "&", lasts_xattr);
228  }
229  errno = ENOATTR;
230  return -1;
231 }
232 
233 /* clean redirector cache */
234 
235 void XrdFfsPosix_clear_from_rdr_cache(const char *rdrurl)
236 {
237  int fd;
238  fd = XrdFfsPosix_open(rdrurl, O_CREAT | O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
239  if ( fd != -1 )
240  {
241  XrdFfsPosix_close(fd);
242  XrdFfsPosix_unlink(rdrurl);
243  }
244 }
245 
246 /* Posix IO functions to operation on all data servers */
247 
249  char *url;
250  int *res;
251  int *err;
252  mode_t st_mode;
253 };
254 
256 {
257  struct XrdFfsPosixX_deleteall_args* args = (struct XrdFfsPosixX_deleteall_args*) x;
258 
259  if (S_ISREG(args->st_mode))
260  *(args->res) = XrdFfsPosix_unlink(args->url);
261  else if (S_ISDIR(args->st_mode))
262  *(args->res) = XrdFfsPosix_rmdir(args->url);
263 
264  *(args->err) = errno;
265  return NULL;
266 }
267 
268 int XrdFfsPosix_deleteall(const char *rdrurl, const char *path, uid_t user_uid, mode_t st_mode)
269 {
270  int i, nurls, res;
271  char *newurls[XrdFfs_MAX_NUM_NODES];
272  int res_i[XrdFfs_MAX_NUM_NODES];
273  int errno_i[XrdFfs_MAX_NUM_NODES];
276 
277  nurls = XrdFfsMisc_get_all_urls(rdrurl, newurls, XrdFfs_MAX_NUM_NODES);
278 
279  for (i = 0; i < nurls; i++)
280  {
281  errno_i[i] = 0;
282  strncat(newurls[i],path, MAXROOTURLLEN - strlen(newurls[i]) -1);
283  XrdFfsMisc_xrd_secsss_editurl(newurls[i], user_uid, 0);
284  args[i].url = newurls[i];
285  args[i].err = &errno_i[i];
286  args[i].res = &res_i[i];
287  args[i].st_mode = st_mode;
288 #ifdef NOUSE_QUEUE
289  XrdFfsPosix_x_deleteall((void*) &args[i]);
290  }
291 #else
292  jobs[i] = XrdFfsQueue_create_task(XrdFfsPosix_x_deleteall, (void**)(&args[i]), 0);
293  }
294  for (i = 0; i < nurls; i++)
295  {
296  XrdFfsQueue_wait_task(jobs[i]);
297  XrdFfsQueue_free_task(jobs[i]);
298  }
299 #endif
300  res = -1;
301  errno = ENOENT;
302  for (i = 0; i < nurls; i++)
303  if (res_i[i] == 0)
304  {
305  res = 0;
306  errno = 0;
307  }
308  else if (res_i[i] != 0 && errno_i[i] == 125) // host is down
309  {
310  res = -1;
311  errno = ETIMEDOUT;
312  syslog(LOG_WARNING, "WARNING: unlink/rmdir(%s) failed (connection timeout)", newurls[i]);
313  break;
314  }
315  else if (res_i[i] != 0 && errno_i[i] != ENOENT)
316  {
317  res = -1;
318  errno = errno_i[i];
319  syslog(LOG_WARNING, "WARNING: unlink/rmdir(%s) failed (errno = %d)", newurls[i], errno);
320  break;
321  }
322 
323  for (i = 0; i < nurls; i++)
324  free(newurls[i]);
325 
326  return res;
327 }
328 
329 int XrdFfsPosix_unlinkall(const char *rdrurl, const char *path, uid_t user_uid)
330 {
331  return XrdFfsPosix_deleteall(rdrurl, path, user_uid, S_IFREG);
332 }
333 
334 int XrdFfsPosix_rmdirall(const char *rdrurl, const char *path, uid_t user_uid)
335 {
336  return XrdFfsPosix_deleteall(rdrurl, path, user_uid, S_IFDIR);
337 }
338 
339 int XrdFfsPosix_renameall(const char *rdrurl, const char *from, const char *to, uid_t user_uid)
340 {
341  int i, nurls, res, rval = 0;
342  struct stat stbuf;
343  char fromurl[1024], tourl[1024], *newurls[XrdFfs_MAX_NUM_NODES];
344 
345  nurls = XrdFfsMisc_get_all_urls(rdrurl, newurls, XrdFfs_MAX_NUM_NODES);
346  if (nurls < 0) rval = -1;
347 
348  for (i = 0; i < nurls; i++)
349  {
350  errno = 0;
351 
352  fromurl[0]='\0';
353  strcat(fromurl, newurls[i]);
354  strncat(fromurl, from, MAXROOTURLLEN - strlen(fromurl) -1);
355  tourl[0]='\0';
356  strcat(tourl, newurls[i]);
357  strncat(tourl, to, MAXROOTURLLEN - strlen(tourl) -1);
358 
359  XrdFfsMisc_xrd_secsss_editurl(fromurl, user_uid, 0);
360  XrdFfsMisc_xrd_secsss_editurl(tourl, user_uid, 0);
361  res = (XrdFfsPosix_stat(fromurl, &stbuf));
362  if (res == 0)
363  {
364 /* XrdFfsPosix_rename doesn't need this protection
365  newdir = strdup(tourl);
366  newdir = dirname(newdir);
367  if (XrdFfsPosix_stat(newdir, &stbuf) == -1)
368  XrdFfsPosix_mkdir(newdir, 0777);
369 
370  free(newdir);
371 */
372  rval = XrdFfsPosix_rename(fromurl, tourl);
373  if (rval == -1)
374  {
375  syslog(LOG_WARNING, "WARNING: rename(%s, %s) failed (errno = %d)", fromurl, tourl, errno);
376  break;
377  }
378 /* if a successful rename is followed by a failed one, will return failure (and leave both old and new files) for
379  user to investigate. */
380  }
381  }
382 
383  for (i = 0; i < nurls; i++)
384  free(newurls[i]);
385 
386  if (rval != 0 && errno == 0) errno = EIO;
387  return rval;
388 }
389 
390 int XrdFfsPosix_truncateall(const char *rdrurl, const char *path, off_t size, uid_t user_uid)
391 {
392  int i, nurls, res, rval = 0;
393  struct stat stbuf;
394  char *newurls[XrdFfs_MAX_NUM_NODES];
395 
396  nurls = XrdFfsMisc_get_all_urls(rdrurl, newurls, XrdFfs_MAX_NUM_NODES);
397  if (nurls < 0) rval = -1;
398 
399  for (i = 0; i < nurls; i++)
400  {
401  errno = 0;
402  strncat(newurls[i],path, MAXROOTURLLEN - strlen(newurls[i]) -1);
403  XrdFfsMisc_xrd_secsss_editurl(newurls[i], user_uid, 0);
404  res = (XrdFfsPosix_stat(newurls[i], &stbuf));
405  if (res == 0)
406  {
407  if (S_ISREG(stbuf.st_mode))
408  rval = XrdFfsPosix_truncate(newurls[i], size);
409  else
410  rval = -1;
411  if (rval == -1)
412  {
413  syslog(LOG_WARNING, "WARNING: (f)truncate(%s) failed (errno = %d)", newurls[i], errno);
414  break;
415  }
416 /* again, it will be messy if a successful truncate is followed by a failed one */
417  }
418  else if (errno != ENOENT)
419  rval = -1;
420  }
421 
422  for (i = 0; i < nurls; i++)
423  free(newurls[i]);
424 
425  if (rval != 0 && errno == 0) errno = EIO;
426  return rval;
427 }
428 
430  char *url;
431  int *res;
432  int *err;
434 };
435 
436 /*
437  It seems xrootd posix return dp[i] != NULL even if the dir
438  doesn't exist on a data server. XrdFfsPosix_readdir() returns
439  NULL in this case.
440 
441  Do we need some protection here? We are not in trouble so far
442  because FUSE's _getattr will test the existence of the dir
443  so we know that at least one data server has the directory.
444  */
446 {
448  DIR *dp;
449  struct dirent *de;
450 
451 /*
452  Xrootd's Opendir will not return NULL even under some error. For instance,
453  when it is supposed to return ENOENT or ENOTDIR, it actually returns
454  EINPROGRESS (115), and DIR *dp will not be NULL.
455  */
456  dp = XrdFfsPosix_opendir(args->url);
457  if ( dp == NULL && errno != 0)
458  {
459  *(args->err) = errno;
460  *(args->res) = -1;
461  if (dp != NULL)
463  }
464  else
465  {
466  *(args->res) = 0;
467  while ((de = XrdFfsPosix_readdir(dp)) != NULL)
468  XrdFfsDent_names_add(args->dents, de->d_name);
470  }
471  return NULL;
472 }
473 
474 int XrdFfsPosix_readdirall(const char *rdrurl, const char *path, char*** direntarray, uid_t user_uid)
475 {
476  int i, j, n, nents, nurls;
477  bool hasDirLock = false;
478 
479  char *newurls[XrdFfs_MAX_NUM_NODES];
480  int res_i[XrdFfs_MAX_NUM_NODES];
481  int errno_i[XrdFfs_MAX_NUM_NODES];
482  struct XrdFfsDentnames *dir_i[XrdFfs_MAX_NUM_NODES] = {0};
485 
486 // for (i = 0; i < XrdFfs_MAX_NUM_NODES; i++)
487 // dir_i[i] = NULL;
488 
489  nurls = XrdFfsMisc_get_all_urls(rdrurl, newurls, XrdFfs_MAX_NUM_NODES);
490 /*
491  If a directory doesn't exist on any data server, it is better to return -1 with errno = ENOENT
492  than to return 0 with errno = 0. But this is difficult because it depends on correct returning
493  from XrdPosixXrootd::Opendir(). This has never been a problem for xrootdfs itself because FUSE
494  does stat() before readdir().
495 
496  In the use case of XrdPssDir::Opendir(), it does expect this function to return -1/ENOENT. In
497  this use case the "rdrurl" contains the complete URL and "path" contains "" so "nurls" will be
498  zero if no data server has the directory. The following is a quick and dirty fix for this use
499  case. The orignal code was: if (nurls < 0) { errno = EACCES; return -1; }
500  */
501  if (nurls <= 0)
502  {
503  errno = (nurls == 0? ENOENT : EACCES);
504  return -1;
505  }
506 
507  for (i = 0; i < nurls; i++)
508  {
509  errno_i[i] = 0;
510  strncat(newurls[i], path, MAXROOTURLLEN - strlen(newurls[i]) -1);
511  XrdFfsMisc_xrd_secsss_editurl(newurls[i], user_uid, 0);
512  args[i].url = newurls[i];
513  args[i].err = &errno_i[i];
514  args[i].res = &res_i[i];
515  args[i].dents = &dir_i[i];
516 #ifdef NOUSE_QUEUE
517  XrdFfsPosix_x_readdirall((void*) &args[i]);
518  }
519 #else
520  jobs[i] = XrdFfsQueue_create_task(XrdFfsPosix_x_readdirall, (void**)(&args[i]), 0);
521  }
522  for (i = 0; i < nurls; i++)
523  {
524  XrdFfsQueue_wait_task(jobs[i]);
525  XrdFfsQueue_free_task(jobs[i]);
526  }
527 #endif
528 
529  errno = 0;
530  for (i = 0; i < nurls; i++)
531  if (res_i[i] != 0 && errno_i[i] == 125) // when host i is down
532  {
533  errno = ETIMEDOUT;
534  syslog(LOG_WARNING, "WARNING: opendir(%s) failed (connection timeout)", newurls[i]);
535  break;
536  }
537 
538  for (i = 0; i < nurls; i++)
539  free(newurls[i]);
540  for (i = 1; i < nurls; i++)
541  XrdFfsDent_names_join(&dir_i[i], &dir_i[i-1]);
542 
543  char *last = NULL, **dnarraytmp;
544 
545  n = XrdFfsDent_names_extract(&dir_i[nurls-1], &dnarraytmp);
546  *direntarray = (char **) malloc(sizeof(char*) * n);
547 
548 // note that dnarraytmp[] may contain redundant entries
549 
550  nents = 0;
551  for (i = 0; i < n; i++)
552  {
553  // put DIR_LOCK to the last one to allow rm -rf to work...
554  //
555  if (! strcmp(dnarraytmp[i], "DIR_LOCK"))
556  {
557  hasDirLock = true;
558  continue;
559  }
560 
561  if (i != 0) // can be used to filter out .lock .fail, etc.
562  {
563  char *tmp, *tmp_dot;
564  tmp = strdup(dnarraytmp[i]);
565  tmp_dot = tmp + strlen(tmp) - 5;
566 
567  if (! strcmp(tmp_dot, ".lock") || ! strcmp(tmp_dot, ".fail")) // filter out .lock/.fail files
568  {
569  for (j = nents - 1; j >= 0; j--)
570  {
571  tmp_dot[0] = '\0';
572  if (! strcmp(tmp, (*direntarray)[j]))
573  {
574  tmp_dot[0] = '.';
575  free(tmp);
576  break;
577  }
578  }
579  if (j >= 0) continue; // found the file cooresponding to the .lock/.fail
580  }
581  free(tmp);
582  }
583 
584  if (last == NULL || strcmp(last, dnarraytmp[i]) != 0)
585  {
586  last = dnarraytmp[i];
587  (*direntarray)[nents++] = strdup(dnarraytmp[i]);
588  }
589  }
590 
591  for (i = 0; i < n; i++) free(dnarraytmp[i]); // do not mergo with the above because the above loop has 'break'.
592  free(dnarraytmp);
593 
594 /* inject this list into dent cache */
595 
596  char *p;
597  p = strdup(path);
598  XrdFfsDent_cache_fill(p, direntarray, nents);
599  free(p);
600 
601  if (hasDirLock) (*direntarray)[nents++] = strdup("DIR_LOCK");
602 
603  return nents;
604 }
605 
606 /*
607  struct XrdFfsPosixX_statvfsall_args, void XrdFfsPosix_x_statvfsall(), int XrdFfsPosiXrdFfsPosix_x_statvfsall() are
608  organized in such a way to allow using pthread if needed
609  */
610 
612  char *url;
613  int *res;
614  int *err;
615  struct statvfs *stbuf;
616  short osscgroup;
617 };
618 
620 {
622  char xattr[256];
623  off_t oss_size;
624  long long llVal;
625 
626  *(args->res) = XrdFfsPosix_getxattr(args->url, "xroot.space.oss.space", xattr, 256);
627  *(args->err) = errno;
628  sscanf((const char*)xattr, "%lld", &llVal);
629  oss_size = static_cast<off_t>(llVal);
630  args->stbuf->f_blocks = (fsblkcnt_t) (oss_size / args->stbuf->f_bsize);
631 // sscanf((const char*)xattr, "%lld", &(args->stbuf->f_blocks));
632  if (*(args->res) == -1)
633  {
634  args->stbuf->f_blocks = 0;
635  args->stbuf->f_bavail = 0;
636  args->stbuf->f_bfree = 0;
637  return NULL;
638  }
639  *(args->res) = XrdFfsPosix_getxattr(args->url, "xroot.space.oss.free", xattr, 256);
640  *(args->err) = errno;
641  sscanf((const char*)xattr, "%lld", &llVal);
642  oss_size = static_cast<off_t>(llVal);
643  args->stbuf->f_bavail = (fsblkcnt_t) (oss_size / args->stbuf->f_bsize);
644 // sscanf((const char*)xattr, "%lld", &(args->stbuf->f_bavail));
645  if (*(args->res) == -1)
646  {
647  args->stbuf->f_blocks = 0;
648  args->stbuf->f_bavail = 0;
649  args->stbuf->f_bfree = 0;
650  return NULL;
651  }
652 
653 /*
654  The relation of the output of df and stbuf->f_blocks, f_bfree and f_bavail is
655  Filesystem Size Used Avail Use% Mounted on
656  f_blocks f_blocks - f_bfree f_bavail
657 
658  In the case of querying without oss.cgroup, f_bfree = f_bavail (e.g. Used is used space by all oss.space)
659  In the case of querying with oss.cgroup, Used is used space by the specified oss.space (oss_size/f_bsize) and
660  therefore f_bfree = f_blocks - oss_size / f_bsize (e.g. Used is oss_size / f_bsize)
661  */
662 
663  if (args->osscgroup != 1)
664  args->stbuf->f_bfree = args->stbuf->f_bavail;
665  else
666  {
667  *(args->res) = XrdFfsPosix_getxattr(args->url, "xroot.space.oss.used", xattr, 256);
668  *(args->err) = errno;
669  sscanf((const char*)xattr, "%lld", &llVal);
670  oss_size = static_cast<off_t>(llVal);
671  args->stbuf->f_bfree = args->stbuf->f_blocks - (fsblkcnt_t) (oss_size / args->stbuf->f_bsize);
672 // args->stbuf->f_bfree = args->stbuf->f_blocks - oss_size;
673  }
674  return NULL;
675 }
676 
677 int XrdFfsPosix_statvfsall(const char *rdrurl, const char *path, struct statvfs *stbuf, uid_t user_uid)
678 {
679  int i, nurls;
680  short osscgroup;
681 
682  char *newurls[XrdFfs_MAX_NUM_NODES];
683  int res_i[XrdFfs_MAX_NUM_NODES];
684  int errno_i[XrdFfs_MAX_NUM_NODES];
685  struct statvfs stbuf_i[XrdFfs_MAX_NUM_NODES];
688 
689  nurls = XrdFfsMisc_get_all_urls(rdrurl, newurls, XrdFfs_MAX_NUM_NODES);
690  if (nurls < 0)
691  {
692  errno = EACCES;
693  return -1;
694  }
695 
696  if (strstr(path, "oss.cgroup") != NULL)
697  osscgroup = 1;
698  else
699  osscgroup = 0;
700  for (i = 0; i < nurls; i++)
701  {
702  strncat(newurls[i], path, MAXROOTURLLEN - strlen(newurls[i]) -1);
703 // XrdFfsMisc_xrd_secsss_editurl(newurls[i], user_uid);
704  args[i].url = newurls[i];
705  args[i].res = &res_i[i];
706  args[i].err = &errno_i[i];
707  stbuf_i[i].f_bsize = stbuf->f_bsize;
708  args[i].stbuf = &(stbuf_i[i]);
709  args[i].osscgroup = osscgroup;
710 #ifdef NOUSE_QUEUE
711  XrdFfsPosix_x_statvfsall((void*) &args[i]);
712  }
713 #else
714  jobs[i] = XrdFfsQueue_create_task(XrdFfsPosix_x_statvfsall, (void**)(&args[i]), 0);
715  }
716  for (i = 0; i < nurls; i++)
717  {
718  XrdFfsQueue_wait_task(jobs[i]);
719  XrdFfsQueue_free_task(jobs[i]);
720  }
721 #endif
722  /*
723  for statfs call, we don't care about return code and errno
724  */
725  stbuf->f_blocks = 0;
726  stbuf->f_bfree = 0;
727  stbuf->f_bavail = 0;
728  for (i = 0; i < nurls; i++)
729  {
730  stbuf->f_blocks += args[i].stbuf->f_blocks;
731  stbuf->f_bavail += args[i].stbuf->f_bavail;
732  stbuf->f_bfree += args[i].stbuf->f_bfree;
733  }
734 
735  for (i = 0; i < nurls; i++)
736  free(newurls[i]);
737 
738  return 0;
739 }
740 
741 /* XrdFfsPosiXrdFfsPosix_x_statall() */
742 
744  char *url;
745  int *res;
746  int *err;
747  struct stat *stbuf;
748 };
749 
750 void* XrdFfsPosix_x_statall(void *x)
751 {
752  struct XrdFfsPosixX_statall_args *args = (struct XrdFfsPosixX_statall_args *)x;
753 
754  *(args->res) = XrdFfsPosix_stat(args->url, args->stbuf);
755  *(args->err) = errno;
756  return (void *)0;
757 }
758 
759 int XrdFfsPosix_statall(const char *rdrurl, const char *path, struct stat *stbuf, uid_t user_uid)
760 {
761  int i, res, nurls;
762 
763  char *newurls[XrdFfs_MAX_NUM_NODES];
764  int res_i[XrdFfs_MAX_NUM_NODES];
765  int errno_i[XrdFfs_MAX_NUM_NODES];
766  struct stat stbuf_i[XrdFfs_MAX_NUM_NODES];
769 
770  char *p1, *p2, *dir, *file, rootpath[MAXROOTURLLEN];
771 
772  rootpath[0] = '\0';
773  strncat(rootpath,rdrurl, MAXROOTURLLEN - strlen(rootpath) -1);
774  strncat(rootpath,path, MAXROOTURLLEN - strlen(rootpath) -1);
775  p1 = strdup(path);
776  p2 = strdup(path);
777  dir = dirname(p1);
778  file = basename(p2);
779 
780 // if task queue is too long, or if the stat() is from an ls -l command, the stat() against redirector
782  {
783  XrdFfsMisc_xrd_secsss_editurl(rootpath, user_uid, 0);
784  res = XrdFfsPosix_stat(rootpath, stbuf);
785 // maybe a data server is down since the last _readdir()? in that case, continue
786 // we also saw a case where redirectors report the file exist but meta redirector report
787 // that the file doesn't exist, and we need to continue at here
788  if (res == 0)
789  {
790  free(p1);
791  free(p2);
792  return 0;
793  }
794  }
795  free(p1);
796  free(p2);
797 
798  nurls = XrdFfsMisc_get_all_urls(rdrurl, newurls, XrdFfs_MAX_NUM_NODES);
799 
800  for (i = 0; i < nurls; i++)
801  {
802  strncat(newurls[i], path, MAXROOTURLLEN - strlen(path) -1);
803  XrdFfsMisc_xrd_secsss_editurl(newurls[i], user_uid, 0);
804  args[i].url = newurls[i];
805  args[i].res = &res_i[i];
806  args[i].err = &errno_i[i];
807  args[i].stbuf = &(stbuf_i[i]);
808 #ifdef NOUSE_QUEUE
809  XrdFfsPosix_x_statall((void*) &args[i]);
810  }
811 #else
812  jobs[i] = XrdFfsQueue_create_task(XrdFfsPosix_x_statall, (void**)(&args[i]), 0);
813  }
814  for (i = 0; i < nurls; i++)
815  {
816  XrdFfsQueue_wait_task(jobs[i]);
817  XrdFfsQueue_free_task(jobs[i]);
818  }
819 #endif
820  res = -1;
821  errno = ENOENT;
822  for (i = 0; i < nurls; i++)
823  {
824  time_t max_mtime = 0;
825  if (res_i[i] == 0)
826  {
827  if (stbuf_i[i].st_mtime <= max_mtime) continue;
828  res = 0;
829  errno = 0;
830  memcpy((void*)stbuf, (void*)(&stbuf_i[i]), sizeof(struct stat));
831  break;
832  }
833  else if (res_i[i] != 0 && errno_i[i] == 125) // when host i is down
834  {
835  res = -1;
836  errno = ETIMEDOUT;
837  syslog(LOG_WARNING, "WARNING: stat(%s) failed (connection timeout)", newurls[i]);
838  }
839  }
840 
841  for (i = 0; i < nurls; i++)
842  free(newurls[i]);
843 
844  return res;
845 }
846 
847 #ifdef __cplusplus
848  }
849 #endif
int XrdFfsDent_cache_search(char *dname, char *dentname)
Definition: XrdFfsDent.cc:247
void XrdFfsDent_names_join(struct XrdFfsDentnames **p, struct XrdFfsDentnames **n)
Definition: XrdFfsDent.cc:78
void XrdFfsDent_names_add(struct XrdFfsDentnames **p, char *name)
Definition: XrdFfsDent.cc:56
int XrdFfsDent_cache_fill(char *dname, char ***dnarray, int nents)
Definition: XrdFfsDent.cc:219
int XrdFfsDent_names_extract(struct XrdFfsDentnames **p, char ***dnarray)
Definition: XrdFfsDent.cc:100
int XrdFfsMisc_get_number_of_data_servers()
Definition: XrdFfsMisc.cc:132
void XrdFfsMisc_xrd_secsss_editurl(char *url, uid_t user_uid, int *id)
Definition: XrdFfsMisc.cc:424
int XrdFfsMisc_get_all_urls(const char *oldurl, char **newurls, const int nnodes)
Definition: XrdFfsMisc.cc:172
#define XrdFfs_MAX_NUM_NODES
Definition: XrdFfsMisc.hh:34
int XrdFfsPosix_ftruncate(int fildes, off_t offset)
Definition: XrdFfsPosix.cc:172
int XrdFfsPosix_rmdirall(const char *rdrurl, const char *path, uid_t user_uid)
Definition: XrdFfsPosix.cc:334
int XrdFfsPosix_rename(const char *oldpath, const char *newpath)
Definition: XrdFfsPosix.cc:167
DIR * XrdFfsPosix_opendir(const char *path)
Definition: XrdFfsPosix.cc:82
int XrdFfsPosix_open(const char *path, int oflags, mode_t mode)
Definition: XrdFfsPosix.cc:122
int XrdFfsPosix_fsync(int fildes)
Definition: XrdFfsPosix.cc:157
int XrdFfsPosix_unlink(const char *path)
Definition: XrdFfsPosix.cc:162
void * XrdFfsPosix_x_statvfsall(void *x)
Definition: XrdFfsPosix.cc:619
int XrdFfsPosix_renameall(const char *rdrurl, const char *from, const char *to, uid_t user_uid)
Definition: XrdFfsPosix.cc:339
void XrdFfsPosix_clear_from_rdr_cache(const char *rdrurl)
Definition: XrdFfsPosix.cc:235
int XrdFfsPosix_truncate(const char *path, off_t Size)
Definition: XrdFfsPosix.cc:176
ssize_t XrdFfsPosix_pwrite(int fildes, const void *buf, size_t nbyte, off_t offset)
Definition: XrdFfsPosix.cc:152
#define ENOATTR
Definition: XrdFfsPosix.cc:41
void * XrdFfsPosix_x_readdirall(void *x)
Definition: XrdFfsPosix.cc:445
int XrdFfsPosix_truncateall(const char *rdrurl, const char *path, off_t size, uid_t user_uid)
Definition: XrdFfsPosix.cc:390
ssize_t XrdFfsPosix_read(int fildes, void *buf, size_t nbyte)
Definition: XrdFfsPosix.cc:137
int XrdFfsPosix_closedir(DIR *dirp)
Definition: XrdFfsPosix.cc:92
int XrdFfsPosix_rmdir(const char *path)
Definition: XrdFfsPosix.cc:117
struct dirent * XrdFfsPosix_readdir(DIR *dirp)
Definition: XrdFfsPosix.cc:87
void * XrdFfsPosix_x_statall(void *x)
Definition: XrdFfsPosix.cc:750
off_t XrdFfsPosix_lseek(int fildes, off_t offset, int whence)
Definition: XrdFfsPosix.cc:132
int XrdFfsPosix_close(int fildes)
Definition: XrdFfsPosix.cc:127
ssize_t XrdFfsPosix_pread(int fildes, void *buf, size_t nbyte, off_t offset)
Definition: XrdFfsPosix.cc:142
int XrdFfsPosix_statvfsall(const char *rdrurl, const char *path, struct statvfs *stbuf, uid_t user_uid)
Definition: XrdFfsPosix.cc:677
int XrdFfsPosix_deleteall(const char *rdrurl, const char *path, uid_t user_uid, mode_t st_mode)
Definition: XrdFfsPosix.cc:268
struct XrdFfsDentnames ** dents
Definition: XrdFfsPosix.cc:433
int XrdFfsPosix_readdirall(const char *rdrurl, const char *path, char ***direntarray, uid_t user_uid)
Definition: XrdFfsPosix.cc:474
int XrdFfsPosix_statall(const char *rdrurl, const char *path, struct stat *stbuf, uid_t user_uid)
Definition: XrdFfsPosix.cc:759
int XrdFfsPosix_unlinkall(const char *rdrurl, const char *path, uid_t user_uid)
Definition: XrdFfsPosix.cc:329
int XrdFfsPosix_stat(const char *path, struct stat *buf)
Definition: XrdFfsPosix.cc:66
int XrdFfsPosix_mkdir(const char *path, mode_t mode)
Definition: XrdFfsPosix.cc:97
void * XrdFfsPosix_x_deleteall(void *x)
Definition: XrdFfsPosix.cc:255
#define MAXROOTURLLEN
Definition: XrdFfsPosix.cc:64
long long XrdFfsPosix_getxattr(const char *path, const char *name, void *value, unsigned long long size)
Definition: XrdFfsPosix.cc:181
ssize_t XrdFfsPosix_write(int fildes, const void *buf, size_t nbyte)
Definition: XrdFfsPosix.cc:147
void XrdFfsQueue_free_task(struct XrdFfsQueueTasks *task)
Definition: XrdFfsQueue.cc:111
struct XrdFfsQueueTasks * XrdFfsQueue_create_task(void *(*func)(void *), void **args, short initstat)
Definition: XrdFfsQueue.cc:97
unsigned int XrdFfsQueue_count_tasks()
Definition: XrdFfsQueue.cc:131
void XrdFfsQueue_wait_task(struct XrdFfsQueueTasks *task)
Definition: XrdFfsQueue.cc:123
int stat(const char *path, struct stat *buf)
int statvfs(const char *path, struct statvfs *buf)
Send file/filesystem queries to an XRootD cluster.
XRootDStatus DeepLocate(const std::string &path, OpenFlags::Flags flags, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
const std::string & GetAddress() const
Get address.
Path location info.
Location & At(uint32_t index)
Get the location at index.
URL representation.
Definition: XrdClURL.hh:31
const std::string & GetPath() const
Get the path.
Definition: XrdClURL.hh:217
static ssize_t Pread(int fildes, void *buf, size_t nbyte, off_t offset)
Pread() conforms to POSIX.1-2001 pread()
static int Closedir(DIR *dirp)
Closedir() conforms to POSIX.1-2001 closedir()
static int Stat(const char *path, struct stat *buf)
Stat() conforms to POSIX.1-2001 stat()
static int Mkdir(const char *path, mode_t mode)
Mkdir() conforms to POSIX.1-2001 mkdir()
static int Unlink(const char *path)
Unlink() conforms to POSIX.1-2001 unlink()
static int Rmdir(const char *path)
Rmdir() conforms to POSIX.1-2001 rmdir()
static int Rename(const char *oldpath, const char *newpath)
Rename() conforms to POSIX.1-2001 rename()
static int Close(int fildes)
Close() conforms to POSIX.1-2001 close()
static ssize_t Write(int fildes, const void *buf, size_t nbyte)
Write() conforms to POSIX.1-2001 write()
static struct dirent * Readdir(DIR *dirp)
static int Ftruncate(int fildes, off_t offset)
Ftruncate() conforms to POSIX.1-2001 ftruncate()
static DIR * Opendir(const char *path)
Opendir() conforms to POSIX.1-2001 opendir()
static int Fsync(int fildes)
Fsync() conforms to POSIX.1-2001 fsync()
static long long Getxattr(const char *path, const char *name, void *value, unsigned long long size)
static ssize_t Read(int fildes, void *buf, size_t nbyte)
Read() conforms to POSIX.1-2001 read()
static off_t Lseek(int fildes, off_t offset, int whence)
Lseek() conforms to POSIX.1-2001 lseek()
static int Open(const char *path, int oflag, mode_t mode=0, XrdPosixCallBack *cbP=0)
static ssize_t Pwrite(int fildes, const void *buf, size_t nbyte, off_t offset)
Pwrite() conforms to POSIX.1-2001 pwrite()
static int Truncate(const char *path, off_t offset)
Telldir() conforms to POSIX.1-2001 telldir()
static INT to(const char *buffer)
Definition: XrdZipUtils.hh:91
bool IsOK() const
We're fine.
Definition: XrdClStatus.hh:124