XRootD
Loading...
Searching...
No Matches
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"
53#include "XrdOss/XrdOssCopy.hh"
54#include "XrdOss/XrdOssError.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"
62#include "XrdOuc/XrdOucUtils.hh"
63#include "XrdOuc/XrdOucXAttr.hh"
64#include "XrdSys/XrdSysError.hh"
67
68/******************************************************************************/
69/* E r r o r R o u t i n g O b j e c t */
70/******************************************************************************/
71
73
75
76extern 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*/
113int 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
247int 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
332int 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)
#define EPNAME(x)
XrdSysTrace OssTrace
XrdSysError OssEroute
XrdOssSys * XrdOssSS
Definition XrdOssApi.cc:82
#define spAssign
Definition XrdOssApi.hh:257
#define Check_RO(act, flags, path, opname)
Definition XrdOssApi.hh:394
#define XRDOSS_E8018
#define OSS_ASIZE
#define OSS_CGROUP
#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
#define XRDEXP_NOFICL
#define XRDEXP_NOCHECK
#define XRDEXP_RCREATE
#define XRDEXP_NOXATTR
#define XRDEXP_MIGPRG
#define close(a)
Definition XrdPosix.hh:48
#define open
Definition XrdPosix.hh:76
#define unlink(a)
Definition XrdPosix.hh:113
#define stat(a, b)
Definition XrdPosix.hh:101
XrdOucString Path
struct myOpts opts
static const char * Name()
const char * group
const char * path
static int Alloc(allocInfo &aInfo)
static char * Parse(const char *token, char *cbuff, int cblen)
static XrdOssCache_FS * fsfirst
static XrdOssCache_FS * Find(const char *Path, int lklen=0)
static void Adjust(dev_t devid, off_t size)
const char * Path
const char * LFN
unsigned long long pOpts
XrdOssCreateInfo(const char *path, const char *lfn, mode_t amode, int opts)
static const int minSNbsz
int GenRemotePath(const char *, char *)
Definition XrdOssApi.cc:254
int StageCreate
Definition XrdOssApi.hh:230
XrdOucPListAnchor SPList
Definition XrdOssApi.hh:256
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
void Set(int aval)
const char * Name()
unsigned long long Flag()
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)
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
static XrdSysXAttr * Xat