]> git.proxmox.com Git - ceph.git/blame - ceph/src/java/native/libcephfs_jni.cc
update sources to v12.1.3
[ceph.git] / ceph / src / java / native / libcephfs_jni.cc
CommitLineData
7c673cae
FG
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 */
100static 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 */
123static 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 */
143static jfieldID cephstat_mode_fid;
144static jfieldID cephstat_uid_fid;
145static jfieldID cephstat_gid_fid;
146static jfieldID cephstat_size_fid;
147static jfieldID cephstat_blksize_fid;
148static jfieldID cephstat_blocks_fid;
149static jfieldID cephstat_a_time_fid;
150static jfieldID cephstat_m_time_fid;
151static jfieldID cephstat_is_file_fid;
152static jfieldID cephstat_is_directory_fid;
153static jfieldID cephstat_is_symlink_fid;
154
155/* Cached field IDs for com.ceph.fs.CephStatVFS */
156static jfieldID cephstatvfs_bsize_fid;
157static jfieldID cephstatvfs_frsize_fid;
158static jfieldID cephstatvfs_blocks_fid;
159static jfieldID cephstatvfs_bavail_fid;
160static jfieldID cephstatvfs_files_fid;
161static jfieldID cephstatvfs_fsid_fid;
162static jfieldID cephstatvfs_namemax_fid;
163
164/* Cached field IDs for com.ceph.fs.CephMount */
165static jfieldID cephmount_instance_ptr_fid;
166
167/* Cached field IDs for com.ceph.fs.CephFileExtent */
168static jclass cephfileextent_cls;
169static 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
188static void cephThrowNullArg(JNIEnv *env, const char *msg)
189{
190 THROW(env, "java/lang/NullPointerException", msg);
191}
192
193static void cephThrowOutOfMemory(JNIEnv *env, const char *msg)
194{
195 THROW(env, "java/lang/OutOfMemoryError", msg);
196}
197
198static void cephThrowInternal(JNIEnv *env, const char *msg)
199{
200 THROW(env, "java/lang/InternalError", msg);
201}
202
203static void cephThrowIndexBounds(JNIEnv *env, const char *msg)
204{
205 THROW(env, "java/lang/IndexOutOfBoundsException", msg);
206}
207
208static void cephThrowIllegalArg(JNIEnv *env, const char *msg)
209{
210 THROW(env, "java/lang/IllegalArgumentException", msg);
211}
212
213static void cephThrowFNF(JNIEnv *env, const char *msg)
214{
215 THROW(env, "java/io/FileNotFoundException", msg);
216}
217
218static void cephThrowFileExists(JNIEnv *env, const char *msg)
219{
220 THROW(env, CEPH_FILEEXISTS_CP, msg);
221}
222
223static void cephThrowNotDir(JNIEnv *env, const char *msg)
224{
225 THROW(env, CEPH_NOTDIR_CP, msg);
226}
227
228static 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 */
270static 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 */
278static 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 */
361JNIEXPORT 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 */
372JNIEXPORT 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 */
409JNIEXPORT 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 */
453JNIEXPORT 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 */
479JNIEXPORT 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 */
501JNIEXPORT 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 */
545JNIEXPORT 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
595out:
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 */
605JNIEXPORT 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 */
640JNIEXPORT 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 */
688JNIEXPORT 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 */
715JNIEXPORT 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 */
751JNIEXPORT 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
867out:
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 */
878JNIEXPORT 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 */
924JNIEXPORT 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 */
960JNIEXPORT 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 */
1005JNIEXPORT 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 */
1041JNIEXPORT 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 */
1077JNIEXPORT 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 */
1113JNIEXPORT 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 */
1186JNIEXPORT 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
1229static 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 */
1263JNIEXPORT 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 */
1305JNIEXPORT 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 */
1347JNIEXPORT 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 */
1393JNIEXPORT 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 */
1429JNIEXPORT 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 */
1455JNIEXPORT 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 */
1491JNIEXPORT 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 */
1528JNIEXPORT 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 */
1580JNIEXPORT 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 */
1606JNIEXPORT 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 */
1649JNIEXPORT 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 */
1691JNIEXPORT 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 */
1734JNIEXPORT 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 */
1761JNIEXPORT 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 */
1786JNIEXPORT 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 */
1829JNIEXPORT 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 */
1861JNIEXPORT 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 */
1885JNIEXPORT 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
1929do_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 */
1956JNIEXPORT 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
2000do_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 */
2027JNIEXPORT 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
2113out:
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 */
2123JNIEXPORT 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
2209out:
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 */
2219JNIEXPORT 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 */
2265JNIEXPORT 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 */
2311JNIEXPORT 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 */
2393JNIEXPORT 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 */
2475JNIEXPORT 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 */
2501JNIEXPORT 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 */
2527JNIEXPORT 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
2576out:
2577 if (buf)
2578 delete [] buf;
2579
2580 return pool;
2581}
2582
d2e6a577
FG
2583/**
2584 * Class: com_ceph_fs_CephMount
2585 * Method: native_ceph_get_default_data_pool_name
2586 * Signature: (J)Ljava/lang/String;
2587 */
2588JNIEXPORT jstring JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1get_1default_1data_1pool_1name
2589 (JNIEnv *env, jclass clz, jlong j_mntp)
2590{
2591 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
2592 CephContext *cct = ceph_get_mount_context(cmount);
2593 jstring pool = NULL;
2594 int ret, buflen = 0;
2595 char *buf = NULL;
2596
2597 CHECK_MOUNTED(cmount, NULL);
2598
2599 ldout(cct, 10) << "jni: get_default_data_pool_name" << dendl;
2600
2601 ret = ceph_get_default_data_pool_name(cmount, NULL, 0);
2602 if (ret < 0)
2603 goto out;
2604 buflen = ret;
2605 buf = new (std::nothrow) char[buflen+1]; /* +1 for '\0' */
2606 if (!buf) {
2607 cephThrowOutOfMemory(env, "head allocation failed");
2608 goto out;
2609 }
2610 memset(buf, 0, (buflen+1)*sizeof(*buf));
2611 ret = ceph_get_default_data_pool_name(cmount, buf, buflen);
2612
2613 ldout(cct, 10) << "jni: get_default_data_pool_name: ret " << ret << dendl;
2614
2615 if (ret < 0)
2616 handle_error(env, ret);
2617 else
2618 pool = env->NewStringUTF(buf);
2619
2620out:
2621 if (buf)
2622 delete [] buf;
2623
2624 return pool;
2625}
2626
2627
7c673cae
FG
2628/*
2629 * Class: com_ceph_fs_CephMount
2630 * Method: native_ceph_localize_reads
2631 * Signature: (JZ)I
2632 */
2633JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1localize_1reads
2634 (JNIEnv *env, jclass clz, jlong j_mntp, jboolean j_on)
2635{
2636 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
2637 CephContext *cct = ceph_get_mount_context(cmount);
2638 int ret, val = j_on ? 1 : 0;
2639
2640 CHECK_MOUNTED(cmount, -1);
2641
2642 ldout(cct, 10) << "jni: localize_reads: val " << val << dendl;
2643
2644 ret = ceph_localize_reads(cmount, val);
2645
2646 ldout(cct, 10) << "jni: localize_reads: exit ret " << ret << dendl;
2647
2648 if (ret)
2649 handle_error(env, ret);
2650
2651 return ret;
2652}
2653
2654/*
2655 * Class: com_ceph_fs_CephMount
2656 * Method: native_ceph_get_stripe_unit_granularity
2657 * Signature: (J)I
2658 */
2659JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1get_1stripe_1unit_1granularity
2660 (JNIEnv *env, jclass clz, jlong j_mntp)
2661{
2662 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
2663 CephContext *cct = ceph_get_mount_context(cmount);
2664 int ret;
2665
2666 CHECK_MOUNTED(cmount, -1);
2667
2668 ldout(cct, 10) << "jni: get_stripe_unit_granularity" << dendl;
2669
2670 ret = ceph_get_stripe_unit_granularity(cmount);
2671
2672 ldout(cct, 10) << "jni: get_stripe_unit_granularity: exit ret " << ret << dendl;
2673
2674 if (ret < 0)
2675 handle_error(env, ret);
2676
2677 return ret;
2678}
2679
2680/*
2681 * Class: com_ceph_fs_CephMount
2682 * Method: native_ceph_get_pool_id
2683 * Signature: (JLjava/lang/String;)I
2684 */
2685JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1get_1pool_1id
2686 (JNIEnv *env, jclass clz, jlong j_mntp, jstring jname)
2687{
2688 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
2689 CephContext *cct = ceph_get_mount_context(cmount);
2690 const char *c_name;
2691 int ret;
2692
2693 CHECK_MOUNTED(cmount, -1);
2694 CHECK_ARG_NULL(jname, "@name is null", -1);
2695
2696 c_name = env->GetStringUTFChars(jname, NULL);
2697 if (!c_name) {
2698 cephThrowInternal(env, "failed to pin memory");
2699 return -1;
2700 }
2701
2702 ldout(cct, 10) << "jni: get_pool_id: name " << c_name << dendl;
2703
2704 ret = ceph_get_pool_id(cmount, c_name);
2705 if (ret < 0)
2706 handle_error(env, ret);
2707
2708 ldout(cct, 10) << "jni: get_pool_id: ret " << ret << dendl;
2709
2710 env->ReleaseStringUTFChars(jname, c_name);
2711
2712 return ret;
2713}
2714
2715/*
2716 * Class: com_ceph_fs_CephMount
2717 * Method: native_ceph_get_pool_replication
2718 * Signature: (JI)I
2719 */
2720JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1get_1pool_1replication
2721 (JNIEnv *env, jclass clz, jlong j_mntp, jint jpoolid)
2722{
2723 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
2724 CephContext *cct = ceph_get_mount_context(cmount);
2725 int ret;
2726
2727 CHECK_MOUNTED(cmount, -1);
2728
2729 ldout(cct, 10) << "jni: get_pool_replication: poolid " << jpoolid << dendl;
2730
2731 ret = ceph_get_pool_replication(cmount, jpoolid);
2732 if (ret < 0)
2733 handle_error(env, ret);
2734
2735 ldout(cct, 10) << "jni: get_pool_replication: ret " << ret << dendl;
2736
2737 return ret;
2738}
2739
2740/*
2741 * Class: com_ceph_fs_CephMount
2742 * Method: native_ceph_get_file_extent_osds
2743 * Signature: (JIJ)Lcom/ceph/fs/CephFileExtent;
2744 */
2745JNIEXPORT jobject JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1get_1file_1extent_1osds
2746 (JNIEnv *env, jclass clz, jlong mntp, jint fd, jlong off)
2747{
2748 struct ceph_mount_info *cmount = get_ceph_mount(mntp);
2749 CephContext *cct = ceph_get_mount_context(cmount);
2750 jobject extent = NULL;
2751 int ret, nosds, *osds = NULL;
2752 jintArray osd_array;
2753 loff_t len;
2754
2755 CHECK_MOUNTED(cmount, NULL);
2756
2757 ldout(cct, 10) << "jni: get_file_extent_osds: fd " << fd << " off " << off << dendl;
2758
2759 for (;;) {
2760 /* get pg size */
2761 ret = ceph_get_file_extent_osds(cmount, fd, off, NULL, NULL, 0);
2762 if (ret < 0)
2763 break;
2764
2765 /* alloc osd id array */
2766 if (osds)
2767 delete [] osds;
2768 nosds = ret;
2769 osds = new int[nosds];
2770
2771 /* get osd ids */
2772 ret = ceph_get_file_extent_osds(cmount, fd, off, &len, osds, nosds);
2773 if (ret == -ERANGE)
2774 continue;
2775 else
2776 break;
2777 }
2778
2779 ldout(cct, 10) << "jni: get_file_extent_osds: ret " << ret << dendl;
2780
2781 if (ret < 0) {
2782 handle_error(env, ret);
2783 goto out;
2784 }
2785
2786 nosds = ret;
2787
2788 osd_array = env->NewIntArray(nosds);
2789 if (!osd_array)
2790 goto out;
2791
2792 env->SetIntArrayRegion(osd_array, 0, nosds, osds);
2793 if (env->ExceptionOccurred())
2794 goto out;
2795
2796 extent = env->NewObject(cephfileextent_cls, cephfileextent_ctor_fid, off, len, osd_array);
2797 if (!extent)
2798 goto out;
2799
2800out:
2801 if (osds)
2802 delete [] osds;
2803
2804 return extent;
2805}
2806
2807/*
2808 * Class: com_ceph_fs_CephMount
2809 * Method: native_ceph_get_osd_crush_location
2810 * Signature: (JI)[Ljava/lang/String;
2811 */
2812JNIEXPORT jobjectArray JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1get_1osd_1crush_1location
2813 (JNIEnv *env, jclass clz, jlong j_mntp, jint osdid)
2814{
2815 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
2816 CephContext *cct = ceph_get_mount_context(cmount);
2817 jobjectArray path = NULL;
2818 vector<string> str_path;
2819 int ret, bufpos, buflen = 0;
2820 char *buf = NULL;
2821
2822 CHECK_MOUNTED(cmount, NULL);
2823
2824 ldout(cct, 10) << "jni: osd loc: osd " << osdid << dendl;
2825
2826 for (;;) {
2827 /* get length of the location path */
2828 ret = ceph_get_osd_crush_location(cmount, osdid, NULL, 0);
2829 if (ret < 0)
2830 break;
2831
2832 /* alloc path buffer */
2833 if (buf)
2834 delete [] buf;
2835 buflen = ret;
2836 buf = new char[buflen+1];
2837 memset(buf, 0, buflen*sizeof(*buf));
2838
2839 /* empty path */
2840 if (buflen == 0)
2841 break;
2842
2843 /* get the path */
2844 ret = ceph_get_osd_crush_location(cmount, osdid, buf, buflen);
2845 if (ret == -ERANGE)
2846 continue;
2847 else
2848 break;
2849 }
2850
2851 ldout(cct, 10) << "jni: osd loc: osd " << osdid << " ret " << ret << dendl;
2852
2853 if (ret < 0) {
2854 handle_error(env, ret);
2855 goto out;
2856 }
2857
2858 bufpos = 0;
2859 while (bufpos < ret) {
2860 string type(buf + bufpos);
2861 bufpos += type.size() + 1;
2862 string name(buf + bufpos);
2863 bufpos += name.size() + 1;
2864 str_path.push_back(type);
2865 str_path.push_back(name);
2866 }
2867
2868 path = env->NewObjectArray(str_path.size(), env->FindClass("java/lang/String"), NULL);
2869 if (!path)
2870 goto out;
2871
2872 for (unsigned i = 0; i < str_path.size(); i++) {
2873 jstring ent = env->NewStringUTF(str_path[i].c_str());
2874 if (!ent)
2875 goto out;
2876 env->SetObjectArrayElement(path, i, ent);
2877 if (env->ExceptionOccurred())
2878 goto out;
2879 env->DeleteLocalRef(ent);
2880 }
2881
2882out:
2883 if (buf)
2884 delete [] buf;
2885
2886 return path;
2887}
2888
2889/*
2890 * sockaddrToInetAddress uses with the following license, and is adapted for
2891 * use in this project by using Ceph JNI exception utilities.
2892 *
2893 * ----
2894 *
2895 * Copyright (C) 2010 The Android Open Source Project
2896 *
2897 * Licensed under the Apache License, Version 2.0 (the "License");
2898 * you may not use this file except in compliance with the License.
2899 * You may obtain a copy of the License at
2900 *
2901 * http://www.apache.org/licenses/LICENSE-2.0
2902 *
2903 * Unless required by applicable law or agreed to in writing, software
2904 * distributed under the License is distributed on an "AS IS" BASIS,
2905 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2906 * See the License for the specific language governing permissions and
2907 * limitations under the License.
2908 */
2909jobject sockaddrToInetAddress(JNIEnv* env, const sockaddr_storage& ss, jint* port) {
2910 // Convert IPv4-mapped IPv6 addresses to IPv4 addresses.
2911 // The RI states "Java will never return an IPv4-mapped address".
2912 const sockaddr_in6& sin6 = reinterpret_cast<const sockaddr_in6&>(ss);
2913 if (ss.ss_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sin6.sin6_addr)) {
2914 // Copy the IPv6 address into the temporary sockaddr_storage.
2915 sockaddr_storage tmp;
2916 memset(&tmp, 0, sizeof(tmp));
2917 memcpy(&tmp, &ss, sizeof(sockaddr_in6));
2918 // Unmap it into an IPv4 address.
2919 sockaddr_in& sin = reinterpret_cast<sockaddr_in&>(tmp);
2920 sin.sin_family = AF_INET;
2921 sin.sin_port = sin6.sin6_port;
2922 memcpy(&sin.sin_addr.s_addr, &sin6.sin6_addr.s6_addr[12], 4);
2923 // Do the regular conversion using the unmapped address.
2924 return sockaddrToInetAddress(env, tmp, port);
2925 }
2926
2927 const void* rawAddress;
2928 size_t addressLength;
2929 int sin_port = 0;
2930 int scope_id = 0;
2931 if (ss.ss_family == AF_INET) {
2932 const sockaddr_in& sin = reinterpret_cast<const sockaddr_in&>(ss);
2933 rawAddress = &sin.sin_addr.s_addr;
2934 addressLength = 4;
2935 sin_port = ntohs(sin.sin_port);
2936 } else if (ss.ss_family == AF_INET6) {
2937 const sockaddr_in6& sin6 = reinterpret_cast<const sockaddr_in6&>(ss);
2938 rawAddress = &sin6.sin6_addr.s6_addr;
2939 addressLength = 16;
2940 sin_port = ntohs(sin6.sin6_port);
2941 scope_id = sin6.sin6_scope_id;
2942 } else if (ss.ss_family == AF_UNIX) {
2943 const sockaddr_un& sun = reinterpret_cast<const sockaddr_un&>(ss);
2944 rawAddress = &sun.sun_path;
2945 addressLength = strlen(sun.sun_path);
2946 } else {
2947 // We can't throw SocketException. We aren't meant to see bad addresses, so seeing one
2948 // really does imply an internal error.
2949 //jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
2950 // "sockaddrToInetAddress unsupported ss_family: %i", ss.ss_family);
2951 cephThrowIllegalArg(env, "sockaddrToInetAddress unsupposed ss_family");
2952 return NULL;
2953 }
2954 if (port != NULL) {
2955 *port = sin_port;
2956 }
2957
2958 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(addressLength));
2959 if (byteArray.get() == NULL) {
2960 return NULL;
2961 }
2962 env->SetByteArrayRegion(byteArray.get(), 0, addressLength,
2963 reinterpret_cast<jbyte*>(const_cast<void*>(rawAddress)));
2964
2965 if (ss.ss_family == AF_UNIX) {
2966 // Note that we get here for AF_UNIX sockets on accept(2). The unix(7) man page claims
2967 // that the peer's sun_path will contain the path, but in practice it doesn't, and the
2968 // peer length is returned as 2 (meaning only the sun_family field was set).
2969 //
2970 // Ceph Note: this isn't supported. inetUnixAddress appears to just be
2971 // something in Dalvik/Android stuff.
2972 cephThrowInternal(env, "OSD address should never be a UNIX socket");
2973 return NULL;
2974 //static jmethodID ctor = env->GetMethodID(JniConstants::inetUnixAddressClass, "<init>", "([B)V");
2975 //return env->NewObject(JniConstants::inetUnixAddressClass, ctor, byteArray.get());
2976 }
2977
2978 if (addressLength == 4) {
2979 static jmethodID getByAddressMethod = env->GetStaticMethodID(JniConstants::inetAddressClass,
2980 "getByAddress", "(Ljava/lang/String;[B)Ljava/net/InetAddress;");
2981 if (getByAddressMethod == NULL) {
2982 return NULL;
2983 }
2984 return env->CallStaticObjectMethod(JniConstants::inetAddressClass, getByAddressMethod,
2985 NULL, byteArray.get());
2986 } else if (addressLength == 16) {
2987 static jmethodID getByAddressMethod = env->GetStaticMethodID(JniConstants::inet6AddressClass,
2988 "getByAddress", "(Ljava/lang/String;[BI)Ljava/net/Inet6Address;");
2989 if (getByAddressMethod == NULL) {
2990 return NULL;
2991 }
2992 return env->CallStaticObjectMethod(JniConstants::inet6AddressClass, getByAddressMethod,
2993 NULL, byteArray.get(), scope_id);
2994 } else {
2995 abort();
2996 return NULL;
2997 }
2998}
2999
3000/*
3001 * Class: com_ceph_fs_CephMount
3002 * Method: native_ceph_get_osd_addr
3003 * Signature: (JI)Ljava/net/InetAddress;
3004 */
3005JNIEXPORT jobject JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1get_1osd_1addr
3006 (JNIEnv *env, jclass clz, jlong j_mntp, jint osd)
3007{
3008 struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
3009 CephContext *cct = ceph_get_mount_context(cmount);
3010 struct sockaddr_storage addr;
3011 int ret;
3012
3013 CHECK_MOUNTED(cmount, NULL);
3014
3015 ldout(cct, 10) << "jni: get_osd_addr: osd " << osd << dendl;
3016
3017 ret = ceph_get_osd_addr(cmount, osd, &addr);
3018
3019 ldout(cct, 10) << "jni: get_osd_addr: ret " << ret << dendl;
3020
3021 if (ret < 0) {
3022 handle_error(env, ret);
3023 return NULL;
3024 }
3025
3026 return sockaddrToInetAddress(env, addr, NULL);
3027}