// ---------------------------------------------------------------------- // File: XrdMgmOfsFile.hh // Author: Andreas-Joachim Peters - CERN // ---------------------------------------------------------------------- /************************************************************************ * EOS - the CERN Disk Storage System * * Copyright (C) 2011 CERN/Switzerland * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* ************************************************************************/ /*----------------------------------------------------------------------------*/ /** * @file XrdMgmOfsFile.hh * * @brief XRootD OFS plugin class implementing file meta data handling of EOS * * Many functions in the MgmOfs interface take CGI parameters. The supported * CGI parameter are: * "eos.ruid" - uid role the client wants * "eos.rgid" - gid role the client wants * "eos.space" - space a user wants to use for scheduling a write * "eos.checksum" - checksum a file should have * "eos.lfn" - use this name as path name not the path parameter (used by prefix * redirector MGM's ... * "eos.bookingsize" - reserve the requested bytes in a file placement * "eos.cli.access=pio" - ask for a parallel open (changes the response of an * open for RAIN layouts) * "eos.app" - set the application name reported by monitoring * "eos.targetsize" - expected size of a file to be uploaded * "eos.blockchecksum=ignore" - disable block checksum verification * */ /*----------------------------------------------------------------------------*/ #ifndef __EOSMGM_MGMOFSFILE__HH__ #define __EOSMGM_MGMOFSFILE__HH__ #include "common/Mapping.hh" #include "common/Logging.hh" #include "mgm/Messaging.hh" #include "mgm/proc/IProcCommand.hh" #include "XrdOuc/XrdOucErrInfo.hh" #include "XrdSfs/XrdSfsInterface.hh" USE_EOSMGMNAMESPACE //! Forward declaration class XrdSfsAio; class XrdSecEntity; //------------------------------------------------------------------------------ //! Class implementing files and operations //------------------------------------------------------------------------------ class XrdMgmOfsFile : public XrdSfsFile, eos::common::LogId { public: //---------------------------------------------------------------------------- //! Constructor //---------------------------------------------------------------------------- XrdMgmOfsFile(char* user = 0, int MonID = 0): XrdSfsFile(user, MonID), eos::common::LogId() { vid = eos::common::VirtualIdentity::Nobody(); } //---------------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------------- virtual ~XrdMgmOfsFile(); //---------------------------------------------------------------------------- // hard link attributes //---------------------------------------------------------------------------- static constexpr char* k_mdino = (char*)"sys.eos.mdino"; static constexpr char* k_nlink = (char*)"sys.eos.nlink"; static int handleHardlinkDelete(std::shared_ptr cmd, std::shared_ptr fmd, eos::common::VirtualIdentity& vid); //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // utility function: create copy-on-write clone //---------------------------------------------------------------------------- static const int cowUpdate = 0; // do copy, for file updates static const int cowDelete = 1; // do rename, for file deletes static const int cowUnlink = 2; // create hard link, when name vanishes e.g. Recycle static int create_cow(int cowType, std::shared_ptr dmd, std::shared_ptr fmd, eos::common::VirtualIdentity& vid, XrdOucErrInfo& error); //---------------------------------------------------------------------------- // open a file //---------------------------------------------------------------------------- int open(eos::common::VirtualIdentity* vid, const char* fileName, XrdSfsFileOpenMode openMode, mode_t createMode, const XrdSecEntity* client, const char* opaque); int open(const char* fileName, XrdSfsFileOpenMode openMode, mode_t createMode, const XrdSecEntity* client = 0, const char* opaque = 0) { return open(0, fileName, openMode, createMode, client, opaque); } //---------------------------------------------------------------------------- // close a file //---------------------------------------------------------------------------- int close(); //---------------------------------------------------------------------------- //! get file name //---------------------------------------------------------------------------- const char* FName() { return fileName.c_str(); } //---------------------------------------------------------------------------- //! return mmap address (we don't need it) //---------------------------------------------------------------------------- int getMmap(void** Addr, off_t& Size) { if (Addr) { Addr = 0; } Size = 0; return SFS_OK; } //---------------------------------------------------------------------------- //! file pre-read fakes ok (we don't need it) //---------------------------------------------------------------------------- int read(XrdSfsFileOffset fileOffset, XrdSfsXferSize preread_sz) { return SFS_OK; } //---------------------------------------------------------------------------- //! Read a partial result of a 'proc' interface command //! //! @param offset where to read from the result //! @param buff buffer where to place the result //! @param blen maximum size to read //! //! @return number of bytes read upon success or SFS_ERROR //! //! @note This read is only used to stream back 'proc' command results to //! the EOS shell since all normal files get a redirection or error during //! the file open. //---------------------------------------------------------------------------- XrdSfsXferSize read(XrdSfsFileOffset offset, char* buff, XrdSfsXferSize blen); //---------------------------------------------------------------------------- //! File read in async mode - NOT SUPPORTED //---------------------------------------------------------------------------- int read(XrdSfsAio* aioparm) { static const char* epname = "aioread"; return Emsg(epname, error, EOPNOTSUPP, "read aio - not supported", fileName.c_str()); } //---------------------------------------------------------------------------- //! Read file pages into a buffer and return corresponding checksums. //! //! @param offset - The offset where the read is to start. It may be //! unaligned with certain caveats relative to csvec. //! @param buffer - pointer to buffer where the bytes are to be placed. //! @param rdlen - The number of bytes to read. The amount must be an //! integral number of XrdSfsPage::Size bytes. //! @param csvec - A vector of entries to be filled with the cooresponding //! CRC32C checksum for each page. However, if the offset is //! unaligned, then csvec[0] contains the crc for the page //! fragment that brings it to alignment for csvec[1]. //! It must be sized to hold all aligned XrdSys::Pagesize //! crc's plus additional ones for leading and ending page //! fragments, if any. //! @param opts - Processing options (see above). //! //! @return >= 0 The number of bytes that placed in buffer. //! @return SFS_ERROR File could not be read, error holds the reason. //---------------------------------------------------------------------------- XrdSfsXferSize pgRead(XrdSfsFileOffset offset, char* buffer, XrdSfsXferSize rdlen, uint32_t* csvec, uint64_t opts = 0) override; //---------------------------------------------------------------------------- //! Read file pages and checksums using asynchronous I/O - NOT SUPPORTED //! //! @param aioparm - Pointer to async I/O object controlling the I/O. //! @param opts - Processing options (see above). //! //! @return SFS_OK Request accepted and will be scheduled. //! @return SFS_ERROR File could not be read, error holds the reason. //----------------------------------------------------------------------------- int pgRead(XrdSfsAio* aioparm, uint64_t opts = 0) override { static const char* epname = "aioPgRead"; return Emsg(epname, error, EOPNOTSUPP, "pgRead aio - not supported", fileName.c_str()); } //---------------------------------------------------------------------------- //! Write to file - NOT SUPPORTED (no use case) //---------------------------------------------------------------------------- XrdSfsXferSize write(XrdSfsFileOffset fileOffset, const char* buffer, XrdSfsXferSize buffer_size) override { static const char* epname = "write"; return Emsg(epname, error, EOPNOTSUPP, "write - not supported", fileName.c_str()); } //---------------------------------------------------------------------------- //! File write in async mode - NOT SUPPORTED //---------------------------------------------------------------------------- int write(XrdSfsAio* aioparm) { static const char* epname = "aiowrite"; return Emsg(epname, error, EOPNOTSUPP, "write aio - not supported", fileName.c_str()); } //---------------------------------------------------------------------------- //! Write file pages into a file with corresponding checksums - NOT SUPPORTED //! //! @param offset - The offset where the write is to start. It may be //! unaligned with certain caveats relative to csvec. //! @param buffer - pointer to buffer containing the bytes to write. //! @param wrlen - The number of bytes to write. If amount is not an //! integral number of XrdSys::PageSize bytes, then this must //! be the last write to the file at or above the offset. //! @param csvec - A vector which contains the corresponding CRC32 checksum //! for each page or page fragment. If offset is unaligned //! then csvec[0] is the crc of the leading fragment to //! align the subsequent full page who's crc is in csvec[1]. //! It must be sized to hold all aligned XrdSys::Pagesize //! crc's plus additional ones for leading and ending page //! fragments, if any. //! @param opts - Processing options (see above). //! //! @return >= 0 The number of bytes written. //! @return SFS_ERROR File could not be read, error holds the reason. //---------------------------------------------------------------------------- XrdSfsXferSize pgWrite(XrdSfsFileOffset offset, char* buffer, XrdSfsXferSize wrlen, uint32_t* csvec, uint64_t opts = 0) override { static const char* epname = "PgWrite"; return Emsg(epname, error, EOPNOTSUPP, "pgWrite - not supported", fileName.c_str()); } //---------------------------------------------------------------------------- //! Write file pages and checksums using asynchronous I/O - NOT SUPPORTED //! //! @param aioparm - Pointer to async I/O object controlling the I/O. //! @param opts - Processing options (see above). //! //! @return SFS_OK Request accepted and will be scheduled. //! @return SFS_ERROR File could not be read, error holds the reason. //---------------------------------------------------------------------------- int pgWrite(XrdSfsAio* aioparm, uint64_t opts = 0) override { static const char* epname = "aioPgWrite"; return Emsg(epname, error, EOPNOTSUPP, "pgWrite aio - not supported", fileName.c_str()); } //---------------------------------------------------------------------------- //! file sync //---------------------------------------------------------------------------- int sync(); //---------------------------------------------------------------------------- //! file sync aio //---------------------------------------------------------------------------- int sync(XrdSfsAio* aiop); //---------------------------------------------------------------------------- // file stat //---------------------------------------------------------------------------- int stat(struct stat* buf); //---------------------------------------------------------------------------- // file truncate //---------------------------------------------------------------------------- int truncate(XrdSfsFileOffset fileOffset); //---------------------------------------------------------------------------- //! get checksum info (returns nothing - not supported) //---------------------------------------------------------------------------- int getCXinfo(char cxtype[4], int& cxrsz) { return cxrsz = 0; } //---------------------------------------------------------------------------- //! fctl fakes ok //---------------------------------------------------------------------------- int fctl(int, const char*, XrdOucErrInfo&) { return 0; } //---------------------------------------------------------------------------- //! error message function //---------------------------------------------------------------------------- int Emsg(const char*, XrdOucErrInfo&, int, const char* x, const char* y = ""); #ifdef IN_TEST_HARNESS public: #else private: #endif //---------------------------------------------------------------------------- //! Check if this is a client retry with exclusion of some diskserver. This //! happens usually for CMS workflows. To distinguish such a scenario from //! a legitimate retry due to a recoverable error, we need to serarch for the //! "tried=" opaque tag without a corresponding "triedrc=" tag. //! //! @param is_rw true if is RW otherwise false //! @param lid file layout id //! //! @return true if this is a retry for a RAIN file with the user excluding //! some diskservers, otherwise false. //---------------------------------------------------------------------------- bool IsRainRetryWithExclusion(bool is_rw, unsigned long lid) const; //---------------------------------------------------------------------------- //! Parse the triedrc opaque info and return the corresponding error number //! //! @param input input string in the form of "enoent,ioerr,fserr,srverr" //! //! @return error number //---------------------------------------------------------------------------- int GetTriedrcErrno(const std::string& input) const; //---------------------------------------------------------------------------- //! Handle (delegated) TPC redirection //! //! @return true if redirection required (the error object will be properly //! populated with the redirection host and port info), otherwise //! false //---------------------------------------------------------------------------- bool RedirectTpcAccess(); //---------------------------------------------------------------------------- //! Dump scheduling info //! //! @param selected_fs list of selected file systems //! @param proxys list of data proxy endpoints //! @param fwall_eps firewall entrypoints //---------------------------------------------------------------------------- void LogSchedulingInfo(const std::vector& selected_fs, const std::vector& proxy_eps, const std::vector& fwall_eps) const; //---------------------------------------------------------------------------- //! Get file system ids excluded from scheduling //! //! return list of file system ids to exclude //---------------------------------------------------------------------------- std::vector GetExcludedFsids() const; //---------------------------------------------------------------------------- //! Get the application name if specified //! //! @param open_opaque open opaque information //! @param client XrdSecEntity identifying the request //! //! @return application name or empty string if nothing specified //---------------------------------------------------------------------------- static const std::string GetApplicationName(XrdOucEnv* open_opaque, const XrdSecEntity* client); //---------------------------------------------------------------------------- //! Get POSIX open flags from the given XRootD open mode //! //! @param open_mode XRootD open mode see XrdSfsInterface.hh //! //! @return POSIX open flags see man 2 open //---------------------------------------------------------------------------- static int GetPosixOpenFlags(XrdSfsFileOpenMode open_mode); //---------------------------------------------------------------------------- //! Get XRootD acceess operation bases on the given open flags //! //! @param open_flags POSIX open flags //! //! @return access opeation type see XrdAccAuthorization.hh //---------------------------------------------------------------------------- static Access_Operation GetXrdAccessOperation(int open_flags); int oh {0}; //< file handle std::string fileName; //< file name XrdOucEnv* openOpaque {nullptr}; //< opaque info given with 'open' unsigned long long mFid {0ull}; //< Namespace file identifier std::unique_ptr mProcCmd {nullptr}; // Proc command object std::shared_ptr fmd {nullptr}; //< File meta data object eos::common::VirtualIdentity vid; //< virtual ID of the client std::string mEosKey; ///< File specific encryption key //! Flag to toggle obfuscation (-1 take directory default, 0 disable, 1 enable) int mEosObfuscate { -1}; bool mIsZeroSize {false}; //< Mark if file is zero size }; #endif