You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

250 lines
5.9 KiB

  1. /*
  2. ISC License
  3. Copyright (c) 2020, Antonio SJ Musumeci <trapexit@spawn.link>
  4. Permission to use, copy, modify, and/or distribute this software for any
  5. purpose with or without fee is hereby granted, provided that the above
  6. copyright notice and this permission notice appear in all copies.
  7. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  10. ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  12. ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  13. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  14. */
  15. #include "ef.hpp"
  16. #include "errno.hpp"
  17. #include "fs_inode.hpp"
  18. #include "wyhash.h"
  19. #include <cstdint>
  20. #include <string>
  21. #include <pthread.h>
  22. #include <string.h>
  23. #include <sys/stat.h>
  24. typedef uint64_t (*inodefunc_t)(const char*,const uint64_t,const mode_t,const dev_t,const ino_t);
  25. static uint64_t hybrid_hash(const char*,const uint64_t,const mode_t,const dev_t,const ino_t);
  26. static inodefunc_t g_func = hybrid_hash;
  27. static
  28. uint32_t
  29. h64_to_h32(uint64_t h_)
  30. {
  31. return (h_ - (h_ >> 32));
  32. }
  33. static
  34. uint64_t
  35. passthrough(const char *fusepath_,
  36. const uint64_t fusepath_len_,
  37. const mode_t mode_,
  38. const dev_t dev_,
  39. const ino_t ino_)
  40. {
  41. return ino_;
  42. }
  43. static
  44. uint64_t
  45. path_hash(const char *fusepath_,
  46. const uint64_t fusepath_len_,
  47. const mode_t mode_,
  48. const dev_t dev_,
  49. const ino_t ino_)
  50. {
  51. return wyhash(fusepath_,
  52. fusepath_len_,
  53. fs::inode::MAGIC,
  54. _wyp);
  55. }
  56. static
  57. uint64_t
  58. path_hash32(const char *fusepath_,
  59. const uint64_t fusepath_len_,
  60. const mode_t mode_,
  61. const dev_t dev_,
  62. const ino_t ino_)
  63. {
  64. uint64_t h;
  65. h = path_hash(fusepath_,
  66. fusepath_len_,
  67. mode_,
  68. dev_,
  69. ino_);
  70. return h64_to_h32(h);
  71. }
  72. static
  73. uint64_t
  74. devino_hash(const char *fusepath_,
  75. const uint64_t fusepath_len_,
  76. const mode_t mode_,
  77. const dev_t dev_,
  78. const ino_t ino_)
  79. {
  80. uint64_t buf[2];
  81. buf[0] = dev_;
  82. buf[1] = ino_;
  83. return wyhash((void*)&buf[0],
  84. sizeof(buf),
  85. fs::inode::MAGIC,
  86. _wyp);
  87. }
  88. static
  89. uint64_t
  90. devino_hash32(const char *fusepath_,
  91. const uint64_t fusepath_len_,
  92. const mode_t mode_,
  93. const dev_t dev_,
  94. const ino_t ino_)
  95. {
  96. uint64_t h;
  97. h = devino_hash(fusepath_,
  98. fusepath_len_,
  99. mode_,
  100. dev_,
  101. ino_);
  102. return h64_to_h32(h);
  103. }
  104. static
  105. uint64_t
  106. hybrid_hash(const char *fusepath_,
  107. const uint64_t fusepath_len_,
  108. const mode_t mode_,
  109. const dev_t dev_,
  110. const ino_t ino_)
  111. {
  112. return (S_ISDIR(mode_) ?
  113. path_hash(fusepath_,fusepath_len_,mode_,dev_,ino_) :
  114. devino_hash(fusepath_,fusepath_len_,mode_,dev_,ino_));
  115. }
  116. static
  117. uint64_t
  118. hybrid_hash32(const char *fusepath_,
  119. const uint64_t fusepath_len_,
  120. const mode_t mode_,
  121. const dev_t dev_,
  122. const ino_t ino_)
  123. {
  124. return (S_ISDIR(mode_) ?
  125. path_hash32(fusepath_,fusepath_len_,mode_,dev_,ino_) :
  126. devino_hash32(fusepath_,fusepath_len_,mode_,dev_,ino_));
  127. }
  128. namespace fs
  129. {
  130. namespace inode
  131. {
  132. int
  133. set_algo(const std::string &algo_)
  134. {
  135. if(algo_ == "passthrough")
  136. g_func = passthrough;
  137. ef(algo_ == "path-hash")
  138. g_func = path_hash;
  139. ef(algo_ == "path-hash32")
  140. g_func = path_hash32;
  141. ef(algo_ == "devino-hash")
  142. g_func = devino_hash;
  143. ef(algo_ == "devino-hash32")
  144. g_func = devino_hash32;
  145. ef(algo_ == "hybrid-hash")
  146. g_func = hybrid_hash;
  147. ef(algo_ == "hybrid-hash32")
  148. g_func = hybrid_hash32;
  149. else
  150. return -EINVAL;
  151. return 0;
  152. }
  153. std::string
  154. get_algo(void)
  155. {
  156. if(g_func == passthrough)
  157. return "passthrough";
  158. if(g_func == path_hash)
  159. return "path-hash";
  160. if(g_func == path_hash32)
  161. return "path-hash32";
  162. if(g_func == devino_hash)
  163. return "devino-hash";
  164. if(g_func == devino_hash32)
  165. return "devino-hash32";
  166. if(g_func == hybrid_hash)
  167. return "hybrid-hash";
  168. if(g_func == hybrid_hash32)
  169. return "hybrid-hash32";
  170. return std::string();
  171. }
  172. uint64_t
  173. calc(const char *fusepath_,
  174. const uint64_t fusepath_len_,
  175. const mode_t mode_,
  176. const dev_t dev_,
  177. const ino_t ino_)
  178. {
  179. return g_func(fusepath_,fusepath_len_,mode_,dev_,ino_);
  180. }
  181. uint64_t
  182. calc(std::string const &fusepath_,
  183. const mode_t mode_,
  184. const dev_t dev_,
  185. const ino_t ino_)
  186. {
  187. return calc(fusepath_.c_str(),
  188. fusepath_.size(),
  189. mode_,
  190. dev_,
  191. ino_);
  192. }
  193. void
  194. calc(const char *fusepath_,
  195. const uint64_t fusepath_len_,
  196. struct stat *st_)
  197. {
  198. st_->st_ino = calc(fusepath_,
  199. fusepath_len_,
  200. st_->st_mode,
  201. st_->st_dev,
  202. st_->st_ino);
  203. }
  204. void
  205. calc(const char *fusepath_,
  206. struct stat *st_)
  207. {
  208. calc(fusepath_,strlen(fusepath_),st_);
  209. }
  210. void
  211. calc(const std::string &fusepath_,
  212. struct stat *st_)
  213. {
  214. calc(fusepath_.c_str(),fusepath_.size(),st_);
  215. }
  216. }
  217. }