diff --git a/src/XrdOss/XrdOss.cc b/src/XrdOss/XrdOss.cc index ad85c3c35f9..a58ae6b5f35 100644 --- a/src/XrdOss/XrdOss.cc +++ b/src/XrdOss/XrdOss.cc @@ -1,6 +1,6 @@ /******************************************************************************/ /* */ -/* X r d O s s . h h */ +/* X r d O s s . c c */ /* */ /* (c) 2019 by the Board of Trustees of the Leland Stanford, Jr., University */ /* All Rights Reserved */ @@ -105,7 +105,7 @@ int XrdOss::StatLS(XrdOucEnv &env, const char *cgrp, char *buff, int &blen) /* S t a t P F */ /******************************************************************************/ -int XrdOss::StatPF(const char *path, struct stat *buff) +int XrdOss::StatPF(const char *path, struct stat *buff, int opts) { (void)path; (void)buff; return -ENOTSUP; diff --git a/src/XrdOss/XrdOss.hh b/src/XrdOss/XrdOss.hh index d24368b862a..e828e52728d 100644 --- a/src/XrdOss/XrdOss.hh +++ b/src/XrdOss/XrdOss.hh @@ -75,7 +75,7 @@ public: //! @return 0 upon success or -errno or -osserr (see XrdOssError.hh). //----------------------------------------------------------------------------- -virtual int Opendir(const char *path, XrdOucEnv &env) {return -ENOTDIR;} +virtual int Opendir(const char *path, XrdOucEnv &env) {return -ENOTDIR;} //----------------------------------------------------------------------------- //! Get the next directory entry. @@ -88,7 +88,7 @@ virtual int Opendir(const char *path, XrdOucEnv &env) {return -ENOTDIR;} //! @return 0 upon success or -errno or -osserr (see XrdOssError.hh). //----------------------------------------------------------------------------- -virtual int Readdir(char *buff, int blen) {return -ENOTDIR;} +virtual int Readdir(char *buff, int blen) {return -ENOTDIR;} //----------------------------------------------------------------------------- //! Set the stat() buffer where stat information is to be placed corresponding @@ -101,7 +101,7 @@ virtual int Readdir(char *buff, int blen) {return -ENOTDIR;} //! @note This is a one-time call as stat structure is reused for each Readdir. //----------------------------------------------------------------------------- -virtual int StatRet(struct stat *) {return -ENOTSUP;} +virtual int StatRet(struct stat *) {return -ENOTSUP;} /******************************************************************************/ /* F i l e O r i e n t e d M e t h o d s */ @@ -114,13 +114,13 @@ virtual int StatRet(struct stat *) {return -ENOTSUP;} //! @return 0 upon success or -errno or -osserr (see XrdOssError.hh). //----------------------------------------------------------------------------- -virtual int Fchmod(mode_t mode) {return -EISDIR;} +virtual int Fchmod(mode_t mode) {return -EISDIR;} //----------------------------------------------------------------------------- //! Flush filesystem cached pages for this file (used for checksums). //----------------------------------------------------------------------------- -virtual void Flush() {} +virtual void Flush() {} //----------------------------------------------------------------------------- //! Return state information for this file. @@ -130,7 +130,7 @@ virtual void Flush() {} //! @return 0 upon success or -errno or -osserr (see XrdOssError.hh). //----------------------------------------------------------------------------- -virtual int Fstat(struct stat *) {return -EISDIR;} +virtual int Fstat(struct stat *buf) {return -EISDIR;} //----------------------------------------------------------------------------- //! Synchronize associated file with media (synchronous). @@ -138,7 +138,7 @@ virtual int Fstat(struct stat *) {return -EISDIR;} //! @return 0 upon success or -errno or -osserr (see XrdOssError.hh). //----------------------------------------------------------------------------- -virtual int Fsync() {return -EISDIR;} +virtual int Fsync() {return -EISDIR;} //----------------------------------------------------------------------------- //! Synchronize associated file with media (asynchronous). @@ -148,7 +148,7 @@ virtual int Fsync() {return -EISDIR;} //! @return 0 upon success or -errno or -osserr (see XrdOssError.hh). //----------------------------------------------------------------------------- -virtual int Fsync(XrdSfsAio *aiop) {return -EISDIR;} +virtual int Fsync(XrdSfsAio *aiop) {return -EISDIR;} //----------------------------------------------------------------------------- //! Set the size of the associated file. @@ -158,15 +158,7 @@ virtual int Fsync(XrdSfsAio *aiop) {return -EISDIR;} //! @return 0 upon success or -errno or -osserr (see XrdOssError.hh). //----------------------------------------------------------------------------- -virtual int Ftruncate(unsigned long long) {return -EISDIR;} - -//----------------------------------------------------------------------------- -//! Return the underlying file descriptor. -//! -//! @return -1 if there is no file descriptor or a non-negative FD number. -//----------------------------------------------------------------------------- - -virtual int getFD() {return -1;} +virtual int Ftruncate(unsigned long long) {return -EISDIR;} //----------------------------------------------------------------------------- //! Return the memory mapped characteristics of the file. @@ -178,7 +170,7 @@ virtual int getFD() {return -1;} //! returned. Note that zero length files cannot be memory mapped. //----------------------------------------------------------------------------- -virtual off_t getMmap(void **) {return 0;} +virtual off_t getMmap(void **) {return 0;} //----------------------------------------------------------------------------- //! Return file compression charectistics. @@ -189,7 +181,7 @@ virtual off_t getMmap(void **) {return 0;} //! zero is returned (file not compressed). //----------------------------------------------------------------------------- -virtual int isCompressed(char *cxidp=0) {(void)cxidp; return -EISDIR;} +virtual int isCompressed(char *cxidp=0) {(void)cxidp; return -EISDIR;} //----------------------------------------------------------------------------- //! Open a file. @@ -287,7 +279,7 @@ virtual int pgWrite(XrdSfsAio* aoiparm, uint64_t opts); //! @return 0 upon success or -errno or -osserr (see XrdOssError.hh). //----------------------------------------------------------------------------- -virtual ssize_t Read(off_t offset, size_t size) {return (ssize_t)-EISDIR;} +virtual ssize_t Read(off_t offset, size_t size) {return (ssize_t)-EISDIR;} //----------------------------------------------------------------------------- //! Read file bytes into a buffer. @@ -312,7 +304,7 @@ virtual ssize_t Read(void *buffer, off_t offset, size_t size) //! (see XrdOssError.hh). //----------------------------------------------------------------------------- -virtual int Read(XrdSfsAio *aoip) {(void)aoip; return (ssize_t)-EISDIR;} +virtual int Read(XrdSfsAio *aoip) {(void)aoip; return (ssize_t)-EISDIR;} //----------------------------------------------------------------------------- //! Read uncompressed file bytes into a buffer. @@ -363,7 +355,7 @@ virtual ssize_t Write(const void *buffer, off_t offset, size_t size) //! (see XrdOssError.hh). //----------------------------------------------------------------------------- -virtual int Write(XrdSfsAio *aiop) {(void)aiop; return (ssize_t)-EISDIR;} +virtual int Write(XrdSfsAio *aiop) {(void)aiop; return (ssize_t)-EISDIR;} //----------------------------------------------------------------------------- //! Write file bytes as directed by the write vector. @@ -400,8 +392,7 @@ virtual int Close(long long *retsz=0)=0; // static const uint16_t DF_isDir = 0x0001; //!< Object is for a directory static const uint16_t DF_isFile = 0x0002; //!< Object is for a file -static const uint16_t DF_isOpen = 0x0010; //!< Object target has been opened -static const uint16_t DF_isProxy = 0x0020; //!< Object is a proxy object +static const uint16_t DF_isProxy = 0x0010; //!< Object is a proxy object uint16_t DFType() {return dfType;} @@ -419,24 +410,44 @@ uint16_t DFType() {return dfType;} virtual int Fctl(int cmd, int alen, const char *args, char **resp=0); +//----------------------------------------------------------------------------- +//! Return the underlying file descriptor. +//! +//! @return -1 if there is no file descriptor or a non-negative FD number. +//----------------------------------------------------------------------------- + +virtual int getFD() {return fd;} + +//----------------------------------------------------------------------------- +//! Return trace identifier associated with this object. +//! +//! @return Pointer to trace identifier +//----------------------------------------------------------------------------- +virtual +const char *getTID() {return tident;} + //----------------------------------------------------------------------------- //! Constructor and Destructor //! -//! @param dftpe - The type of the object. +//! @param tid - Pointer to the trace identifier. +//! @param dftype - The type of the object. +//! @param fdnum - The value for the file descriptor. //----------------------------------------------------------------------------- - XrdOssDF(uint16_t dftype=0) - : pgwEOF(0), fd(-1), dfType(dftype), rsvd(0) {} + XrdOssDF(const char *tid="", uint16_t dftype=0, int fdnum=-1) + : tident(tid), pgwEOF(0), fd(fdnum), dfType(dftype), + rsvd(0) {} virtual ~XrdOssDF() {} protected: -off_t pgwEOF; // Highest short offset on pgWrite (0 means none yet) -int fd; // The associated file descriptor. -uint16_t dfType; // Type of this object -short rsvd; // Reserved +const char *tident; // Trace identifier +off_t pgwEOF; // Highest short offset on pgWrite (0 means none yet) +int fd; // The associated file descriptor. +uint16_t dfType; // Type of this object +short rsvd; // Reserved }; /******************************************************************************/ @@ -729,14 +740,28 @@ virtual int StatLS(XrdOucEnv &env, const char *path, //----------------------------------------------------------------------------- //! Return state information on a resident physical file or directory. //! -//! @param path - Pointer to the path in question. No translation is -//! done on this path. +//! @param path - Pointer to the path in question. //! @param buff - Pointer to the structure where info it to be returned. +//! @param opts - Options: +//! PF_dInfo - provide bdevID in st_rdev and partID in st_dev +//! based on path. If path is nil then the contents +//! of the of buff is used as the input source. +//! PF_dNums - provide number of bdev's in st_rdev and the +//! number of partitions in st_dev. The path +//! argument is ignored. This superceeds PF_dInfo. +//! PF_isLFN - Do N2N translation on path (default is none). //! //! @return 0 upon success or -errno or -osserr (see XrdOssError.hh). //----------------------------------------------------------------------------- -virtual int StatPF(const char *path, struct stat *buff); +static const int PF_dInfo = 0x00000001; +static const int PF_dNums = 0x00000002; +static const int PF_isLFN = 0x00000004; + +virtual int StatPF(const char *path, struct stat *buff, int opts); + +virtual int StatPF(const char *path, struct stat *buff) + {return StatPF(path, buff, 0);} // Backward compat //----------------------------------------------------------------------------- //! Return space information for a space name. @@ -782,7 +807,8 @@ virtual int StatXA(const char *path, char *buff, int &blen, //! @return 0 upon success or -errno or -osserr (see XrdOssError.hh). //----------------------------------------------------------------------------- -virtual int StatXP(const char *, unsigned long long &, XrdOucEnv *x=0); +virtual int StatXP(const char *path, unsigned long long &attr, + XrdOucEnv *envP=0); //----------------------------------------------------------------------------- //! Truncate a file. diff --git a/src/XrdOss/XrdOssApi.cc b/src/XrdOss/XrdOssApi.cc index 5977f7197bf..54678ac8873 100644 --- a/src/XrdOss/XrdOssApi.cc +++ b/src/XrdOss/XrdOssApi.cc @@ -494,8 +494,11 @@ int XrdOssDir::Opendir(const char *dir_path, XrdOucEnv &Env) // Get the processing flags for this directory // - pflags = XrdOssSS->PathOpts(dir_path); - ateof = 0; + unsigned long long pflags = XrdOssSS->PathOpts(dir_path); + if (pflags & XRDEXP_STAGE) dOpts |= isStage; + if (pflags & XRDEXP_NODREAD) dOpts |= noDread; + if (pflags & XRDEXP_NOCHECK) dOpts |= noCheck; + ateof = false; // Generate local path // @@ -505,12 +508,15 @@ int XrdOssDir::Opendir(const char *dir_path, XrdOucEnv &Env) else local_path = actual_path; else local_path = (char *)dir_path; -// If this is a local filesystem request, open locally. +// If this is a local filesystem request, open locally. We also obtian the +// underlying file descriptor. // - if (!(pflags & XRDEXP_STAGE) || (pflags & XRDEXP_NODREAD)) + if (!(dOpts & isStage) || (dOpts & noDread)) {TRACE(Opendir, "lcl path " <MSS_Stat(remote_path,&fstat))) return retc; // if (!(S_ISDIR(fstat.st_mode))) return -ENOTDIR; -// isopen = 1; +// isopen = true; // return XrdOssOK; // } // Open the directory at the remote location. // if (!(mssfd = XrdOssSS->MSS_Opendir(remote_path, retc))) return retc; - isopen = 1; + isopen = true; return XrdOssOK; } @@ -577,19 +583,19 @@ int XrdOssDir::Readdir(char *buff, int blen) if ((rp = readdir(lclfd))) {strlcpy(buff, rp->d_name, blen); #ifdef HAVE_FSTATAT - if (Stat && fstatat(dirFD, rp->d_name, Stat, 0)) return -errno; + if (Stat && fstatat(fd, rp->d_name, Stat, 0)) return -errno; #endif return XrdOssOK; } - *buff = '\0'; ateof = 1; + *buff = '\0'; ateof = true; return -errno; } // Simulate the read operation, if need be. // - if (pflags & XRDEXP_NODREAD) + if (noDread) {if (ateof) *buff = '\0'; - else {*buff = '.'; ateof = 1;} + else {*buff = '.'; ateof = true;} return XrdOssOK; } @@ -629,14 +635,6 @@ int XrdOssDir::StatRet(struct stat *buff) return -ENOTSUP; #endif -// Now obtain the correct file descriptor which is special in Solaris -// -#ifdef __solaris__ - dirFD = lclfd->dd_fd; -#else - dirFD = dirfd(lclfd); -#endif - // All is well // Stat = buff; @@ -658,15 +656,25 @@ int XrdOssDir::Close(long long *retsz) { int retc; +// We do not support returing a size +// + if (retsz) *retsz = 0; + // Make sure this object is open // if (!isopen) return -XRDOSS_E8002; // Close whichever handle is open // - if (lclfd) {if (!(retc = closedir(lclfd))) lclfd = 0;} - else if (mssfd) { if (!(retc = XrdOssSS->MSS_Closedir(mssfd))) mssfd = 0;} - else retc = 0; + if (lclfd) + {if (!(retc = closedir(lclfd))) + {lclfd = 0; + isopen = false; + } + } else { + if (mssfd) { if (!(retc = XrdOssSS->MSS_Closedir(mssfd))) mssfd = 0;} + else retc = 0; + } // Indicate whether or not we really closed this object // diff --git a/src/XrdOss/XrdOssApi.hh b/src/XrdOss/XrdOssApi.hh index 99e53b1eaa0..fd3c59a5979 100644 --- a/src/XrdOss/XrdOssApi.hh +++ b/src/XrdOss/XrdOssApi.hh @@ -57,19 +57,22 @@ int Readdir(char *buff, int blen); int StatRet(struct stat *buff); // Constructor and destructor - XrdOssDir(const char *tid) : lclfd(0), mssfd(0), Stat(0), tident(tid), - pflags(0), ateof(0), isopen(0), dirFD(0) - {} - ~XrdOssDir() {if (isopen > 0) Close(); isopen = 0;} + XrdOssDir(const char *tid, DIR *dP=0) + : XrdOssDF(tid, DF_isDir), + lclfd(dP), mssfd(0), Stat(0), ateof(false), + isopen(dP != 0), dOpts(0) {if (dP) fd = dirfd(dP);} + + ~XrdOssDir() {if (isopen) Close();} private: DIR *lclfd; void *mssfd; struct stat *Stat; -const char *tident; -unsigned long long pflags; - int ateof; - int isopen; - int dirFD; + bool ateof; + bool isopen; +unsigned char dOpts; +static const int isStage = 0x01; +static const int noCheck = 0x02; +static const int noDread = 0x04; }; /******************************************************************************/ @@ -97,7 +100,6 @@ int Fstat(struct stat *); int Fsync(); int Fsync(XrdSfsAio *aiop); int Ftruncate(unsigned long long); -int getFD() {return fd;} off_t getMmap(void **addr); int isCompressed(char *cxidp=0); ssize_t Read( off_t, size_t); @@ -109,10 +111,10 @@ ssize_t Write(const void *, off_t, size_t); int Write(XrdSfsAio *aiop); // Constructor and destructor - XrdOssFile(const char *tid) - {cxobj = 0; rawio = 0; cxpgsz = 0; cxid[0] = '\0'; - mmFile = 0; tident = tid; - } + XrdOssFile(const char *tid, int fdnum=-1) + : XrdOssDF(tid, DF_isFile, fdnum), + cxobj(0), cacheP(0), mmFile(0), + rawio(0), cxpgsz(0) {cxid[0] = '\0';} virtual ~XrdOssFile() {if (fd >= 0) Close();} @@ -123,7 +125,6 @@ static int AioFailure; oocx_CXFile *cxobj; XrdOssCache_FS *cacheP; XrdOssMioFile *mmFile; -const char *tident; long long FSize; int rawio; int cxpgsz; @@ -183,7 +184,7 @@ int StatFS(const char *path, char *buff, int &blen, XrdOucEnv *Env=0); int StatFS(const char *path, unsigned long long &Opt, long long &fSize, long long &fSpace); int StatLS(XrdOucEnv &env, const char *path, char *buff, int &blen); -int StatPF(const char *, struct stat *); +int StatPF(const char *, struct stat *, int); int StatVS(XrdOssVSInfo *sP, const char *sname=0, int updt=0); int StatXA(const char *path, char *buff, int &blen, XrdOucEnv *Env=0); int StatXP(const char *path, unsigned long long &attr, XrdOucEnv *Env=0); diff --git a/src/XrdOss/XrdOssCache.cc b/src/XrdOss/XrdOssCache.cc index fc1885a609e..0225cba26ab 100644 --- a/src/XrdOss/XrdOssCache.cc +++ b/src/XrdOss/XrdOssCache.cc @@ -29,20 +29,28 @@ /******************************************************************************/ #include +#include #include #include +#include #include +#include #include #include #include #include #include +#ifdef __linux__ +#include +#endif + #include "XrdOss/XrdOssCache.hh" #include "XrdOss/XrdOssOpaque.hh" #include "XrdOss/XrdOssPath.hh" #include "XrdOss/XrdOssSpace.hh" #include "XrdOss/XrdOssTrace.hh" +#include "XrdOuc/XrdOucStream.hh" #include "XrdSys/XrdSysHeaders.hh" #include "XrdSys/XrdSysPlatform.hh" @@ -74,6 +82,21 @@ int XrdOssCache::ovhAlloc= 0; int XrdOssCache::Quotas = 0; int XrdOssCache::Usage = 0; +namespace XrdOssCacheDevs +{ +struct devID + {int bdevID; + int partID; + char nDev[16]; + }; + +std::map dev2ID; + +int devNMax = 1; +int prtNMax = 1; +} +using namespace XrdOssCacheDevs; + /******************************************************************************/ /* X r d O s s C a c h e _ F S D a t a M e t h o d s */ /******************************************************************************/ @@ -82,7 +105,6 @@ XrdOssCache_FSData::XrdOssCache_FSData(const char *fsp, STATFS_t &fsbuff, dev_t fsID) { - path = strdup(fsp); size = static_cast(fsbuff.f_blocks) * static_cast(fsbuff.FS_BLKSZ); @@ -97,7 +119,20 @@ XrdOssCache_FSData::XrdOssCache_FSData(const char *fsp, updt = time(0); next = 0; stat = 0; - seen = 0; + +// This is created only for new partitions! +// + std::map::iterator it = dev2ID.find(fsID); + if (it != dev2ID.end()) + {bdevID = static_cast(it->second.bdevID); + if (it->second.partID == 0) it->second.partID = prtNMax++; + partID = static_cast(it->second.partID); + devN = it->second.nDev; + } else { + bdevID = 0; + partID = static_cast(prtNMax++); + devN = "dev"; + } } /******************************************************************************/ @@ -339,6 +374,8 @@ int XrdOssCache_FS::getSpace(XrdOssCache_Space &Space, XrdOssCache_Group *fsg, pVec[i].aPath = fsg->fsVec[i].apVec; pVec[i].Total = fsd->size; pVec[i].Free = fsd->frsz; + pVec[i].bdevID= fsd->bdevID; + pVec[i].partID= fsd->partID; } } XrdOssCache::Mutex.UnLock(); @@ -529,6 +566,34 @@ int XrdOssCache::Alloc(XrdOssCache::allocInfo &aInfo) return datfd; } +/******************************************************************************/ +/* D e v I n f o */ +/******************************************************************************/ + +void XrdOssCache::DevInfo(struct stat &buf, bool limits) +{ + +// Check if only the maximum values ae to be returned +// + if (limits) + {memset(&buf, 0, sizeof(struct stat)); + buf.st_dev = static_cast(XrdOssCacheDevs::prtNMax); + buf.st_rdev = static_cast(XrdOssCacheDevs::devNMax); + return; + } + +// Look up the device info +// + std::map::iterator it = dev2ID.find(buf.st_dev); + if (it != dev2ID.end()) + {buf.st_rdev = static_cast(it->second.bdevID); + buf.st_dev = static_cast(it->second.partID); + } else { + buf.st_rdev = 0; + buf.st_dev = 0; + } +} + /******************************************************************************/ /* F i n d */ /******************************************************************************/ @@ -616,13 +681,119 @@ void XrdOssCache::List(const char *lname, XrdSysError &Eroute) do {pP--;} while(*pP != '/'); *pP = '\0'; theCmd = "space"; } else {pP=0; theCmd = "cache";} - snprintf(buff, sizeof(buff), "%s%s %s %s", lname, theCmd, - fsp->group, fsp->path); + snprintf(buff, sizeof(buff), "%s%s %s %s -> %s[%d:%d]", lname, theCmd, + fsp->group, fsp->path, fsp->fsdata->devN, + fsp->fsdata->bdevID, fsp->fsdata->partID); if (pP) *pP = '/'; Eroute.Say(buff); fsp = fsp->next; } while(fsp != fsfirst); } + +/******************************************************************************/ +/* M a p D e v s */ +/******************************************************************************/ + +void XrdOssCache::MapDevs(bool dBug) +{ +#ifdef __linux__ + const char *pPart = "/proc/partitions"; + std::map dn2id; + XrdOucStream strm; + std::string sOrg; + char *line, *sMaj, *sMin, *sBlk, *sDev, sAlt[16], sDN[sizeof(devID::nDev)]; + dev_t dNode; + int dNum, n, fd, vMaj, vMin; + +// Our first step is to find all of the block devices on this machine and +// map them to device numbers (our own as well as the st_dev values). +// + if ((fd = open(pPart, O_RDONLY)) < 0) return; + strm.Attach(fd); + +// Read through the table until the end getting information we need +// + while((line = strm.GetLine())) + {if (!(sMaj = strm.GetToken()) || !isdigit(*sMaj)) continue; + if (!(vMaj = atoi(sMaj))) continue; + if (!(sMin = strm.GetToken()) || !isdigit(*sMin)) continue; + vMin = atoi(sMin); + if (!(sBlk = strm.GetToken()) || !isdigit(*sBlk)) continue; + if (!(sDev = strm.GetToken())) continue; + + // Preprocess LVM devices + // + if (!strncmp(sDev, "dm-", 3)) + {if (!MapDM(sDev, sAlt, sizeof(sAlt))) + {if (dBug) std::cerr <<"Config " < dev[0]" <::iterator it = dn2id.find(std::string(sDev)); + if (it != dn2id.end()) dNum = it->second; + else {dNum = devNMax++; + dn2id[std::string(sDev)] = dNum; + } + + // Add the device to out map + // + dNode = makedev(vMaj, vMin); + devID theID = {dNum, 0, {0}}; + strcpy(theID.nDev, sDN); + dev2ID[dNode] = theID; + + // Print result if so wanted + // + if (dBug) std::cerr <<"Config " < " <d_type == DT_LNK && dP->d_name[1] == 'd' + && (dP->d_name[0] == 's' || dP->d_name[0] == 'h')) + {if ((int)strlen(dP->d_name) < blen) + {strcpy(buff, dP->d_name); aOK = true; break;} + } + } + + closedir(slaves); + return aOK; +} /******************************************************************************/ /* P a r s e */ diff --git a/src/XrdOss/XrdOssCache.hh b/src/XrdOss/XrdOssCache.hh index e86f1f29c4d..98381cb384d 100644 --- a/src/XrdOss/XrdOssCache.hh +++ b/src/XrdOss/XrdOssCache.hh @@ -112,9 +112,11 @@ long long size; long long frsz; dev_t fsid; const char *path; +const char *devN; time_t updt; int stat; -unsigned int seen; +unsigned short bdevID; +unsigned short partID; XrdOssCache_FSData(const char *, STATFS_t &, dev_t); ~XrdOssCache_FSData() {if (path) free((void *)path);} @@ -233,6 +235,8 @@ struct allocInfo static int Alloc(allocInfo &aInfo); +static void DevInfo(struct stat &buf, bool limits=false); + static XrdOssCache_FS *Find(const char *Path, int lklen=0); static int Init(const char *UDir, const char *Qfile, int isSOL); @@ -241,6 +245,8 @@ static int Init(long long aMin, int ovhd, int aFuzz); static void List(const char *lname, XrdSysError &Eroute); +static void MapDevs(bool dBug=false); + static char *Parse(const char *token, char *cbuff, int cblen); static void *Scan(int cscanint); @@ -261,6 +267,7 @@ static XrdOssCache_FSData *fsdata; // -> Filesystem data static int fsCount; // Number of file systems private: +static bool MapDM(const char *ldm, char *buff, int blen); static long long minAlloc; static double fuzAlloc; diff --git a/src/XrdOss/XrdOssConfig.cc b/src/XrdOss/XrdOssConfig.cc index 965dc133bcf..5d35a3a073c 100644 --- a/src/XrdOss/XrdOssConfig.cc +++ b/src/XrdOss/XrdOssConfig.cc @@ -215,6 +215,7 @@ XrdOssSys::XrdOssSys() STT_Lib = 0; STT_Parms = 0; STT_Func = 0; + STT_Fund = 0; STT_PreOp = 0; STT_DoN2N = 1; STT_V2 = 0; @@ -279,6 +280,10 @@ int XrdOssSys::Configure(const char *configfn, XrdSysError &Eroute, } if (FDFence < 0 || FDFence >= FDLimit) FDFence = FDLimit >> 1; +// Configure devices +// + XrdOssCache::MapDevs(OssTrace.What != 0); + // Process the configuration file // NoGo = ConfigProc(Eroute); diff --git a/src/XrdOss/XrdOssError.hh b/src/XrdOss/XrdOssError.hh index 3fa4a9c9295..cecf15e4c48 100644 --- a/src/XrdOss/XrdOssError.hh +++ b/src/XrdOss/XrdOssError.hh @@ -58,8 +58,10 @@ #define XRDOSS_E8024 8024 #define XRDOSS_E8025 8025 #define XRDOSS_E8026 8026 +#define XRDOSS_E8027 8027 +#define XRDOSS_E8028 8028 -#define XRDOSS_ELAST 8026 +#define XRDOSS_ELAST 8028 #define XRDOSS_T8001 "directory object in use (internal error)" #define XRDOSS_T8002 "directory object not open (internal error)" @@ -87,4 +89,6 @@ #define XRDOSS_T8024 "invalid response from remote storage service" #define XRDOSS_T8025 "unable to queue stage request to the remote storage service" #define XRDOSS_T8026 "file creation is prohibited" +#define XRDOSS_T8027 "path is not a relative path" +#define XRDOSS_T8028 "dynamic cast failed (internal error)" #endif diff --git a/src/XrdOss/XrdOssStat.cc b/src/XrdOss/XrdOssStat.cc index 2e065c166b5..12c14054117 100644 --- a/src/XrdOss/XrdOssStat.cc +++ b/src/XrdOss/XrdOssStat.cc @@ -273,15 +273,46 @@ int XrdOssSys::StatLS(XrdOucEnv &env, const char *path, char *buff, int &blen) Output: Returns XrdOssOK upon success and -errno upon failure. */ -int XrdOssSys::StatPF(const char *path, struct stat *buff) +int XrdOssSys::StatPF(const char *path, struct stat *buff, int opts) { + char lcl_path[MAXPATHLEN+1]; int retc; -// Stat the file in the local filesystem. Return result. +// If just the maximum values wanted then we can return these right away // - retc = (STT_Func ? (*STT_Func)(path, buff, XRDOSS_resonly, 0) : - stat (path, buff)); - return (retc ? (errno ? -errno : -ENOMSG) : XrdOssOK); + if (opts & PF_dNums) + {XrdOssCache::DevInfo(*buff, true); + return 0; + } + +// Check if path is nil and do he appropriate thing +// + if (!path) + {if (opts & PF_dInfo) XrdOssCache::DevInfo(*buff, false); + else return -EINVAL; + return 0; + } + +// Check if we should do lfn2pfn conversion (previously we didn't allow it) +// + if (lcl_N2N && (opts & PF_isLFN)) + {if ((retc = lcl_N2N->lfn2pfn(path, lcl_path, sizeof(lcl_path)))) + return retc; + path = lcl_path; + } + +// We no longer use the custom stat plug-in for this function. It never +// worked in the first place, anyway. +// + if (stat(path, buff)) return (errno ? -errno : -ENOMSG); + +// Check if device info is to be returned +// + if (opts & PF_dInfo) XrdOssCache::DevInfo(*buff); + +// All done +// + return XrdOssOK; } /******************************************************************************/ @@ -435,8 +466,8 @@ int XrdOssSys::getCname(const char *path, struct stat *sbuff, char *cgbuff) // Now determine if we should get the cache group name. There is none // for offline files and it's always public for directories. // - if (S_ISDIR(sbuff->st_mode)) strcpy(cgbuff, "public"); - else if (sbuff->st_mode & S_IFBLK) strcpy(cgbuff, "*"); + if (S_ISDIR(sbuff->st_mode)) strcpy(cgbuff, "public"); + else if (S_ISBLK(sbuff->st_mode)) strcpy(cgbuff, "*"); else XrdOssPath::getCname(thePath, cgbuff); // All done diff --git a/src/XrdOss/XrdOssVS.hh b/src/XrdOss/XrdOssVS.hh index be835693fd4..ee3b89d1535 100644 --- a/src/XrdOss/XrdOssVS.hh +++ b/src/XrdOss/XrdOssVS.hh @@ -36,12 +36,28 @@ //----------------------------------------------------------------------------- //! Class describing the patitions associated with a space. This is returned -//! as a vector by StatVS() when so requested. Note that pPath poins to a path +//! as a vector by StatVS() when so requested. Note that pPath points to a path //! associated with the partition. No inference should be made about this -//! path other thant it is one of, perhaps of many, paths associated with the +//! path other than it is one of, perhaps of many, paths associated with the //! partition. The aPath vector provides specific paths that are associated -//! with allocated files in this partition relative to the space name. There -//! may be many of these for the partition; it always ends with a nil pointer. +//! with allocated files in the partition relative to the space name. There +//! may be many of these for the partition. The vector always ends with a nil +//! pointer. +//! +//! The bdevID is a unique identifier for each block device. It is currently +//! only supported in Linux. Other systems assign all partitions the generic ID +//! of 0. Even in Linux, the ID will be zero for softwared devices (though not +//! for LVM devices backed by a real device). Softwared devices such as +//! distributed file systems cannot be identified correctly as they do not +//! provide sufficiently distinguishing information. +//! +//! The partID is an ascending value that uniquely identifies a partition +//! irrespective of its associated bdevID. However, using this information to +//! schedule read/write requests is not trivial and may overwhelm the +//! underlying device if it has many partitions. You can check if the system +//! correctly identified all devices using DevID(0,x,y). If 'x' is one upon +//! return, then using partID for scheduling is the only recourse as either +//! no real devices were found or the system only has one such device. //----------------------------------------------------------------------------- class XrdOssVSPart @@ -51,9 +67,13 @@ const char *pPath; // Valid path to partition (not the allocation path) const char **aPath; // Allocation root paths for this partition long long Total; // Total bytes long long Free; // Total bytes free -void *rsvd; // Reserved +unsigned short bdevID; // Device unique ID (bdevs may have many partitions) +unsigned short partID; // Partition unique ID (parts may have the same bdevID) +int rsvd1; +void *rsvd2; // Reserved - XrdOssVSPart() : pPath(0), aPath(0), Total(0), Free(0), rsvd(0) + XrdOssVSPart() : pPath(0), aPath(0), Total(0), Free(0), + bdevID(0), partID(0), rsvd1(0), rsvd2(0) {} ~XrdOssVSPart() {} };