]> git.proxmox.com Git - ceph.git/blob - ceph/src/java/native/libcephfs_jni.cc
975a092dace5a0429b3423632adedba5570306cb
[ceph.git] / ceph / src / java / native / libcephfs_jni.cc
1 /*
2 * Permission is hereby granted, free of charge, to any person obtaining a
3 * copy of this software and associated documentation files (the "Software"),
4 * to deal in the Software without restriction, including without limitation
5 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
6 * and/or sell copies of the Software, and to permit persons to whom the
7 * Software is furnished to do so, subject to the following conditions:
8 *
9 * The above copyright notice and this permission notice shall be included in
10 * all copies or substantial portions of the Software.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
18 * DEALINGS IN THE SOFTWARE.
19 */
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <sys/un.h>
27 #include <jni.h>
28
29 #include "ScopedLocalRef.h"
30 #include "JniConstants.h"
31
32 #include "include/cephfs/libcephfs.h"
33 #include "common/dout.h"
34
35 #define dout_subsys ceph_subsys_javaclient
36
37 #include "com_ceph_fs_CephMount.h"
38
39 #define CEPH_STAT_CP "com/ceph/fs/CephStat"
40 #define CEPH_STAT_VFS_CP "com/ceph/fs/CephStatVFS"
41 #define CEPH_FILE_EXTENT_CP "com/ceph/fs/CephFileExtent"
42 #define CEPH_MOUNT_CP "com/ceph/fs/CephMount"
43 #define CEPH_NOTMOUNTED_CP "com/ceph/fs/CephNotMountedException"
44 #define CEPH_FILEEXISTS_CP "com/ceph/fs/CephFileAlreadyExistsException"
45 #define CEPH_ALREADYMOUNTED_CP "com/ceph/fs/CephAlreadyMountedException"
46 #define CEPH_NOTDIR_CP "com/ceph/fs/CephNotDirectoryException"
47
48 /*
49 * Flags to open(). must be synchronized with CephMount.java
50 *
51 * There are two versions of flags: the version in Java and the version in the
52 * target library (e.g. libc or libcephfs). We control the Java values and map
53 * to the target value with fixup_* functions below. This is much faster than
54 * keeping the values in Java and making a cross-JNI up-call to retrieve them,
55 * and makes it easy to keep any platform specific value changes in this file.
56 */
57 #define JAVA_O_RDONLY 1
58 #define JAVA_O_RDWR 2
59 #define JAVA_O_APPEND 4
60 #define JAVA_O_CREAT 8
61 #define JAVA_O_TRUNC 16
62 #define JAVA_O_EXCL 32
63 #define JAVA_O_WRONLY 64
64 #define JAVA_O_DIRECTORY 128
65
66 /*
67 * Whence flags for seek(). sync with CephMount.java if changed.
68 *
69 * Mapping of SEEK_* done in seek function.
70 */
71 #define JAVA_SEEK_SET 1
72 #define JAVA_SEEK_CUR 2
73 #define JAVA_SEEK_END 3
74
75 /*
76 * File attribute flags. sync with CephMount.java if changed.
77 */
78 #define JAVA_SETATTR_MODE 1
79 #define JAVA_SETATTR_UID 2
80 #define JAVA_SETATTR_GID 4
81 #define JAVA_SETATTR_MTIME 8
82 #define JAVA_SETATTR_ATIME 16
83
84 /*
85 * Setxattr flags. sync with CephMount.java if changed.
86 */
87 #define JAVA_XATTR_CREATE 1
88 #define JAVA_XATTR_REPLACE 2
89 #define JAVA_XATTR_NONE 3
90
91 /*
92 * flock flags. sync with CephMount.java if changed.
93 */
94 #define JAVA_LOCK_SH 1
95 #define JAVA_LOCK_EX 2
96 #define JAVA_LOCK_NB 4
97 #define JAVA_LOCK_UN 8
98
99 /* Map JAVA_O_* open flags to values in libc */
100 static inline int fixup_open_flags(jint jflags)
101 {
102 int ret = 0;
103
104 #define FIXUP_OPEN_FLAG(name) \
105 if (jflags & JAVA_##name) \
106 ret |= name;
107
108 FIXUP_OPEN_FLAG(O_RDONLY)
109 FIXUP_OPEN_FLAG(O_RDWR)
110 FIXUP_OPEN_FLAG(O_APPEND)
111 FIXUP_OPEN_FLAG(O_CREAT)
112 FIXUP_OPEN_FLAG(O_TRUNC)
113 FIXUP_OPEN_FLAG(O_EXCL)
114 FIXUP_OPEN_FLAG(O_WRONLY)
115 FIXUP_OPEN_FLAG(O_DIRECTORY)
116
117 #undef FIXUP_OPEN_FLAG
118
119 return ret;
120 }
121
122 /* Map JAVA_SETATTR_* to values in ceph lib */
123 static inline int fixup_attr_mask(jint jmask)
124 {
125 int mask = 0;
126
127 #define FIXUP_ATTR_MASK(name) \
128 if (jmask & JAVA_##name) \
129 mask |= CEPH_##name;
130
131 FIXUP_ATTR_MASK(SETATTR_MODE)
132 FIXUP_ATTR_MASK(SETATTR_UID)
133 FIXUP_ATTR_MASK(SETATTR_GID)
134 FIXUP_ATTR_MASK(SETATTR_MTIME)
135 FIXUP_ATTR_MASK(SETATTR_ATIME)
136
137 #undef FIXUP_ATTR_MASK
138
139 return mask;
140 }
141
142 /* Cached field IDs for com.ceph.fs.CephStat */
143 static jfieldID cephstat_mode_fid;
144 static jfieldID cephstat_uid_fid;
145 static jfieldID cephstat_gid_fid;
146 static jfieldID cephstat_size_fid;
147 static jfieldID cephstat_blksize_fid;
148 static jfieldID cephstat_blocks_fid;
149 static jfieldID cephstat_a_time_fid;
150 static jfieldID cephstat_m_time_fid;
151 static jfieldID cephstat_is_file_fid;
152 static jfieldID cephstat_is_directory_fid;
153 static jfieldID cephstat_is_symlink_fid;
154
155 /* Cached field IDs for com.ceph.fs.CephStatVFS */
156 static jfieldID cephstatvfs_bsize_fid;
157 static jfieldID cephstatvfs_frsize_fid;
158 static jfieldID cephstatvfs_blocks_fid;
159 static jfieldID cephstatvfs_bavail_fid;
160 static jfieldID cephstatvfs_files_fid;
161 static jfieldID cephstatvfs_fsid_fid;
162 static jfieldID cephstatvfs_namemax_fid;
163
164 /* Cached field IDs for com.ceph.fs.CephMount */
165 static jfieldID cephmount_instance_ptr_fid;
166
167 /* Cached field IDs for com.ceph.fs.CephFileExtent */
168 static jclass cephfileextent_cls;
169 static jmethodID cephfileextent_ctor_fid;
170
171 /*
172 * Exception throwing helper. Adapted from Apache Hadoop header
173 * org_apache_hadoop.h by adding the do {} while (0) construct.
174 */
175 #define THROW(env, exception_name, message) \
176 do { \
177 jclass ecls = env->FindClass(exception_name); \
178 if (ecls) { \
179 int ret = env->ThrowNew(ecls, message); \
180 if (ret < 0) { \
181 printf("(CephFS) Fatal Error\n"); \
182 } \
183 env->DeleteLocalRef(ecls); \
184 } \
185 } while (0)
186
187
188 static void cephThrowNullArg(JNIEnv *env, const char *msg)
189 {
190 THROW(env, "java/lang/NullPointerException", msg);
191 }
192
193 static void cephThrowOutOfMemory(JNIEnv *env, const char *msg)
194 {
195 THROW(env, "java/lang/OutOfMemoryError", msg);
196 }
197
198 static void cephThrowInternal(JNIEnv *env, const char *msg)
199 {
200 THROW(env, "java/lang/InternalError", msg);
201 }
202
203 static void cephThrowIndexBounds(JNIEnv *env, const char *msg)
204 {
205 THROW(env, "java/lang/IndexOutOfBoundsException", msg);
206 }
207
208 static void cephThrowIllegalArg(JNIEnv *env, const char *msg)
209 {
210 THROW(env, "java/lang/IllegalArgumentException", msg);
211 }
212
213 static void cephThrowFNF(JNIEnv *env, const char *msg)
214 {
215 THROW(env, "java/io/FileNotFoundException", msg);
216 }
217
218 static void cephThrowFileExists(JNIEnv *env, const char *msg)
219 {
220 THROW(env, CEPH_FILEEXISTS_CP, msg);
221 }
222
223 static void cephThrowNotDir(JNIEnv *env, const char *msg)
224 {
225 THROW(env, CEPH_NOTDIR_CP, msg);
226 }
227
228 static void handle_error(JNIEnv *env, int rc)
229 {
230 switch (rc) {
231 case -ENOENT:
232 cephThrowFNF(env, "");
233 return;
234 case -EEXIST:
235 cephThrowFileExists(env, "");
236 return;
237 case -ENOTDIR:
238 cephThrowNotDir(env, "");
239 return;
240 default:
241 break;
242 }
243
244 THROW(env, "java/io/IOException", strerror(-rc));
245 }
246
247 #define CHECK_ARG_NULL(v, m, r) do { \
248 if (!(v)) { \
249 cephThrowNullArg(env, (m)); \
250 return (r); \
251 } } while (0)
252
253 #define CHECK_ARG_BOUNDS(c, m, r) do { \
254 if ((c)) { \
255 cephThrowIndexBounds(env, (m)); \
256 return (r); \
257 } } while (0)
258
259 #define CHECK_MOUNTED(_c, _r) do { \
260 if (!ceph_is_mounted((_c))) { \
261 THROW(env, CEPH_NOTMOUNTED_CP, "not mounted"); \
262 return (_r); \
263 } } while (0)
264
265 /*
266 * Cast a jlong to ceph_mount_info. Each JNI function is expected to pass in
267 * the class instance variable instance_ptr. Passing a parameter is faster
268 * than reaching back into Java via an upcall to retreive this pointer.
269 */
270 static inline struct ceph_mount_info *get_ceph_mount(jlong j_mntp)
271 {
272 return (struct ceph_mount_info *)j_mntp;
273 }
274
275 /*
276 * Setup cached field IDs
277 */
278 static void setup_field_ids(JNIEnv *env, jclass clz)
279 {
280 jclass cephstat_cls;
281 jclass cephstatvfs_cls;
282 jclass tmp_cephfileextent_cls;
283
284 /*
285 * Get a fieldID from a class with a specific type
286 *
287 * clz: jclass
288 * field: field in clz
289 * type: integer, long, etc..
290 *
291 * This macro assumes some naming convention that is used
292 * only in this file:
293 *
294 * GETFID(cephstat, mode, I) gets translated into
295 * cephstat_mode_fid = env->GetFieldID(cephstat_cls, "mode", "I");
296 */
297 #define GETFID(clz, field, type) do { \
298 clz ## _ ## field ## _fid = env->GetFieldID(clz ## _cls, #field, #type); \
299 if ( ! clz ## _ ## field ## _fid ) \
300 return; \
301 } while (0)
302
303 /* Cache CephStat fields */
304
305 cephstat_cls = env->FindClass(CEPH_STAT_CP);
306 if (!cephstat_cls)
307 return;
308
309 GETFID(cephstat, mode, I);
310 GETFID(cephstat, uid, I);
311 GETFID(cephstat, gid, I);
312 GETFID(cephstat, size, J);
313 GETFID(cephstat, blksize, J);
314 GETFID(cephstat, blocks, J);
315 GETFID(cephstat, a_time, J);
316 GETFID(cephstat, m_time, J);
317 GETFID(cephstat, is_file, Z);
318 GETFID(cephstat, is_directory, Z);
319 GETFID(cephstat, is_symlink, Z);
320
321 /* Cache CephStatVFS fields */
322
323 cephstatvfs_cls = env->FindClass(CEPH_STAT_VFS_CP);
324 if (!cephstatvfs_cls)
325 return;
326
327 GETFID(cephstatvfs, bsize, J);
328 GETFID(cephstatvfs, frsize, J);
329 GETFID(cephstatvfs, blocks, J);
330 GETFID(cephstatvfs, bavail, J);
331 GETFID(cephstatvfs, files, J);
332 GETFID(cephstatvfs, fsid, J);
333 GETFID(cephstatvfs, namemax, J);
334
335 /* Cache CephFileExtent fields */
336
337 tmp_cephfileextent_cls = env->FindClass(CEPH_FILE_EXTENT_CP);
338 if (!tmp_cephfileextent_cls)
339 return;
340
341 cephfileextent_cls = (jclass)env->NewGlobalRef(tmp_cephfileextent_cls);
342 env->DeleteLocalRef(tmp_cephfileextent_cls);
343
344 cephfileextent_ctor_fid = env->GetMethodID(cephfileextent_cls, "<init>", "(JJ[I)V");
345 if (!cephfileextent_ctor_fid)
346 return;
347
348 JniConstants::init(env);
349
350 #undef GETFID
351
352 cephmount_instance_ptr_fid = env->GetFieldID(clz, "instance_ptr", "J");
353 }
354
355
356 /*
357 * Class: com_ceph_fs_CephMount
358 * Method: native_initialize
359 * Signature: ()V
360 */
361 JNIEXPORT void JNICALL Java_com_ceph_fs_CephMount_native_1initialize
362 (JNIEnv *env, jclass clz)
363 {
364 setup_field_ids(env, clz);
365 }
366
367 /*
368 * Class: com_ceph_fs_CephMount
369 * Method: native_ceph_create
370 * Signature: (Lcom/ceph/fs/CephMount;Ljava/lang/String;)I
371 */
372 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1create
373 (JNIEnv *env, jclass clz, jobject j_cephmount, jstring j_id)
374 {
375 struct ceph_mount_info *cmount;
376 const char *c_id = NULL;
377 int ret;
378
379 CHECK_ARG_NULL(j_cephmount, "@mount is null", -1);
380
381 if (j_id) {
382 c_id = env->GetStringUTFChars(j_id, NULL);
383 if (!c_id) {
384 cephThrowInternal(env, "Failed to pin memory");
385 return -1;
386 }
387 }
388
389 ret = ceph_create(&cmount, c_id);
390
391 if (c_id)
392 env->ReleaseStringUTFChars(j_id, c_id);
393
394 if (ret) {
395 THROW(env, "java/lang/RuntimeException", "failed to create Ceph mount object");
396 return ret;
397 }
398
399 env->SetLongField(j_cephmount, cephmount_instance_ptr_fid, (long)cmount);
400
401 return ret;
402 }
403
404 /*
405 * Class: com_ceph_fs_CephMount
406 * Method: native_ceph_mount
407 * Signature: (JLjava/lang/String;)I
408 */
409 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1mount
410 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_root)
411 {
412 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
413 CephContext *cct = ceph_get_mount_context(cmount);
414 const char *c_root = NULL;
415 int ret;
416
417 /*
418 * Toss a message up if we are already mounted.
419 */
420 if (ceph_is_mounted(cmount)) {
421 THROW(env, CEPH_ALREADYMOUNTED_CP, "");
422 return -1;
423 }
424
425 if (j_root) {
426 c_root = env->GetStringUTFChars(j_root, NULL);
427 if (!c_root) {
428 cephThrowInternal(env, "Failed to pin memory");
429 return -1;
430 }
431 }
432
433 ldout(cct, 10) << "jni: ceph_mount: " << (c_root ? c_root : "<NULL>") << dendl;
434
435 ret = ceph_mount(cmount, c_root);
436
437 ldout(cct, 10) << "jni: ceph_mount: exit ret " << ret << dendl;
438
439 if (c_root)
440 env->ReleaseStringUTFChars(j_root, c_root);
441
442 if (ret)
443 handle_error(env, ret);
444
445 return ret;
446 }
447
448 /*
449 * Class: com_ceph_fs_CephMount
450 * Method: native_ceph_unmount
451 * Signature: (J)I
452 */
453 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1unmount
454 (JNIEnv *env, jclass clz, jlong j_mntp)
455 {
456 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
457 CephContext *cct = ceph_get_mount_context(cmount);
458 int ret;
459
460 ldout(cct, 10) << "jni: ceph_unmount enter" << dendl;
461
462 CHECK_MOUNTED(cmount, -1);
463
464 ret = ceph_unmount(cmount);
465
466 ldout(cct, 10) << "jni: ceph_unmount exit ret " << ret << dendl;
467
468 if (ret)
469 handle_error(env, ret);
470
471 return ret;
472 }
473
474 /*
475 * Class: com_ceph_fs_CephMount
476 * Method: native_ceph_release
477 * Signature: (J)I
478 */
479 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1release
480 (JNIEnv *env, jclass clz, jlong j_mntp)
481 {
482 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
483 CephContext *cct = ceph_get_mount_context(cmount);
484 int ret;
485
486 ldout(cct, 10) << "jni: ceph_release called" << dendl;
487
488 ret = ceph_release(cmount);
489
490 if (ret)
491 handle_error(env, ret);
492
493 return ret;
494 }
495
496 /*
497 * Class: com_ceph_fs_CephMount
498 * Method: native_ceph_conf_set
499 * Signature: (JLjava/lang/String;Ljava/lang/String;)I
500 */
501 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1conf_1set
502 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_opt, jstring j_val)
503 {
504 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
505 CephContext *cct = ceph_get_mount_context(cmount);
506 const char *c_opt, *c_val;
507 int ret;
508
509 CHECK_ARG_NULL(j_opt, "@option is null", -1);
510 CHECK_ARG_NULL(j_val, "@value is null", -1);
511
512 c_opt = env->GetStringUTFChars(j_opt, NULL);
513 if (!c_opt) {
514 cephThrowInternal(env, "failed to pin memory");
515 return -1;
516 }
517
518 c_val = env->GetStringUTFChars(j_val, NULL);
519 if (!c_val) {
520 env->ReleaseStringUTFChars(j_opt, c_opt);
521 cephThrowInternal(env, "failed to pin memory");
522 return -1;
523 }
524
525 ldout(cct, 10) << "jni: conf_set: opt " << c_opt << " val " << c_val << dendl;
526
527 ret = ceph_conf_set(cmount, c_opt, c_val);
528
529 ldout(cct, 10) << "jni: conf_set: exit ret " << ret << dendl;
530
531 env->ReleaseStringUTFChars(j_opt, c_opt);
532 env->ReleaseStringUTFChars(j_val, c_val);
533
534 if (ret)
535 handle_error(env, ret);
536
537 return ret;
538 }
539
540 /*
541 * Class: com_ceph_fs_CephMount
542 * Method: native_ceph_conf_get
543 * Signature: (JLjava/lang/String;)Ljava/lang/String;
544 */
545 JNIEXPORT jstring JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1conf_1get
546 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_opt)
547 {
548 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
549 CephContext *cct = ceph_get_mount_context(cmount);
550 const char *c_opt;
551 jstring value = NULL;
552 int ret, buflen;
553 char *buf;
554
555 CHECK_ARG_NULL(j_opt, "@option is null", NULL);
556
557 c_opt = env->GetStringUTFChars(j_opt, NULL);
558 if (!c_opt) {
559 cephThrowInternal(env, "failed to pin memory");
560 return NULL;
561 }
562
563 buflen = 128;
564 buf = new (std::nothrow) char[buflen];
565 if (!buf) {
566 cephThrowOutOfMemory(env, "head allocation failed");
567 goto out;
568 }
569
570 while (1) {
571 memset(buf, 0, sizeof(char)*buflen);
572 ldout(cct, 10) << "jni: conf_get: opt " << c_opt << " len " << buflen << dendl;
573 ret = ceph_conf_get(cmount, c_opt, buf, buflen);
574 if (ret == -ENAMETOOLONG) {
575 buflen *= 2;
576 delete [] buf;
577 buf = new (std::nothrow) char[buflen];
578 if (!buf) {
579 cephThrowOutOfMemory(env, "head allocation failed");
580 goto out;
581 }
582 } else
583 break;
584 }
585
586 ldout(cct, 10) << "jni: conf_get: ret " << ret << dendl;
587
588 if (ret == 0)
589 value = env->NewStringUTF(buf);
590 else if (ret != -ENOENT)
591 handle_error(env, ret);
592
593 delete [] buf;
594
595 out:
596 env->ReleaseStringUTFChars(j_opt, c_opt);
597 return value;
598 }
599
600 /*
601 * Class: com_ceph_fs_CephMount
602 * Method: native_ceph_conf_read_file
603 * Signature: (JLjava/lang/String;)I
604 */
605 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1conf_1read_1file
606 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path)
607 {
608 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
609 CephContext *cct = ceph_get_mount_context(cmount);
610 const char *c_path;
611 int ret;
612
613 CHECK_ARG_NULL(j_path, "@path is null", -1);
614
615 c_path = env->GetStringUTFChars(j_path, NULL);
616 if (!c_path) {
617 cephThrowInternal(env, "failed to pin memory");
618 return -1;
619 }
620
621 ldout(cct, 10) << "jni: conf_read_file: path " << c_path << dendl;
622
623 ret = ceph_conf_read_file(cmount, c_path);
624
625 ldout(cct, 10) << "jni: conf_read_file: exit ret " << ret << dendl;
626
627 env->ReleaseStringUTFChars(j_path, c_path);
628
629 if (ret)
630 handle_error(env, ret);
631
632 return ret;
633 }
634
635 /*
636 * Class: com_ceph_fs_CephMount
637 * Method: native_ceph_statfs
638 * Signature: (JLjava/lang/String;Lcom/ceph/fs/CephStatVFS;)I
639 */
640 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1statfs
641 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path, jobject j_cephstatvfs)
642 {
643 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
644 CephContext *cct = ceph_get_mount_context(cmount);
645 const char *c_path;
646 struct statvfs st;
647 int ret;
648
649 CHECK_ARG_NULL(j_path, "@path is null", -1);
650 CHECK_ARG_NULL(j_cephstatvfs, "@stat is null", -1);
651 CHECK_MOUNTED(cmount, -1);
652
653 c_path = env->GetStringUTFChars(j_path, NULL);
654 if (!c_path) {
655 cephThrowInternal(env, "Failed to pin memory");
656 return -1;
657 }
658
659 ldout(cct, 10) << "jni: statfs: path " << c_path << dendl;
660
661 ret = ceph_statfs(cmount, c_path, &st);
662
663 ldout(cct, 10) << "jni: statfs: exit ret " << ret << dendl;
664
665 env->ReleaseStringUTFChars(j_path, c_path);
666
667 if (ret) {
668 handle_error(env, ret);
669 return ret;
670 }
671
672 env->SetLongField(j_cephstatvfs, cephstatvfs_bsize_fid, st.f_bsize);
673 env->SetLongField(j_cephstatvfs, cephstatvfs_frsize_fid, st.f_frsize);
674 env->SetLongField(j_cephstatvfs, cephstatvfs_blocks_fid, st.f_blocks);
675 env->SetLongField(j_cephstatvfs, cephstatvfs_bavail_fid, st.f_bavail);
676 env->SetLongField(j_cephstatvfs, cephstatvfs_files_fid, st.f_files);
677 env->SetLongField(j_cephstatvfs, cephstatvfs_fsid_fid, st.f_fsid);
678 env->SetLongField(j_cephstatvfs, cephstatvfs_namemax_fid, st.f_namemax);
679
680 return ret;
681 }
682
683 /*
684 * Class: com_ceph_fs_CephMount
685 * Method: native_ceph_getcwd
686 * Signature: (J)Ljava/lang/String;
687 */
688 JNIEXPORT jstring JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1getcwd
689 (JNIEnv *env, jclass clz, jlong j_mntp)
690 {
691 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
692 CephContext *cct = ceph_get_mount_context(cmount);
693 const char *c_cwd;
694
695 CHECK_MOUNTED(cmount, NULL);
696
697 ldout(cct, 10) << "jni: getcwd: enter" << dendl;
698
699 c_cwd = ceph_getcwd(cmount);
700 if (!c_cwd) {
701 cephThrowOutOfMemory(env, "ceph_getcwd");
702 return NULL;
703 }
704
705 ldout(cct, 10) << "jni: getcwd: exit ret " << c_cwd << dendl;
706
707 return env->NewStringUTF(c_cwd);
708 }
709
710 /*
711 * Class: com_ceph_fs_CephMount
712 * Method: native_ceph_chdir
713 * Signature: (JLjava/lang/String;)I
714 */
715 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1chdir
716 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path)
717 {
718 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
719 CephContext *cct = ceph_get_mount_context(cmount);
720 const char *c_path;
721 int ret;
722
723 CHECK_ARG_NULL(j_path, "@path is null", -1);
724 CHECK_MOUNTED(cmount, -1);
725
726 c_path = env->GetStringUTFChars(j_path, NULL);
727 if (!c_path) {
728 cephThrowInternal(env, "failed to pin memory");
729 return -1;
730 }
731
732 ldout(cct, 10) << "jni: chdir: path " << c_path << dendl;
733
734 ret = ceph_chdir(cmount, c_path);
735
736 ldout(cct, 10) << "jni: chdir: exit ret " << ret << dendl;
737
738 env->ReleaseStringUTFChars(j_path, c_path);
739
740 if (ret)
741 handle_error(env, ret);
742
743 return ret;
744 }
745
746 /*
747 * Class: com_ceph_fs_CephMount
748 * Method: native_ceph_listdir
749 * Signature: (JLjava/lang/String;)[Ljava/lang/String;
750 */
751 JNIEXPORT jobjectArray JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1listdir
752 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path)
753 {
754 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
755 CephContext *cct = ceph_get_mount_context(cmount);
756 struct ceph_dir_result *dirp;
757 list<string>::iterator it;
758 list<string> contents;
759 const char *c_path;
760 jobjectArray dirlist;
761 string *ent;
762 int ret, buflen, bufpos, i;
763 jstring name;
764 char *buf;
765
766 CHECK_ARG_NULL(j_path, "@path is null", NULL);
767 CHECK_MOUNTED(cmount, NULL);
768
769 c_path = env->GetStringUTFChars(j_path, NULL);
770 if (!c_path) {
771 cephThrowInternal(env, "failed to pin memory");
772 return NULL;
773 }
774
775 ldout(cct, 10) << "jni: listdir: opendir: path " << c_path << dendl;
776
777 /* ret < 0 also includes -ENOTDIR which should return NULL */
778 ret = ceph_opendir(cmount, c_path, &dirp);
779 if (ret) {
780 env->ReleaseStringUTFChars(j_path, c_path);
781 handle_error(env, ret);
782 return NULL;
783 }
784
785 ldout(cct, 10) << "jni: listdir: opendir: exit ret " << ret << dendl;
786
787 /* buffer for ceph_getdnames() results */
788 buflen = 256;
789 buf = new (std::nothrow) char[buflen];
790 if (!buf) {
791 cephThrowOutOfMemory(env, "heap allocation failed");
792 goto out;
793 }
794
795 while (1) {
796 ldout(cct, 10) << "jni: listdir: getdnames: enter" << dendl;
797 ret = ceph_getdnames(cmount, dirp, buf, buflen);
798 if (ret == -ERANGE) {
799 delete [] buf;
800 buflen *= 2;
801 buf = new (std::nothrow) char[buflen];
802 if (!buf) {
803 cephThrowOutOfMemory(env, "heap allocation failed");
804 goto out;
805 }
806 continue;
807 }
808
809 ldout(cct, 10) << "jni: listdir: getdnames: exit ret " << ret << dendl;
810
811 if (ret <= 0)
812 break;
813
814 /* got at least one name */
815 bufpos = 0;
816 while (bufpos < ret) {
817 ent = new (std::nothrow) string(buf + bufpos);
818 if (!ent) {
819 delete [] buf;
820 cephThrowOutOfMemory(env, "heap allocation failed");
821 goto out;
822 }
823
824 /* filter out dot files: xref: java.io.File::list() */
825 if (ent->compare(".") && ent->compare("..")) {
826 contents.push_back(*ent);
827 ldout(cct, 20) << "jni: listdir: take path " << *ent << dendl;
828 }
829
830 bufpos += ent->size() + 1;
831 delete ent;
832 }
833 }
834
835 delete [] buf;
836
837 if (ret < 0) {
838 handle_error(env, ret);
839 goto out;
840 }
841
842 /* directory list */
843 dirlist = env->NewObjectArray(contents.size(), env->FindClass("java/lang/String"), NULL);
844 if (!dirlist)
845 goto out;
846
847 /*
848 * Fill directory listing array.
849 *
850 * FIXME: how should a partially filled array be cleaned-up properly?
851 */
852 for (i = 0, it = contents.begin(); it != contents.end(); ++it) {
853 name = env->NewStringUTF(it->c_str());
854 if (!name)
855 goto out;
856 env->SetObjectArrayElement(dirlist, i++, name);
857 if (env->ExceptionOccurred())
858 goto out;
859 env->DeleteLocalRef(name);
860 }
861
862 env->ReleaseStringUTFChars(j_path, c_path);
863 ceph_closedir(cmount, dirp);
864
865 return dirlist;
866
867 out:
868 env->ReleaseStringUTFChars(j_path, c_path);
869 ceph_closedir(cmount, dirp);
870 return NULL;
871 }
872
873 /*
874 * Class: com_ceph_fs_CephMount
875 * Method: native_ceph_link
876 * Signature: (JLjava/lang/String;Ljava/lang/String;)I
877 */
878 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1link
879 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_oldpath, jstring j_newpath)
880 {
881 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
882 CephContext *cct = ceph_get_mount_context(cmount);
883 const char *c_oldpath, *c_newpath;
884 int ret;
885
886 CHECK_ARG_NULL(j_oldpath, "@oldpath is null", -1);
887 CHECK_ARG_NULL(j_newpath, "@newpath is null", -1);
888 CHECK_MOUNTED(cmount, -1);
889
890 c_oldpath = env->GetStringUTFChars(j_oldpath, NULL);
891 if (!c_oldpath) {
892 cephThrowInternal(env, "failed to pin memory");
893 return -1;
894 }
895
896 c_newpath = env->GetStringUTFChars(j_newpath, NULL);
897 if (!c_newpath) {
898 env->ReleaseStringUTFChars(j_oldpath, c_oldpath);
899 cephThrowInternal(env, "failed to pin memory");
900 return -1;
901 }
902
903 ldout(cct, 10) << "jni: link: oldpath " << c_oldpath <<
904 " newpath " << c_newpath << dendl;
905
906 ret = ceph_link(cmount, c_oldpath, c_newpath);
907
908 ldout(cct, 10) << "jni: link: exit ret " << ret << dendl;
909
910 env->ReleaseStringUTFChars(j_oldpath, c_oldpath);
911 env->ReleaseStringUTFChars(j_newpath, c_newpath);
912
913 if (ret)
914 handle_error(env, ret);
915
916 return ret;
917 }
918
919 /*
920 * Class: com_ceph_fs_CephMount
921 * Method: native_ceph_unlink
922 * Signature: (JLjava/lang/String;)I
923 */
924 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1unlink
925 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path)
926 {
927 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
928 CephContext *cct = ceph_get_mount_context(cmount);
929 const char *c_path;
930 int ret;
931
932 CHECK_ARG_NULL(j_path, "@path is null", -1);
933 CHECK_MOUNTED(cmount, -1);
934
935 c_path = env->GetStringUTFChars(j_path, NULL);
936 if (!c_path) {
937 cephThrowInternal(env, "failed to pin memory");
938 return -1;
939 }
940
941 ldout(cct, 10) << "jni: unlink: path " << c_path << dendl;
942
943 ret = ceph_unlink(cmount, c_path);
944
945 ldout(cct, 10) << "jni: unlink: exit ret " << ret << dendl;
946
947 env->ReleaseStringUTFChars(j_path, c_path);
948
949 if (ret)
950 handle_error(env, ret);
951
952 return ret;
953 }
954
955 /*
956 * Class: com_ceph_fs_CephMount
957 * Method: native_ceph_rename
958 * Signature: (JLjava/lang/String;Ljava/lang/String;)I
959 */
960 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1rename
961 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_from, jstring j_to)
962 {
963 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
964 CephContext *cct = ceph_get_mount_context(cmount);
965 const char *c_from, *c_to;
966 int ret;
967
968 CHECK_ARG_NULL(j_from, "@from is null", -1);
969 CHECK_ARG_NULL(j_to, "@to is null", -1);
970 CHECK_MOUNTED(cmount, -1);
971
972 c_from = env->GetStringUTFChars(j_from, NULL);
973 if (!c_from) {
974 cephThrowInternal(env, "Failed to pin memory!");
975 return -1;
976 }
977
978 c_to = env->GetStringUTFChars(j_to, NULL);
979 if (!c_to) {
980 env->ReleaseStringUTFChars(j_from, c_from);
981 cephThrowInternal(env, "Failed to pin memory.");
982 return -1;
983 }
984
985 ldout(cct, 10) << "jni: rename: from " << c_from << " to " << c_to << dendl;
986
987 ret = ceph_rename(cmount, c_from, c_to);
988
989 ldout(cct, 10) << "jni: rename: exit ret " << ret << dendl;
990
991 env->ReleaseStringUTFChars(j_from, c_from);
992 env->ReleaseStringUTFChars(j_to, c_to);
993
994 if (ret)
995 handle_error(env, ret);
996
997 return ret;
998 }
999
1000 /*
1001 * Class: com_ceph_fs_CephMount
1002 * Method: native_ceph_mkdir
1003 * Signature: (JLjava/lang/String;I)I
1004 */
1005 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1mkdir
1006 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path, jint j_mode)
1007 {
1008 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1009 CephContext *cct = ceph_get_mount_context(cmount);
1010 const char *c_path;
1011 int ret;
1012
1013 CHECK_ARG_NULL(j_path, "@path is null", -1);
1014 CHECK_MOUNTED(cmount, -1);
1015
1016 c_path = env->GetStringUTFChars(j_path, NULL);
1017 if (!c_path) {
1018 cephThrowInternal(env, "failed to pin memory");
1019 return -1;
1020 }
1021
1022 ldout(cct, 10) << "jni: mkdir: path " << c_path << " mode " << (int)j_mode << dendl;
1023
1024 ret = ceph_mkdir(cmount, c_path, (int)j_mode);
1025
1026 ldout(cct, 10) << "jni: mkdir: exit ret " << ret << dendl;
1027
1028 env->ReleaseStringUTFChars(j_path, c_path);
1029
1030 if (ret)
1031 handle_error(env, ret);
1032
1033 return ret;
1034 }
1035
1036 /*
1037 * Class: com_ceph_fs_CephMount
1038 * Method: native_ceph_mkdirs
1039 * Signature: (JLjava/lang/String;I)I
1040 */
1041 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1mkdirs
1042 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path, jint j_mode)
1043 {
1044 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1045 CephContext *cct = ceph_get_mount_context(cmount);
1046 const char *c_path;
1047 int ret;
1048
1049 CHECK_ARG_NULL(j_path, "@path is null", -1);
1050 CHECK_MOUNTED(cmount, -1);
1051
1052 c_path = env->GetStringUTFChars(j_path, NULL);
1053 if (!c_path) {
1054 cephThrowInternal(env, "failed to pin memory");
1055 return -1;
1056 }
1057
1058 ldout(cct, 10) << "jni: mkdirs: path " << c_path << " mode " << (int)j_mode << dendl;
1059
1060 ret = ceph_mkdirs(cmount, c_path, (int)j_mode);
1061
1062 ldout(cct, 10) << "jni: mkdirs: exit ret " << ret << dendl;
1063
1064 env->ReleaseStringUTFChars(j_path, c_path);
1065
1066 if (ret)
1067 handle_error(env, ret);
1068
1069 return ret;
1070 }
1071
1072 /*
1073 * Class: com_ceph_fs_CephMount
1074 * Method: native_ceph_rmdir
1075 * Signature: (JLjava/lang/String;)I
1076 */
1077 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1rmdir
1078 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path)
1079 {
1080 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1081 CephContext *cct = ceph_get_mount_context(cmount);
1082 const char *c_path;
1083 int ret;
1084
1085 CHECK_ARG_NULL(j_path, "@path is null", -1);
1086 CHECK_MOUNTED(cmount, -1);
1087
1088 c_path = env->GetStringUTFChars(j_path, NULL);
1089 if (!c_path) {
1090 cephThrowInternal(env, "failed to pin memory");
1091 return -1;
1092 }
1093
1094 ldout(cct, 10) << "jni: rmdir: path " << c_path << dendl;
1095
1096 ret = ceph_rmdir(cmount, c_path);
1097
1098 ldout(cct, 10) << "jni: rmdir: exit ret " << ret << dendl;
1099
1100 env->ReleaseStringUTFChars(j_path, c_path);
1101
1102 if (ret)
1103 handle_error(env, ret);
1104
1105 return ret;
1106 }
1107
1108 /*
1109 * Class: com_ceph_fs_CephMount
1110 * Method: native_ceph_readlink
1111 * Signature: (JLjava/lang/String;)Ljava/lang/String;
1112 */
1113 JNIEXPORT jstring JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1readlink
1114 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path)
1115 {
1116 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1117 CephContext *cct = ceph_get_mount_context(cmount);
1118 const char *c_path;
1119 char *linkname;
1120 struct ceph_statx stx;
1121 jstring j_linkname;
1122
1123 CHECK_ARG_NULL(j_path, "@path is null", NULL);
1124 CHECK_MOUNTED(cmount, NULL);
1125
1126 c_path = env->GetStringUTFChars(j_path, NULL);
1127 if (!c_path) {
1128 cephThrowInternal(env, "failed to pin memory");
1129 return NULL;
1130 }
1131
1132 for (;;) {
1133 ldout(cct, 10) << "jni: readlink: lstatx " << c_path << dendl;
1134 int ret = ceph_statx(cmount, c_path, &stx, CEPH_STATX_SIZE,
1135 AT_SYMLINK_NOFOLLOW);
1136 ldout(cct, 10) << "jni: readlink: lstat exit ret " << ret << dendl;
1137 if (ret) {
1138 env->ReleaseStringUTFChars(j_path, c_path);
1139 handle_error(env, ret);
1140 return NULL;
1141 }
1142
1143 linkname = new (std::nothrow) char[stx.stx_size + 1];
1144 if (!linkname) {
1145 env->ReleaseStringUTFChars(j_path, c_path);
1146 cephThrowOutOfMemory(env, "head allocation failed");
1147 return NULL;
1148 }
1149
1150 ldout(cct, 10) << "jni: readlink: size " << stx.stx_size << " path " << c_path << dendl;
1151
1152 ret = ceph_readlink(cmount, c_path, linkname, stx.stx_size + 1);
1153
1154 ldout(cct, 10) << "jni: readlink: exit ret " << ret << dendl;
1155
1156 if (ret < 0) {
1157 delete [] linkname;
1158 env->ReleaseStringUTFChars(j_path, c_path);
1159 handle_error(env, ret);
1160 return NULL;
1161 }
1162
1163 /* re-stat and try again */
1164 if (ret > (int)stx.stx_size) {
1165 delete [] linkname;
1166 continue;
1167 }
1168
1169 linkname[ret] = '\0';
1170 break;
1171 }
1172
1173 env->ReleaseStringUTFChars(j_path, c_path);
1174
1175 j_linkname = env->NewStringUTF(linkname);
1176 delete [] linkname;
1177
1178 return j_linkname;
1179 }
1180
1181 /*
1182 * Class: com_ceph_fs_CephMount
1183 * Method: native_ceph_symlink
1184 * Signature: (JLjava/lang/String;Ljava/lang/String;)I
1185 */
1186 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1symlink
1187 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_oldpath, jstring j_newpath)
1188 {
1189 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1190 CephContext *cct = ceph_get_mount_context(cmount);
1191 const char *c_oldpath, *c_newpath;
1192 int ret;
1193
1194 CHECK_ARG_NULL(j_oldpath, "@oldpath is null", -1);
1195 CHECK_ARG_NULL(j_newpath, "@newpath is null", -1);
1196 CHECK_MOUNTED(cmount, -1);
1197
1198 c_oldpath = env->GetStringUTFChars(j_oldpath, NULL);
1199 if (!c_oldpath) {
1200 cephThrowInternal(env, "failed to pin memory");
1201 return -1;
1202 }
1203
1204 c_newpath = env->GetStringUTFChars(j_newpath, NULL);
1205 if (!c_newpath) {
1206 env->ReleaseStringUTFChars(j_oldpath, c_oldpath);
1207 cephThrowInternal(env, "failed to pin memory");
1208 return -1;
1209 }
1210
1211 ldout(cct, 10) << "jni: symlink: oldpath " << c_oldpath <<
1212 " newpath " << c_newpath << dendl;
1213
1214 ret = ceph_symlink(cmount, c_oldpath, c_newpath);
1215
1216 ldout(cct, 10) << "jni: symlink: exit ret " << ret << dendl;
1217
1218 env->ReleaseStringUTFChars(j_oldpath, c_oldpath);
1219 env->ReleaseStringUTFChars(j_newpath, c_newpath);
1220
1221 if (ret)
1222 handle_error(env, ret);
1223
1224 return ret;
1225 }
1226
1227 #define CEPH_J_CEPHSTAT_MASK (CEPH_STATX_UID|CEPH_STATX_GID|CEPH_STATX_SIZE|CEPH_STATX_BLOCKS|CEPH_STATX_MTIME|CEPH_STATX_ATIME)
1228
1229 static void fill_cephstat(JNIEnv *env, jobject j_cephstat, struct ceph_statx *stx)
1230 {
1231 env->SetIntField(j_cephstat, cephstat_mode_fid, stx->stx_mode);
1232 env->SetIntField(j_cephstat, cephstat_uid_fid, stx->stx_uid);
1233 env->SetIntField(j_cephstat, cephstat_gid_fid, stx->stx_gid);
1234 env->SetLongField(j_cephstat, cephstat_size_fid, stx->stx_size);
1235 env->SetLongField(j_cephstat, cephstat_blksize_fid, stx->stx_blksize);
1236 env->SetLongField(j_cephstat, cephstat_blocks_fid, stx->stx_blocks);
1237
1238 long long time = stx->stx_mtime.tv_sec;
1239 time *= 1000;
1240 time += stx->stx_mtime.tv_nsec / 1000000;
1241 env->SetLongField(j_cephstat, cephstat_m_time_fid, time);
1242
1243 time = stx->stx_atime.tv_sec;
1244 time *= 1000;
1245 time += stx->stx_atime.tv_nsec / 1000000;
1246 env->SetLongField(j_cephstat, cephstat_a_time_fid, time);
1247
1248 env->SetBooleanField(j_cephstat, cephstat_is_file_fid,
1249 S_ISREG(stx->stx_mode) ? JNI_TRUE : JNI_FALSE);
1250
1251 env->SetBooleanField(j_cephstat, cephstat_is_directory_fid,
1252 S_ISDIR(stx->stx_mode) ? JNI_TRUE : JNI_FALSE);
1253
1254 env->SetBooleanField(j_cephstat, cephstat_is_symlink_fid,
1255 S_ISLNK(stx->stx_mode) ? JNI_TRUE : JNI_FALSE);
1256 }
1257
1258 /*
1259 * Class: com_ceph_fs_CephMount
1260 * Method: native_ceph_lstat
1261 * Signature: (JLjava/lang/String;Lcom/ceph/fs/CephStat;)I
1262 */
1263 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1lstat
1264 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path, jobject j_cephstat)
1265 {
1266 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1267 CephContext *cct = ceph_get_mount_context(cmount);
1268 const char *c_path;
1269 struct ceph_statx stx;
1270 int ret;
1271
1272 CHECK_ARG_NULL(j_path, "@path is null", -1);
1273 CHECK_ARG_NULL(j_cephstat, "@stat is null", -1);
1274 CHECK_MOUNTED(cmount, -1);
1275
1276 c_path = env->GetStringUTFChars(j_path, NULL);
1277 if (!c_path) {
1278 cephThrowInternal(env, "Failed to pin memory");
1279 return -1;
1280 }
1281
1282 ldout(cct, 10) << "jni: lstat: path " << c_path << dendl;
1283
1284 ret = ceph_statx(cmount, c_path, &stx, CEPH_J_CEPHSTAT_MASK, AT_SYMLINK_NOFOLLOW);
1285
1286 ldout(cct, 10) << "jni: lstat exit ret " << ret << dendl;
1287
1288 env->ReleaseStringUTFChars(j_path, c_path);
1289
1290 if (ret) {
1291 handle_error(env, ret);
1292 return ret;
1293 }
1294
1295 fill_cephstat(env, j_cephstat, &stx);
1296
1297 return ret;
1298 }
1299
1300 /*
1301 * Class: com_ceph_fs_CephMount
1302 * Method: native_ceph_stat
1303 * Signature: (JLjava/lang/String;Lcom/ceph/fs/CephStat;)I
1304 */
1305 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1stat
1306 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path, jobject j_cephstat)
1307 {
1308 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1309 CephContext *cct = ceph_get_mount_context(cmount);
1310 const char *c_path;
1311 struct ceph_statx stx;
1312 int ret;
1313
1314 CHECK_ARG_NULL(j_path, "@path is null", -1);
1315 CHECK_ARG_NULL(j_cephstat, "@stat is null", -1);
1316 CHECK_MOUNTED(cmount, -1);
1317
1318 c_path = env->GetStringUTFChars(j_path, NULL);
1319 if (!c_path) {
1320 cephThrowInternal(env, "Failed to pin memory");
1321 return -1;
1322 }
1323
1324 ldout(cct, 10) << "jni: lstat: path " << c_path << dendl;
1325
1326 ret = ceph_statx(cmount, c_path, &stx, CEPH_J_CEPHSTAT_MASK, 0);
1327
1328 ldout(cct, 10) << "jni: lstat exit ret " << ret << dendl;
1329
1330 env->ReleaseStringUTFChars(j_path, c_path);
1331
1332 if (ret) {
1333 handle_error(env, ret);
1334 return ret;
1335 }
1336
1337 fill_cephstat(env, j_cephstat, &stx);
1338
1339 return ret;
1340 }
1341
1342 /*
1343 * Class: com_ceph_fs_CephMount
1344 * Method: native_ceph_setattr
1345 * Signature: (JLjava/lang/String;Lcom/ceph/fs/CephStat;I)I
1346 */
1347 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1setattr
1348 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path, jobject j_cephstat, jint j_mask)
1349 {
1350 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1351 CephContext *cct = ceph_get_mount_context(cmount);
1352 const char *c_path;
1353 struct ceph_statx stx;
1354 int ret, mask = fixup_attr_mask(j_mask);
1355
1356 CHECK_ARG_NULL(j_path, "@path is null", -1);
1357 CHECK_ARG_NULL(j_cephstat, "@stat is null", -1);
1358 CHECK_MOUNTED(cmount, -1);
1359
1360 c_path = env->GetStringUTFChars(j_path, NULL);
1361 if (!c_path) {
1362 cephThrowInternal(env, "Failed to pin memory");
1363 return -1;
1364 }
1365
1366 memset(&stx, 0, sizeof(stx));
1367
1368 stx.stx_mode = env->GetIntField(j_cephstat, cephstat_mode_fid);
1369 stx.stx_uid = env->GetIntField(j_cephstat, cephstat_uid_fid);
1370 stx.stx_gid = env->GetIntField(j_cephstat, cephstat_gid_fid);
1371 stx.stx_mtime.tv_sec = env->GetLongField(j_cephstat, cephstat_m_time_fid);
1372 stx.stx_atime.tv_sec = env->GetLongField(j_cephstat, cephstat_a_time_fid);
1373
1374 ldout(cct, 10) << "jni: setattr: path " << c_path << " mask " << mask << dendl;
1375
1376 ret = ceph_setattrx(cmount, c_path, &stx, mask, 0);
1377
1378 ldout(cct, 10) << "jni: setattr: exit ret " << ret << dendl;
1379
1380 env->ReleaseStringUTFChars(j_path, c_path);
1381
1382 if (ret)
1383 handle_error(env, ret);
1384
1385 return ret;
1386 }
1387
1388 /*
1389 * Class: com_ceph_fs_CephMount
1390 * Method: native_ceph_chmod
1391 * Signature: (JLjava/lang/String;I)I
1392 */
1393 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1chmod
1394 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path, jint j_mode)
1395 {
1396 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1397 CephContext *cct = ceph_get_mount_context(cmount);
1398 const char *c_path;
1399 int ret;
1400
1401 CHECK_ARG_NULL(j_path, "@path is null", -1);
1402 CHECK_MOUNTED(cmount, -1);
1403
1404 c_path = env->GetStringUTFChars(j_path, NULL);
1405 if (!c_path) {
1406 cephThrowInternal(env, "Failed to pin memory");
1407 return -1;
1408 }
1409
1410 ldout(cct, 10) << "jni: chmod: path " << c_path << " mode " << (int)j_mode << dendl;
1411
1412 ret = ceph_chmod(cmount, c_path, (int)j_mode);
1413
1414 ldout(cct, 10) << "jni: chmod: exit ret " << ret << dendl;
1415
1416 env->ReleaseStringUTFChars(j_path, c_path);
1417
1418 if (ret)
1419 handle_error(env, ret);
1420
1421 return ret;
1422 }
1423
1424 /*
1425 * Class: com_ceph_fs_CephMount
1426 * Method: native_ceph_fchmod
1427 * Signature: (JII)I
1428 */
1429 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1fchmod
1430 (JNIEnv *env, jclass clz, jlong j_mntp, jint j_fd, jint j_mode)
1431 {
1432 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1433 CephContext *cct = ceph_get_mount_context(cmount);
1434 int ret;
1435
1436 CHECK_MOUNTED(cmount, -1);
1437
1438 ldout(cct, 10) << "jni: fchmod: fd " << (int)j_fd << " mode " << (int)j_mode << dendl;
1439
1440 ret = ceph_fchmod(cmount, (int)j_fd, (int)j_mode);
1441
1442 ldout(cct, 10) << "jni: fchmod: exit ret " << ret << dendl;
1443
1444 if (ret)
1445 handle_error(env, ret);
1446
1447 return ret;
1448 }
1449
1450 /*
1451 * Class: com_ceph_fs_CephMount
1452 * Method: native_ceph_truncate
1453 * Signature: (JLjava/lang/String;J)I
1454 */
1455 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1truncate
1456 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path, jlong j_size)
1457 {
1458 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1459 CephContext *cct = ceph_get_mount_context(cmount);
1460 const char *c_path;
1461 int ret;
1462
1463 CHECK_ARG_NULL(j_path, "@path is null", -1);
1464 CHECK_MOUNTED(cmount, -1);
1465
1466 c_path = env->GetStringUTFChars(j_path, NULL);
1467 if (!c_path) {
1468 cephThrowInternal(env, "Failed to pin memory");
1469 return -1;
1470 }
1471
1472 ldout(cct, 10) << "jni: truncate: path " << c_path << " size " << (loff_t)j_size << dendl;
1473
1474 ret = ceph_truncate(cmount, c_path, (loff_t)j_size);
1475
1476 ldout(cct, 10) << "jni: truncate: exit ret " << ret << dendl;
1477
1478 env->ReleaseStringUTFChars(j_path, c_path);
1479
1480 if (ret)
1481 handle_error(env, ret);
1482
1483 return ret;
1484 }
1485
1486 /*
1487 * Class: com_ceph_fs_CephMount
1488 * Method: native_ceph_open
1489 * Signature: (JLjava/lang/String;II)I
1490 */
1491 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1open
1492 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path, jint j_flags, jint j_mode)
1493 {
1494 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1495 CephContext *cct = ceph_get_mount_context(cmount);
1496 const char *c_path;
1497 int ret, flags = fixup_open_flags(j_flags);
1498
1499 CHECK_ARG_NULL(j_path, "@path is null", -1);
1500 CHECK_MOUNTED(cmount, -1);
1501
1502 c_path = env->GetStringUTFChars(j_path, NULL);
1503 if (!c_path) {
1504 cephThrowInternal(env, "Failed to pin memory");
1505 return -1;
1506 }
1507
1508 ldout(cct, 10) << "jni: open: path " << c_path << " flags " << flags
1509 << " mode " << (int)j_mode << dendl;
1510
1511 ret = ceph_open(cmount, c_path, flags, (int)j_mode);
1512
1513 ldout(cct, 10) << "jni: open: exit ret " << ret << dendl;
1514
1515 env->ReleaseStringUTFChars(j_path, c_path);
1516
1517 if (ret < 0)
1518 handle_error(env, ret);
1519
1520 return ret;
1521 }
1522
1523 /*
1524 * Class: com_ceph_fs_CephMount
1525 * Method: native_ceph_open_layout
1526 * Signature: (JLjava/lang/String;IIIIILjava/lang/String;)I
1527 */
1528 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1open_1layout
1529 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path, jint j_flags, jint j_mode,
1530 jint stripe_unit, jint stripe_count, jint object_size, jstring j_data_pool)
1531 {
1532 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1533 CephContext *cct = ceph_get_mount_context(cmount);
1534 const char *c_path, *c_data_pool = NULL;
1535 int ret, flags = fixup_open_flags(j_flags);
1536
1537 CHECK_ARG_NULL(j_path, "@path is null", -1);
1538 CHECK_MOUNTED(cmount, -1);
1539
1540 c_path = env->GetStringUTFChars(j_path, NULL);
1541 if (!c_path) {
1542 cephThrowInternal(env, "Failed to pin memory");
1543 return -1;
1544 }
1545
1546 if (j_data_pool) {
1547 c_data_pool = env->GetStringUTFChars(j_data_pool, NULL);
1548 if (!c_data_pool) {
1549 env->ReleaseStringUTFChars(j_path, c_path);
1550 cephThrowInternal(env, "Failed to pin memory");
1551 return -1;
1552 }
1553 }
1554
1555 ldout(cct, 10) << "jni: open_layout: path " << c_path << " flags " << flags
1556 << " mode " << (int)j_mode << " stripe_unit " << stripe_unit
1557 << " stripe_count " << stripe_count << " object_size " << object_size
1558 << " data_pool " << (c_data_pool ? c_data_pool : "<NULL>") << dendl;
1559
1560 ret = ceph_open_layout(cmount, c_path, flags, (int)j_mode,
1561 (int)stripe_unit, (int)stripe_count, (int)object_size, c_data_pool);
1562
1563 ldout(cct, 10) << "jni: open_layout: exit ret " << ret << dendl;
1564
1565 env->ReleaseStringUTFChars(j_path, c_path);
1566 if (j_data_pool)
1567 env->ReleaseStringUTFChars(j_data_pool, c_data_pool);
1568
1569 if (ret < 0)
1570 handle_error(env, ret);
1571
1572 return ret;
1573 }
1574
1575 /*
1576 * Class: com_ceph_fs_CephMount
1577 * Method: native_ceph_close
1578 * Signature: (JI)I
1579 */
1580 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1close
1581 (JNIEnv *env, jclass clz, jlong j_mntp, jint j_fd)
1582 {
1583 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1584 CephContext *cct = ceph_get_mount_context(cmount);
1585 int ret;
1586
1587 CHECK_MOUNTED(cmount, -1);
1588
1589 ldout(cct, 10) << "jni: close: fd " << (int)j_fd << dendl;
1590
1591 ret = ceph_close(cmount, (int)j_fd);
1592
1593 ldout(cct, 10) << "jni: close: ret " << ret << dendl;
1594
1595 if (ret)
1596 handle_error(env, ret);
1597
1598 return ret;
1599 }
1600
1601 /*
1602 * Class: com_ceph_fs_CephMount
1603 * Method: native_ceph_lseek
1604 * Signature: (JIJI)J
1605 */
1606 JNIEXPORT jlong JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1lseek
1607 (JNIEnv *env, jclass clz, jlong j_mntp, jint j_fd, jlong j_offset, jint j_whence)
1608 {
1609 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1610 CephContext *cct = ceph_get_mount_context(cmount);
1611 int whence;
1612 jlong ret;
1613
1614 CHECK_MOUNTED(cmount, -1);
1615
1616 switch (j_whence) {
1617 case JAVA_SEEK_SET:
1618 whence = SEEK_SET;
1619 break;
1620 case JAVA_SEEK_CUR:
1621 whence = SEEK_CUR;
1622 break;
1623 case JAVA_SEEK_END:
1624 whence = SEEK_END;
1625 break;
1626 default:
1627 cephThrowIllegalArg(env, "Unknown whence value");
1628 return -1;
1629 }
1630
1631 ldout(cct, 10) << "jni: lseek: fd " << (int)j_fd << " offset "
1632 << (long)j_offset << " whence " << whence << dendl;
1633
1634 ret = ceph_lseek(cmount, (int)j_fd, (long)j_offset, whence);
1635
1636 ldout(cct, 10) << "jni: lseek: exit ret " << ret << dendl;
1637
1638 if (ret < 0)
1639 handle_error(env, ret);
1640
1641 return ret;
1642 }
1643
1644 /*
1645 * Class: com_ceph_fs_CephMount
1646 * Method: native_ceph_read
1647 * Signature: (JI[BJJ)J
1648 */
1649 JNIEXPORT jlong JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1read
1650 (JNIEnv *env, jclass clz, jlong j_mntp, jint j_fd, jbyteArray j_buf, jlong j_size, jlong j_offset)
1651 {
1652 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1653 CephContext *cct = ceph_get_mount_context(cmount);
1654 jsize buf_size;
1655 jbyte *c_buf;
1656 long ret;
1657
1658 CHECK_ARG_NULL(j_buf, "@buf is null", -1);
1659 CHECK_ARG_BOUNDS(j_size < 0, "@size is negative", -1);
1660 CHECK_MOUNTED(cmount, -1);
1661
1662 buf_size = env->GetArrayLength(j_buf);
1663 CHECK_ARG_BOUNDS(j_size > buf_size, "@size > @buf.length", -1);
1664
1665 c_buf = env->GetByteArrayElements(j_buf, NULL);
1666 if (!c_buf) {
1667 cephThrowInternal(env, "failed to pin memory");
1668 return -1;
1669 }
1670
1671 ldout(cct, 10) << "jni: read: fd " << (int)j_fd << " len " << (long)j_size <<
1672 " offset " << (long)j_offset << dendl;
1673
1674 ret = ceph_read(cmount, (int)j_fd, (char*)c_buf, (long)j_size, (long)j_offset);
1675
1676 ldout(cct, 10) << "jni: read: exit ret " << ret << dendl;
1677
1678 if (ret < 0)
1679 handle_error(env, (int)ret);
1680 else
1681 env->ReleaseByteArrayElements(j_buf, c_buf, 0);
1682
1683 return (jlong)ret;
1684 }
1685
1686 /*
1687 * Class: com_ceph_fs_CephMount
1688 * Method: native_ceph_write
1689 * Signature: (JI[BJJ)J
1690 */
1691 JNIEXPORT jlong JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1write
1692 (JNIEnv *env, jclass clz, jlong j_mntp, jint j_fd, jbyteArray j_buf, jlong j_size, jlong j_offset)
1693 {
1694 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1695 CephContext *cct = ceph_get_mount_context(cmount);
1696 jsize buf_size;
1697 jbyte *c_buf;
1698 long ret;
1699
1700 CHECK_ARG_NULL(j_buf, "@buf is null", -1);
1701 CHECK_ARG_BOUNDS(j_size < 0, "@size is negative", -1);
1702 CHECK_MOUNTED(cmount, -1);
1703
1704 buf_size = env->GetArrayLength(j_buf);
1705 CHECK_ARG_BOUNDS(j_size > buf_size, "@size > @buf.length", -1);
1706
1707 c_buf = env->GetByteArrayElements(j_buf, NULL);
1708 if (!c_buf) {
1709 cephThrowInternal(env, "failed to pin memory");
1710 return -1;
1711 }
1712
1713 ldout(cct, 10) << "jni: write: fd " << (int)j_fd << " len " << (long)j_size <<
1714 " offset " << (long)j_offset << dendl;
1715
1716 ret = ceph_write(cmount, (int)j_fd, (char*)c_buf, (long)j_size, (long)j_offset);
1717
1718 ldout(cct, 10) << "jni: write: exit ret " << ret << dendl;
1719
1720 if (ret < 0)
1721 handle_error(env, (int)ret);
1722 else
1723 env->ReleaseByteArrayElements(j_buf, c_buf, JNI_ABORT);
1724
1725 return ret;
1726 }
1727
1728
1729 /*
1730 * Class: com_ceph_fs_CephMount
1731 * Method: native_ceph_ftruncate
1732 * Signature: (JIJ)I
1733 */
1734 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1ftruncate
1735 (JNIEnv *env, jclass clz, jlong j_mntp, jint j_fd, jlong j_size)
1736 {
1737 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1738 CephContext *cct = ceph_get_mount_context(cmount);
1739 int ret;
1740
1741 CHECK_MOUNTED(cmount, -1);
1742
1743 ldout(cct, 10) << "jni: ftruncate: fd " << (int)j_fd <<
1744 " size " << (loff_t)j_size << dendl;
1745
1746 ret = ceph_ftruncate(cmount, (int)j_fd, (loff_t)j_size);
1747
1748 ldout(cct, 10) << "jni: ftruncate: exit ret " << ret << dendl;
1749
1750 if (ret)
1751 handle_error(env, ret);
1752
1753 return ret;
1754 }
1755
1756 /*
1757 * Class: com_ceph_fs_CephMount
1758 * Method: native_ceph_fsync
1759 * Signature: (JIZ)I
1760 */
1761 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1fsync
1762 (JNIEnv *env, jclass clz, jlong j_mntp, jint j_fd, jboolean j_dataonly)
1763 {
1764 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1765 CephContext *cct = ceph_get_mount_context(cmount);
1766 int ret;
1767
1768 ldout(cct, 10) << "jni: fsync: fd " << (int)j_fd <<
1769 " dataonly " << (j_dataonly ? 1 : 0) << dendl;
1770
1771 ret = ceph_fsync(cmount, (int)j_fd, j_dataonly ? 1 : 0);
1772
1773 ldout(cct, 10) << "jni: fsync: exit ret " << ret << dendl;
1774
1775 if (ret)
1776 handle_error(env, ret);
1777
1778 return ret;
1779 }
1780
1781 /*
1782 * Class: com_ceph_fs_CephMount
1783 * Method: native_ceph_flock
1784 * Signature: (JIZ)I
1785 */
1786 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1flock
1787 (JNIEnv *env, jclass clz, jlong j_mntp, jint j_fd, jint j_operation, jlong j_owner)
1788 {
1789 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1790 CephContext *cct = ceph_get_mount_context(cmount);
1791 int ret;
1792
1793 ldout(cct, 10) << "jni: flock: fd " << (int)j_fd <<
1794 " operation " << j_operation << " owner " << j_owner << dendl;
1795
1796 int operation = 0;
1797
1798 #define MAP_FLOCK_FLAG(JNI_MASK, NATIVE_MASK) do { \
1799 if ((j_operation & JNI_MASK) != 0) { \
1800 operation |= NATIVE_MASK; \
1801 j_operation &= ~JNI_MASK; \
1802 } \
1803 } while(0)
1804 MAP_FLOCK_FLAG(JAVA_LOCK_SH, LOCK_SH);
1805 MAP_FLOCK_FLAG(JAVA_LOCK_EX, LOCK_EX);
1806 MAP_FLOCK_FLAG(JAVA_LOCK_NB, LOCK_NB);
1807 MAP_FLOCK_FLAG(JAVA_LOCK_UN, LOCK_UN);
1808 if (j_operation != 0) {
1809 cephThrowIllegalArg(env, "flock flags");
1810 return -EINVAL;
1811 }
1812 #undef MAP_FLOCK_FLAG
1813
1814 ret = ceph_flock(cmount, (int)j_fd, operation, (uint64_t) j_owner);
1815
1816 ldout(cct, 10) << "jni: flock: exit ret " << ret << dendl;
1817
1818 if (ret)
1819 handle_error(env, ret);
1820
1821 return ret;
1822 }
1823
1824 /*
1825 * Class: com_ceph_fs_CephMount
1826 * Method: native_ceph_fstat
1827 * Signature: (JILcom/ceph/fs/CephStat;)I
1828 */
1829 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1fstat
1830 (JNIEnv *env, jclass clz, jlong j_mntp, jint j_fd, jobject j_cephstat)
1831 {
1832 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1833 CephContext *cct = ceph_get_mount_context(cmount);
1834 struct ceph_statx stx;
1835 int ret;
1836
1837 CHECK_ARG_NULL(j_cephstat, "@stat is null", -1);
1838 CHECK_MOUNTED(cmount, -1);
1839
1840 ldout(cct, 10) << "jni: fstat: fd " << (int)j_fd << dendl;
1841
1842 ret = ceph_fstatx(cmount, (int)j_fd, &stx, CEPH_J_CEPHSTAT_MASK, 0);
1843
1844 ldout(cct, 10) << "jni: fstat exit ret " << ret << dendl;
1845
1846 if (ret) {
1847 handle_error(env, ret);
1848 return ret;
1849 }
1850
1851 fill_cephstat(env, j_cephstat, &stx);
1852
1853 return ret;
1854 }
1855
1856 /*
1857 * Class: com_ceph_fs_CephMount
1858 * Method: native_ceph_sync_fs
1859 * Signature: (J)I
1860 */
1861 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1sync_1fs
1862 (JNIEnv *env, jclass clz, jlong j_mntp)
1863 {
1864 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1865 CephContext *cct = ceph_get_mount_context(cmount);
1866 int ret;
1867
1868 ldout(cct, 10) << "jni: sync_fs: enter" << dendl;
1869
1870 ret = ceph_sync_fs(cmount);
1871
1872 ldout(cct, 10) << "jni: sync_fs: exit ret " << ret << dendl;
1873
1874 if (ret)
1875 handle_error(env, ret);
1876
1877 return ret;
1878 }
1879
1880 /*
1881 * Class: com_ceph_fs_CephMount
1882 * Method: native_ceph_getxattr
1883 * Signature: (JLjava/lang/String;Ljava/lang/String;[B)J
1884 */
1885 JNIEXPORT jlong JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1getxattr
1886 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path, jstring j_name, jbyteArray j_buf)
1887 {
1888 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1889 CephContext *cct = ceph_get_mount_context(cmount);
1890 const char *c_path;
1891 const char *c_name;
1892 jsize buf_size;
1893 jbyte *c_buf = NULL; /* please gcc with goto */
1894 long ret;
1895
1896 CHECK_ARG_NULL(j_path, "@path is null", -1);
1897 CHECK_ARG_NULL(j_name, "@name is null", -1);
1898 CHECK_MOUNTED(cmount, -1);
1899
1900 c_path = env->GetStringUTFChars(j_path, NULL);
1901 if (!c_path) {
1902 cephThrowInternal(env, "Failed to pin memory");
1903 return -1;
1904 }
1905
1906 c_name = env->GetStringUTFChars(j_name, NULL);
1907 if (!c_name) {
1908 env->ReleaseStringUTFChars(j_path, c_path);
1909 cephThrowInternal(env, "Failed to pin memory");
1910 return -1;
1911 }
1912
1913 /* just lookup the size if buf is null */
1914 if (!j_buf) {
1915 buf_size = 0;
1916 goto do_getxattr;
1917 }
1918
1919 c_buf = env->GetByteArrayElements(j_buf, NULL);
1920 if (!c_buf) {
1921 env->ReleaseStringUTFChars(j_path, c_path);
1922 env->ReleaseStringUTFChars(j_name, c_name);
1923 cephThrowInternal(env, "failed to pin memory");
1924 return -1;
1925 }
1926
1927 buf_size = env->GetArrayLength(j_buf);
1928
1929 do_getxattr:
1930
1931 ldout(cct, 10) << "jni: getxattr: path " << c_path << " name " << c_name <<
1932 " len " << buf_size << dendl;
1933
1934 ret = ceph_getxattr(cmount, c_path, c_name, c_buf, buf_size);
1935 if (ret == -ERANGE)
1936 ret = ceph_getxattr(cmount, c_path, c_name, c_buf, 0);
1937
1938 ldout(cct, 10) << "jni: getxattr: exit ret " << ret << dendl;
1939
1940 env->ReleaseStringUTFChars(j_path, c_path);
1941 env->ReleaseStringUTFChars(j_name, c_name);
1942 if (j_buf)
1943 env->ReleaseByteArrayElements(j_buf, c_buf, 0);
1944
1945 if (ret < 0)
1946 handle_error(env, (int)ret);
1947
1948 return (jlong)ret;
1949 }
1950
1951 /*
1952 * Class: com_ceph_fs_CephMount
1953 * Method: native_ceph_lgetxattr
1954 * Signature: (JLjava/lang/String;Ljava/lang/String;[B)I
1955 */
1956 JNIEXPORT jlong JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1lgetxattr
1957 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path, jstring j_name, jbyteArray j_buf)
1958 {
1959 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
1960 CephContext *cct = ceph_get_mount_context(cmount);
1961 const char *c_path;
1962 const char *c_name;
1963 jsize buf_size;
1964 jbyte *c_buf = NULL; /* please gcc with goto */
1965 long ret;
1966
1967 CHECK_ARG_NULL(j_path, "@path is null", -1);
1968 CHECK_ARG_NULL(j_name, "@name is null", -1);
1969 CHECK_MOUNTED(cmount, -1);
1970
1971 c_path = env->GetStringUTFChars(j_path, NULL);
1972 if (!c_path) {
1973 cephThrowInternal(env, "Failed to pin memory");
1974 return -1;
1975 }
1976
1977 c_name = env->GetStringUTFChars(j_name, NULL);
1978 if (!c_name) {
1979 env->ReleaseStringUTFChars(j_path, c_path);
1980 cephThrowInternal(env, "Failed to pin memory");
1981 return -1;
1982 }
1983
1984 /* just lookup the size if buf is null */
1985 if (!j_buf) {
1986 buf_size = 0;
1987 goto do_lgetxattr;
1988 }
1989
1990 c_buf = env->GetByteArrayElements(j_buf, NULL);
1991 if (!c_buf) {
1992 env->ReleaseStringUTFChars(j_path, c_path);
1993 env->ReleaseStringUTFChars(j_name, c_name);
1994 cephThrowInternal(env, "failed to pin memory");
1995 return -1;
1996 }
1997
1998 buf_size = env->GetArrayLength(j_buf);
1999
2000 do_lgetxattr:
2001
2002 ldout(cct, 10) << "jni: lgetxattr: path " << c_path << " name " << c_name <<
2003 " len " << buf_size << dendl;
2004
2005 ret = ceph_lgetxattr(cmount, c_path, c_name, c_buf, buf_size);
2006 if (ret == -ERANGE)
2007 ret = ceph_lgetxattr(cmount, c_path, c_name, c_buf, 0);
2008
2009 ldout(cct, 10) << "jni: lgetxattr: exit ret " << ret << dendl;
2010
2011 env->ReleaseStringUTFChars(j_path, c_path);
2012 env->ReleaseStringUTFChars(j_name, c_name);
2013 if (j_buf)
2014 env->ReleaseByteArrayElements(j_buf, c_buf, 0);
2015
2016 if (ret < 0)
2017 handle_error(env, (int)ret);
2018
2019 return (jlong)ret;
2020 }
2021
2022 /*
2023 * Class: com_ceph_fs_CephMount
2024 * Method: native_ceph_listxattr
2025 * Signature: (JLjava/lang/String;)[Ljava/lang/String;
2026 */
2027 JNIEXPORT jobjectArray JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1listxattr
2028 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path)
2029 {
2030 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
2031 CephContext *cct = ceph_get_mount_context(cmount);
2032 jobjectArray xattrlist;
2033 const char *c_path;
2034 string *ent;
2035 jstring name;
2036 list<string>::iterator it;
2037 list<string> contents;
2038 int ret, buflen, bufpos, i;
2039 char *buf;
2040
2041 CHECK_ARG_NULL(j_path, "@path is null", NULL);
2042 CHECK_MOUNTED(cmount, NULL);
2043
2044 c_path = env->GetStringUTFChars(j_path, NULL);
2045 if (!c_path) {
2046 cephThrowInternal(env, "Failed to pin memory");
2047 return NULL;
2048 }
2049
2050 buflen = 1024;
2051 buf = new (std::nothrow) char[buflen];
2052 if (!buf) {
2053 cephThrowOutOfMemory(env, "head allocation failed");
2054 goto out;
2055 }
2056
2057 while (1) {
2058 ldout(cct, 10) << "jni: listxattr: path " << c_path << " len " << buflen << dendl;
2059 ret = ceph_listxattr(cmount, c_path, buf, buflen);
2060 if (ret == -ERANGE) {
2061 delete [] buf;
2062 buflen *= 2;
2063 buf = new (std::nothrow) char[buflen];
2064 if (!buf) {
2065 cephThrowOutOfMemory(env, "heap allocation failed");
2066 goto out;
2067 }
2068 continue;
2069 }
2070 break;
2071 }
2072
2073 ldout(cct, 10) << "jni: listxattr: ret " << ret << dendl;
2074
2075 if (ret < 0) {
2076 delete [] buf;
2077 handle_error(env, ret);
2078 goto out;
2079 }
2080
2081 bufpos = 0;
2082 while (bufpos < ret) {
2083 ent = new (std::nothrow) string(buf + bufpos);
2084 if (!ent) {
2085 delete [] buf;
2086 cephThrowOutOfMemory(env, "heap allocation failed");
2087 goto out;
2088 }
2089 contents.push_back(*ent);
2090 bufpos += ent->size() + 1;
2091 delete ent;
2092 }
2093
2094 delete [] buf;
2095
2096 xattrlist = env->NewObjectArray(contents.size(), env->FindClass("java/lang/String"), NULL);
2097 if (!xattrlist)
2098 goto out;
2099
2100 for (i = 0, it = contents.begin(); it != contents.end(); ++it) {
2101 name = env->NewStringUTF(it->c_str());
2102 if (!name)
2103 goto out;
2104 env->SetObjectArrayElement(xattrlist, i++, name);
2105 if (env->ExceptionOccurred())
2106 goto out;
2107 env->DeleteLocalRef(name);
2108 }
2109
2110 env->ReleaseStringUTFChars(j_path, c_path);
2111 return xattrlist;
2112
2113 out:
2114 env->ReleaseStringUTFChars(j_path, c_path);
2115 return NULL;
2116 }
2117
2118 /*
2119 * Class: com_ceph_fs_CephMount
2120 * Method: native_ceph_llistxattr
2121 * Signature: (JLjava/lang/String;)[Ljava/lang/String;
2122 */
2123 JNIEXPORT jobjectArray JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1llistxattr
2124 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path)
2125 {
2126 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
2127 CephContext *cct = ceph_get_mount_context(cmount);
2128 jobjectArray xattrlist;
2129 const char *c_path;
2130 string *ent;
2131 jstring name;
2132 list<string>::iterator it;
2133 list<string> contents;
2134 int ret, buflen, bufpos, i;
2135 char *buf;
2136
2137 CHECK_ARG_NULL(j_path, "@path is null", NULL);
2138 CHECK_MOUNTED(cmount, NULL);
2139
2140 c_path = env->GetStringUTFChars(j_path, NULL);
2141 if (!c_path) {
2142 cephThrowInternal(env, "Failed to pin memory");
2143 return NULL;
2144 }
2145
2146 buflen = 1024;
2147 buf = new (std::nothrow) char[buflen];
2148 if (!buf) {
2149 cephThrowOutOfMemory(env, "head allocation failed");
2150 goto out;
2151 }
2152
2153 while (1) {
2154 ldout(cct, 10) << "jni: llistxattr: path " << c_path << " len " << buflen << dendl;
2155 ret = ceph_llistxattr(cmount, c_path, buf, buflen);
2156 if (ret == -ERANGE) {
2157 delete [] buf;
2158 buflen *= 2;
2159 buf = new (std::nothrow) char[buflen];
2160 if (!buf) {
2161 cephThrowOutOfMemory(env, "heap allocation failed");
2162 goto out;
2163 }
2164 continue;
2165 }
2166 break;
2167 }
2168
2169 ldout(cct, 10) << "jni: llistxattr: ret " << ret << dendl;
2170
2171 if (ret < 0) {
2172 delete [] buf;
2173 handle_error(env, ret);
2174 goto out;
2175 }
2176
2177 bufpos = 0;
2178 while (bufpos < ret) {
2179 ent = new (std::nothrow) string(buf + bufpos);
2180 if (!ent) {
2181 delete [] buf;
2182 cephThrowOutOfMemory(env, "heap allocation failed");
2183 goto out;
2184 }
2185 contents.push_back(*ent);
2186 bufpos += ent->size() + 1;
2187 delete ent;
2188 }
2189
2190 delete [] buf;
2191
2192 xattrlist = env->NewObjectArray(contents.size(), env->FindClass("java/lang/String"), NULL);
2193 if (!xattrlist)
2194 goto out;
2195
2196 for (i = 0, it = contents.begin(); it != contents.end(); ++it) {
2197 name = env->NewStringUTF(it->c_str());
2198 if (!name)
2199 goto out;
2200 env->SetObjectArrayElement(xattrlist, i++, name);
2201 if (env->ExceptionOccurred())
2202 goto out;
2203 env->DeleteLocalRef(name);
2204 }
2205
2206 env->ReleaseStringUTFChars(j_path, c_path);
2207 return xattrlist;
2208
2209 out:
2210 env->ReleaseStringUTFChars(j_path, c_path);
2211 return NULL;
2212 }
2213
2214 /*
2215 * Class: com_ceph_fs_CephMount
2216 * Method: native_ceph_removexattr
2217 * Signature: (JLjava/lang/String;Ljava/lang/String;)I
2218 */
2219 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1removexattr
2220 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path, jstring j_name)
2221 {
2222 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
2223 CephContext *cct = ceph_get_mount_context(cmount);
2224 const char *c_path;
2225 const char *c_name;
2226 int ret;
2227
2228 CHECK_ARG_NULL(j_path, "@path is null", -1);
2229 CHECK_ARG_NULL(j_name, "@name is null", -1);
2230 CHECK_MOUNTED(cmount, -1);
2231
2232 c_path = env->GetStringUTFChars(j_path, NULL);
2233 if (!c_path) {
2234 cephThrowInternal(env, "Failed to pin memory");
2235 return -1;
2236 }
2237
2238 c_name = env->GetStringUTFChars(j_name, NULL);
2239 if (!c_name) {
2240 env->ReleaseStringUTFChars(j_path, c_path);
2241 cephThrowInternal(env, "Failed to pin memory");
2242 return -1;
2243 }
2244
2245 ldout(cct, 10) << "jni: removexattr: path " << c_path << " name " << c_name << dendl;
2246
2247 ret = ceph_removexattr(cmount, c_path, c_name);
2248
2249 ldout(cct, 10) << "jni: removexattr: exit ret " << ret << dendl;
2250
2251 env->ReleaseStringUTFChars(j_path, c_path);
2252 env->ReleaseStringUTFChars(j_name, c_name);
2253
2254 if (ret)
2255 handle_error(env, ret);
2256
2257 return ret;
2258 }
2259
2260 /*
2261 * Class: com_ceph_fs_CephMount
2262 * Method: native_ceph_lremovexattr
2263 * Signature: (JLjava/lang/String;Ljava/lang/String;)I
2264 */
2265 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1lremovexattr
2266 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path, jstring j_name)
2267 {
2268 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
2269 CephContext *cct = ceph_get_mount_context(cmount);
2270 const char *c_path;
2271 const char *c_name;
2272 int ret;
2273
2274 CHECK_ARG_NULL(j_path, "@path is null", -1);
2275 CHECK_ARG_NULL(j_name, "@name is null", -1);
2276 CHECK_MOUNTED(cmount, -1);
2277
2278 c_path = env->GetStringUTFChars(j_path, NULL);
2279 if (!c_path) {
2280 cephThrowInternal(env, "Failed to pin memory");
2281 return -1;
2282 }
2283
2284 c_name = env->GetStringUTFChars(j_name, NULL);
2285 if (!c_name) {
2286 env->ReleaseStringUTFChars(j_path, c_path);
2287 cephThrowInternal(env, "Failed to pin memory");
2288 return -1;
2289 }
2290
2291 ldout(cct, 10) << "jni: lremovexattr: path " << c_path << " name " << c_name << dendl;
2292
2293 ret = ceph_lremovexattr(cmount, c_path, c_name);
2294
2295 ldout(cct, 10) << "jni: lremovexattr: exit ret " << ret << dendl;
2296
2297 env->ReleaseStringUTFChars(j_path, c_path);
2298 env->ReleaseStringUTFChars(j_name, c_name);
2299
2300 if (ret)
2301 handle_error(env, ret);
2302
2303 return ret;
2304 }
2305
2306 /*
2307 * Class: com_ceph_fs_CephMount
2308 * Method: native_ceph_setxattr
2309 * Signature: (JLjava/lang/String;Ljava/lang/String;[BJI)I
2310 */
2311 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1setxattr
2312 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path, jstring j_name,
2313 jbyteArray j_buf, jlong j_size, jint j_flags)
2314 {
2315 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
2316 CephContext *cct = ceph_get_mount_context(cmount);
2317 const char *c_path;
2318 const char *c_name;
2319 jsize buf_size;
2320 jbyte *c_buf;
2321 int ret, flags;
2322
2323 CHECK_ARG_NULL(j_path, "@path is null", -1);
2324 CHECK_ARG_NULL(j_name, "@name is null", -1);
2325 CHECK_ARG_NULL(j_buf, "@buf is null", -1);
2326 CHECK_ARG_BOUNDS(j_size < 0, "@size is negative", -1);
2327 CHECK_MOUNTED(cmount, -1);
2328
2329 buf_size = env->GetArrayLength(j_buf);
2330 CHECK_ARG_BOUNDS(j_size > buf_size, "@size > @buf.length", -1);
2331
2332 c_path = env->GetStringUTFChars(j_path, NULL);
2333 if (!c_path) {
2334 cephThrowInternal(env, "Failed to pin memory");
2335 return -1;
2336 }
2337
2338 c_name = env->GetStringUTFChars(j_name, NULL);
2339 if (!c_name) {
2340 env->ReleaseStringUTFChars(j_path, c_path);
2341 cephThrowInternal(env, "Failed to pin memory");
2342 return -1;
2343 }
2344
2345 c_buf = env->GetByteArrayElements(j_buf, NULL);
2346 if (!c_buf) {
2347 env->ReleaseStringUTFChars(j_path, c_path);
2348 env->ReleaseStringUTFChars(j_name, c_name);
2349 cephThrowInternal(env, "failed to pin memory");
2350 return -1;
2351 }
2352
2353 switch (j_flags) {
2354 case JAVA_XATTR_CREATE:
2355 flags = CEPH_XATTR_CREATE;
2356 break;
2357 case JAVA_XATTR_REPLACE:
2358 flags = CEPH_XATTR_REPLACE;
2359 break;
2360 case JAVA_XATTR_NONE:
2361 flags = 0;
2362 break;
2363 default:
2364 env->ReleaseStringUTFChars(j_path, c_path);
2365 env->ReleaseStringUTFChars(j_name, c_name);
2366 env->ReleaseByteArrayElements(j_buf, c_buf, JNI_ABORT);
2367 cephThrowIllegalArg(env, "setxattr flag");
2368 return -1;
2369 }
2370
2371 ldout(cct, 10) << "jni: setxattr: path " << c_path << " name " << c_name
2372 << " len " << j_size << " flags " << flags << dendl;
2373
2374 ret = ceph_setxattr(cmount, c_path, c_name, c_buf, j_size, flags);
2375
2376 ldout(cct, 10) << "jni: setxattr: exit ret " << ret << dendl;
2377
2378 env->ReleaseStringUTFChars(j_path, c_path);
2379 env->ReleaseStringUTFChars(j_name, c_name);
2380 env->ReleaseByteArrayElements(j_buf, c_buf, JNI_ABORT);
2381
2382 if (ret)
2383 handle_error(env, ret);
2384
2385 return ret;
2386 }
2387
2388 /*
2389 * Class: com_ceph_fs_CephMount
2390 * Method: native_ceph_lsetxattr
2391 * Signature: (JLjava/lang/String;Ljava/lang/String;[BJI)I
2392 */
2393 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1lsetxattr
2394 (JNIEnv *env, jclass clz, jlong j_mntp, jstring j_path, jstring j_name,
2395 jbyteArray j_buf, jlong j_size, jint j_flags)
2396 {
2397 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
2398 CephContext *cct = ceph_get_mount_context(cmount);
2399 const char *c_path;
2400 const char *c_name;
2401 jsize buf_size;
2402 jbyte *c_buf;
2403 int ret, flags;
2404
2405 CHECK_ARG_NULL(j_path, "@path is null", -1);
2406 CHECK_ARG_NULL(j_name, "@name is null", -1);
2407 CHECK_ARG_NULL(j_buf, "@buf is null", -1);
2408 CHECK_ARG_BOUNDS(j_size < 0, "@size is negative", -1);
2409 CHECK_MOUNTED(cmount, -1);
2410
2411 buf_size = env->GetArrayLength(j_buf);
2412 CHECK_ARG_BOUNDS(j_size > buf_size, "@size > @buf.length", -1);
2413
2414 c_path = env->GetStringUTFChars(j_path, NULL);
2415 if (!c_path) {
2416 cephThrowInternal(env, "Failed to pin memory");
2417 return -1;
2418 }
2419
2420 c_name = env->GetStringUTFChars(j_name, NULL);
2421 if (!c_name) {
2422 env->ReleaseStringUTFChars(j_path, c_path);
2423 cephThrowInternal(env, "Failed to pin memory");
2424 return -1;
2425 }
2426
2427 c_buf = env->GetByteArrayElements(j_buf, NULL);
2428 if (!c_buf) {
2429 env->ReleaseStringUTFChars(j_path, c_path);
2430 env->ReleaseStringUTFChars(j_name, c_name);
2431 cephThrowInternal(env, "failed to pin memory");
2432 return -1;
2433 }
2434
2435 switch (j_flags) {
2436 case JAVA_XATTR_CREATE:
2437 flags = CEPH_XATTR_CREATE;
2438 break;
2439 case JAVA_XATTR_REPLACE:
2440 flags = CEPH_XATTR_REPLACE;
2441 break;
2442 case JAVA_XATTR_NONE:
2443 flags = 0;
2444 break;
2445 default:
2446 env->ReleaseStringUTFChars(j_path, c_path);
2447 env->ReleaseStringUTFChars(j_name, c_name);
2448 env->ReleaseByteArrayElements(j_buf, c_buf, JNI_ABORT);
2449 cephThrowIllegalArg(env, "lsetxattr flag");
2450 return -1;
2451 }
2452
2453 ldout(cct, 10) << "jni: lsetxattr: path " << c_path << " name " << c_name
2454 << " len " << j_size << " flags " << flags << dendl;
2455
2456 ret = ceph_lsetxattr(cmount, c_path, c_name, c_buf, j_size, flags);
2457
2458 ldout(cct, 10) << "jni: lsetxattr: exit ret " << ret << dendl;
2459
2460 env->ReleaseStringUTFChars(j_path, c_path);
2461 env->ReleaseStringUTFChars(j_name, c_name);
2462 env->ReleaseByteArrayElements(j_buf, c_buf, JNI_ABORT);
2463
2464 if (ret)
2465 handle_error(env, ret);
2466
2467 return ret;
2468 }
2469
2470 /*
2471 * Class: com_ceph_fs_CephMount
2472 * Method: native_ceph_get_file_stripe_unit
2473 * Signature: (JI)I
2474 */
2475 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1get_1file_1stripe_1unit
2476 (JNIEnv *env, jclass clz, jlong j_mntp, jint j_fd)
2477 {
2478 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
2479 CephContext *cct = ceph_get_mount_context(cmount);
2480 int ret;
2481
2482 CHECK_MOUNTED(cmount, -1);
2483
2484 ldout(cct, 10) << "jni: get_file_stripe_unit: fd " << (int)j_fd << dendl;
2485
2486 ret = ceph_get_file_stripe_unit(cmount, (int)j_fd);
2487
2488 ldout(cct, 10) << "jni: get_file_stripe_unit: exit ret " << ret << dendl;
2489
2490 if (ret < 0)
2491 handle_error(env, ret);
2492
2493 return ret;
2494 }
2495
2496 /*
2497 * Class: com_ceph_fs_CephMount
2498 * Method: native_ceph_get_file_replication
2499 * Signature: (JI)I
2500 */
2501 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1get_1file_1replication
2502 (JNIEnv *env, jclass clz, jlong j_mntp, jint j_fd)
2503 {
2504 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
2505 CephContext *cct = ceph_get_mount_context(cmount);
2506 int ret;
2507
2508 CHECK_MOUNTED(cmount, -1);
2509
2510 ldout(cct, 10) << "jni: get_file_replication: fd " << (int)j_fd << dendl;
2511
2512 ret = ceph_get_file_replication(cmount, (int)j_fd);
2513
2514 ldout(cct, 10) << "jni: get_file_replication: exit ret " << ret << dendl;
2515
2516 if (ret < 0)
2517 handle_error(env, ret);
2518
2519 return ret;
2520 }
2521
2522 /*
2523 * Class: com_ceph_fs_CephMount
2524 * Method: native_ceph_get_file_pool_name
2525 * Signature: (JI)Ljava/lang/String;
2526 */
2527 JNIEXPORT jstring JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1get_1file_1pool_1name
2528 (JNIEnv *env, jclass clz, jlong j_mntp, jint j_fd)
2529 {
2530 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
2531 CephContext *cct = ceph_get_mount_context(cmount);
2532 jstring pool = NULL;
2533 int ret, buflen = 0;
2534 char *buf = NULL;
2535
2536 CHECK_MOUNTED(cmount, NULL);
2537
2538 ldout(cct, 10) << "jni: get_file_pool_name: fd " << (int)j_fd << dendl;
2539
2540 for (;;) {
2541 /* get pool name length (len==0) */
2542 ret = ceph_get_file_pool_name(cmount, (int)j_fd, NULL, 0);
2543 if (ret < 0)
2544 break;
2545
2546 /* allocate buffer */
2547 if (buf)
2548 delete [] buf;
2549 buflen = ret;
2550 buf = new (std::nothrow) char[buflen+1]; /* +1 for '\0' */
2551 if (!buf) {
2552 cephThrowOutOfMemory(env, "head allocation failed");
2553 goto out;
2554 }
2555 memset(buf, 0, (buflen+1)*sizeof(*buf));
2556
2557 /* handle zero-length pool name!? */
2558 if (buflen == 0)
2559 break;
2560
2561 /* fill buffer */
2562 ret = ceph_get_file_pool_name(cmount, (int)j_fd, buf, buflen);
2563 if (ret == -ERANGE) /* size changed! */
2564 continue;
2565 else
2566 break;
2567 }
2568
2569 ldout(cct, 10) << "jni: get_file_pool_name: ret " << ret << dendl;
2570
2571 if (ret < 0)
2572 handle_error(env, ret);
2573 else
2574 pool = env->NewStringUTF(buf);
2575
2576 out:
2577 if (buf)
2578 delete [] buf;
2579
2580 return pool;
2581 }
2582
2583 /*
2584 * Class: com_ceph_fs_CephMount
2585 * Method: native_ceph_localize_reads
2586 * Signature: (JZ)I
2587 */
2588 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1localize_1reads
2589 (JNIEnv *env, jclass clz, jlong j_mntp, jboolean j_on)
2590 {
2591 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
2592 CephContext *cct = ceph_get_mount_context(cmount);
2593 int ret, val = j_on ? 1 : 0;
2594
2595 CHECK_MOUNTED(cmount, -1);
2596
2597 ldout(cct, 10) << "jni: localize_reads: val " << val << dendl;
2598
2599 ret = ceph_localize_reads(cmount, val);
2600
2601 ldout(cct, 10) << "jni: localize_reads: exit ret " << ret << dendl;
2602
2603 if (ret)
2604 handle_error(env, ret);
2605
2606 return ret;
2607 }
2608
2609 /*
2610 * Class: com_ceph_fs_CephMount
2611 * Method: native_ceph_get_stripe_unit_granularity
2612 * Signature: (J)I
2613 */
2614 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1get_1stripe_1unit_1granularity
2615 (JNIEnv *env, jclass clz, jlong j_mntp)
2616 {
2617 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
2618 CephContext *cct = ceph_get_mount_context(cmount);
2619 int ret;
2620
2621 CHECK_MOUNTED(cmount, -1);
2622
2623 ldout(cct, 10) << "jni: get_stripe_unit_granularity" << dendl;
2624
2625 ret = ceph_get_stripe_unit_granularity(cmount);
2626
2627 ldout(cct, 10) << "jni: get_stripe_unit_granularity: exit ret " << ret << dendl;
2628
2629 if (ret < 0)
2630 handle_error(env, ret);
2631
2632 return ret;
2633 }
2634
2635 /*
2636 * Class: com_ceph_fs_CephMount
2637 * Method: native_ceph_get_pool_id
2638 * Signature: (JLjava/lang/String;)I
2639 */
2640 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1get_1pool_1id
2641 (JNIEnv *env, jclass clz, jlong j_mntp, jstring jname)
2642 {
2643 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
2644 CephContext *cct = ceph_get_mount_context(cmount);
2645 const char *c_name;
2646 int ret;
2647
2648 CHECK_MOUNTED(cmount, -1);
2649 CHECK_ARG_NULL(jname, "@name is null", -1);
2650
2651 c_name = env->GetStringUTFChars(jname, NULL);
2652 if (!c_name) {
2653 cephThrowInternal(env, "failed to pin memory");
2654 return -1;
2655 }
2656
2657 ldout(cct, 10) << "jni: get_pool_id: name " << c_name << dendl;
2658
2659 ret = ceph_get_pool_id(cmount, c_name);
2660 if (ret < 0)
2661 handle_error(env, ret);
2662
2663 ldout(cct, 10) << "jni: get_pool_id: ret " << ret << dendl;
2664
2665 env->ReleaseStringUTFChars(jname, c_name);
2666
2667 return ret;
2668 }
2669
2670 /*
2671 * Class: com_ceph_fs_CephMount
2672 * Method: native_ceph_get_pool_replication
2673 * Signature: (JI)I
2674 */
2675 JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1get_1pool_1replication
2676 (JNIEnv *env, jclass clz, jlong j_mntp, jint jpoolid)
2677 {
2678 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
2679 CephContext *cct = ceph_get_mount_context(cmount);
2680 int ret;
2681
2682 CHECK_MOUNTED(cmount, -1);
2683
2684 ldout(cct, 10) << "jni: get_pool_replication: poolid " << jpoolid << dendl;
2685
2686 ret = ceph_get_pool_replication(cmount, jpoolid);
2687 if (ret < 0)
2688 handle_error(env, ret);
2689
2690 ldout(cct, 10) << "jni: get_pool_replication: ret " << ret << dendl;
2691
2692 return ret;
2693 }
2694
2695 /*
2696 * Class: com_ceph_fs_CephMount
2697 * Method: native_ceph_get_file_extent_osds
2698 * Signature: (JIJ)Lcom/ceph/fs/CephFileExtent;
2699 */
2700 JNIEXPORT jobject JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1get_1file_1extent_1osds
2701 (JNIEnv *env, jclass clz, jlong mntp, jint fd, jlong off)
2702 {
2703 struct ceph_mount_info *cmount = get_ceph_mount(mntp);
2704 CephContext *cct = ceph_get_mount_context(cmount);
2705 jobject extent = NULL;
2706 int ret, nosds, *osds = NULL;
2707 jintArray osd_array;
2708 loff_t len;
2709
2710 CHECK_MOUNTED(cmount, NULL);
2711
2712 ldout(cct, 10) << "jni: get_file_extent_osds: fd " << fd << " off " << off << dendl;
2713
2714 for (;;) {
2715 /* get pg size */
2716 ret = ceph_get_file_extent_osds(cmount, fd, off, NULL, NULL, 0);
2717 if (ret < 0)
2718 break;
2719
2720 /* alloc osd id array */
2721 if (osds)
2722 delete [] osds;
2723 nosds = ret;
2724 osds = new int[nosds];
2725
2726 /* get osd ids */
2727 ret = ceph_get_file_extent_osds(cmount, fd, off, &len, osds, nosds);
2728 if (ret == -ERANGE)
2729 continue;
2730 else
2731 break;
2732 }
2733
2734 ldout(cct, 10) << "jni: get_file_extent_osds: ret " << ret << dendl;
2735
2736 if (ret < 0) {
2737 handle_error(env, ret);
2738 goto out;
2739 }
2740
2741 nosds = ret;
2742
2743 osd_array = env->NewIntArray(nosds);
2744 if (!osd_array)
2745 goto out;
2746
2747 env->SetIntArrayRegion(osd_array, 0, nosds, osds);
2748 if (env->ExceptionOccurred())
2749 goto out;
2750
2751 extent = env->NewObject(cephfileextent_cls, cephfileextent_ctor_fid, off, len, osd_array);
2752 if (!extent)
2753 goto out;
2754
2755 out:
2756 if (osds)
2757 delete [] osds;
2758
2759 return extent;
2760 }
2761
2762 /*
2763 * Class: com_ceph_fs_CephMount
2764 * Method: native_ceph_get_osd_crush_location
2765 * Signature: (JI)[Ljava/lang/String;
2766 */
2767 JNIEXPORT jobjectArray JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1get_1osd_1crush_1location
2768 (JNIEnv *env, jclass clz, jlong j_mntp, jint osdid)
2769 {
2770 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
2771 CephContext *cct = ceph_get_mount_context(cmount);
2772 jobjectArray path = NULL;
2773 vector<string> str_path;
2774 int ret, bufpos, buflen = 0;
2775 char *buf = NULL;
2776
2777 CHECK_MOUNTED(cmount, NULL);
2778
2779 ldout(cct, 10) << "jni: osd loc: osd " << osdid << dendl;
2780
2781 for (;;) {
2782 /* get length of the location path */
2783 ret = ceph_get_osd_crush_location(cmount, osdid, NULL, 0);
2784 if (ret < 0)
2785 break;
2786
2787 /* alloc path buffer */
2788 if (buf)
2789 delete [] buf;
2790 buflen = ret;
2791 buf = new char[buflen+1];
2792 memset(buf, 0, buflen*sizeof(*buf));
2793
2794 /* empty path */
2795 if (buflen == 0)
2796 break;
2797
2798 /* get the path */
2799 ret = ceph_get_osd_crush_location(cmount, osdid, buf, buflen);
2800 if (ret == -ERANGE)
2801 continue;
2802 else
2803 break;
2804 }
2805
2806 ldout(cct, 10) << "jni: osd loc: osd " << osdid << " ret " << ret << dendl;
2807
2808 if (ret < 0) {
2809 handle_error(env, ret);
2810 goto out;
2811 }
2812
2813 bufpos = 0;
2814 while (bufpos < ret) {
2815 string type(buf + bufpos);
2816 bufpos += type.size() + 1;
2817 string name(buf + bufpos);
2818 bufpos += name.size() + 1;
2819 str_path.push_back(type);
2820 str_path.push_back(name);
2821 }
2822
2823 path = env->NewObjectArray(str_path.size(), env->FindClass("java/lang/String"), NULL);
2824 if (!path)
2825 goto out;
2826
2827 for (unsigned i = 0; i < str_path.size(); i++) {
2828 jstring ent = env->NewStringUTF(str_path[i].c_str());
2829 if (!ent)
2830 goto out;
2831 env->SetObjectArrayElement(path, i, ent);
2832 if (env->ExceptionOccurred())
2833 goto out;
2834 env->DeleteLocalRef(ent);
2835 }
2836
2837 out:
2838 if (buf)
2839 delete [] buf;
2840
2841 return path;
2842 }
2843
2844 /*
2845 * sockaddrToInetAddress uses with the following license, and is adapted for
2846 * use in this project by using Ceph JNI exception utilities.
2847 *
2848 * ----
2849 *
2850 * Copyright (C) 2010 The Android Open Source Project
2851 *
2852 * Licensed under the Apache License, Version 2.0 (the "License");
2853 * you may not use this file except in compliance with the License.
2854 * You may obtain a copy of the License at
2855 *
2856 * http://www.apache.org/licenses/LICENSE-2.0
2857 *
2858 * Unless required by applicable law or agreed to in writing, software
2859 * distributed under the License is distributed on an "AS IS" BASIS,
2860 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2861 * See the License for the specific language governing permissions and
2862 * limitations under the License.
2863 */
2864 jobject sockaddrToInetAddress(JNIEnv* env, const sockaddr_storage& ss, jint* port) {
2865 // Convert IPv4-mapped IPv6 addresses to IPv4 addresses.
2866 // The RI states "Java will never return an IPv4-mapped address".
2867 const sockaddr_in6& sin6 = reinterpret_cast<const sockaddr_in6&>(ss);
2868 if (ss.ss_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sin6.sin6_addr)) {
2869 // Copy the IPv6 address into the temporary sockaddr_storage.
2870 sockaddr_storage tmp;
2871 memset(&tmp, 0, sizeof(tmp));
2872 memcpy(&tmp, &ss, sizeof(sockaddr_in6));
2873 // Unmap it into an IPv4 address.
2874 sockaddr_in& sin = reinterpret_cast<sockaddr_in&>(tmp);
2875 sin.sin_family = AF_INET;
2876 sin.sin_port = sin6.sin6_port;
2877 memcpy(&sin.sin_addr.s_addr, &sin6.sin6_addr.s6_addr[12], 4);
2878 // Do the regular conversion using the unmapped address.
2879 return sockaddrToInetAddress(env, tmp, port);
2880 }
2881
2882 const void* rawAddress;
2883 size_t addressLength;
2884 int sin_port = 0;
2885 int scope_id = 0;
2886 if (ss.ss_family == AF_INET) {
2887 const sockaddr_in& sin = reinterpret_cast<const sockaddr_in&>(ss);
2888 rawAddress = &sin.sin_addr.s_addr;
2889 addressLength = 4;
2890 sin_port = ntohs(sin.sin_port);
2891 } else if (ss.ss_family == AF_INET6) {
2892 const sockaddr_in6& sin6 = reinterpret_cast<const sockaddr_in6&>(ss);
2893 rawAddress = &sin6.sin6_addr.s6_addr;
2894 addressLength = 16;
2895 sin_port = ntohs(sin6.sin6_port);
2896 scope_id = sin6.sin6_scope_id;
2897 } else if (ss.ss_family == AF_UNIX) {
2898 const sockaddr_un& sun = reinterpret_cast<const sockaddr_un&>(ss);
2899 rawAddress = &sun.sun_path;
2900 addressLength = strlen(sun.sun_path);
2901 } else {
2902 // We can't throw SocketException. We aren't meant to see bad addresses, so seeing one
2903 // really does imply an internal error.
2904 //jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
2905 // "sockaddrToInetAddress unsupported ss_family: %i", ss.ss_family);
2906 cephThrowIllegalArg(env, "sockaddrToInetAddress unsupposed ss_family");
2907 return NULL;
2908 }
2909 if (port != NULL) {
2910 *port = sin_port;
2911 }
2912
2913 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(addressLength));
2914 if (byteArray.get() == NULL) {
2915 return NULL;
2916 }
2917 env->SetByteArrayRegion(byteArray.get(), 0, addressLength,
2918 reinterpret_cast<jbyte*>(const_cast<void*>(rawAddress)));
2919
2920 if (ss.ss_family == AF_UNIX) {
2921 // Note that we get here for AF_UNIX sockets on accept(2). The unix(7) man page claims
2922 // that the peer's sun_path will contain the path, but in practice it doesn't, and the
2923 // peer length is returned as 2 (meaning only the sun_family field was set).
2924 //
2925 // Ceph Note: this isn't supported. inetUnixAddress appears to just be
2926 // something in Dalvik/Android stuff.
2927 cephThrowInternal(env, "OSD address should never be a UNIX socket");
2928 return NULL;
2929 //static jmethodID ctor = env->GetMethodID(JniConstants::inetUnixAddressClass, "<init>", "([B)V");
2930 //return env->NewObject(JniConstants::inetUnixAddressClass, ctor, byteArray.get());
2931 }
2932
2933 if (addressLength == 4) {
2934 static jmethodID getByAddressMethod = env->GetStaticMethodID(JniConstants::inetAddressClass,
2935 "getByAddress", "(Ljava/lang/String;[B)Ljava/net/InetAddress;");
2936 if (getByAddressMethod == NULL) {
2937 return NULL;
2938 }
2939 return env->CallStaticObjectMethod(JniConstants::inetAddressClass, getByAddressMethod,
2940 NULL, byteArray.get());
2941 } else if (addressLength == 16) {
2942 static jmethodID getByAddressMethod = env->GetStaticMethodID(JniConstants::inet6AddressClass,
2943 "getByAddress", "(Ljava/lang/String;[BI)Ljava/net/Inet6Address;");
2944 if (getByAddressMethod == NULL) {
2945 return NULL;
2946 }
2947 return env->CallStaticObjectMethod(JniConstants::inet6AddressClass, getByAddressMethod,
2948 NULL, byteArray.get(), scope_id);
2949 } else {
2950 abort();
2951 return NULL;
2952 }
2953 }
2954
2955 /*
2956 * Class: com_ceph_fs_CephMount
2957 * Method: native_ceph_get_osd_addr
2958 * Signature: (JI)Ljava/net/InetAddress;
2959 */
2960 JNIEXPORT jobject JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1get_1osd_1addr
2961 (JNIEnv *env, jclass clz, jlong j_mntp, jint osd)
2962 {
2963 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
2964 CephContext *cct = ceph_get_mount_context(cmount);
2965 struct sockaddr_storage addr;
2966 int ret;
2967
2968 CHECK_MOUNTED(cmount, NULL);
2969
2970 ldout(cct, 10) << "jni: get_osd_addr: osd " << osd << dendl;
2971
2972 ret = ceph_get_osd_addr(cmount, osd, &addr);
2973
2974 ldout(cct, 10) << "jni: get_osd_addr: ret " << ret << dendl;
2975
2976 if (ret < 0) {
2977 handle_error(env, ret);
2978 return NULL;
2979 }
2980
2981 return sockaddrToInetAddress(env, addr, NULL);
2982 }