fuse.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891
  1. /*
  2. * Present a block device as a raw image through FUSE
  3. *
  4. * Copyright (c) 2020 Max Reitz <mreitz@redhat.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; under version 2 or later of the License.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #define FUSE_USE_VERSION 31
  19. #include "qemu/osdep.h"
  20. #include "qemu/memalign.h"
  21. #include "block/aio.h"
  22. #include "block/block_int-common.h"
  23. #include "block/export.h"
  24. #include "block/fuse.h"
  25. #include "block/qapi.h"
  26. #include "qapi/error.h"
  27. #include "qapi/qapi-commands-block.h"
  28. #include "qemu/main-loop.h"
  29. #include "system/block-backend.h"
  30. #include <fuse.h>
  31. #include <fuse_lowlevel.h>
  32. #if defined(CONFIG_FALLOCATE_ZERO_RANGE)
  33. #include <linux/falloc.h>
  34. #endif
  35. #ifdef __linux__
  36. #include <linux/fs.h>
  37. #endif
  38. /* Prevent overly long bounce buffer allocations */
  39. #define FUSE_MAX_BOUNCE_BYTES (MIN(BDRV_REQUEST_MAX_BYTES, 64 * 1024 * 1024))
  40. typedef struct FuseExport {
  41. BlockExport common;
  42. struct fuse_session *fuse_session;
  43. struct fuse_buf fuse_buf;
  44. unsigned int in_flight; /* atomic */
  45. bool mounted, fd_handler_set_up;
  46. char *mountpoint;
  47. bool writable;
  48. bool growable;
  49. /* Whether allow_other was used as a mount option or not */
  50. bool allow_other;
  51. mode_t st_mode;
  52. uid_t st_uid;
  53. gid_t st_gid;
  54. } FuseExport;
  55. static GHashTable *exports;
  56. static const struct fuse_lowlevel_ops fuse_ops;
  57. static void fuse_export_shutdown(BlockExport *exp);
  58. static void fuse_export_delete(BlockExport *exp);
  59. static void init_exports_table(void);
  60. static int setup_fuse_export(FuseExport *exp, const char *mountpoint,
  61. bool allow_other, Error **errp);
  62. static void read_from_fuse_export(void *opaque);
  63. static bool is_regular_file(const char *path, Error **errp);
  64. static void fuse_export_drained_begin(void *opaque)
  65. {
  66. FuseExport *exp = opaque;
  67. aio_set_fd_handler(exp->common.ctx,
  68. fuse_session_fd(exp->fuse_session),
  69. NULL, NULL, NULL, NULL, NULL);
  70. exp->fd_handler_set_up = false;
  71. }
  72. static void fuse_export_drained_end(void *opaque)
  73. {
  74. FuseExport *exp = opaque;
  75. /* Refresh AioContext in case it changed */
  76. exp->common.ctx = blk_get_aio_context(exp->common.blk);
  77. aio_set_fd_handler(exp->common.ctx,
  78. fuse_session_fd(exp->fuse_session),
  79. read_from_fuse_export, NULL, NULL, NULL, exp);
  80. exp->fd_handler_set_up = true;
  81. }
  82. static bool fuse_export_drained_poll(void *opaque)
  83. {
  84. FuseExport *exp = opaque;
  85. return qatomic_read(&exp->in_flight) > 0;
  86. }
  87. static const BlockDevOps fuse_export_blk_dev_ops = {
  88. .drained_begin = fuse_export_drained_begin,
  89. .drained_end = fuse_export_drained_end,
  90. .drained_poll = fuse_export_drained_poll,
  91. };
  92. static int fuse_export_create(BlockExport *blk_exp,
  93. BlockExportOptions *blk_exp_args,
  94. Error **errp)
  95. {
  96. FuseExport *exp = container_of(blk_exp, FuseExport, common);
  97. BlockExportOptionsFuse *args = &blk_exp_args->u.fuse;
  98. int ret;
  99. assert(blk_exp_args->type == BLOCK_EXPORT_TYPE_FUSE);
  100. /* For growable and writable exports, take the RESIZE permission */
  101. if (args->growable || blk_exp_args->writable) {
  102. uint64_t blk_perm, blk_shared_perm;
  103. blk_get_perm(exp->common.blk, &blk_perm, &blk_shared_perm);
  104. ret = blk_set_perm(exp->common.blk, blk_perm | BLK_PERM_RESIZE,
  105. blk_shared_perm, errp);
  106. if (ret < 0) {
  107. return ret;
  108. }
  109. }
  110. blk_set_dev_ops(exp->common.blk, &fuse_export_blk_dev_ops, exp);
  111. /*
  112. * We handle draining ourselves using an in-flight counter and by disabling
  113. * the FUSE fd handler. Do not queue BlockBackend requests, they need to
  114. * complete so the in-flight counter reaches zero.
  115. */
  116. blk_set_disable_request_queuing(exp->common.blk, true);
  117. init_exports_table();
  118. /*
  119. * It is important to do this check before calling is_regular_file() --
  120. * that function will do a stat(), which we would have to handle if we
  121. * already exported something on @mountpoint. But we cannot, because
  122. * we are currently caught up here.
  123. * (Note that ideally we would want to resolve relative paths here,
  124. * but bdrv_make_absolute_filename() might do the wrong thing for
  125. * paths that contain colons, and realpath() would resolve symlinks,
  126. * which we do not want: The mount point is not going to be the
  127. * symlink's destination, but the link itself.)
  128. * So this will not catch all potential clashes, but hopefully at
  129. * least the most common one of specifying exactly the same path
  130. * string twice.
  131. */
  132. if (g_hash_table_contains(exports, args->mountpoint)) {
  133. error_setg(errp, "There already is a FUSE export on '%s'",
  134. args->mountpoint);
  135. ret = -EEXIST;
  136. goto fail;
  137. }
  138. if (!is_regular_file(args->mountpoint, errp)) {
  139. ret = -EINVAL;
  140. goto fail;
  141. }
  142. exp->mountpoint = g_strdup(args->mountpoint);
  143. exp->writable = blk_exp_args->writable;
  144. exp->growable = args->growable;
  145. /* set default */
  146. if (!args->has_allow_other) {
  147. args->allow_other = FUSE_EXPORT_ALLOW_OTHER_AUTO;
  148. }
  149. exp->st_mode = S_IFREG | S_IRUSR;
  150. if (exp->writable) {
  151. exp->st_mode |= S_IWUSR;
  152. }
  153. exp->st_uid = getuid();
  154. exp->st_gid = getgid();
  155. if (args->allow_other == FUSE_EXPORT_ALLOW_OTHER_AUTO) {
  156. /* Ignore errors on our first attempt */
  157. ret = setup_fuse_export(exp, args->mountpoint, true, NULL);
  158. exp->allow_other = ret == 0;
  159. if (ret < 0) {
  160. ret = setup_fuse_export(exp, args->mountpoint, false, errp);
  161. }
  162. } else {
  163. exp->allow_other = args->allow_other == FUSE_EXPORT_ALLOW_OTHER_ON;
  164. ret = setup_fuse_export(exp, args->mountpoint, exp->allow_other, errp);
  165. }
  166. if (ret < 0) {
  167. goto fail;
  168. }
  169. return 0;
  170. fail:
  171. fuse_export_delete(blk_exp);
  172. return ret;
  173. }
  174. /**
  175. * Allocates the global @exports hash table.
  176. */
  177. static void init_exports_table(void)
  178. {
  179. if (exports) {
  180. return;
  181. }
  182. exports = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
  183. }
  184. /**
  185. * Create exp->fuse_session and mount it.
  186. */
  187. static int setup_fuse_export(FuseExport *exp, const char *mountpoint,
  188. bool allow_other, Error **errp)
  189. {
  190. const char *fuse_argv[4];
  191. char *mount_opts;
  192. struct fuse_args fuse_args;
  193. int ret;
  194. /*
  195. * max_read needs to match what fuse_init() sets.
  196. * max_write need not be supplied.
  197. */
  198. mount_opts = g_strdup_printf("max_read=%zu,default_permissions%s",
  199. FUSE_MAX_BOUNCE_BYTES,
  200. allow_other ? ",allow_other" : "");
  201. fuse_argv[0] = ""; /* Dummy program name */
  202. fuse_argv[1] = "-o";
  203. fuse_argv[2] = mount_opts;
  204. fuse_argv[3] = NULL;
  205. fuse_args = (struct fuse_args)FUSE_ARGS_INIT(3, (char **)fuse_argv);
  206. exp->fuse_session = fuse_session_new(&fuse_args, &fuse_ops,
  207. sizeof(fuse_ops), exp);
  208. g_free(mount_opts);
  209. if (!exp->fuse_session) {
  210. error_setg(errp, "Failed to set up FUSE session");
  211. ret = -EIO;
  212. goto fail;
  213. }
  214. ret = fuse_session_mount(exp->fuse_session, mountpoint);
  215. if (ret < 0) {
  216. error_setg(errp, "Failed to mount FUSE session to export");
  217. ret = -EIO;
  218. goto fail;
  219. }
  220. exp->mounted = true;
  221. g_hash_table_insert(exports, g_strdup(mountpoint), NULL);
  222. aio_set_fd_handler(exp->common.ctx,
  223. fuse_session_fd(exp->fuse_session),
  224. read_from_fuse_export, NULL, NULL, NULL, exp);
  225. exp->fd_handler_set_up = true;
  226. return 0;
  227. fail:
  228. fuse_export_shutdown(&exp->common);
  229. return ret;
  230. }
  231. /**
  232. * Callback to be invoked when the FUSE session FD can be read from.
  233. * (This is basically the FUSE event loop.)
  234. */
  235. static void read_from_fuse_export(void *opaque)
  236. {
  237. FuseExport *exp = opaque;
  238. int ret;
  239. blk_exp_ref(&exp->common);
  240. qatomic_inc(&exp->in_flight);
  241. do {
  242. ret = fuse_session_receive_buf(exp->fuse_session, &exp->fuse_buf);
  243. } while (ret == -EINTR);
  244. if (ret < 0) {
  245. goto out;
  246. }
  247. fuse_session_process_buf(exp->fuse_session, &exp->fuse_buf);
  248. out:
  249. if (qatomic_fetch_dec(&exp->in_flight) == 1) {
  250. aio_wait_kick(); /* wake AIO_WAIT_WHILE() */
  251. }
  252. blk_exp_unref(&exp->common);
  253. }
  254. static void fuse_export_shutdown(BlockExport *blk_exp)
  255. {
  256. FuseExport *exp = container_of(blk_exp, FuseExport, common);
  257. if (exp->fuse_session) {
  258. fuse_session_exit(exp->fuse_session);
  259. if (exp->fd_handler_set_up) {
  260. aio_set_fd_handler(exp->common.ctx,
  261. fuse_session_fd(exp->fuse_session),
  262. NULL, NULL, NULL, NULL, NULL);
  263. exp->fd_handler_set_up = false;
  264. }
  265. }
  266. if (exp->mountpoint) {
  267. /*
  268. * Safe to drop now, because we will not handle any requests
  269. * for this export anymore anyway.
  270. */
  271. g_hash_table_remove(exports, exp->mountpoint);
  272. }
  273. }
  274. static void fuse_export_delete(BlockExport *blk_exp)
  275. {
  276. FuseExport *exp = container_of(blk_exp, FuseExport, common);
  277. if (exp->fuse_session) {
  278. if (exp->mounted) {
  279. fuse_session_unmount(exp->fuse_session);
  280. }
  281. fuse_session_destroy(exp->fuse_session);
  282. }
  283. free(exp->fuse_buf.mem);
  284. g_free(exp->mountpoint);
  285. }
  286. /**
  287. * Check whether @path points to a regular file. If not, put an
  288. * appropriate message into *errp.
  289. */
  290. static bool is_regular_file(const char *path, Error **errp)
  291. {
  292. struct stat statbuf;
  293. int ret;
  294. ret = stat(path, &statbuf);
  295. if (ret < 0) {
  296. error_setg_errno(errp, errno, "Failed to stat '%s'", path);
  297. return false;
  298. }
  299. if (!S_ISREG(statbuf.st_mode)) {
  300. error_setg(errp, "'%s' is not a regular file", path);
  301. return false;
  302. }
  303. return true;
  304. }
  305. /**
  306. * A chance to set change some parameters supplied to FUSE_INIT.
  307. */
  308. static void fuse_init(void *userdata, struct fuse_conn_info *conn)
  309. {
  310. /*
  311. * MIN_NON_ZERO() would not be wrong here, but what we set here
  312. * must equal what has been passed to fuse_session_new().
  313. * Therefore, as long as max_read must be passed as a mount option
  314. * (which libfuse claims will be changed at some point), we have
  315. * to set max_read to a fixed value here.
  316. */
  317. conn->max_read = FUSE_MAX_BOUNCE_BYTES;
  318. conn->max_write = MIN_NON_ZERO(BDRV_REQUEST_MAX_BYTES, conn->max_write);
  319. }
  320. /**
  321. * Let clients look up files. Always return ENOENT because we only
  322. * care about the mountpoint itself.
  323. */
  324. static void fuse_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
  325. {
  326. fuse_reply_err(req, ENOENT);
  327. }
  328. /**
  329. * Let clients get file attributes (i.e., stat() the file).
  330. */
  331. static void fuse_getattr(fuse_req_t req, fuse_ino_t inode,
  332. struct fuse_file_info *fi)
  333. {
  334. struct stat statbuf;
  335. int64_t length, allocated_blocks;
  336. time_t now = time(NULL);
  337. FuseExport *exp = fuse_req_userdata(req);
  338. length = blk_getlength(exp->common.blk);
  339. if (length < 0) {
  340. fuse_reply_err(req, -length);
  341. return;
  342. }
  343. allocated_blocks = bdrv_get_allocated_file_size(blk_bs(exp->common.blk));
  344. if (allocated_blocks <= 0) {
  345. allocated_blocks = DIV_ROUND_UP(length, 512);
  346. } else {
  347. allocated_blocks = DIV_ROUND_UP(allocated_blocks, 512);
  348. }
  349. statbuf = (struct stat) {
  350. .st_ino = inode,
  351. .st_mode = exp->st_mode,
  352. .st_nlink = 1,
  353. .st_uid = exp->st_uid,
  354. .st_gid = exp->st_gid,
  355. .st_size = length,
  356. .st_blksize = blk_bs(exp->common.blk)->bl.request_alignment,
  357. .st_blocks = allocated_blocks,
  358. .st_atime = now,
  359. .st_mtime = now,
  360. .st_ctime = now,
  361. };
  362. fuse_reply_attr(req, &statbuf, 1.);
  363. }
  364. static int fuse_do_truncate(const FuseExport *exp, int64_t size,
  365. bool req_zero_write, PreallocMode prealloc)
  366. {
  367. uint64_t blk_perm, blk_shared_perm;
  368. BdrvRequestFlags truncate_flags = 0;
  369. bool add_resize_perm;
  370. int ret, ret_check;
  371. /* Growable and writable exports have a permanent RESIZE permission */
  372. add_resize_perm = !exp->growable && !exp->writable;
  373. if (req_zero_write) {
  374. truncate_flags |= BDRV_REQ_ZERO_WRITE;
  375. }
  376. if (add_resize_perm) {
  377. if (!qemu_in_main_thread()) {
  378. /* Changing permissions like below only works in the main thread */
  379. return -EPERM;
  380. }
  381. blk_get_perm(exp->common.blk, &blk_perm, &blk_shared_perm);
  382. ret = blk_set_perm(exp->common.blk, blk_perm | BLK_PERM_RESIZE,
  383. blk_shared_perm, NULL);
  384. if (ret < 0) {
  385. return ret;
  386. }
  387. }
  388. ret = blk_truncate(exp->common.blk, size, true, prealloc,
  389. truncate_flags, NULL);
  390. if (add_resize_perm) {
  391. /* Must succeed, because we are only giving up the RESIZE permission */
  392. ret_check = blk_set_perm(exp->common.blk, blk_perm,
  393. blk_shared_perm, &error_abort);
  394. assert(ret_check == 0);
  395. }
  396. return ret;
  397. }
  398. /**
  399. * Let clients set file attributes. Only resizing and changing
  400. * permissions (st_mode, st_uid, st_gid) is allowed.
  401. * Changing permissions is only allowed as far as it will actually
  402. * permit access: Read-only exports cannot be given +w, and exports
  403. * without allow_other cannot be given a different UID or GID, and
  404. * they cannot be given non-owner access.
  405. */
  406. static void fuse_setattr(fuse_req_t req, fuse_ino_t inode, struct stat *statbuf,
  407. int to_set, struct fuse_file_info *fi)
  408. {
  409. FuseExport *exp = fuse_req_userdata(req);
  410. int supported_attrs;
  411. int ret;
  412. supported_attrs = FUSE_SET_ATTR_SIZE | FUSE_SET_ATTR_MODE;
  413. if (exp->allow_other) {
  414. supported_attrs |= FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID;
  415. }
  416. if (to_set & ~supported_attrs) {
  417. fuse_reply_err(req, ENOTSUP);
  418. return;
  419. }
  420. /* Do some argument checks first before committing to anything */
  421. if (to_set & FUSE_SET_ATTR_MODE) {
  422. /*
  423. * Without allow_other, non-owners can never access the export, so do
  424. * not allow setting permissions for them
  425. */
  426. if (!exp->allow_other &&
  427. (statbuf->st_mode & (S_IRWXG | S_IRWXO)) != 0)
  428. {
  429. fuse_reply_err(req, EPERM);
  430. return;
  431. }
  432. /* +w for read-only exports makes no sense, disallow it */
  433. if (!exp->writable &&
  434. (statbuf->st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0)
  435. {
  436. fuse_reply_err(req, EROFS);
  437. return;
  438. }
  439. }
  440. if (to_set & FUSE_SET_ATTR_SIZE) {
  441. if (!exp->writable) {
  442. fuse_reply_err(req, EACCES);
  443. return;
  444. }
  445. ret = fuse_do_truncate(exp, statbuf->st_size, true, PREALLOC_MODE_OFF);
  446. if (ret < 0) {
  447. fuse_reply_err(req, -ret);
  448. return;
  449. }
  450. }
  451. if (to_set & FUSE_SET_ATTR_MODE) {
  452. /* Ignore FUSE-supplied file type, only change the mode */
  453. exp->st_mode = (statbuf->st_mode & 07777) | S_IFREG;
  454. }
  455. if (to_set & FUSE_SET_ATTR_UID) {
  456. exp->st_uid = statbuf->st_uid;
  457. }
  458. if (to_set & FUSE_SET_ATTR_GID) {
  459. exp->st_gid = statbuf->st_gid;
  460. }
  461. fuse_getattr(req, inode, fi);
  462. }
  463. /**
  464. * Let clients open a file (i.e., the exported image).
  465. */
  466. static void fuse_open(fuse_req_t req, fuse_ino_t inode,
  467. struct fuse_file_info *fi)
  468. {
  469. fuse_reply_open(req, fi);
  470. }
  471. /**
  472. * Handle client reads from the exported image.
  473. */
  474. static void fuse_read(fuse_req_t req, fuse_ino_t inode,
  475. size_t size, off_t offset, struct fuse_file_info *fi)
  476. {
  477. FuseExport *exp = fuse_req_userdata(req);
  478. int64_t length;
  479. void *buf;
  480. int ret;
  481. /* Limited by max_read, should not happen */
  482. if (size > FUSE_MAX_BOUNCE_BYTES) {
  483. fuse_reply_err(req, EINVAL);
  484. return;
  485. }
  486. /**
  487. * Clients will expect short reads at EOF, so we have to limit
  488. * offset+size to the image length.
  489. */
  490. length = blk_getlength(exp->common.blk);
  491. if (length < 0) {
  492. fuse_reply_err(req, -length);
  493. return;
  494. }
  495. if (offset + size > length) {
  496. size = length - offset;
  497. }
  498. buf = qemu_try_blockalign(blk_bs(exp->common.blk), size);
  499. if (!buf) {
  500. fuse_reply_err(req, ENOMEM);
  501. return;
  502. }
  503. ret = blk_pread(exp->common.blk, offset, size, buf, 0);
  504. if (ret >= 0) {
  505. fuse_reply_buf(req, buf, size);
  506. } else {
  507. fuse_reply_err(req, -ret);
  508. }
  509. qemu_vfree(buf);
  510. }
  511. /**
  512. * Handle client writes to the exported image.
  513. */
  514. static void fuse_write(fuse_req_t req, fuse_ino_t inode, const char *buf,
  515. size_t size, off_t offset, struct fuse_file_info *fi)
  516. {
  517. FuseExport *exp = fuse_req_userdata(req);
  518. int64_t length;
  519. int ret;
  520. /* Limited by max_write, should not happen */
  521. if (size > BDRV_REQUEST_MAX_BYTES) {
  522. fuse_reply_err(req, EINVAL);
  523. return;
  524. }
  525. if (!exp->writable) {
  526. fuse_reply_err(req, EACCES);
  527. return;
  528. }
  529. /**
  530. * Clients will expect short writes at EOF, so we have to limit
  531. * offset+size to the image length.
  532. */
  533. length = blk_getlength(exp->common.blk);
  534. if (length < 0) {
  535. fuse_reply_err(req, -length);
  536. return;
  537. }
  538. if (offset + size > length) {
  539. if (exp->growable) {
  540. ret = fuse_do_truncate(exp, offset + size, true, PREALLOC_MODE_OFF);
  541. if (ret < 0) {
  542. fuse_reply_err(req, -ret);
  543. return;
  544. }
  545. } else {
  546. size = length - offset;
  547. }
  548. }
  549. ret = blk_pwrite(exp->common.blk, offset, size, buf, 0);
  550. if (ret >= 0) {
  551. fuse_reply_write(req, size);
  552. } else {
  553. fuse_reply_err(req, -ret);
  554. }
  555. }
  556. /**
  557. * Let clients perform various fallocate() operations.
  558. */
  559. static void fuse_fallocate(fuse_req_t req, fuse_ino_t inode, int mode,
  560. off_t offset, off_t length,
  561. struct fuse_file_info *fi)
  562. {
  563. FuseExport *exp = fuse_req_userdata(req);
  564. int64_t blk_len;
  565. int ret;
  566. if (!exp->writable) {
  567. fuse_reply_err(req, EACCES);
  568. return;
  569. }
  570. blk_len = blk_getlength(exp->common.blk);
  571. if (blk_len < 0) {
  572. fuse_reply_err(req, -blk_len);
  573. return;
  574. }
  575. #ifdef CONFIG_FALLOCATE_PUNCH_HOLE
  576. if (mode & FALLOC_FL_KEEP_SIZE) {
  577. length = MIN(length, blk_len - offset);
  578. }
  579. #endif /* CONFIG_FALLOCATE_PUNCH_HOLE */
  580. if (!mode) {
  581. /* We can only fallocate at the EOF with a truncate */
  582. if (offset < blk_len) {
  583. fuse_reply_err(req, EOPNOTSUPP);
  584. return;
  585. }
  586. if (offset > blk_len) {
  587. /* No preallocation needed here */
  588. ret = fuse_do_truncate(exp, offset, true, PREALLOC_MODE_OFF);
  589. if (ret < 0) {
  590. fuse_reply_err(req, -ret);
  591. return;
  592. }
  593. }
  594. ret = fuse_do_truncate(exp, offset + length, true,
  595. PREALLOC_MODE_FALLOC);
  596. }
  597. #ifdef CONFIG_FALLOCATE_PUNCH_HOLE
  598. else if (mode & FALLOC_FL_PUNCH_HOLE) {
  599. if (!(mode & FALLOC_FL_KEEP_SIZE)) {
  600. fuse_reply_err(req, EINVAL);
  601. return;
  602. }
  603. do {
  604. int size = MIN(length, BDRV_REQUEST_MAX_BYTES);
  605. ret = blk_pwrite_zeroes(exp->common.blk, offset, size,
  606. BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK);
  607. if (ret == -ENOTSUP) {
  608. /*
  609. * fallocate() specifies to return EOPNOTSUPP for unsupported
  610. * operations
  611. */
  612. ret = -EOPNOTSUPP;
  613. }
  614. offset += size;
  615. length -= size;
  616. } while (ret == 0 && length > 0);
  617. }
  618. #endif /* CONFIG_FALLOCATE_PUNCH_HOLE */
  619. #ifdef CONFIG_FALLOCATE_ZERO_RANGE
  620. else if (mode & FALLOC_FL_ZERO_RANGE) {
  621. if (!(mode & FALLOC_FL_KEEP_SIZE) && offset + length > blk_len) {
  622. /* No need for zeroes, we are going to write them ourselves */
  623. ret = fuse_do_truncate(exp, offset + length, false,
  624. PREALLOC_MODE_OFF);
  625. if (ret < 0) {
  626. fuse_reply_err(req, -ret);
  627. return;
  628. }
  629. }
  630. do {
  631. int size = MIN(length, BDRV_REQUEST_MAX_BYTES);
  632. ret = blk_pwrite_zeroes(exp->common.blk,
  633. offset, size, 0);
  634. offset += size;
  635. length -= size;
  636. } while (ret == 0 && length > 0);
  637. }
  638. #endif /* CONFIG_FALLOCATE_ZERO_RANGE */
  639. else {
  640. ret = -EOPNOTSUPP;
  641. }
  642. fuse_reply_err(req, ret < 0 ? -ret : 0);
  643. }
  644. /**
  645. * Let clients fsync the exported image.
  646. */
  647. static void fuse_fsync(fuse_req_t req, fuse_ino_t inode, int datasync,
  648. struct fuse_file_info *fi)
  649. {
  650. FuseExport *exp = fuse_req_userdata(req);
  651. int ret;
  652. ret = blk_flush(exp->common.blk);
  653. fuse_reply_err(req, ret < 0 ? -ret : 0);
  654. }
  655. /**
  656. * Called before an FD to the exported image is closed. (libfuse
  657. * notes this to be a way to return last-minute errors.)
  658. */
  659. static void fuse_flush(fuse_req_t req, fuse_ino_t inode,
  660. struct fuse_file_info *fi)
  661. {
  662. fuse_fsync(req, inode, 1, fi);
  663. }
  664. #ifdef CONFIG_FUSE_LSEEK
  665. /**
  666. * Let clients inquire allocation status.
  667. */
  668. static void fuse_lseek(fuse_req_t req, fuse_ino_t inode, off_t offset,
  669. int whence, struct fuse_file_info *fi)
  670. {
  671. FuseExport *exp = fuse_req_userdata(req);
  672. if (whence != SEEK_HOLE && whence != SEEK_DATA) {
  673. fuse_reply_err(req, EINVAL);
  674. return;
  675. }
  676. while (true) {
  677. int64_t pnum;
  678. int ret;
  679. ret = bdrv_block_status_above(blk_bs(exp->common.blk), NULL,
  680. offset, INT64_MAX, &pnum, NULL, NULL);
  681. if (ret < 0) {
  682. fuse_reply_err(req, -ret);
  683. return;
  684. }
  685. if (!pnum && (ret & BDRV_BLOCK_EOF)) {
  686. int64_t blk_len;
  687. /*
  688. * If blk_getlength() rounds (e.g. by sectors), then the
  689. * export length will be rounded, too. However,
  690. * bdrv_block_status_above() may return EOF at unaligned
  691. * offsets. We must not let this become visible and thus
  692. * always simulate a hole between @offset (the real EOF)
  693. * and @blk_len (the client-visible EOF).
  694. */
  695. blk_len = blk_getlength(exp->common.blk);
  696. if (blk_len < 0) {
  697. fuse_reply_err(req, -blk_len);
  698. return;
  699. }
  700. if (offset > blk_len || whence == SEEK_DATA) {
  701. fuse_reply_err(req, ENXIO);
  702. } else {
  703. fuse_reply_lseek(req, offset);
  704. }
  705. return;
  706. }
  707. if (ret & BDRV_BLOCK_DATA) {
  708. if (whence == SEEK_DATA) {
  709. fuse_reply_lseek(req, offset);
  710. return;
  711. }
  712. } else {
  713. if (whence == SEEK_HOLE) {
  714. fuse_reply_lseek(req, offset);
  715. return;
  716. }
  717. }
  718. /* Safety check against infinite loops */
  719. if (!pnum) {
  720. fuse_reply_err(req, ENXIO);
  721. return;
  722. }
  723. offset += pnum;
  724. }
  725. }
  726. #endif
  727. static const struct fuse_lowlevel_ops fuse_ops = {
  728. .init = fuse_init,
  729. .lookup = fuse_lookup,
  730. .getattr = fuse_getattr,
  731. .setattr = fuse_setattr,
  732. .open = fuse_open,
  733. .read = fuse_read,
  734. .write = fuse_write,
  735. .fallocate = fuse_fallocate,
  736. .flush = fuse_flush,
  737. .fsync = fuse_fsync,
  738. #ifdef CONFIG_FUSE_LSEEK
  739. .lseek = fuse_lseek,
  740. #endif
  741. };
  742. const BlockExportDriver blk_exp_fuse = {
  743. .type = BLOCK_EXPORT_TYPE_FUSE,
  744. .instance_size = sizeof(FuseExport),
  745. .create = fuse_export_create,
  746. .delete = fuse_export_delete,
  747. .request_shutdown = fuse_export_shutdown,
  748. };