1 | /*
|
---|
2 | Unix SMB/CIFS implementation.
|
---|
3 | Wrap disk only vfs functions to sidestep dodgy compilers.
|
---|
4 | Copyright (C) Tim Potter 1998
|
---|
5 | Copyright (C) Jeremy Allison 2007
|
---|
6 | Copyright (C) Brian Chrisman 2011 <bchrisman@gmail.com>
|
---|
7 | Copyright (C) Richard Sharpe 2011 <realrichardsharpe@gmail.com>
|
---|
8 |
|
---|
9 | This program is free software; you can redistribute it and/or modify
|
---|
10 | it under the terms of the GNU General Public License as published by
|
---|
11 | the Free Software Foundation; either version 3 of the License, or
|
---|
12 | (at your option) any later version.
|
---|
13 |
|
---|
14 | This program is distributed in the hope that it will be useful,
|
---|
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
17 | GNU General Public License for more details.
|
---|
18 |
|
---|
19 | You should have received a copy of the GNU General Public License
|
---|
20 | along with this program. If not, see <http://www.gnu.org/licenses/>.
|
---|
21 | */
|
---|
22 |
|
---|
23 | /*
|
---|
24 | * This VFS only works with the libceph.so user-space client. It is not needed
|
---|
25 | * if you are using the kernel client or the FUSE client.
|
---|
26 | *
|
---|
27 | * Add the following smb.conf parameter to each share that will be hosted on
|
---|
28 | * Ceph:
|
---|
29 | *
|
---|
30 | * vfs objects = ceph [any others you need go here]
|
---|
31 | */
|
---|
32 |
|
---|
33 | #include "includes.h"
|
---|
34 | #include "smbd/smbd.h"
|
---|
35 | #include <dirent.h>
|
---|
36 | #include <sys/statvfs.h>
|
---|
37 | #include "cephfs/libcephfs.h"
|
---|
38 | #include "smbprofile.h"
|
---|
39 |
|
---|
40 | #undef DBGC_CLASS
|
---|
41 | #define DBGC_CLASS DBGC_VFS
|
---|
42 |
|
---|
43 | #ifndef LIBCEPHFS_VERSION
|
---|
44 | #define LIBCEPHFS_VERSION(maj, min, extra) ((maj << 16) + (min << 8) + extra)
|
---|
45 | #define LIBCEPHFS_VERSION_CODE LIBCEPHFS_VERSION(0, 0, 0)
|
---|
46 | #endif
|
---|
47 |
|
---|
48 | /*
|
---|
49 | * Use %llu whenever we have a 64bit unsigned int, and cast to (long long unsigned)
|
---|
50 | */
|
---|
51 | #define llu(_var) ((long long unsigned)_var)
|
---|
52 |
|
---|
53 | /*
|
---|
54 | * Note, libceph's return code model is to return -errno! So we have to convert
|
---|
55 | * to what Samba expects, with is set errno to -return and return -1
|
---|
56 | */
|
---|
57 | #define WRAP_RETURN(_res) \
|
---|
58 | errno = 0; \
|
---|
59 | if (_res < 0) { \
|
---|
60 | errno = -_res; \
|
---|
61 | return -1; \
|
---|
62 | } \
|
---|
63 | return _res \
|
---|
64 |
|
---|
65 | /*
|
---|
66 | * We mount only one file system and then all shares are assumed to be in that.
|
---|
67 | * FIXME: If we want to support more than one FS, then we have to deal with
|
---|
68 | * this differently.
|
---|
69 | *
|
---|
70 | * So, cmount tells us if we have been this way before and whether
|
---|
71 | * we need to mount ceph and cmount_cnt tells us how many times we have
|
---|
72 | * connected
|
---|
73 | */
|
---|
74 | static struct ceph_mount_info * cmount = NULL;
|
---|
75 | static uint32_t cmount_cnt = 0;
|
---|
76 |
|
---|
77 | /* Check for NULL pointer parameters in cephwrap_* functions */
|
---|
78 |
|
---|
79 | /* We don't want to have NULL function pointers lying around. Someone
|
---|
80 | is sure to try and execute them. These stubs are used to prevent
|
---|
81 | this possibility. */
|
---|
82 |
|
---|
83 | static int cephwrap_connect(struct vfs_handle_struct *handle, const char *service, const char *user)
|
---|
84 | {
|
---|
85 | int ret;
|
---|
86 | char buf[256];
|
---|
87 |
|
---|
88 | const char * conf_file;
|
---|
89 |
|
---|
90 | if (cmount) {
|
---|
91 | handle->data = cmount; /* We have been here before */
|
---|
92 | cmount_cnt++;
|
---|
93 | return 0;
|
---|
94 | }
|
---|
95 |
|
---|
96 | conf_file = lp_parm_const_string(SNUM(handle->conn), "ceph", "config_file", NULL);
|
---|
97 |
|
---|
98 | DEBUG(2, ( "[CEPH] calling: ceph_create\n" ));
|
---|
99 | ret = ceph_create(&cmount, NULL);
|
---|
100 | if (ret)
|
---|
101 | goto err_out;
|
---|
102 |
|
---|
103 | if (conf_file) {
|
---|
104 | /* Override the config file */
|
---|
105 | DEBUG(2, ( "[CEPH] calling: ceph_conf_read_file\n" ));
|
---|
106 | ret = ceph_conf_read_file(cmount, conf_file);
|
---|
107 | } else {
|
---|
108 |
|
---|
109 | DEBUG(2, ( "[CEPH] calling: ceph_conf_read_file with %s\n", conf_file));
|
---|
110 | ret = ceph_conf_read_file(cmount, NULL);
|
---|
111 | }
|
---|
112 |
|
---|
113 | if (ret)
|
---|
114 | goto err_out;
|
---|
115 |
|
---|
116 | DEBUG(2, ( "[CEPH] calling: ceph_conf_get\n" ));
|
---|
117 | ret = ceph_conf_get(cmount, "log file", buf, sizeof(buf));
|
---|
118 | if (ret < 0)
|
---|
119 | goto err_out;
|
---|
120 |
|
---|
121 | DEBUG(2, ("[CEPH] calling: ceph_mount\n"));
|
---|
122 | ret = ceph_mount(cmount, NULL);
|
---|
123 | if (ret < 0)
|
---|
124 | goto err_out;
|
---|
125 |
|
---|
126 |
|
---|
127 | /*
|
---|
128 | * encode mount context/state into our vfs/connection holding structure
|
---|
129 | * cmount is a ceph_mount_t*
|
---|
130 | */
|
---|
131 | handle->data = cmount;
|
---|
132 | cmount_cnt++;
|
---|
133 |
|
---|
134 | return 0;
|
---|
135 |
|
---|
136 | err_out:
|
---|
137 | /*
|
---|
138 | * Handle the error correctly. Ceph returns -errno.
|
---|
139 | */
|
---|
140 | DEBUG(2, ("[CEPH] Error return: %s\n", strerror(-ret)));
|
---|
141 | WRAP_RETURN(ret);
|
---|
142 | }
|
---|
143 |
|
---|
144 | static void cephwrap_disconnect(struct vfs_handle_struct *handle)
|
---|
145 | {
|
---|
146 | if (!cmount) {
|
---|
147 | DEBUG(0, ("[CEPH] Error, ceph not mounted\n"));
|
---|
148 | return;
|
---|
149 | }
|
---|
150 |
|
---|
151 | /* Should we unmount/shutdown? Only if the last disconnect? */
|
---|
152 | if (--cmount_cnt) {
|
---|
153 | DEBUG(10, ("[CEPH] Not shuting down CEPH because still more connections\n"));
|
---|
154 | return;
|
---|
155 | }
|
---|
156 |
|
---|
157 | ceph_shutdown(cmount);
|
---|
158 |
|
---|
159 | cmount = NULL; /* Make it safe */
|
---|
160 | }
|
---|
161 |
|
---|
162 | /* Disk operations */
|
---|
163 |
|
---|
164 | static uint64_t cephwrap_disk_free(struct vfs_handle_struct *handle,
|
---|
165 | const char *path, uint64_t *bsize,
|
---|
166 | uint64_t *dfree, uint64_t *dsize)
|
---|
167 | {
|
---|
168 | struct statvfs statvfs_buf;
|
---|
169 | int ret;
|
---|
170 |
|
---|
171 | if (!(ret = ceph_statfs(handle->data, path, &statvfs_buf))) {
|
---|
172 | /*
|
---|
173 | * Provide all the correct values.
|
---|
174 | */
|
---|
175 | *bsize = statvfs_buf.f_bsize;
|
---|
176 | *dfree = statvfs_buf.f_bavail;
|
---|
177 | *dsize = statvfs_buf.f_blocks;
|
---|
178 | DEBUG(10, ("[CEPH] bsize: %llu, dfree: %llu, dsize: %llu\n",
|
---|
179 | llu(*bsize), llu(*dfree), llu(*dsize)));
|
---|
180 | return *dfree;
|
---|
181 | } else {
|
---|
182 | DEBUG(10, ("[CEPH] ceph_statfs returned %d\n", ret));
|
---|
183 | WRAP_RETURN(ret);
|
---|
184 | }
|
---|
185 | }
|
---|
186 |
|
---|
187 | static int cephwrap_get_quota(struct vfs_handle_struct *handle,
|
---|
188 | const char *path, enum SMB_QUOTA_TYPE qtype,
|
---|
189 | unid_t id, SMB_DISK_QUOTA *qt)
|
---|
190 | {
|
---|
191 | /* libceph: Ceph does not implement this */
|
---|
192 | #if 0
|
---|
193 | /* was ifdef HAVE_SYS_QUOTAS */
|
---|
194 | int ret;
|
---|
195 |
|
---|
196 | ret = ceph_get_quota(handle->conn->connectpath, qtype, id, qt);
|
---|
197 |
|
---|
198 | if (ret) {
|
---|
199 | errno = -ret;
|
---|
200 | ret = -1;
|
---|
201 | }
|
---|
202 |
|
---|
203 | return ret;
|
---|
204 | #else
|
---|
205 | errno = ENOSYS;
|
---|
206 | return -1;
|
---|
207 | #endif
|
---|
208 | }
|
---|
209 |
|
---|
210 | static int cephwrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
|
---|
211 | {
|
---|
212 | /* libceph: Ceph does not implement this */
|
---|
213 | #if 0
|
---|
214 | /* was ifdef HAVE_SYS_QUOTAS */
|
---|
215 | int ret;
|
---|
216 |
|
---|
217 | ret = ceph_set_quota(handle->conn->connectpath, qtype, id, qt);
|
---|
218 | if (ret) {
|
---|
219 | errno = -ret;
|
---|
220 | ret = -1;
|
---|
221 | }
|
---|
222 |
|
---|
223 | return ret;
|
---|
224 | #else
|
---|
225 | WRAP_RETURN(-ENOSYS);
|
---|
226 | #endif
|
---|
227 | }
|
---|
228 |
|
---|
229 | static int cephwrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
|
---|
230 | {
|
---|
231 | struct statvfs statvfs_buf;
|
---|
232 | int ret;
|
---|
233 |
|
---|
234 | ret = ceph_statfs(handle->data, path, &statvfs_buf);
|
---|
235 | if (ret < 0) {
|
---|
236 | WRAP_RETURN(ret);
|
---|
237 | } else {
|
---|
238 | statbuf->OptimalTransferSize = statvfs_buf.f_frsize;
|
---|
239 | statbuf->BlockSize = statvfs_buf.f_bsize;
|
---|
240 | statbuf->TotalBlocks = statvfs_buf.f_blocks;
|
---|
241 | statbuf->BlocksAvail = statvfs_buf.f_bfree;
|
---|
242 | statbuf->UserBlocksAvail = statvfs_buf.f_bavail;
|
---|
243 | statbuf->TotalFileNodes = statvfs_buf.f_files;
|
---|
244 | statbuf->FreeFileNodes = statvfs_buf.f_ffree;
|
---|
245 | statbuf->FsIdentifier = statvfs_buf.f_fsid;
|
---|
246 | DEBUG(10, ("[CEPH] f_bsize: %ld, f_blocks: %ld, f_bfree: %ld, f_bavail: %ld\n",
|
---|
247 | (long int)statvfs_buf.f_bsize, (long int)statvfs_buf.f_blocks,
|
---|
248 | (long int)statvfs_buf.f_bfree, (long int)statvfs_buf.f_bavail));
|
---|
249 | }
|
---|
250 | return ret;
|
---|
251 | }
|
---|
252 |
|
---|
253 | /* Directory operations */
|
---|
254 |
|
---|
255 | static DIR *cephwrap_opendir(struct vfs_handle_struct *handle, const char *fname, const char *mask, uint32_t attr)
|
---|
256 | {
|
---|
257 | int ret = 0;
|
---|
258 | struct ceph_dir_result *result;
|
---|
259 | DEBUG(10, ("[CEPH] opendir(%p, %s)\n", handle, fname));
|
---|
260 |
|
---|
261 | /* Returns NULL if it does not exist or there are problems ? */
|
---|
262 | ret = ceph_opendir(handle->data, fname, &result);
|
---|
263 | if (ret < 0) {
|
---|
264 | result = NULL;
|
---|
265 | errno = -ret; /* We return result which is NULL in this case */
|
---|
266 | }
|
---|
267 |
|
---|
268 | DEBUG(10, ("[CEPH] opendir(...) = %d\n", ret));
|
---|
269 | return (DIR *) result;
|
---|
270 | }
|
---|
271 |
|
---|
272 | static DIR *cephwrap_fdopendir(struct vfs_handle_struct *handle,
|
---|
273 | struct files_struct *fsp,
|
---|
274 | const char *mask,
|
---|
275 | uint32_t attributes)
|
---|
276 | {
|
---|
277 | int ret = 0;
|
---|
278 | struct ceph_dir_result *result;
|
---|
279 | DEBUG(10, ("[CEPH] fdopendir(%p, %p)\n", handle, fsp));
|
---|
280 |
|
---|
281 | ret = ceph_opendir(handle->data, fsp->fsp_name->base_name, &result);
|
---|
282 | if (ret < 0) {
|
---|
283 | result = NULL;
|
---|
284 | errno = -ret; /* We return result which is NULL in this case */
|
---|
285 | }
|
---|
286 |
|
---|
287 | DEBUG(10, ("[CEPH] fdopendir(...) = %d\n", ret));
|
---|
288 | return (DIR *) result;
|
---|
289 | }
|
---|
290 |
|
---|
291 | static struct dirent *cephwrap_readdir(struct vfs_handle_struct *handle,
|
---|
292 | DIR *dirp,
|
---|
293 | SMB_STRUCT_STAT *sbuf)
|
---|
294 | {
|
---|
295 | struct dirent *result;
|
---|
296 |
|
---|
297 | DEBUG(10, ("[CEPH] readdir(%p, %p)\n", handle, dirp));
|
---|
298 | result = ceph_readdir(handle->data, (struct ceph_dir_result *) dirp);
|
---|
299 | DEBUG(10, ("[CEPH] readdir(...) = %p\n", result));
|
---|
300 |
|
---|
301 | /* Default Posix readdir() does not give us stat info.
|
---|
302 | * Set to invalid to indicate we didn't return this info. */
|
---|
303 | if (sbuf)
|
---|
304 | SET_STAT_INVALID(*sbuf);
|
---|
305 | return result;
|
---|
306 | }
|
---|
307 |
|
---|
308 | static void cephwrap_seekdir(struct vfs_handle_struct *handle, DIR *dirp, long offset)
|
---|
309 | {
|
---|
310 | DEBUG(10, ("[CEPH] seekdir(%p, %p, %ld)\n", handle, dirp, offset));
|
---|
311 | ceph_seekdir(handle->data, (struct ceph_dir_result *) dirp, offset);
|
---|
312 | }
|
---|
313 |
|
---|
314 | static long cephwrap_telldir(struct vfs_handle_struct *handle, DIR *dirp)
|
---|
315 | {
|
---|
316 | long ret;
|
---|
317 | DEBUG(10, ("[CEPH] telldir(%p, %p)\n", handle, dirp));
|
---|
318 | ret = ceph_telldir(handle->data, (struct ceph_dir_result *) dirp);
|
---|
319 | DEBUG(10, ("[CEPH] telldir(...) = %ld\n", ret));
|
---|
320 | WRAP_RETURN(ret);
|
---|
321 | }
|
---|
322 |
|
---|
323 | static void cephwrap_rewinddir(struct vfs_handle_struct *handle, DIR *dirp)
|
---|
324 | {
|
---|
325 | DEBUG(10, ("[CEPH] rewinddir(%p, %p)\n", handle, dirp));
|
---|
326 | ceph_rewinddir(handle->data, (struct ceph_dir_result *) dirp);
|
---|
327 | }
|
---|
328 |
|
---|
329 | static int cephwrap_mkdir(struct vfs_handle_struct *handle, const char *path, mode_t mode)
|
---|
330 | {
|
---|
331 | int result;
|
---|
332 | bool has_dacl = False;
|
---|
333 | char *parent = NULL;
|
---|
334 |
|
---|
335 | DEBUG(10, ("[CEPH] mkdir(%p, %s)\n", handle, path));
|
---|
336 |
|
---|
337 | if (lp_inherit_acls(SNUM(handle->conn))
|
---|
338 | && parent_dirname(talloc_tos(), path, &parent, NULL)
|
---|
339 | && (has_dacl = directory_has_default_acl(handle->conn, parent)))
|
---|
340 | mode = 0777;
|
---|
341 |
|
---|
342 | TALLOC_FREE(parent);
|
---|
343 |
|
---|
344 | result = ceph_mkdir(handle->data, path, mode);
|
---|
345 |
|
---|
346 | /*
|
---|
347 | * Note. This order is important
|
---|
348 | */
|
---|
349 | if (result) {
|
---|
350 | WRAP_RETURN(result);
|
---|
351 | } else if (result == 0 && !has_dacl) {
|
---|
352 | /*
|
---|
353 | * We need to do this as the default behavior of POSIX ACLs
|
---|
354 | * is to set the mask to be the requested group permission
|
---|
355 | * bits, not the group permission bits to be the requested
|
---|
356 | * group permission bits. This is not what we want, as it will
|
---|
357 | * mess up any inherited ACL bits that were set. JRA.
|
---|
358 | */
|
---|
359 | int saved_errno = errno; /* We may get ENOSYS */
|
---|
360 | if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
|
---|
361 | errno = saved_errno;
|
---|
362 | }
|
---|
363 |
|
---|
364 | return result;
|
---|
365 | }
|
---|
366 |
|
---|
367 | static int cephwrap_rmdir(struct vfs_handle_struct *handle, const char *path)
|
---|
368 | {
|
---|
369 | int result;
|
---|
370 |
|
---|
371 | DEBUG(10, ("[CEPH] rmdir(%p, %s)\n", handle, path));
|
---|
372 | result = ceph_rmdir(handle->data, path);
|
---|
373 | DEBUG(10, ("[CEPH] rmdir(...) = %d\n", result));
|
---|
374 | WRAP_RETURN(result);
|
---|
375 | }
|
---|
376 |
|
---|
377 | static int cephwrap_closedir(struct vfs_handle_struct *handle, DIR *dirp)
|
---|
378 | {
|
---|
379 | int result;
|
---|
380 |
|
---|
381 | DEBUG(10, ("[CEPH] closedir(%p, %p)\n", handle, dirp));
|
---|
382 | result = ceph_closedir(handle->data, (struct ceph_dir_result *) dirp);
|
---|
383 | DEBUG(10, ("[CEPH] closedir(...) = %d\n", result));
|
---|
384 | WRAP_RETURN(result);
|
---|
385 | }
|
---|
386 |
|
---|
387 | /* File operations */
|
---|
388 |
|
---|
389 | static int cephwrap_open(struct vfs_handle_struct *handle,
|
---|
390 | struct smb_filename *smb_fname,
|
---|
391 | files_struct *fsp, int flags, mode_t mode)
|
---|
392 | {
|
---|
393 | int result = -ENOENT;
|
---|
394 | DEBUG(10, ("[CEPH] open(%p, %s, %p, %d, %d)\n", handle, smb_fname_str_dbg(smb_fname), fsp, flags, mode));
|
---|
395 |
|
---|
396 | if (smb_fname->stream_name) {
|
---|
397 | goto out;
|
---|
398 | }
|
---|
399 |
|
---|
400 | result = ceph_open(handle->data, smb_fname->base_name, flags, mode);
|
---|
401 | out:
|
---|
402 | DEBUG(10, ("[CEPH] open(...) = %d\n", result));
|
---|
403 | WRAP_RETURN(result);
|
---|
404 | }
|
---|
405 |
|
---|
406 | static int cephwrap_close(struct vfs_handle_struct *handle, files_struct *fsp)
|
---|
407 | {
|
---|
408 | int result;
|
---|
409 |
|
---|
410 | DEBUG(10, ("[CEPH] close(%p, %p)\n", handle, fsp));
|
---|
411 | result = ceph_close(handle->data, fsp->fh->fd);
|
---|
412 | DEBUG(10, ("[CEPH] close(...) = %d\n", result));
|
---|
413 |
|
---|
414 | WRAP_RETURN(result);
|
---|
415 | }
|
---|
416 |
|
---|
417 | static ssize_t cephwrap_read(struct vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
|
---|
418 | {
|
---|
419 | ssize_t result;
|
---|
420 |
|
---|
421 | DEBUG(10, ("[CEPH] read(%p, %p, %p, %llu)\n", handle, fsp, data, llu(n)));
|
---|
422 |
|
---|
423 | /* Using -1 for the offset means read/write rather than pread/pwrite */
|
---|
424 | result = ceph_read(handle->data, fsp->fh->fd, data, n, -1);
|
---|
425 | DEBUG(10, ("[CEPH] read(...) = %llu\n", llu(result)));
|
---|
426 | WRAP_RETURN(result);
|
---|
427 | }
|
---|
428 |
|
---|
429 | static ssize_t cephwrap_pread(struct vfs_handle_struct *handle, files_struct *fsp, void *data,
|
---|
430 | size_t n, off_t offset)
|
---|
431 | {
|
---|
432 | ssize_t result;
|
---|
433 |
|
---|
434 | DEBUG(10, ("[CEPH] pread(%p, %p, %p, %llu, %llu)\n", handle, fsp, data, llu(n), llu(offset)));
|
---|
435 |
|
---|
436 | result = ceph_read(handle->data, fsp->fh->fd, data, n, offset);
|
---|
437 | DEBUG(10, ("[CEPH] pread(...) = %llu\n", llu(result)));
|
---|
438 | WRAP_RETURN(result);
|
---|
439 | }
|
---|
440 |
|
---|
441 |
|
---|
442 | static ssize_t cephwrap_write(struct vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
|
---|
443 | {
|
---|
444 | ssize_t result;
|
---|
445 |
|
---|
446 | DEBUG(10, ("[CEPH] write(%p, %p, %p, %llu)\n", handle, fsp, data, llu(n)));
|
---|
447 |
|
---|
448 | result = ceph_write(handle->data, fsp->fh->fd, data, n, -1);
|
---|
449 |
|
---|
450 | DEBUG(10, ("[CEPH] write(...) = %llu\n", llu(result)));
|
---|
451 | if (result < 0) {
|
---|
452 | WRAP_RETURN(result);
|
---|
453 | }
|
---|
454 | fsp->fh->pos += result;
|
---|
455 | return result;
|
---|
456 | }
|
---|
457 |
|
---|
458 | static ssize_t cephwrap_pwrite(struct vfs_handle_struct *handle, files_struct *fsp, const void *data,
|
---|
459 | size_t n, off_t offset)
|
---|
460 | {
|
---|
461 | ssize_t result;
|
---|
462 |
|
---|
463 | DEBUG(10, ("[CEPH] pwrite(%p, %p, %p, %llu, %llu)\n", handle, fsp, data, llu(n), llu(offset)));
|
---|
464 | result = ceph_write(handle->data, fsp->fh->fd, data, n, offset);
|
---|
465 | DEBUG(10, ("[CEPH] pwrite(...) = %llu\n", llu(result)));
|
---|
466 | WRAP_RETURN(result);
|
---|
467 | }
|
---|
468 |
|
---|
469 | static off_t cephwrap_lseek(struct vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
|
---|
470 | {
|
---|
471 | off_t result = 0;
|
---|
472 |
|
---|
473 | DEBUG(10, ("[CEPH] cephwrap_lseek\n"));
|
---|
474 | /* Cope with 'stat' file opens. */
|
---|
475 | if (fsp->fh->fd != -1) {
|
---|
476 | result = ceph_lseek(handle->data, fsp->fh->fd, offset, whence);
|
---|
477 | }
|
---|
478 | WRAP_RETURN(result);
|
---|
479 | }
|
---|
480 |
|
---|
481 | static ssize_t cephwrap_sendfile(struct vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
|
---|
482 | off_t offset, size_t n)
|
---|
483 | {
|
---|
484 | /*
|
---|
485 | * We cannot support sendfile because libceph is in user space.
|
---|
486 | */
|
---|
487 | DEBUG(10, ("[CEPH] cephwrap_sendfile\n"));
|
---|
488 | errno = ENOTSUP;
|
---|
489 | return -1;
|
---|
490 | }
|
---|
491 |
|
---|
492 | static ssize_t cephwrap_recvfile(struct vfs_handle_struct *handle,
|
---|
493 | int fromfd,
|
---|
494 | files_struct *tofsp,
|
---|
495 | off_t offset,
|
---|
496 | size_t n)
|
---|
497 | {
|
---|
498 | /*
|
---|
499 | * We cannot support recvfile because libceph is in user space.
|
---|
500 | */
|
---|
501 | DEBUG(10, ("[CEPH] cephwrap_recvfile\n"));
|
---|
502 | errno=ENOTSUP;
|
---|
503 | return -1;
|
---|
504 | }
|
---|
505 |
|
---|
506 | static int cephwrap_rename(struct vfs_handle_struct *handle,
|
---|
507 | const struct smb_filename *smb_fname_src,
|
---|
508 | const struct smb_filename *smb_fname_dst)
|
---|
509 | {
|
---|
510 | int result = -1;
|
---|
511 | DEBUG(10, ("[CEPH] cephwrap_rename\n"));
|
---|
512 | if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
|
---|
513 | errno = ENOENT;
|
---|
514 | return result;
|
---|
515 | }
|
---|
516 |
|
---|
517 | result = ceph_rename(handle->data, smb_fname_src->base_name, smb_fname_dst->base_name);
|
---|
518 | WRAP_RETURN(result);
|
---|
519 | }
|
---|
520 |
|
---|
521 | static int cephwrap_fsync(struct vfs_handle_struct *handle, files_struct *fsp)
|
---|
522 | {
|
---|
523 | int result;
|
---|
524 | DEBUG(10, ("[CEPH] cephwrap_fsync\n"));
|
---|
525 | result = ceph_fsync(handle->data, fsp->fh->fd, false);
|
---|
526 | WRAP_RETURN(result);
|
---|
527 | }
|
---|
528 |
|
---|
529 | static int cephwrap_stat(struct vfs_handle_struct *handle,
|
---|
530 | struct smb_filename *smb_fname)
|
---|
531 | {
|
---|
532 | int result = -1;
|
---|
533 | struct stat stbuf;
|
---|
534 |
|
---|
535 | DEBUG(10, ("[CEPH] stat(%p, %s)\n", handle, smb_fname_str_dbg(smb_fname)));
|
---|
536 |
|
---|
537 | if (smb_fname->stream_name) {
|
---|
538 | errno = ENOENT;
|
---|
539 | return result;
|
---|
540 | }
|
---|
541 |
|
---|
542 | result = ceph_stat(handle->data, smb_fname->base_name, (struct stat *) &stbuf);
|
---|
543 | DEBUG(10, ("[CEPH] stat(...) = %d\n", result));
|
---|
544 | if (result < 0) {
|
---|
545 | WRAP_RETURN(result);
|
---|
546 | } else {
|
---|
547 | DEBUG(10, ("[CEPH]\tstbuf = {dev = %llu, ino = %llu, mode = 0x%x, nlink = %llu, "
|
---|
548 | "uid = %d, gid = %d, rdev = %llu, size = %llu, blksize = %llu, "
|
---|
549 | "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu}\n",
|
---|
550 | llu(stbuf.st_dev), llu(stbuf.st_ino), stbuf.st_mode, llu(stbuf.st_nlink),
|
---|
551 | stbuf.st_uid, stbuf.st_gid, llu(stbuf.st_rdev), llu(stbuf.st_size), llu(stbuf.st_blksize),
|
---|
552 | llu(stbuf.st_blocks), llu(stbuf.st_atime), llu(stbuf.st_mtime), llu(stbuf.st_ctime)));
|
---|
553 | }
|
---|
554 | init_stat_ex_from_stat(
|
---|
555 | &smb_fname->st, &stbuf,
|
---|
556 | lp_fake_directory_create_times(SNUM(handle->conn)));
|
---|
557 | DEBUG(10, ("[CEPH] mode = 0x%x\n", smb_fname->st.st_ex_mode));
|
---|
558 | return result;
|
---|
559 | }
|
---|
560 |
|
---|
561 | static int cephwrap_fstat(struct vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
|
---|
562 | {
|
---|
563 | int result = -1;
|
---|
564 | struct stat stbuf;
|
---|
565 |
|
---|
566 | DEBUG(10, ("[CEPH] fstat(%p, %d)\n", handle, fsp->fh->fd));
|
---|
567 | result = ceph_fstat(handle->data, fsp->fh->fd, (struct stat *) &stbuf);
|
---|
568 | DEBUG(10, ("[CEPH] fstat(...) = %d\n", result));
|
---|
569 | if (result < 0) {
|
---|
570 | WRAP_RETURN(result);
|
---|
571 | } else {
|
---|
572 | DEBUG(10, ("[CEPH]\tstbuf = {dev = %llu, ino = %llu, mode = 0x%x, nlink = %llu, "
|
---|
573 | "uid = %d, gid = %d, rdev = %llu, size = %llu, blksize = %llu, "
|
---|
574 | "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu}\n",
|
---|
575 | llu(stbuf.st_dev), llu(stbuf.st_ino), stbuf.st_mode, llu(stbuf.st_nlink),
|
---|
576 | stbuf.st_uid, stbuf.st_gid, llu(stbuf.st_rdev), llu(stbuf.st_size), llu(stbuf.st_blksize),
|
---|
577 | llu(stbuf.st_blocks), llu(stbuf.st_atime), llu(stbuf.st_mtime), llu(stbuf.st_ctime)));
|
---|
578 | }
|
---|
579 |
|
---|
580 | init_stat_ex_from_stat(
|
---|
581 | sbuf, &stbuf,
|
---|
582 | lp_fake_directory_create_times(SNUM(handle->conn)));
|
---|
583 | DEBUG(10, ("[CEPH] mode = 0x%x\n", sbuf->st_ex_mode));
|
---|
584 | return result;
|
---|
585 | }
|
---|
586 |
|
---|
587 | static int cephwrap_lstat(struct vfs_handle_struct *handle,
|
---|
588 | struct smb_filename *smb_fname)
|
---|
589 | {
|
---|
590 | int result = -1;
|
---|
591 | struct stat stbuf;
|
---|
592 |
|
---|
593 | DEBUG(10, ("[CEPH] lstat(%p, %s)\n", handle, smb_fname_str_dbg(smb_fname)));
|
---|
594 |
|
---|
595 | if (smb_fname->stream_name) {
|
---|
596 | errno = ENOENT;
|
---|
597 | return result;
|
---|
598 | }
|
---|
599 |
|
---|
600 | result = ceph_lstat(handle->data, smb_fname->base_name, &stbuf);
|
---|
601 | DEBUG(10, ("[CEPH] lstat(...) = %d\n", result));
|
---|
602 | if (result < 0) {
|
---|
603 | WRAP_RETURN(result);
|
---|
604 | }
|
---|
605 | init_stat_ex_from_stat(
|
---|
606 | &smb_fname->st, &stbuf,
|
---|
607 | lp_fake_directory_create_times(SNUM(handle->conn)));
|
---|
608 | return result;
|
---|
609 | }
|
---|
610 |
|
---|
611 | static int cephwrap_unlink(struct vfs_handle_struct *handle,
|
---|
612 | const struct smb_filename *smb_fname)
|
---|
613 | {
|
---|
614 | int result = -1;
|
---|
615 |
|
---|
616 | DEBUG(10, ("[CEPH] unlink(%p, %s)\n", handle, smb_fname_str_dbg(smb_fname)));
|
---|
617 | if (smb_fname->stream_name) {
|
---|
618 | errno = ENOENT;
|
---|
619 | return result;
|
---|
620 | }
|
---|
621 | result = ceph_unlink(handle->data, smb_fname->base_name);
|
---|
622 | DEBUG(10, ("[CEPH] unlink(...) = %d\n", result));
|
---|
623 | WRAP_RETURN(result);
|
---|
624 | }
|
---|
625 |
|
---|
626 | static int cephwrap_chmod(struct vfs_handle_struct *handle, const char *path, mode_t mode)
|
---|
627 | {
|
---|
628 | int result;
|
---|
629 |
|
---|
630 | DEBUG(10, ("[CEPH] chmod(%p, %s, %d)\n", handle, path, mode));
|
---|
631 |
|
---|
632 | /*
|
---|
633 | * We need to do this due to the fact that the default POSIX ACL
|
---|
634 | * chmod modifies the ACL *mask* for the group owner, not the
|
---|
635 | * group owner bits directly. JRA.
|
---|
636 | */
|
---|
637 |
|
---|
638 |
|
---|
639 | {
|
---|
640 | int saved_errno = errno; /* We might get ENOSYS */
|
---|
641 | if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
|
---|
642 | return result;
|
---|
643 | }
|
---|
644 | /* Error - return the old errno. */
|
---|
645 | errno = saved_errno;
|
---|
646 | }
|
---|
647 |
|
---|
648 | result = ceph_chmod(handle->data, path, mode);
|
---|
649 | DEBUG(10, ("[CEPH] chmod(...) = %d\n", result));
|
---|
650 | WRAP_RETURN(result);
|
---|
651 | }
|
---|
652 |
|
---|
653 | static int cephwrap_fchmod(struct vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
|
---|
654 | {
|
---|
655 | int result;
|
---|
656 |
|
---|
657 | DEBUG(10, ("[CEPH] fchmod(%p, %p, %d)\n", handle, fsp, mode));
|
---|
658 |
|
---|
659 | /*
|
---|
660 | * We need to do this due to the fact that the default POSIX ACL
|
---|
661 | * chmod modifies the ACL *mask* for the group owner, not the
|
---|
662 | * group owner bits directly. JRA.
|
---|
663 | */
|
---|
664 |
|
---|
665 | {
|
---|
666 | int saved_errno = errno; /* We might get ENOSYS */
|
---|
667 | if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
|
---|
668 | return result;
|
---|
669 | }
|
---|
670 | /* Error - return the old errno. */
|
---|
671 | errno = saved_errno;
|
---|
672 | }
|
---|
673 |
|
---|
674 | #if defined(HAVE_FCHMOD)
|
---|
675 | result = ceph_fchmod(handle->data, fsp->fh->fd, mode);
|
---|
676 | DEBUG(10, ("[CEPH] fchmod(...) = %d\n", result));
|
---|
677 | WRAP_RETURN(result);
|
---|
678 | #else
|
---|
679 | errno = ENOSYS;
|
---|
680 | #endif
|
---|
681 | return -1;
|
---|
682 | }
|
---|
683 |
|
---|
684 | static int cephwrap_chown(struct vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
|
---|
685 | {
|
---|
686 | int result;
|
---|
687 | DEBUG(10, ("[CEPH] chown(%p, %s, %d, %d)\n", handle, path, uid, gid));
|
---|
688 | result = ceph_chown(handle->data, path, uid, gid);
|
---|
689 | DEBUG(10, ("[CEPH] chown(...) = %d\n", result));
|
---|
690 | WRAP_RETURN(result);
|
---|
691 | }
|
---|
692 |
|
---|
693 | static int cephwrap_fchown(struct vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
|
---|
694 | {
|
---|
695 | int result;
|
---|
696 | #ifdef HAVE_FCHOWN
|
---|
697 |
|
---|
698 | DEBUG(10, ("[CEPH] fchown(%p, %p, %d, %d)\n", handle, fsp, uid, gid));
|
---|
699 | result = ceph_fchown(handle->data, fsp->fh->fd, uid, gid);
|
---|
700 | DEBUG(10, ("[CEPH] fchown(...) = %d\n", result));
|
---|
701 | WRAP_RETURN(result);
|
---|
702 | #else
|
---|
703 | errno = ENOSYS;
|
---|
704 | result = -1;
|
---|
705 | #endif
|
---|
706 | return result;
|
---|
707 | }
|
---|
708 |
|
---|
709 | static int cephwrap_lchown(struct vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
|
---|
710 | {
|
---|
711 | int result;
|
---|
712 |
|
---|
713 | DEBUG(10, ("[CEPH] lchown(%p, %s, %d, %d)\n", handle, path, uid, gid));
|
---|
714 | result = ceph_lchown(handle->data, path, uid, gid);
|
---|
715 | DEBUG(10, ("[CEPH] lchown(...) = %d\n", result));
|
---|
716 | WRAP_RETURN(result);
|
---|
717 | }
|
---|
718 |
|
---|
719 | static int cephwrap_chdir(struct vfs_handle_struct *handle, const char *path)
|
---|
720 | {
|
---|
721 | int result = -1;
|
---|
722 | DEBUG(10, ("[CEPH] chdir(%p, %s)\n", handle, path));
|
---|
723 | /*
|
---|
724 | * If the path is just / use chdir because Ceph is below / and
|
---|
725 | * cannot deal with changing directory above its mount point
|
---|
726 | */
|
---|
727 | if (path && !strcmp(path, "/"))
|
---|
728 | return chdir(path);
|
---|
729 |
|
---|
730 | result = ceph_chdir(handle->data, path);
|
---|
731 | DEBUG(10, ("[CEPH] chdir(...) = %d\n", result));
|
---|
732 | WRAP_RETURN(result);
|
---|
733 | }
|
---|
734 |
|
---|
735 | static char *cephwrap_getwd(struct vfs_handle_struct *handle)
|
---|
736 | {
|
---|
737 | const char *cwd = ceph_getcwd(handle->data);
|
---|
738 | DEBUG(10, ("[CEPH] getwd(%p) = %s\n", handle, cwd));
|
---|
739 | return SMB_STRDUP(cwd);
|
---|
740 | }
|
---|
741 |
|
---|
742 | static int cephwrap_ntimes(struct vfs_handle_struct *handle,
|
---|
743 | const struct smb_filename *smb_fname,
|
---|
744 | struct smb_file_time *ft)
|
---|
745 | {
|
---|
746 | struct utimbuf buf;
|
---|
747 | int result;
|
---|
748 |
|
---|
749 | if (null_timespec(ft->atime)) {
|
---|
750 | buf.actime = smb_fname->st.st_ex_atime.tv_sec;
|
---|
751 | } else {
|
---|
752 | buf.actime = ft->atime.tv_sec;
|
---|
753 | }
|
---|
754 | if (null_timespec(ft->mtime)) {
|
---|
755 | buf.modtime = smb_fname->st.st_ex_mtime.tv_sec;
|
---|
756 | } else {
|
---|
757 | buf.modtime = ft->mtime.tv_sec;
|
---|
758 | }
|
---|
759 | if (!null_timespec(ft->create_time)) {
|
---|
760 | set_create_timespec_ea(handle->conn, smb_fname,
|
---|
761 | ft->create_time);
|
---|
762 | }
|
---|
763 | if (buf.actime == smb_fname->st.st_ex_atime.tv_sec &&
|
---|
764 | buf.modtime == smb_fname->st.st_ex_mtime.tv_sec) {
|
---|
765 | return 0;
|
---|
766 | }
|
---|
767 |
|
---|
768 | result = ceph_utime(handle->data, smb_fname->base_name, &buf);
|
---|
769 | DEBUG(10, ("[CEPH] ntimes(%p, %s, {%ld, %ld, %ld, %ld}) = %d\n", handle, smb_fname_str_dbg(smb_fname),
|
---|
770 | ft->mtime.tv_sec, ft->atime.tv_sec, ft->ctime.tv_sec,
|
---|
771 | ft->create_time.tv_sec, result));
|
---|
772 | return result;
|
---|
773 | }
|
---|
774 |
|
---|
775 | static int strict_allocate_ftruncate(struct vfs_handle_struct *handle, files_struct *fsp, off_t len)
|
---|
776 | {
|
---|
777 | off_t space_to_write;
|
---|
778 | uint64_t space_avail;
|
---|
779 | uint64_t bsize,dfree,dsize;
|
---|
780 | int ret;
|
---|
781 | NTSTATUS status;
|
---|
782 | SMB_STRUCT_STAT *pst;
|
---|
783 |
|
---|
784 | status = vfs_stat_fsp(fsp);
|
---|
785 | if (!NT_STATUS_IS_OK(status)) {
|
---|
786 | return -1;
|
---|
787 | }
|
---|
788 | pst = &fsp->fsp_name->st;
|
---|
789 |
|
---|
790 | #ifdef S_ISFIFO
|
---|
791 | if (S_ISFIFO(pst->st_ex_mode))
|
---|
792 | return 0;
|
---|
793 | #endif
|
---|
794 |
|
---|
795 | if (pst->st_ex_size == len)
|
---|
796 | return 0;
|
---|
797 |
|
---|
798 | /* Shrink - just ftruncate. */
|
---|
799 | if (pst->st_ex_size > len)
|
---|
800 | return ftruncate(fsp->fh->fd, len);
|
---|
801 |
|
---|
802 | space_to_write = len - pst->st_ex_size;
|
---|
803 |
|
---|
804 | /* for allocation try fallocate first. This can fail on some
|
---|
805 | platforms e.g. when the filesystem doesn't support it and no
|
---|
806 | emulation is being done by the libc (like on AIX with JFS1). In that
|
---|
807 | case we do our own emulation. fallocate implementations can
|
---|
808 | return ENOTSUP or EINVAL in cases like that. */
|
---|
809 | ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
|
---|
810 | if (ret == -1 && errno == ENOSPC) {
|
---|
811 | return -1;
|
---|
812 | }
|
---|
813 | if (ret == 0) {
|
---|
814 | return 0;
|
---|
815 | }
|
---|
816 | DEBUG(10,("[CEPH] strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
|
---|
817 | "error %d. Falling back to slow manual allocation\n", errno));
|
---|
818 |
|
---|
819 | /* available disk space is enough or not? */
|
---|
820 | space_avail =
|
---|
821 | get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
|
---|
822 | /* space_avail is 1k blocks */
|
---|
823 | if (space_avail == (uint64_t)-1 ||
|
---|
824 | ((uint64_t)space_to_write/1024 > space_avail) ) {
|
---|
825 | errno = ENOSPC;
|
---|
826 | return -1;
|
---|
827 | }
|
---|
828 |
|
---|
829 | /* Write out the real space on disk. */
|
---|
830 | return vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
|
---|
831 | }
|
---|
832 |
|
---|
833 | static int cephwrap_ftruncate(struct vfs_handle_struct *handle, files_struct *fsp, off_t len)
|
---|
834 | {
|
---|
835 | int result = -1;
|
---|
836 | SMB_STRUCT_STAT st;
|
---|
837 | char c = 0;
|
---|
838 | off_t currpos;
|
---|
839 |
|
---|
840 | DEBUG(10, ("[CEPH] ftruncate(%p, %p, %llu\n", handle, fsp, llu(len)));
|
---|
841 |
|
---|
842 | if (lp_strict_allocate(SNUM(fsp->conn))) {
|
---|
843 | result = strict_allocate_ftruncate(handle, fsp, len);
|
---|
844 | return result;
|
---|
845 | }
|
---|
846 |
|
---|
847 | /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
|
---|
848 | sys_ftruncate if the system supports it. Then I discovered that
|
---|
849 | you can have some filesystems that support ftruncate
|
---|
850 | expansion and some that don't! On Linux fat can't do
|
---|
851 | ftruncate extend but ext2 can. */
|
---|
852 |
|
---|
853 | result = ceph_ftruncate(handle->data, fsp->fh->fd, len);
|
---|
854 | if (result == 0)
|
---|
855 | goto done;
|
---|
856 |
|
---|
857 | /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
|
---|
858 | extend a file with ftruncate. Provide alternate implementation
|
---|
859 | for this */
|
---|
860 | currpos = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
|
---|
861 | if (currpos == -1) {
|
---|
862 | goto done;
|
---|
863 | }
|
---|
864 |
|
---|
865 | /* Do an fstat to see if the file is longer than the requested
|
---|
866 | size in which case the ftruncate above should have
|
---|
867 | succeeded or shorter, in which case seek to len - 1 and
|
---|
868 | write 1 byte of zero */
|
---|
869 | if (SMB_VFS_FSTAT(fsp, &st) == -1) {
|
---|
870 | goto done;
|
---|
871 | }
|
---|
872 |
|
---|
873 | #ifdef S_ISFIFO
|
---|
874 | if (S_ISFIFO(st.st_ex_mode)) {
|
---|
875 | result = 0;
|
---|
876 | goto done;
|
---|
877 | }
|
---|
878 | #endif
|
---|
879 |
|
---|
880 | if (st.st_ex_size == len) {
|
---|
881 | result = 0;
|
---|
882 | goto done;
|
---|
883 | }
|
---|
884 |
|
---|
885 | if (st.st_ex_size > len) {
|
---|
886 | /* the sys_ftruncate should have worked */
|
---|
887 | goto done;
|
---|
888 | }
|
---|
889 |
|
---|
890 | if (SMB_VFS_LSEEK(fsp, len-1, SEEK_SET) != len -1)
|
---|
891 | goto done;
|
---|
892 |
|
---|
893 | if (SMB_VFS_WRITE(fsp, &c, 1)!=1)
|
---|
894 | goto done;
|
---|
895 |
|
---|
896 | /* Seek to where we were */
|
---|
897 | if (SMB_VFS_LSEEK(fsp, currpos, SEEK_SET) != currpos)
|
---|
898 | goto done;
|
---|
899 | result = 0;
|
---|
900 |
|
---|
901 | done:
|
---|
902 |
|
---|
903 | return result;
|
---|
904 | }
|
---|
905 |
|
---|
906 | static bool cephwrap_lock(struct vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
|
---|
907 | {
|
---|
908 | DEBUG(10, ("[CEPH] lock\n"));
|
---|
909 | return true;
|
---|
910 | }
|
---|
911 |
|
---|
912 | static int cephwrap_kernel_flock(struct vfs_handle_struct *handle, files_struct *fsp,
|
---|
913 | uint32_t share_mode, uint32_t access_mask)
|
---|
914 | {
|
---|
915 | DEBUG(10, ("[CEPH] kernel_flock\n"));
|
---|
916 | /*
|
---|
917 | * We must return zero here and pretend all is good.
|
---|
918 | * One day we might have this in CEPH.
|
---|
919 | */
|
---|
920 | return 0;
|
---|
921 | }
|
---|
922 |
|
---|
923 | static bool cephwrap_getlock(struct vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
|
---|
924 | {
|
---|
925 | DEBUG(10, ("[CEPH] getlock returning false and errno=0\n"));
|
---|
926 |
|
---|
927 | errno = 0;
|
---|
928 | return false;
|
---|
929 | }
|
---|
930 |
|
---|
931 | /*
|
---|
932 | * We cannot let this fall through to the default, because the file might only
|
---|
933 | * be accessible from libceph (which is a user-space client) but the fd might
|
---|
934 | * be for some file the kernel knows about.
|
---|
935 | */
|
---|
936 | static int cephwrap_linux_setlease(struct vfs_handle_struct *handle, files_struct *fsp,
|
---|
937 | int leasetype)
|
---|
938 | {
|
---|
939 | int result = -1;
|
---|
940 |
|
---|
941 | DEBUG(10, ("[CEPH] linux_setlease\n"));
|
---|
942 | errno = ENOSYS;
|
---|
943 | return result;
|
---|
944 | }
|
---|
945 |
|
---|
946 | static int cephwrap_symlink(struct vfs_handle_struct *handle, const char *oldpath, const char *newpath)
|
---|
947 | {
|
---|
948 | int result = -1;
|
---|
949 | DEBUG(10, ("[CEPH] symlink(%p, %s, %s)\n", handle, oldpath, newpath));
|
---|
950 | result = ceph_symlink(handle->data, oldpath, newpath);
|
---|
951 | DEBUG(10, ("[CEPH] symlink(...) = %d\n", result));
|
---|
952 | WRAP_RETURN(result);
|
---|
953 | }
|
---|
954 |
|
---|
955 | static int cephwrap_readlink(struct vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
|
---|
956 | {
|
---|
957 | int result = -1;
|
---|
958 | DEBUG(10, ("[CEPH] readlink(%p, %s, %p, %llu)\n", handle, path, buf, llu(bufsiz)));
|
---|
959 | result = ceph_readlink(handle->data, path, buf, bufsiz);
|
---|
960 | DEBUG(10, ("[CEPH] readlink(...) = %d\n", result));
|
---|
961 | WRAP_RETURN(result);
|
---|
962 | }
|
---|
963 |
|
---|
964 | static int cephwrap_link(struct vfs_handle_struct *handle, const char *oldpath, const char *newpath)
|
---|
965 | {
|
---|
966 | int result = -1;
|
---|
967 | DEBUG(10, ("[CEPH] link(%p, %s, %s)\n", handle, oldpath, newpath));
|
---|
968 | result = ceph_link(handle->data, oldpath, newpath);
|
---|
969 | DEBUG(10, ("[CEPH] link(...) = %d\n", result));
|
---|
970 | WRAP_RETURN(result);
|
---|
971 | }
|
---|
972 |
|
---|
973 | static int cephwrap_mknod(struct vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
|
---|
974 | {
|
---|
975 | int result = -1;
|
---|
976 | DEBUG(10, ("[CEPH] mknod(%p, %s)\n", handle, pathname));
|
---|
977 | result = ceph_mknod(handle->data, pathname, mode, dev);
|
---|
978 | DEBUG(10, ("[CEPH] mknod(...) = %d\n", result));
|
---|
979 | WRAP_RETURN(result);
|
---|
980 | }
|
---|
981 |
|
---|
982 | /*
|
---|
983 | * This is a simple version of real-path ... a better version is needed to
|
---|
984 | * ask libceph about symbolic links.
|
---|
985 | */
|
---|
986 | static char *cephwrap_realpath(struct vfs_handle_struct *handle, const char *path)
|
---|
987 | {
|
---|
988 | char *result;
|
---|
989 | size_t len = strlen(path);
|
---|
990 |
|
---|
991 | result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
|
---|
992 | if (len && (path[0] == '/')) {
|
---|
993 | int r = asprintf(&result, "%s", path);
|
---|
994 | if (r < 0) return NULL;
|
---|
995 | } else if ((len >= 2) && (path[0] == '.') && (path[1] == '/')) {
|
---|
996 | if (len == 2) {
|
---|
997 | int r = asprintf(&result, "%s",
|
---|
998 | handle->conn->connectpath);
|
---|
999 | if (r < 0) return NULL;
|
---|
1000 | } else {
|
---|
1001 | int r = asprintf(&result, "%s/%s",
|
---|
1002 | handle->conn->connectpath, &path[2]);
|
---|
1003 | if (r < 0) return NULL;
|
---|
1004 | }
|
---|
1005 | } else {
|
---|
1006 | int r = asprintf(&result, "%s/%s",
|
---|
1007 | handle->conn->connectpath, path);
|
---|
1008 | if (r < 0) return NULL;
|
---|
1009 | }
|
---|
1010 | DEBUG(10, ("[CEPH] realpath(%p, %s) = %s\n", handle, path, result));
|
---|
1011 | return result;
|
---|
1012 | }
|
---|
1013 |
|
---|
1014 | static int cephwrap_chflags(struct vfs_handle_struct *handle, const char *path,
|
---|
1015 | unsigned int flags)
|
---|
1016 | {
|
---|
1017 | errno = ENOSYS;
|
---|
1018 | return -1;
|
---|
1019 | }
|
---|
1020 |
|
---|
1021 | static int cephwrap_get_real_filename(struct vfs_handle_struct *handle,
|
---|
1022 | const char *path,
|
---|
1023 | const char *name,
|
---|
1024 | TALLOC_CTX *mem_ctx,
|
---|
1025 | char **found_name)
|
---|
1026 | {
|
---|
1027 | /*
|
---|
1028 | * Don't fall back to get_real_filename so callers can differentiate
|
---|
1029 | * between a full directory scan and an actual case-insensitive stat.
|
---|
1030 | */
|
---|
1031 | errno = EOPNOTSUPP;
|
---|
1032 | return -1;
|
---|
1033 | }
|
---|
1034 |
|
---|
1035 | static const char *cephwrap_connectpath(struct vfs_handle_struct *handle,
|
---|
1036 | const char *fname)
|
---|
1037 | {
|
---|
1038 | return handle->conn->connectpath;
|
---|
1039 | }
|
---|
1040 |
|
---|
1041 | /****************************************************************
|
---|
1042 | Extended attribute operations.
|
---|
1043 | *****************************************************************/
|
---|
1044 |
|
---|
1045 | static ssize_t cephwrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
|
---|
1046 | {
|
---|
1047 | int ret;
|
---|
1048 | DEBUG(10, ("[CEPH] getxattr(%p, %s, %s, %p, %llu)\n", handle, path, name, value, llu(size)));
|
---|
1049 | ret = ceph_getxattr(handle->data, path, name, value, size);
|
---|
1050 | DEBUG(10, ("[CEPH] getxattr(...) = %d\n", ret));
|
---|
1051 | if (ret < 0) {
|
---|
1052 | WRAP_RETURN(ret);
|
---|
1053 | } else {
|
---|
1054 | return (ssize_t)ret;
|
---|
1055 | }
|
---|
1056 | }
|
---|
1057 |
|
---|
1058 | static ssize_t cephwrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
|
---|
1059 | {
|
---|
1060 | int ret;
|
---|
1061 | DEBUG(10, ("[CEPH] fgetxattr(%p, %p, %s, %p, %llu)\n", handle, fsp, name, value, llu(size)));
|
---|
1062 | #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
|
---|
1063 | ret = ceph_fgetxattr(handle->data, fsp->fh->fd, name, value, size);
|
---|
1064 | #else
|
---|
1065 | ret = ceph_getxattr(handle->data, fsp->fsp_name->base_name, name, value, size);
|
---|
1066 | #endif
|
---|
1067 | DEBUG(10, ("[CEPH] fgetxattr(...) = %d\n", ret));
|
---|
1068 | if (ret < 0) {
|
---|
1069 | WRAP_RETURN(ret);
|
---|
1070 | } else {
|
---|
1071 | return (ssize_t)ret;
|
---|
1072 | }
|
---|
1073 | }
|
---|
1074 |
|
---|
1075 | static ssize_t cephwrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
|
---|
1076 | {
|
---|
1077 | int ret;
|
---|
1078 | DEBUG(10, ("[CEPH] listxattr(%p, %s, %p, %llu)\n", handle, path, list, llu(size)));
|
---|
1079 | ret = ceph_listxattr(handle->data, path, list, size);
|
---|
1080 | DEBUG(10, ("[CEPH] listxattr(...) = %d\n", ret));
|
---|
1081 | if (ret < 0) {
|
---|
1082 | WRAP_RETURN(ret);
|
---|
1083 | } else {
|
---|
1084 | return (ssize_t)ret;
|
---|
1085 | }
|
---|
1086 | }
|
---|
1087 |
|
---|
1088 | #if 0
|
---|
1089 | static ssize_t cephwrap_llistxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
|
---|
1090 | {
|
---|
1091 | int ret;
|
---|
1092 | DEBUG(10, ("[CEPH] llistxattr(%p, %s, %p, %llu)\n", handle, path, list, llu(size)));
|
---|
1093 | ret = ceph_llistxattr(handle->data, path, list, size);
|
---|
1094 | DEBUG(10, ("[CEPH] listxattr(...) = %d\n", ret));
|
---|
1095 | if (ret < 0) {
|
---|
1096 | WRAP_RETURN(ret);
|
---|
1097 | } else {
|
---|
1098 | return (ssize_t)ret;
|
---|
1099 | }
|
---|
1100 | }
|
---|
1101 | #endif
|
---|
1102 |
|
---|
1103 | static ssize_t cephwrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
|
---|
1104 | {
|
---|
1105 | int ret;
|
---|
1106 | DEBUG(10, ("[CEPH] flistxattr(%p, %p, %s, %llu)\n", handle, fsp, list, llu(size)));
|
---|
1107 | #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
|
---|
1108 | ret = ceph_flistxattr(handle->data, fsp->fh->fd, list, size);
|
---|
1109 | #else
|
---|
1110 | ret = ceph_listxattr(handle->data, fsp->fsp_name->base_name, list, size);
|
---|
1111 | #endif
|
---|
1112 | DEBUG(10, ("[CEPH] flistxattr(...) = %d\n", ret));
|
---|
1113 | if (ret < 0) {
|
---|
1114 | WRAP_RETURN(ret);
|
---|
1115 | } else {
|
---|
1116 | return (ssize_t)ret;
|
---|
1117 | }
|
---|
1118 | }
|
---|
1119 |
|
---|
1120 | static int cephwrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
|
---|
1121 | {
|
---|
1122 | int ret;
|
---|
1123 | DEBUG(10, ("[CEPH] removexattr(%p, %s, %s)\n", handle, path, name));
|
---|
1124 | ret = ceph_removexattr(handle->data, path, name);
|
---|
1125 | DEBUG(10, ("[CEPH] removexattr(...) = %d\n", ret));
|
---|
1126 | WRAP_RETURN(ret);
|
---|
1127 | }
|
---|
1128 |
|
---|
1129 | static int cephwrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
|
---|
1130 | {
|
---|
1131 | int ret;
|
---|
1132 | DEBUG(10, ("[CEPH] fremovexattr(%p, %p, %s)\n", handle, fsp, name));
|
---|
1133 | #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
|
---|
1134 | ret = ceph_fremovexattr(handle->data, fsp->fh->fd, name);
|
---|
1135 | #else
|
---|
1136 | ret = ceph_removexattr(handle->data, fsp->fsp_name->base_name, name);
|
---|
1137 | #endif
|
---|
1138 | DEBUG(10, ("[CEPH] fremovexattr(...) = %d\n", ret));
|
---|
1139 | WRAP_RETURN(ret);
|
---|
1140 | }
|
---|
1141 |
|
---|
1142 | static int cephwrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
|
---|
1143 | {
|
---|
1144 | int ret;
|
---|
1145 | DEBUG(10, ("[CEPH] setxattr(%p, %s, %s, %p, %llu, %d)\n", handle, path, name, value, llu(size), flags));
|
---|
1146 | ret = ceph_setxattr(handle->data, path, name, value, size, flags);
|
---|
1147 | DEBUG(10, ("[CEPH] setxattr(...) = %d\n", ret));
|
---|
1148 | WRAP_RETURN(ret);
|
---|
1149 | }
|
---|
1150 |
|
---|
1151 | static int cephwrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
|
---|
1152 | {
|
---|
1153 | int ret;
|
---|
1154 | DEBUG(10, ("[CEPH] fsetxattr(%p, %p, %s, %p, %llu, %d)\n", handle, fsp, name, value, llu(size), flags));
|
---|
1155 | #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
|
---|
1156 | ret = ceph_fsetxattr(handle->data, fsp->fh->fd,
|
---|
1157 | name, value, size, flags);
|
---|
1158 | #else
|
---|
1159 | ret = ceph_setxattr(handle->data, fsp->fsp_name->base_name, name, value, size, flags);
|
---|
1160 | #endif
|
---|
1161 | DEBUG(10, ("[CEPH] fsetxattr(...) = %d\n", ret));
|
---|
1162 | WRAP_RETURN(ret);
|
---|
1163 | }
|
---|
1164 |
|
---|
1165 | static bool cephwrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
|
---|
1166 | {
|
---|
1167 |
|
---|
1168 | /*
|
---|
1169 | * We do not support AIO yet.
|
---|
1170 | */
|
---|
1171 |
|
---|
1172 | DEBUG(10, ("[CEPH] cephwrap_aio_force(%p, %p) = false (errno = ENOTSUP)\n", handle, fsp));
|
---|
1173 | errno = ENOTSUP;
|
---|
1174 | return false;
|
---|
1175 | }
|
---|
1176 |
|
---|
1177 | static bool cephwrap_is_offline(struct vfs_handle_struct *handle,
|
---|
1178 | const struct smb_filename *fname,
|
---|
1179 | SMB_STRUCT_STAT *sbuf)
|
---|
1180 | {
|
---|
1181 | return false;
|
---|
1182 | }
|
---|
1183 |
|
---|
1184 | static int cephwrap_set_offline(struct vfs_handle_struct *handle,
|
---|
1185 | const struct smb_filename *fname)
|
---|
1186 | {
|
---|
1187 | errno = ENOTSUP;
|
---|
1188 | return -1;
|
---|
1189 | }
|
---|
1190 |
|
---|
1191 | static SMB_ACL_T cephwrap_sys_acl_get_file(struct vfs_handle_struct *handle,
|
---|
1192 | const char *path_p,
|
---|
1193 | SMB_ACL_TYPE_T type,
|
---|
1194 | TALLOC_CTX *mem_ctx)
|
---|
1195 | {
|
---|
1196 | errno = ENOTSUP;
|
---|
1197 | return NULL;
|
---|
1198 | }
|
---|
1199 |
|
---|
1200 | static SMB_ACL_T cephwrap_sys_acl_get_fd(struct vfs_handle_struct *handle,
|
---|
1201 | struct files_struct *fsp,
|
---|
1202 | TALLOC_CTX *mem_ctx)
|
---|
1203 | {
|
---|
1204 | errno = ENOTSUP;
|
---|
1205 | return NULL;
|
---|
1206 | }
|
---|
1207 |
|
---|
1208 | static int cephwrap_sys_acl_set_file(struct vfs_handle_struct *handle,
|
---|
1209 | const char *name,
|
---|
1210 | SMB_ACL_TYPE_T acltype,
|
---|
1211 | SMB_ACL_T theacl)
|
---|
1212 | {
|
---|
1213 | errno = ENOTSUP;
|
---|
1214 | return -1;
|
---|
1215 | }
|
---|
1216 |
|
---|
1217 | static int cephwrap_sys_acl_set_fd(struct vfs_handle_struct *handle,
|
---|
1218 | struct files_struct *fsp,
|
---|
1219 | SMB_ACL_T theacl)
|
---|
1220 | {
|
---|
1221 | errno = ENOTSUP;
|
---|
1222 | return -1;
|
---|
1223 | }
|
---|
1224 |
|
---|
1225 | static int cephwrap_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
|
---|
1226 | const char *path)
|
---|
1227 | {
|
---|
1228 | errno = ENOTSUP;
|
---|
1229 | return -1;
|
---|
1230 | }
|
---|
1231 |
|
---|
1232 | static struct vfs_fn_pointers ceph_fns = {
|
---|
1233 | /* Disk operations */
|
---|
1234 |
|
---|
1235 | .connect_fn = cephwrap_connect,
|
---|
1236 | .disconnect_fn = cephwrap_disconnect,
|
---|
1237 | .disk_free_fn = cephwrap_disk_free,
|
---|
1238 | .get_quota_fn = cephwrap_get_quota,
|
---|
1239 | .set_quota_fn = cephwrap_set_quota,
|
---|
1240 | .statvfs_fn = cephwrap_statvfs,
|
---|
1241 |
|
---|
1242 | /* Directory operations */
|
---|
1243 |
|
---|
1244 | .opendir_fn = cephwrap_opendir,
|
---|
1245 | .fdopendir_fn = cephwrap_fdopendir,
|
---|
1246 | .readdir_fn = cephwrap_readdir,
|
---|
1247 | .seekdir_fn = cephwrap_seekdir,
|
---|
1248 | .telldir_fn = cephwrap_telldir,
|
---|
1249 | .rewind_dir_fn = cephwrap_rewinddir,
|
---|
1250 | .mkdir_fn = cephwrap_mkdir,
|
---|
1251 | .rmdir_fn = cephwrap_rmdir,
|
---|
1252 | .closedir_fn = cephwrap_closedir,
|
---|
1253 |
|
---|
1254 | /* File operations */
|
---|
1255 |
|
---|
1256 | .open_fn = cephwrap_open,
|
---|
1257 | .close_fn = cephwrap_close,
|
---|
1258 | .read_fn = cephwrap_read,
|
---|
1259 | .pread_fn = cephwrap_pread,
|
---|
1260 | .write_fn = cephwrap_write,
|
---|
1261 | .pwrite_fn = cephwrap_pwrite,
|
---|
1262 | .lseek_fn = cephwrap_lseek,
|
---|
1263 | .sendfile_fn = cephwrap_sendfile,
|
---|
1264 | .recvfile_fn = cephwrap_recvfile,
|
---|
1265 | .rename_fn = cephwrap_rename,
|
---|
1266 | .fsync_fn = cephwrap_fsync,
|
---|
1267 | .stat_fn = cephwrap_stat,
|
---|
1268 | .fstat_fn = cephwrap_fstat,
|
---|
1269 | .lstat_fn = cephwrap_lstat,
|
---|
1270 | .unlink_fn = cephwrap_unlink,
|
---|
1271 | .chmod_fn = cephwrap_chmod,
|
---|
1272 | .fchmod_fn = cephwrap_fchmod,
|
---|
1273 | .chown_fn = cephwrap_chown,
|
---|
1274 | .fchown_fn = cephwrap_fchown,
|
---|
1275 | .lchown_fn = cephwrap_lchown,
|
---|
1276 | .chdir_fn = cephwrap_chdir,
|
---|
1277 | .getwd_fn = cephwrap_getwd,
|
---|
1278 | .ntimes_fn = cephwrap_ntimes,
|
---|
1279 | .ftruncate_fn = cephwrap_ftruncate,
|
---|
1280 | .lock_fn = cephwrap_lock,
|
---|
1281 | .kernel_flock_fn = cephwrap_kernel_flock,
|
---|
1282 | .linux_setlease_fn = cephwrap_linux_setlease,
|
---|
1283 | .getlock_fn = cephwrap_getlock,
|
---|
1284 | .symlink_fn = cephwrap_symlink,
|
---|
1285 | .readlink_fn = cephwrap_readlink,
|
---|
1286 | .link_fn = cephwrap_link,
|
---|
1287 | .mknod_fn = cephwrap_mknod,
|
---|
1288 | .realpath_fn = cephwrap_realpath,
|
---|
1289 | .chflags_fn = cephwrap_chflags,
|
---|
1290 | .get_real_filename_fn = cephwrap_get_real_filename,
|
---|
1291 | .connectpath_fn = cephwrap_connectpath,
|
---|
1292 |
|
---|
1293 | /* EA operations. */
|
---|
1294 | .getxattr_fn = cephwrap_getxattr,
|
---|
1295 | .fgetxattr_fn = cephwrap_fgetxattr,
|
---|
1296 | .listxattr_fn = cephwrap_listxattr,
|
---|
1297 | .flistxattr_fn = cephwrap_flistxattr,
|
---|
1298 | .removexattr_fn = cephwrap_removexattr,
|
---|
1299 | .fremovexattr_fn = cephwrap_fremovexattr,
|
---|
1300 | .setxattr_fn = cephwrap_setxattr,
|
---|
1301 | .fsetxattr_fn = cephwrap_fsetxattr,
|
---|
1302 |
|
---|
1303 | /* Posix ACL Operations */
|
---|
1304 | .sys_acl_get_file_fn = cephwrap_sys_acl_get_file,
|
---|
1305 | .sys_acl_get_fd_fn = cephwrap_sys_acl_get_fd,
|
---|
1306 | .sys_acl_set_file_fn = cephwrap_sys_acl_set_file,
|
---|
1307 | .sys_acl_set_fd_fn = cephwrap_sys_acl_set_fd,
|
---|
1308 | .sys_acl_delete_def_file_fn = cephwrap_sys_acl_delete_def_file,
|
---|
1309 |
|
---|
1310 | /* aio operations */
|
---|
1311 | .aio_force_fn = cephwrap_aio_force,
|
---|
1312 |
|
---|
1313 | /* offline operations */
|
---|
1314 | .is_offline_fn = cephwrap_is_offline,
|
---|
1315 | .set_offline_fn = cephwrap_set_offline
|
---|
1316 | };
|
---|
1317 |
|
---|
1318 | NTSTATUS vfs_ceph_init(void);
|
---|
1319 | NTSTATUS vfs_ceph_init(void)
|
---|
1320 | {
|
---|
1321 | return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
|
---|
1322 | "ceph", &ceph_fns);
|
---|
1323 | }
|
---|