ewmscp  ..
outputHandlerGpfs.cpp
Go to the documentation of this file.
1 #include "outputHandlerGpfs.h"
2 #include "block.h"
3 #include "copyRequestTypes.h"
4 #include "gpfsCommon.h"
5 #include "ewmscp.h"
6 #include "timer.h"
7 
8 #include "throwcall.h"
9 #include <fcntl.h>
10 #include <libgen.h>
11 #include <sys/stat.h>
12 #include <sys/types.h>
13 #include <unistd.h>
14 #include <vector>
15 #include <gpfs.h>
16 
17 namespace outputHandler {
18  decltype(Gpfs::factory) Gpfs::factory("Gpfs");
19 
20  std::unique_ptr<base::writer> Gpfs::newWriter(const std::string& path,
21  bool mightAppend,
22  size_t sourceSize,
23  size_t readBlockSize,
25  bool noWrite,
26  std::unique_ptr<ioHandle::attrDataType> attrData,
27  std::unique_ptr<acl::list> aclData ) {
28  return std::unique_ptr<base::writer>(new writerGpfs(path, mightAppend,
29  sourceSize, readBlockSize,
30  state, noWrite,
31  std::move(attrData),
32  std::move(aclData)));
33  }
34  std::unique_ptr<base::writer> Gpfs::newTmpWriter(std::string& path,
35  size_t sourceSize,
36  bool noWrite,
37  std::unique_ptr<ioHandle::attrDataType> attrData,
38  std::unique_ptr<acl::list> aclData) {
39  return std::unique_ptr<base::writer>(new writerGpfs(path,
40  sourceSize,
41  noWrite,
42  std::move(attrData),
43  std::move(aclData),
44  *this));
45  }
46  decltype(Gpfs::writerGpfs::usePreallocate) Gpfs::writerGpfs::usePreallocate('\0', "useGpfsPreallocate", "use gpfs_prealloc for output files");
47  static options::single<bool> useRange('\0', "gpfsOutUseRange", "use range hint in gpfs output", false);
48  static options::single<bool> freeRange('\0', "gpfsOutFreeRange", "use range free in gpfs output", false);
49  static options::single<bool> doClearCache('\0', "gpfsOutClearCache", "clear cache in gpfs output", false);
50 
51  void Gpfs::writerGpfs::doSpecialFdHandling(size_t sourceSize) {
52  if (fd != -1) {
53  if (usePreallocate) {
54  //calculate size which uses entire blocks
55  auto truncatedSize = (sourceSize / getBlockSize()) * getBlockSize();
56  if (truncatedSize > 0) {
57  timerInst(gpfs_prealloc);
58  throwcall::good0(gpfs_prealloc(fd, 0, truncatedSize),
59  "can't gpfs_prealloc ", truncatedSize, " bytes for ", path);
60  }
61  }
62  if (useRange) {
63  gpfs_fcntl_handler fcntl;
64  auto& range = fcntl.buffer.add<gpfsAccessRange_t>(GPFS_ACCESS_RANGE);
65  range.start = 0;
66  range.length = sourceSize;
67  range.isWrite = 1;
68  timerInst(gpfsAccessRange);
69  fcntl.call(fd, path);
70  }
71  }
72  }
73 
74  Gpfs::writerGpfs::writerGpfs(const std::string& aPath,
75  bool mightAppend,
76  size_t sourceSize,
77  size_t readBlockSize,
79  bool noWrite,
80  std::unique_ptr<ioHandle::attrDataType> aAttrData,
81  std::unique_ptr<acl::list> aAclData):
82  posixFileIoCommon(aPath),
83  gpfsIoCommon(aPath),
84  writerPosixFile(aPath, mightAppend, sourceSize, readBlockSize, state, noWrite,
85  std::move(aAttrData),
86  std::move(aAclData)) {
87  doSpecialFdHandling(sourceSize);
88  };
89 
90  Gpfs::writerGpfs::writerGpfs(std::string& aPath,
91  size_t sourceSize,
92  bool noWrite,
93  std::unique_ptr<ioHandle::attrDataType> aAttrData,
94  std::unique_ptr<acl::list> aAclData,
95  base& handler):
96  posixFileIoCommon(aPath),
97  gpfsIoCommon(aPath),
98  writerPosixFile(aPath, noWrite, std::move(aAttrData), std::move(aAclData),handler) {
99  doSpecialFdHandling(sourceSize);
100  };
101 
102  Gpfs::writerGpfs::~writerGpfs() noexcept(false) {
103  if (isUnwinding()) {
104  return;
105  }
106  if (fd != -1) {
107  if (aclData) {
108  setAclData();
109  }
110  if (doClearCache) {
111  gpfs_fcntl_handler fcntl;
112  fcntl.buffer.add<gpfsClearFileCache_t>(GPFS_CLEAR_FILE_CACHE);
113  timerInst(gpfsClearFileCache);
114  fcntl.call(fd, path);
115  }
116  }
117  }
118 
121  leastRecentlyAccessedBlock = b.offset();
122  if (freeRange) {
123  releaseUsedBlocks(b.max_size());
124  }
125  }
126 
129  if (freeRange) {
130  handleParallelUsedBlocks(b.max_size(), b.offset());
131  }
132  }
133 
135  gpfs_acl_handler aclHandler(aclData->entries.size());
136 
137  auto gpfs_ace = aclHandler.begin();
138  for (const auto& rich_ace : aclData->entries) {
139  gpfs_ace->aceType = rich_ace.isAllowedType() ? ACE4_TYPE_ALLOW : ACE4_TYPE_DENY;
140  gpfs_ace->aceFlags = rich_ace.getFlagBits() & (ACE4_FLAG_FILE_INHERIT |
141  ACE4_FLAG_DIR_INHERIT |
142  ACE4_FLAG_NO_PROPAGATE |
143  ACE4_FLAG_INHERIT_ONLY |
144  ACE4_FLAG_GROUP_ID |
145  ACE4_FLAG_INHERITED);
146  gpfs_ace->aceIFlags = 0;
147  gpfs_ace->aceMask = rich_ace.getMaskBits();
148  if (rich_ace.isFlagSet(acl::list::entryType::flagsType::special_who)) {
149  gpfs_ace->aceIFlags = ACE4_IFLAG_SPECIAL_ID;
150  switch (rich_ace.e_id) {
151  case acl::list::entryType::specialIdType::owner_special_id:
152  gpfs_ace->aceWho = ACE4_SPECIAL_OWNER;
153  break;
154  case acl::list::entryType::specialIdType::group_special_id:
155  gpfs_ace->aceWho = ACE4_SPECIAL_GROUP;
156  break;
157  case acl::list::entryType::specialIdType::everyone_special_id:
158  gpfs_ace->aceWho = ACE4_SPECIAL_EVERYONE;
159  break;
160  default:
161  throw std::runtime_error("illegal special id");
162  }
163  } else {
164  gpfs_ace->aceWho = rich_ace.e_id;
165  }
166  gpfs_ace++;
167  }
168  aclHandler.set(fd, path);
169  }
170 
171  base::renameRetvalType Gpfs::rename(const std::string& fromPath,
172  const std::unique_ptr<const genericStat>& readInitialStat,
173  const std::string& toPath,
174  copyRequest::stateType& state) {
175  auto retval = posixFile::rename(fromPath, readInitialStat, toPath, state);
177  auto lastSlash = fromPath.find_last_of('/');
178  auto fromDir = lastSlash == std::string::npos ? "." : fromPath.substr(0, lastSlash);
179  lastSlash = toPath.find_last_of('/');
180  auto toDir = lastSlash == std::string::npos ? "." : toPath.substr(0, lastSlash);
181  if (fromDir != toDir) { // we move from one dir to another with possibly different acls
182  char aclBufferSpace[0x10000];
183  auto aclBuffer = reinterpret_cast<gpfs_opaque_acl_t*>(aclBufferSpace);
184  aclBuffer->acl_buffer_len = sizeof(aclBufferSpace);
185  aclBuffer->acl_version = 0;
186  aclBuffer->acl_type = GPFS_ACL_TYPE_ACCESS;
187  static const std::string pattern("/.aclgetXXXXXX");
188  std::vector<char> tmpName;
189  tmpName.reserve(toDir.size() + pattern.size());
190  tmpName.insert(tmpName.end(), toDir.cbegin(), toDir.cend());
191  tmpName.insert(tmpName.end(), pattern.cbegin(), pattern.cend());
192  tmpName.push_back('\0');
193  if (readInitialStat->isDir()) {
194  timerInst(mkdtemp);
195  throwcall::badval(mkdtemp(tmpName.data()), nullptr, "can't create tmp dir '", tmpName.data(), "'");
196  } else {
197  static timer::anchor a("mkstemp");
199  auto fd = throwcall::badval(mkstemp(tmpName.data()), -1, "can't create tmp file '", tmpName.data(), "'");
200  i.stop();
201  timerInst(close);
202  throwcall::good0(close(fd), "can't close ", tmpName.data());
203  }
204  {
205  timerInst(gpfs_getacl);
206  throwcall::good0(gpfs_getacl(tmpName.data(), 0, aclBuffer), "can't get acl for '", tmpName.data(), "'");
207  }
208  if (readInitialStat->isDir()) {
209  timerInst(rmdir);
210  throwcall::good0(rmdir(tmpName.data()), "can't remove '", tmpName.data(), "'");
211  } else {
212  timerInst(unlink);
213  throwcall::good0(unlink(tmpName.data()), "can't remove '", tmpName.data(), "'");
214  }
215  if (aclBuffer->acl_buffer_len > 0) {
216  timerInst(gpfs_putacl);
217  throwcall::good0(gpfs_putacl(toPath.c_str(), 0, aclBuffer), "can't set acl for '", toPath, "'");
218  }
219  }
220  }
221  return retval;
222  }
223 }; // end namespace outputHandler
block.h
outputHandler::Gpfs::writerGpfs::writeBlockP
void writeBlockP(const block &b) override
Definition: outputHandlerGpfs.cpp:127
block::max_size
size_t max_size() const
Definition: block.h:22
outputHandler::Gpfs::newWriter
std::unique_ptr< writer > newWriter(const std::string &path, bool mightAppend, size_t sourceSize, size_t readBlockSize, copyRequest::stateType &state, bool noWrite, std::unique_ptr< ioHandle::attrDataType >, std::unique_ptr< acl::list > aclData) override
Definition: outputHandlerGpfs.cpp:20
outputHandler::doClearCache
static options::single< bool > doClearCache('\0', "gpfsOutClearCache", "clear cache in gpfs output", false)
block::offset
size_t offset() const
Definition: block.h:25
outputHandler::Gpfs::writerGpfs::usePreallocate
static options::single< bool > usePreallocate
Definition: outputHandlerGpfs.h:13
options::single< bool >
class specialisation for options of type bool
Definition: Options.h:595
outputHandler::posixFile::writerPosixFile::writeBlockP
void writeBlockP(const block &b) override
Definition: outputHandlerPosixFile.cpp:394
throwcall::badval
T badval(T call, t badvalue, const Args &... args)
template function to wrap system calls that return a special bad value on failure
Definition: throwcall.h:54
copyRequestTypes.h
gpfs_acl_handler::begin
const gpfs_ace_v4_t * begin() const
Definition: gpfsFcntlHandler.cpp:70
gpfsIoCommon
Definition: gpfsCommon.h:8
outputHandler::Gpfs::writerGpfs
Definition: outputHandlerGpfs.h:12
acl::list::entryType::flagsType::special_who
@ special_who
copyRequest::stateBitType::done
@ done
aclBuffer
Definition: fixGpfsAcls.cpp:24
posixFileIoCommon::fd
int fd
Definition: posixFileCommon.h:21
outputHandler
Definition: ioHandle.h:9
gpfs_acl_handler
class for handling non-opaque gpfs acls
Definition: gpfsFcntlHandler.h:33
copyRequest::stateType
Definition: copyRequestTypes.h:66
ioHandle::getBlockSize
virtual size_t getBlockSize() const
Definition: ioHandle.h:58
outputHandler::useRange
static options::single< bool > useRange('\0', "gpfsOutUseRange", "use range hint in gpfs output", false)
outputHandlerGpfs.h
genericStat::isDir
bool isDir() const
Definition: genericStat.cpp:92
gpfs_fcntl_handler
class for handling gpfs_fcnt calls with their very special parameter handling
Definition: gpfsFcntlHandler.h:6
outputHandler::Gpfs::newTmpWriter
std::unique_ptr< writer > newTmpWriter(std::string &path, size_t, bool noWrite, std::unique_ptr< ioHandle::attrDataType > attrData, std::unique_ptr< acl::list > aclData) override
Definition: outputHandlerGpfs.cpp:34
outputHandler::posixFile::writerPosixFile::writeBlock
void writeBlock(const block &b) override
Definition: outputHandlerPosixFile.cpp:358
timer::instanceUnscoped::stop
void stop()
Definition: timer.h:107
outputHandler::base
Definition: outputHandler.h:17
outputHandler::base::renameRetvalType::ok
@ ok
timer.h
outputHandler::base::renameRetvalType
renameRetvalType
Definition: outputHandler.h:106
throwcall.h
block
data block, used to hold the data that are being copied (or checksummed).
Definition: block.h:7
timer::instanceUnscoped
Definition: timer.h:95
gpfsCommon.h
outputHandler::Gpfs::writerGpfs::writerGpfs
writerGpfs(const std::string &aPath, bool mightAppend, size_t sourceSize, size_t readBlockSize, copyRequest::stateType &state, bool noWrite, std::unique_ptr< ioHandle::attrDataType > attrData, std::unique_ptr< acl::list > aAclData)
Definition: outputHandlerGpfs.cpp:74
outputHandler::freeRange
static options::single< bool > freeRange('\0', "gpfsOutFreeRange", "use range free in gpfs output", false)
gpfs_fcntl_handler::buffer
union gpfs_fcntl_handler::@2 buffer
timer::anchor
Definition: timer.h:22
gpfs_acl_handler::set
void set(int fd, const std::string &path)
Definition: gpfsFcntlHandler.cpp:123
timerInst
#define timerInst(subfunc)
Definition: timer.h:157
outputHandler::Gpfs::factory
static factoryTemplate< Gpfs > factory
Definition: outputHandlerGpfs.h:10
outputHandler::Gpfs::writerGpfs::~writerGpfs
~writerGpfs() noexcept(false) override
Definition: outputHandlerGpfs.cpp:102
outputHandler::Gpfs::rename
base::renameRetvalType rename(const std::string &fromPath, const std::unique_ptr< const genericStat > &readInitialStat, const std::string &toPath, copyRequest::stateType &state) override
Definition: outputHandlerGpfs.cpp:171
posixFileIoCommon
base class for posixFile reader and writer class with the common stuff like fd, path and xattr handli...
Definition: posixFileCommon.h:17
gpfs_fcntl_handler::call
void call(int fd, const std::string &path)
Definition: gpfsFcntlHandler.cpp:15
outputHandler::Gpfs::writerGpfs::doSpecialFdHandling
void doSpecialFdHandling(size_t sourceSize)
Definition: outputHandlerGpfs.cpp:51
throwcall::good0
void good0(T call, const Args &... args)
template function to wrap system calls that return 0 on success
Definition: throwcall.h:40
outputHandler::Gpfs::writerGpfs::setAclData
void setAclData()
Definition: outputHandlerGpfs.cpp:134
outputHandler::Gpfs::writerGpfs::writeBlock
void writeBlock(const block &b) override
Definition: outputHandlerGpfs.cpp:119
posixFileIoCommon::path
const std::string & path
Definition: posixFileCommon.h:20
ewmscp.h
outputHandler::posixFile::rename
base::renameRetvalType rename(const std::string &fromPath, const std::unique_ptr< const genericStat > &readInitialStat, const std::string &toPath, copyRequest::stateType &state) override
Definition: outputHandlerPosixFile.cpp:153