XRootD
XrdOssCreate.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d O s s C r e a t e . c c */
4 /* */
5 /* (c) 2003 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 /* i n c l u d e s */
33 /******************************************************************************/
34 
35 #include <unistd.h>
36 #include <cerrno>
37 #include <fcntl.h>
38 #include <strings.h>
39 #include <cstdio>
40 #include <utime.h>
41 #include <sys/file.h>
42 #include <sys/stat.h>
43 #include <sys/types.h>
44 #include <sys/param.h>
45 #if defined(__solaris__) || defined(AIX)
46 #include <sys/vnode.h>
47 #endif
48 
49 #include "XrdFrc/XrdFrcXAttr.hh"
50 #include "XrdOss/XrdOssApi.hh"
51 #include "XrdOss/XrdOssCache.hh"
52 #include "XrdOss/XrdOssConfig.hh"
53 #include "XrdOss/XrdOssCopy.hh"
54 #include "XrdOss/XrdOssError.hh"
55 #include "XrdOss/XrdOssOpaque.hh"
56 #include "XrdOss/XrdOssPath.hh"
57 #include "XrdOss/XrdOssSpace.hh"
58 #include "XrdOss/XrdOssTrace.hh"
59 #include "XrdOuc/XrdOuca2x.hh"
60 #include "XrdOuc/XrdOucEnv.hh"
61 #include "XrdOuc/XrdOucExport.hh"
62 #include "XrdOuc/XrdOucUtils.hh"
63 #include "XrdOuc/XrdOucXAttr.hh"
64 #include "XrdSys/XrdSysError.hh"
65 #include "XrdSys/XrdSysHeaders.hh"
66 #include "XrdSys/XrdSysPlatform.hh"
67 
68 /******************************************************************************/
69 /* E r r o r R o u t i n g O b j e c t */
70 /******************************************************************************/
71 
72 extern XrdSysError OssEroute;
73 
74 extern XrdSysTrace OssTrace;
75 
76 extern XrdOssSys *XrdOssSS;
77 
78 /******************************************************************************/
79 /* L o c a l C l a s s e s */
80 /******************************************************************************/
81 
83  {public:
84  unsigned long long pOpts;
85  const char *Path;
86  const char *LFN;
87  mode_t Amode;
88  int cOpts;
89  XrdOssCreateInfo(const char *path, const char *lfn, mode_t amode, int opts)
90  : Path(path), LFN(lfn), Amode(amode), cOpts(opts) {}
92  };
93 
94 /******************************************************************************/
95 /* c r e a t e */
96 /******************************************************************************/
97 
98 /*
99  Function: Create a file named `path' with 'file_mode' access mode bits set.
100 
101  Input: path - The fully qualified name of the file to create.
102  access_mode - The Posix access mode bits to be assigned to the file.
103  These bits correspond to the standard Unix permission
104  bits (e.g., 744 == "rwxr--r--").
105  env - Environmental information.
106  opts - Set as follows:
107  XRDOSS_mkpath - create dir path if it does not exist.
108  XRDOSS_new - the file must not already exist.
109  x00000000 - x are standard open flags (<<8)
110 
111  Output: Returns XRDOSS_OK upon success; (-errno) otherwise.
112 */
113 int XrdOssSys::Create(const char *tident, const char *path, mode_t access_mode,
114  XrdOucEnv &env, int Opts)
115 {
116  EPNAME("Create")
117  const int AMode = S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH; // 775
118  char local_path[MAXPATHLEN+1], *p, pc;
119  local_path[0] = '\0';
120  unsigned long long remotefs;
121  int isLink = 0, Missing = 1, retc = 0, datfd;
122  XrdOssCreateInfo crInfo(local_path, path, access_mode, Opts);
123  struct stat buf;
124 
125 // Get options associated with this path and check if it's r/w
126 //
127  remotefs = Check_RO(Create, crInfo.pOpts, path, "create");
128 
129 // Generate the actual local path for this file.
130 //
131  if ((retc = GenLocalPath(path, local_path))) return retc;
132 
133 // Determine the state of the file. We will need this information as we go on.
134 //
135  if ((Missing = lstat(local_path, &buf))) retc = errno;
136  else {if ((isLink = ((buf.st_mode & S_IFMT) == S_IFLNK)))
137  {if (stat(local_path, &buf))
138  {if (errno != ENOENT) return -errno;
139  OssEroute.Emsg("Create","removing dangling link",local_path);
140  if (unlink(local_path)) retc = errno;
141  Missing = 1; isLink = 0;
142  }
143  }
144  }
145  if (retc && retc != ENOENT) return -retc;
146 
147 // Check if we are requested to create the file at a specific location.
148 // If so set the cgroup to match the location we have been passed in the env.
149  bool forcecg = false;
150  if (Opts & XRDOSS_coloc)
151  {if (crInfo.pOpts & XRDEXP_NOFICL) return -EPERM;
152  const char *colocenv = env.Get("oss.coloc");
153  std::string coloc(colocenv ? colocenv : "");
154  coloc = XrdOucUtils::UrlDecode(coloc);
155  char coloc_local[MAXPATHLEN+1];
156  coloc_local[0] = '\0';
157  if ((retc = GenLocalPath(coloc.c_str(), coloc_local))) return retc;
158  XrdOssCache_FS *cp = XrdOssCache::Find(coloc_local);
159  std::string gpath;
160  if (cp) gpath = cp->group + std::string(":") + cp->path;
161  env.Put(OSS_CGROUP, gpath.c_str());
162  forcecg = true;
163  }
164 
165 // At this point, creation requests may need to be routed via the stagecmd.
166 // This is done if the file/link do not exist. Otherwise, we drop through.
167 //
168  if (StageCreate && Missing)
169  return XrdOssSS->Stage(tident, path, env, Opts>>8,
170  access_mode, crInfo.pOpts);
171 
172 // The file must not exist if it's declared "new". Otherwise, reuse the space.
173 // SetFattr() alaways closes the provided file descriptor!
174 //
175  if (!Missing)
176  {if (Opts & XRDOSS_new) return -EEXIST;
177  if ((buf.st_mode & S_IFMT) == S_IFDIR) return -EISDIR;
178  do {datfd = open(local_path, Opts>>8, access_mode);}
179  while(datfd < 0 && errno == EINTR);
180  if (datfd < 0) return -errno;
181  if ((retc = SetFattr(crInfo, datfd, buf.st_mtime))) return retc;
182  if (Opts>>8 & O_TRUNC && buf.st_size)
183  {off_t theSize = buf.st_size;
184  if (isLink) {buf.st_mode = (buf.st_mode & ~S_IFMT) | S_IFLNK;
185  XrdOssCache::Adjust(local_path, -theSize, &buf);
186  }
187  }
188  return 0;
189  }
190 
191 // If the path is to be created, make sure the path exists at this point
192 //
193  if ((Opts & XRDOSS_mkpath) && (p = rindex(local_path, '/')))
194  {p++; pc = *p; *p = '\0';
195  XrdOucUtils::makePath(local_path, AMode);
196  *p = pc;
197  }
198 
199 // If this is a staging filesystem then we have lots more work to do.
200 //
201  if (remotefs)
202  {char remote_path[MAXPATHLEN+1];
203 
204  // Generate the remote path for this file
205  //
206  if ((retc = GenRemotePath(path,remote_path))) return retc;
207 
208  // Create the file in remote system unless not wanted so
209  //
210  if (crInfo.pOpts & XRDEXP_RCREATE)
211  {if ((retc = MSS_Create(remote_path, access_mode, env)) < 0)
212  {DEBUG("rc" <<retc <<" mode=" <<Xrd::oct1 <<access_mode
213  <<" remote path=" <<remote_path);
214  return retc;
215  }
216  } else if (!(crInfo.pOpts & XRDEXP_NOCHECK))
217  {if (!(retc = MSS_Stat(remote_path))) return -EEXIST;
218  else if (retc != -ENOENT) return retc;
219  }
220  }
221 
222 // Created file in the extended cache or the local name space
223 //
224  if (XrdOssCache::fsfirst && !(crInfo.pOpts & XRDEXP_INPLACE))
225  retc = Alloc_Cache(crInfo, env, forcecg);
226  else retc = Alloc_Local(crInfo, env);
227 
228 // If successful then check if xattrs were actually set
229 //
230  if (retc == XrdOssOK && crInfo.cOpts & XRDOSS_setnoxa)
231  {XrdOucPList *plP = RPList.About(path);
232  if (plP) plP->Set(plP->Flag() | XRDEXP_NOXATTR);
233  }
234 
235 // All done.
236 //
237  return retc;
238 }
239 
240 /******************************************************************************/
241 /* P r i v a t e M e t h o d s */
242 /******************************************************************************/
243 /******************************************************************************/
244 /* A l l o c _ C a c h e */
245 /******************************************************************************/
246 
247 int XrdOssSys::Alloc_Cache(XrdOssCreateInfo &crInfo, XrdOucEnv &env, bool forcecg)
248 {
249  EPNAME("Alloc_Cache")
250  int datfd, rc;
251  const char *spName;
252  char pbuff[MAXPATHLEN+1], cgbuff[XrdOssSpace::minSNbsz], *tmp;
253  XrdOssCache::allocInfo aInfo(crInfo.Path, pbuff, sizeof(pbuff));
254 
255 // Grab the suggested size from the environment
256 //
257  if ((tmp = env.Get(OSS_ASIZE))
258  && XrdOuca2x::a2sz(OssEroute,"invalid asize",tmp,&aInfo.cgSize,0))
259  return -XRDOSS_E8018;
260 
261 // Determine the space we should use for this allocation
262 //
263  spName = env.Get(OSS_CGROUP);
264  if (!spName || (!forcecg && SPList.NotEmpty() && SPList.Default() == spAssign))
265  {XrdOucPList *pl = SPList.About(crInfo.LFN);
266  if (pl && (!spName || pl->Attr() == spAssign)) spName = pl->Name();
267  }
268 
269 // Get the correct cache group and partition path
270 //
271  if ((aInfo.cgPath=XrdOssCache::Parse(spName,cgbuff,sizeof(cgbuff))))
272  aInfo.cgPlen = strlen(aInfo.cgPath);
273 
274 // Allocate space in the cache.
275 //
276  aInfo.cgName = cgbuff;
277  aInfo.aMode = crInfo.Amode;
278  if ((datfd = XrdOssCache::Alloc(aInfo)) < 0) return datfd;
279 
280 // Set the pfn as the extended attribute if we are in new mode
281 //
282  if (!(crInfo.pOpts & XRDEXP_NOXATTR)
283  && (rc = XrdSysFAttr::Xat->Set(XrdFrcXAttrPfn::Name(), crInfo.Path,
284  strlen(crInfo.Path)+1, pbuff, datfd)))
285  {close(datfd); return rc;}
286 
287 // Set extended attributes for this newly created file if allowed to do so.
288 // SetFattr() alaways closes the provided file descriptor!
289 //
290  if ((rc = SetFattr(crInfo, datfd, 1))) return rc;
291 
292 // Now create a symbolic link to the target
293 //
294  if ((symlink(pbuff, crInfo.Path) && errno != EEXIST)
295  || unlink(crInfo.Path) || symlink(pbuff, crInfo.Path))
296  {rc = -errno; unlink(pbuff);}
297 
298 // All done
299 //
300  DEBUG(aInfo.cgName <<" cache for " <<pbuff);
301  return rc;
302 }
303 
304 /******************************************************************************/
305 /* A l l o c _ L o c a l */
306 /******************************************************************************/
307 
309 {
310  int datfd, rc;
311 
312 // Simply open the file in the local filesystem, creating it if need be.
313 //
314  do {datfd = open(crInfo.Path, O_RDWR|O_CREAT|O_TRUNC, crInfo.Amode);}
315  while(datfd < 0 && errno == EINTR);
316  if (datfd < 0) return -errno;
317 
318 // Set extended attributes for this newly created file if allowed to do so.
319 // SetFattr() alaways closes the provided file descriptor!
320 //
321  if ((rc = SetFattr(crInfo, datfd, 1))) return rc;
322 
323 // All done
324 //
325  return XrdOssOK;
326 }
327 
328 /******************************************************************************/
329 /* S e t F a t t r */
330 /******************************************************************************/
331 
332 int XrdOssSys::SetFattr(XrdOssCreateInfo &crInfo, int fd, time_t mtime)
333 {
334  class fdCloser
335  {public:
336  const char *Path;
337  int theFD;
338  int Done(int rc) {if (rc) unlink(Path); return rc;}
339  fdCloser(const char *pn, int fd) : Path(pn), theFD(fd) {}
340  ~fdCloser() {close(theFD);}
341  } Act(crInfo.Path, fd);
342 
344  int rc;
345 
346 // Check if we need or can record the create time
347 //
348  if (!(XRDEXP_MIGPRG & crInfo.pOpts)
349  || (crInfo.pOpts & XRDEXP_NOXATTR)) return Act.Done(0);
350 
351 // Set copy time
352 //
353  crX.Attr.cpyTime = static_cast<long long>(mtime);
354  rc = crX.Set(crInfo.Path, fd);
355 
356 // Check if extended attribute were set and indicate whether it is supported
357 //
358  if (rc == -ENOTSUP) {rc = 0; crInfo.cOpts |= XRDOSS_setnoxa;}
359  return Act.Done(rc);
360 }
#define tident
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
#define spAssign
Definition: XrdOssApi.hh:257
#define Check_RO(act, flags, path, opname)
Definition: XrdOssApi.hh:394
XrdSysTrace OssTrace
XrdOssSys * XrdOssSS
Definition: XrdOssApi.cc:82
XrdSysError OssEroute
#define XRDOSS_E8018
Definition: XrdOssError.hh:52
#define OSS_ASIZE
Definition: XrdOssOpaque.hh:37
#define OSS_CGROUP
Definition: XrdOssOpaque.hh:38
#define XRDOSS_coloc
Definition: XrdOss.hh:529
#define XrdOssOK
Definition: XrdOss.hh:54
#define XRDOSS_setnoxa
Definition: XrdOss.hh:532
#define XRDOSS_new
Definition: XrdOss.hh:527
#define XRDOSS_mkpath
Definition: XrdOss.hh:526
#define XRDEXP_INPLACE
Definition: XrdOucExport.hh:66
#define XRDEXP_NOFICL
Definition: XrdOucExport.hh:89
#define XRDEXP_NOCHECK
Definition: XrdOucExport.hh:50
#define XRDEXP_RCREATE
Definition: XrdOucExport.hh:48
#define XRDEXP_NOXATTR
Definition: XrdOucExport.hh:64
#define XRDEXP_MIGPRG
Definition: XrdOucExport.hh:86
#define close(a)
Definition: XrdPosix.hh:48
#define open
Definition: XrdPosix.hh:78
#define unlink(a)
Definition: XrdPosix.hh:121
#define stat(a, b)
Definition: XrdPosix.hh:105
#define lstat(a, b)
Definition: XrdPosix.hh:107
XrdOucString Path
struct myOpts opts
long long cpyTime
Definition: XrdFrcXAttr.hh:55
static const char * Name()
Definition: XrdFrcXAttr.hh:184
const char * group
Definition: XrdOssCache.hh:139
const char * path
Definition: XrdOssCache.hh:140
static int Alloc(allocInfo &aInfo)
Definition: XrdOssCache.cc:492
static char * Parse(const char *token, char *cbuff, int cblen)
Definition: XrdOssCache.cc:814
static XrdOssCache_FS * fsfirst
Definition: XrdOssCache.hh:269
static XrdOssCache_FS * Find(const char *Path, int lklen=0)
Definition: XrdOssCache.cc:611
static void Adjust(dev_t devid, off_t size)
Definition: XrdOssCache.cc:397
const char * Path
Definition: XrdOssCreate.cc:85
const char * LFN
Definition: XrdOssCreate.cc:86
unsigned long long pOpts
Definition: XrdOssCreate.cc:84
XrdOssCreateInfo(const char *path, const char *lfn, mode_t amode, int opts)
Definition: XrdOssCreate.cc:89
static const int minSNbsz
Definition: XrdOssSpace.hh:45
int GenRemotePath(const char *, char *)
Definition: XrdOssApi.cc:254
int StageCreate
Definition: XrdOssApi.hh:230
XrdOucPListAnchor SPList
Definition: XrdOssApi.hh:256
virtual int Stage(const char *, const char *, XrdOucEnv &, int, mode_t, unsigned long long)
Definition: XrdOssStage.cc:110
int SetFattr(XrdOssCreateInfo &crInfo, int datfd, time_t mtime)
int Alloc_Cache(XrdOssCreateInfo &, XrdOucEnv &, bool)
virtual int Create(const char *, const char *, mode_t, XrdOucEnv &, int opts=0)
int GenLocalPath(const char *, char *)
Definition: XrdOssApi.cc:237
int MSS_Stat(const char *, struct stat *buff=0)
Definition: XrdOssMSS.cc:253
int MSS_Create(const char *path, mode_t, XrdOucEnv &)
Definition: XrdOssMSS.cc:206
XrdOucPListAnchor RPList
Definition: XrdOssApi.hh:264
int Alloc_Local(XrdOssCreateInfo &, XrdOucEnv &)
char * Get(const char *varname)
Definition: XrdOucEnv.hh:69
void Put(const char *varname, const char *value)
Definition: XrdOucEnv.hh:85
XrdOucPList * About(const char *pathname)
Definition: XrdOucPList.hh:92
void Default(unsigned long long x)
Definition: XrdOucPList.hh:101
void Set(int aval)
Definition: XrdOucPList.hh:51
unsigned long long Flag()
Definition: XrdOucPList.hh:42
const char * Name()
Definition: XrdOucPList.hh:43
static std::string UrlDecode(const std::string &input)
static int makePath(char *path, mode_t mode, bool reset=false)
int Set(const char *Path, int fd=-1)
Definition: XrdOucXAttr.hh:139
static int a2sz(XrdSysError &, const char *emsg, const char *item, long long *val, long long minv=-1, long long maxv=-1)
Definition: XrdOuca2x.cc:257
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:116
static XrdSysXAttr * Xat
Definition: XrdSysFAttr.hh:51
virtual int Set(const char *Aname, const void *Aval, int Avsz, const char *Path, int fd=-1, int isNew=0)=0
int Opts
Definition: XrdMpxStats.cc:58
@ oct1
Definition: XrdSysTrace.hh:42