glusterfs

Форк
0
/
glfs-handleops.c 
2652 строки · 60.4 Кб
1
/*
2
 *  Copyright (c) 2013-2018 Red Hat, Inc. <http://www.redhat.com>
3
 *  This file is part of GlusterFS.
4
 *
5
 *  This file is licensed to you under your choice of the GNU Lesser
6
 *  General Public License, version 3 or any later version (LGPLv3 or
7
 *  later), or the GNU General Public License, version 2 (GPLv2), in all
8
 *  cases as published by the Free Software Foundation.
9
 */
10

11
#include "glfs-internal.h"
12
#include "glfs-mem-types.h"
13
#include "glfs.h"
14
#include "gfapi-messages.h"
15

16
int
17
glfs_listxattr_process(void *value, size_t size, dict_t *xattr);
18

19
void
20
glfs_iatt_from_stat(struct stat *stat, int valid, struct iatt *iatt,
21
                    int *glvalid)
22
{
23
    /* validate in args */
24
    if ((stat == NULL) || (iatt == NULL) || (glvalid == NULL)) {
25
        errno = EINVAL;
26
        return;
27
    }
28

29
    *glvalid = 0;
30

31
    if (valid & GFAPI_SET_ATTR_MODE) {
32
        iatt->ia_prot = ia_prot_from_st_mode(stat->st_mode);
33
        *glvalid |= GF_SET_ATTR_MODE;
34
    }
35

36
    if (valid & GFAPI_SET_ATTR_UID) {
37
        iatt->ia_uid = stat->st_uid;
38
        *glvalid |= GF_SET_ATTR_UID;
39
    }
40

41
    if (valid & GFAPI_SET_ATTR_GID) {
42
        iatt->ia_gid = stat->st_gid;
43
        *glvalid |= GF_SET_ATTR_GID;
44
    }
45

46
    if (valid & GFAPI_SET_ATTR_ATIME) {
47
        iatt->ia_atime = stat->st_atime;
48
        iatt->ia_atime_nsec = ST_ATIM_NSEC(stat);
49
        *glvalid |= GF_SET_ATTR_ATIME;
50
    }
51

52
    if (valid & GFAPI_SET_ATTR_MTIME) {
53
        iatt->ia_mtime = stat->st_mtime;
54
        iatt->ia_mtime_nsec = ST_MTIM_NSEC(stat);
55
        *glvalid |= GF_SET_ATTR_MTIME;
56
    }
57

58
    return;
59
}
60

61
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_lookupat, 3.7.4)
62
struct glfs_object *
63
pub_glfs_h_lookupat(struct glfs *fs, struct glfs_object *parent,
64
                    const char *path, struct stat *stat, int follow)
65
{
66
    int ret = 0;
67
    xlator_t *subvol = NULL;
68
    inode_t *inode = NULL;
69
    struct iatt iatt = {
70
        0,
71
    };
72
    struct glfs_object *object = NULL;
73
    loc_t loc = {
74
        0,
75
    };
76

77
    DECLARE_OLD_THIS;
78

79
    /* validate in args */
80
    if (path == NULL) {
81
        errno = EINVAL;
82
        return NULL;
83
    }
84

85
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
86

87
    /* get the active volume */
88
    subvol = glfs_active_subvol(fs);
89
    if (!subvol) {
90
        errno = EIO;
91
        goto out;
92
    }
93

94
    /* get/refresh the in arg objects inode in correlation to the xlator */
95
    if (parent) {
96
        inode = glfs_resolve_inode(fs, subvol, parent);
97
        if (!inode) {
98
            errno = ESTALE;
99
            goto out;
100
        }
101
    }
102

103
    /* fop/op */
104
    ret = glfs_resolve_at(fs, subvol, inode, path, &loc, &iatt, follow, 0);
105

106
    /* populate out args */
107
    if (!ret) {
108
        if (stat)
109
            glfs_iatt_to_stat(fs, &iatt, stat);
110

111
        ret = glfs_create_object(&loc, &object);
112
    }
113

114
out:
115
    loc_wipe(&loc);
116

117
    if (inode)
118
        inode_unref(inode);
119

120
    glfs_subvol_done(fs, subvol);
121

122
    __GLFS_EXIT_FS;
123

124
invalid_fs:
125
    return object;
126
}
127

128
GFAPI_SYMVER_PUBLIC(glfs_h_lookupat34, glfs_h_lookupat, 3.4.2)
129
struct glfs_object *
130
pub_glfs_h_lookupat34(struct glfs *fs, struct glfs_object *parent,
131
                      const char *path, struct stat *stat)
132
{
133
    return pub_glfs_h_lookupat(fs, parent, path, stat, 0);
134
}
135

136
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_statfs, 3.7.0)
137
int
138
pub_glfs_h_statfs(struct glfs *fs, struct glfs_object *object,
139
                  struct statvfs *statvfs)
140
{
141
    int ret = -1;
142
    xlator_t *subvol = NULL;
143
    inode_t *inode = NULL;
144
    loc_t loc = {
145
        0,
146
    };
147

148
    DECLARE_OLD_THIS;
149

150
    /* validate in args */
151
    if ((fs == NULL) || (object == NULL || statvfs == NULL)) {
152
        errno = EINVAL;
153
        return -1;
154
    }
155

156
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
157

158
    /* get the active volume */
159
    subvol = glfs_active_subvol(fs);
160
    if (!subvol) {
161
        ret = -1;
162
        errno = EIO;
163
        goto out;
164
    }
165

166
    /* get/refresh the in arg objects inode in correlation to the xlator */
167
    inode = glfs_resolve_inode(fs, subvol, object);
168
    if (!inode) {
169
        errno = ESTALE;
170
        goto out;
171
    }
172

173
    /* populate loc */
174
    GLFS_LOC_FILL_INODE(inode, loc, out);
175

176
    /* fop/op */
177
    ret = syncop_statfs(subvol, &loc, statvfs, NULL, NULL);
178
    DECODE_SYNCOP_ERR(ret);
179

180
    loc_wipe(&loc);
181

182
out:
183
    if (inode)
184
        inode_unref(inode);
185

186
    glfs_subvol_done(fs, subvol);
187

188
    __GLFS_EXIT_FS;
189

190
invalid_fs:
191
    return ret;
192
}
193

194
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_stat, 3.4.2)
195
int
196
pub_glfs_h_stat(struct glfs *fs, struct glfs_object *object, struct stat *stat)
197
{
198
    int ret = -1;
199
    xlator_t *subvol = NULL;
200
    inode_t *inode = NULL;
201
    loc_t loc = {
202
        0,
203
    };
204
    struct iatt iatt = {
205
        0,
206
    };
207

208
    DECLARE_OLD_THIS;
209

210
    /* validate in args */
211
    if ((fs == NULL) || (object == NULL)) {
212
        errno = EINVAL;
213
        return -1;
214
    }
215

216
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
217

218
    /* get the active volume */
219
    subvol = glfs_active_subvol(fs);
220
    if (!subvol) {
221
        ret = -1;
222
        errno = EIO;
223
        goto out;
224
    }
225

226
    /* get/refresh the in arg objects inode in correlation to the xlator */
227
    inode = glfs_resolve_inode(fs, subvol, object);
228
    if (!inode) {
229
        errno = ESTALE;
230
        goto out;
231
    }
232

233
    /* populate loc */
234
    GLFS_LOC_FILL_INODE(inode, loc, out);
235

236
    /* fop/op */
237
    if (stat) {
238
        ret = syncop_stat(subvol, &loc, &iatt, NULL, NULL);
239
        if (!ret)
240
            /* populate out args */
241
            glfs_iatt_to_stat(fs, &iatt, stat);
242
    } else
243
        ret = syncop_stat(subvol, &loc, NULL, NULL, NULL);
244
    DECODE_SYNCOP_ERR(ret);
245

246
out:
247
    loc_wipe(&loc);
248

249
    if (inode)
250
        inode_unref(inode);
251

252
    glfs_subvol_done(fs, subvol);
253

254
    __GLFS_EXIT_FS;
255

256
invalid_fs:
257
    return ret;
258
}
259

260
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_getattrs, 3.4.2)
261
int
262
pub_glfs_h_getattrs(struct glfs *fs, struct glfs_object *object,
263
                    struct stat *stat)
264
{
265
    int ret = -1;
266
    xlator_t *subvol = NULL;
267
    inode_t *inode = NULL;
268
    struct iatt iatt = {
269
        0,
270
    };
271

272
    /* validate in args */
273
    if ((fs == NULL) || (object == NULL)) {
274
        errno = EINVAL;
275
        return -1;
276
    }
277

278
    DECLARE_OLD_THIS;
279
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
280

281
    /* get the active volume */
282
    subvol = glfs_active_subvol(fs);
283
    if (!subvol) {
284
        ret = -1;
285
        errno = EIO;
286
        goto out;
287
    }
288

289
    /* get/refresh the in arg objects inode in correlation to the xlator */
290
    inode = glfs_resolve_inode(fs, subvol, object);
291
    if (!inode) {
292
        ret = 0;
293
        errno = ESTALE;
294
        goto out;
295
    }
296

297
    /* fop/op */
298
    if (stat) {
299
        ret = glfs_resolve_base(fs, subvol, inode, &iatt);
300
        /* populate out args */
301
        if (!ret) {
302
            glfs_iatt_to_stat(fs, &iatt, stat);
303
        }
304
    } else
305
        ret = glfs_resolve_base(fs, subvol, inode, NULL);
306

307
out:
308
    if (inode)
309
        inode_unref(inode);
310

311
    glfs_subvol_done(fs, subvol);
312

313
    __GLFS_EXIT_FS;
314

315
invalid_fs:
316
    return ret;
317
}
318

319
int
320
glfs_h_getxattrs_common(struct glfs *fs, struct glfs_object *object,
321
                        dict_t **xattr, const char *name,
322
                        gf_boolean_t is_listxattr)
323
{
324
    int ret = 0;
325
    xlator_t *subvol = NULL;
326
    inode_t *inode = NULL;
327
    loc_t loc = {
328
        0,
329
    };
330

331
    /* validate in args */
332
    if ((fs == NULL) || (object == NULL)) {
333
        errno = EINVAL;
334
        return -1;
335
    }
336

337
    if (!is_listxattr) {
338
        if (!name || *name == '\0') {
339
            errno = EINVAL;
340
            return -1;
341
        }
342

343
        if (strlen(name) > GF_XATTR_NAME_MAX) {
344
            errno = ENAMETOOLONG;
345
            return -1;
346
        }
347
    }
348
    /* get the active volume */
349
    subvol = glfs_active_subvol(fs);
350
    if (!subvol) {
351
        ret = -1;
352
        errno = EIO;
353
        goto out;
354
    }
355

356
    /* get/refresh the in arg objects inode in correlation to the xlator */
357
    inode = glfs_resolve_inode(fs, subvol, object);
358
    if (!inode) {
359
        errno = ESTALE;
360
        goto out;
361
    }
362

363
    /* populate loc */
364
    GLFS_LOC_FILL_INODE(inode, loc, out);
365

366
    ret = syncop_getxattr(subvol, &loc, xattr, name, NULL, NULL);
367
    DECODE_SYNCOP_ERR(ret);
368

369
out:
370
    loc_wipe(&loc);
371

372
    if (inode)
373
        inode_unref(inode);
374

375
    glfs_subvol_done(fs, subvol);
376

377
    return ret;
378
}
379

380
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_getxattrs, 3.5.1)
381
int
382
pub_glfs_h_getxattrs(struct glfs *fs, struct glfs_object *object,
383
                     const char *name, void *value, size_t size)
384
{
385
    int ret = -1;
386
    dict_t *xattr = NULL;
387

388
    /* validate in args */
389
    if ((fs == NULL) || (object == NULL)) {
390
        errno = EINVAL;
391
        return -1;
392
    }
393

394
    DECLARE_OLD_THIS;
395
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
396

397
    ret = glfs_h_getxattrs_common(fs, object, &xattr, name, (name == NULL));
398
    if (ret)
399
        goto out;
400

401
    /* If @name is NULL, means get all the xattrs (i.e listxattr). */
402
    if (name)
403
        ret = glfs_getxattr_process(value, size, xattr, name);
404
    else
405
        ret = glfs_listxattr_process(value, size, xattr);
406

407
out:
408
    if (xattr)
409
        dict_unref(xattr);
410

411
    __GLFS_EXIT_FS;
412

413
invalid_fs:
414
    return ret;
415
}
416

417
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_setattrs, 3.4.2)
418
int
419
pub_glfs_h_setattrs(struct glfs *fs, struct glfs_object *object,
420
                    struct stat *stat, int valid)
421
{
422
    int ret = -1;
423
    xlator_t *subvol = NULL;
424
    inode_t *inode = NULL;
425
    loc_t loc = {
426
        0,
427
    };
428
    struct iatt iatt = {
429
        0,
430
    };
431
    int glvalid = 0;
432

433
    /* validate in args */
434
    if ((fs == NULL) || (object == NULL) || (stat == NULL)) {
435
        errno = EINVAL;
436
        return -1;
437
    }
438

439
    DECLARE_OLD_THIS;
440
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
441

442
    /* get the active volume */
443
    subvol = glfs_active_subvol(fs);
444
    if (!subvol) {
445
        ret = -1;
446
        errno = EIO;
447
        goto out;
448
    }
449

450
    /* get/refresh the in arg objects inode in correlation to the xlator */
451
    inode = glfs_resolve_inode(fs, subvol, object);
452
    if (!inode) {
453
        errno = ESTALE;
454
        goto out;
455
    }
456

457
    /* map valid masks from in args */
458
    glfs_iatt_from_stat(stat, valid, &iatt, &glvalid);
459

460
    /* populate loc */
461
    GLFS_LOC_FILL_INODE(inode, loc, out);
462

463
    /* fop/op */
464
    ret = syncop_setattr(subvol, &loc, &iatt, glvalid, 0, 0, NULL, NULL);
465
    DECODE_SYNCOP_ERR(ret);
466
out:
467
    loc_wipe(&loc);
468

469
    if (inode)
470
        inode_unref(inode);
471

472
    glfs_subvol_done(fs, subvol);
473

474
    __GLFS_EXIT_FS;
475

476
invalid_fs:
477
    return ret;
478
}
479

480
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_setxattrs, 3.5.0)
481
int
482
pub_glfs_h_setxattrs(struct glfs *fs, struct glfs_object *object,
483
                     const char *name, const void *value, size_t size,
484
                     int flags)
485
{
486
    int ret = -1;
487
    xlator_t *subvol = NULL;
488
    inode_t *inode = NULL;
489
    loc_t loc = {
490
        0,
491
    };
492
    dict_t *xattr = NULL;
493
    void *value_cp = NULL;
494

495
    /* validate in args */
496
    if ((fs == NULL) || (object == NULL) || (name == NULL) || (value == NULL)) {
497
        errno = EINVAL;
498
        return -1;
499
    }
500

501
    if (!name || *name == '\0') {
502
        errno = EINVAL;
503
        return -1;
504
    }
505

506
    if (strlen(name) > GF_XATTR_NAME_MAX) {
507
        errno = ENAMETOOLONG;
508
        return -1;
509
    }
510

511
    DECLARE_OLD_THIS;
512
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
513

514
    /* get the active volume */
515
    subvol = glfs_active_subvol(fs);
516
    if (!subvol) {
517
        ret = -1;
518
        errno = EIO;
519
        goto out;
520
    }
521

522
    /* get/refresh the in arg objects inode in correlation to the xlator */
523
    inode = glfs_resolve_inode(fs, subvol, object);
524
    if (!inode) {
525
        errno = ESTALE;
526
        goto out;
527
    }
528

529
    value_cp = gf_memdup(value, size);
530
    GF_CHECK_ALLOC_AND_LOG(subvol->name, value_cp, ret,
531
                           "Failed to"
532
                           " duplicate setxattr value",
533
                           out);
534

535
    xattr = dict_for_key_value(name, value_cp, size, _gf_false);
536
    if (!xattr) {
537
        GF_FREE(value_cp);
538
        ret = -1;
539
        errno = ENOMEM;
540
        goto out;
541
    }
542

543
    /* populate loc */
544
    GLFS_LOC_FILL_INODE(inode, loc, out);
545

546
    /* fop/op */
547
    ret = syncop_setxattr(subvol, &loc, xattr, flags, NULL, NULL);
548
    DECODE_SYNCOP_ERR(ret);
549

550
out:
551
    loc_wipe(&loc);
552

553
    if (inode)
554
        inode_unref(inode);
555

556
    if (xattr)
557
        dict_unref(xattr);
558

559
    glfs_subvol_done(fs, subvol);
560

561
    __GLFS_EXIT_FS;
562

563
invalid_fs:
564
    return ret;
565
}
566

567
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_removexattrs, 3.5.1)
568
int
569
pub_glfs_h_removexattrs(struct glfs *fs, struct glfs_object *object,
570
                        const char *name)
571
{
572
    int ret = -1;
573
    xlator_t *subvol = NULL;
574
    inode_t *inode = NULL;
575
    loc_t loc = {
576
        0,
577
    };
578

579
    /* validate in args */
580
    if ((fs == NULL) || (object == NULL) || (name == NULL)) {
581
        errno = EINVAL;
582
        return -1;
583
    }
584

585
    DECLARE_OLD_THIS;
586
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
587

588
    /* get the active volume */
589
    subvol = glfs_active_subvol(fs);
590
    if (!subvol) {
591
        ret = -1;
592
        errno = EIO;
593
        goto out;
594
    }
595

596
    /* get/refresh the in arg objects inode in correlation to the xlator */
597
    inode = glfs_resolve_inode(fs, subvol, object);
598
    if (!inode) {
599
        errno = ESTALE;
600
        goto out;
601
    }
602

603
    /* populate loc */
604
    GLFS_LOC_FILL_INODE(inode, loc, out);
605

606
    /* fop/op */
607
    ret = syncop_removexattr(subvol, &loc, name, NULL, NULL);
608
    DECODE_SYNCOP_ERR(ret);
609

610
out:
611
    loc_wipe(&loc);
612

613
    if (inode)
614
        inode_unref(inode);
615

616
    glfs_subvol_done(fs, subvol);
617

618
    __GLFS_EXIT_FS;
619

620
invalid_fs:
621
    return ret;
622
}
623

624
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_open, 3.4.2)
625
struct glfs_fd *
626
pub_glfs_h_open(struct glfs *fs, struct glfs_object *object, int flags)
627
{
628
    int ret = -1;
629
    struct glfs_fd *glfd = NULL;
630
    xlator_t *subvol = NULL;
631
    inode_t *inode = NULL;
632
    loc_t loc = {
633
        0,
634
    };
635
    dict_t *fop_attr = NULL;
636

637
    /* validate in args */
638
    if ((fs == NULL) || (object == NULL)) {
639
        errno = EINVAL;
640
        return NULL;
641
    }
642

643
    DECLARE_OLD_THIS;
644
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
645

646
    /* get the active volume */
647
    subvol = glfs_active_subvol(fs);
648
    if (!subvol) {
649
        errno = EIO;
650
        goto out;
651
    }
652

653
    /* get/refresh the in arg objects inode in correlation to the xlator */
654
    inode = glfs_resolve_inode(fs, subvol, object);
655
    if (!inode) {
656
        errno = ESTALE;
657
        goto out;
658
    }
659

660
    ret = validate_open_flags(flags, inode->ia_type);
661
    if (ret)
662
        goto out;
663

664
    glfd = glfs_fd_new(fs);
665
    if (!glfd) {
666
        ret = -1;
667
        errno = ENOMEM;
668
        goto out;
669
    }
670

671
    glfd->fd = fd_create(inode, getpid());
672
    if (!glfd->fd) {
673
        ret = -1;
674
        errno = ENOMEM;
675
        goto out;
676
    }
677
    glfd->fd->flags = flags;
678

679
    /* populate loc */
680
    GLFS_LOC_FILL_INODE(inode, loc, out);
681

682
    /* fop/op */
683
    ret = get_fop_attr_thrd_key(&fop_attr);
684
    if (ret)
685
        gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed");
686

687
    if (IA_ISDIR(inode->ia_type))
688
        ret = syncop_opendir(subvol, &loc, glfd->fd, NULL, NULL);
689
    else
690
        ret = syncop_open(subvol, &loc, flags, glfd->fd, fop_attr, NULL);
691

692
    DECODE_SYNCOP_ERR(ret);
693

694
    glfd->fd->flags = flags;
695

696
out:
697
    loc_wipe(&loc);
698

699
    if (inode)
700
        inode_unref(inode);
701
    if (fop_attr)
702
        dict_unref(fop_attr);
703

704
    if (ret && glfd) {
705
        GF_REF_PUT(glfd);
706
        glfd = NULL;
707
    } else if (glfd) {
708
        glfd_set_state_bind(glfd);
709
    }
710

711
    glfs_subvol_done(fs, subvol);
712

713
    __GLFS_EXIT_FS;
714

715
invalid_fs:
716
    return glfd;
717
}
718

719
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_creat, 3.4.2)
720
struct glfs_object *
721
pub_glfs_h_creat(struct glfs *fs, struct glfs_object *parent, const char *path,
722
                 int flags, mode_t mode, struct stat *stat)
723
{
724
    int ret = -1;
725
    fd_t *fd = NULL;
726
    xlator_t *subvol = NULL;
727
    inode_t *inode = NULL;
728
    loc_t loc = {
729
        0,
730
    };
731
    struct iatt iatt = {
732
        0,
733
    };
734
    uuid_t gfid;
735
    dict_t *xattr_req = NULL;
736
    struct glfs_object *object = NULL;
737

738
    /* validate in args */
739
    if ((fs == NULL) || (parent == NULL) || (path == NULL)) {
740
        errno = EINVAL;
741
        return NULL;
742
    }
743

744
    DECLARE_OLD_THIS;
745
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
746

747
    /* get the active volume */
748
    subvol = glfs_active_subvol(fs);
749
    if (!subvol) {
750
        ret = -1;
751
        errno = EIO;
752
        goto out;
753
    }
754

755
    /* get/refresh the in arg objects inode in correlation to the xlator */
756
    inode = glfs_resolve_inode(fs, subvol, parent);
757
    if (!inode) {
758
        ret = -1;
759
        errno = ESTALE;
760
        goto out;
761
    }
762

763
    xattr_req = dict_new();
764
    if (!xattr_req) {
765
        ret = -1;
766
        errno = ENOMEM;
767
        goto out;
768
    }
769

770
    gf_uuid_generate(gfid);
771
    ret = dict_set_gfuuid(xattr_req, "gfid-req", gfid, true);
772
    if (ret) {
773
        ret = -1;
774
        errno = ENOMEM;
775
        goto out;
776
    }
777

778
    GLFS_LOC_FILL_PINODE(inode, loc, ret, errno, out, path);
779

780
    fd = fd_create(loc.inode, getpid());
781
    if (!fd) {
782
        ret = -1;
783
        errno = ENOMEM;
784
        goto out;
785
    }
786
    fd->flags = flags;
787

788
    /* fop/op */
789
    ret = syncop_create(subvol, &loc, flags, mode, fd, &iatt, xattr_req, NULL);
790
    DECODE_SYNCOP_ERR(ret);
791

792
    /* populate out args */
793
    if (ret == 0) {
794
        ret = glfs_loc_link(&loc, &iatt);
795
        if (ret != 0) {
796
            goto out;
797
        }
798

799
        if (stat)
800
            glfs_iatt_to_stat(fs, &iatt, stat);
801

802
        ret = glfs_create_object(&loc, &object);
803
    }
804

805
out:
806
    if (ret && object != NULL) {
807
        /* Release the held reference */
808
        glfs_h_close(object);
809
        object = NULL;
810
    }
811

812
    loc_wipe(&loc);
813

814
    if (inode)
815
        inode_unref(inode);
816

817
    if (xattr_req)
818
        dict_unref(xattr_req);
819

820
    if (fd)
821
        fd_unref(fd);
822

823
    glfs_subvol_done(fs, subvol);
824

825
    __GLFS_EXIT_FS;
826

827
invalid_fs:
828
    return object;
829
}
830

831
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_creat_open, 6.6)
832
struct glfs_object *
833
pub_glfs_h_creat_open(struct glfs *fs, struct glfs_object *parent,
834
                      const char *path, int flags, mode_t mode,
835
                      struct stat *stat, struct glfs_fd **out_fd)
836
{
837
    int ret = -1;
838
    struct glfs_fd *glfd = NULL;
839
    xlator_t *subvol = NULL;
840
    inode_t *inode = NULL;
841
    loc_t loc = {
842
        0,
843
    };
844
    struct iatt iatt = {
845
        0,
846
    };
847
    uuid_t gfid;
848
    dict_t *xattr_req = NULL;
849
    struct glfs_object *object = NULL;
850
    dict_t *fop_attr = NULL;
851

852
    /* validate in args */
853
    if ((fs == NULL) || (parent == NULL) || (path == NULL) ||
854
        (out_fd == NULL)) {
855
        errno = EINVAL;
856
        return NULL;
857
    }
858

859
    DECLARE_OLD_THIS;
860
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
861

862
    /* get the active volume */
863
    subvol = glfs_active_subvol(fs);
864
    if (!subvol) {
865
        ret = -1;
866
        goto out;
867
    }
868

869
    /* get/refresh the in arg objects inode in correlation to the xlator */
870
    inode = glfs_resolve_inode(fs, subvol, parent);
871
    if (!inode) {
872
        ret = -1;
873
        goto out;
874
    }
875

876
    xattr_req = dict_new();
877
    if (!xattr_req) {
878
        ret = -1;
879
        errno = ENOMEM;
880
        goto out;
881
    }
882

883
    gf_uuid_generate(gfid);
884
    ret = dict_set_gfuuid(xattr_req, "gfid-req", gfid, true);
885
    if (ret) {
886
        ret = -1;
887
        errno = ENOMEM;
888
        goto out;
889
    }
890

891
    GLFS_LOC_FILL_PINODE(inode, loc, ret, errno, out, path);
892

893
    glfd = glfs_fd_new(fs);
894
    if (!glfd) {
895
        ret = -1;
896
        errno = ENOMEM;
897
        goto out;
898
    }
899

900
    glfd->fd = fd_create(loc.inode, getpid());
901
    if (!glfd->fd) {
902
        ret = -1;
903
        errno = ENOMEM;
904
        goto out;
905
    }
906
    glfd->fd->flags = flags;
907

908
    ret = get_fop_attr_thrd_key(&fop_attr);
909
    if (ret)
910
        gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed");
911

912
    /* fop/op */
913
    ret = syncop_create(subvol, &loc, flags, mode, glfd->fd, &iatt, xattr_req,
914
                        NULL);
915
    DECODE_SYNCOP_ERR(ret);
916

917
    /* populate out args */
918
    if (ret == 0) {
919
        glfd->fd->flags = flags;
920

921
        ret = glfs_loc_link(&loc, &iatt);
922
        if (ret != 0) {
923
            goto out;
924
        }
925

926
        if (stat)
927
            glfs_iatt_to_stat(fs, &iatt, stat);
928

929
        ret = glfs_create_object(&loc, &object);
930
    }
931

932
out:
933
    if (ret && object != NULL) {
934
        /* Release the held reference */
935
        glfs_h_close(object);
936
        object = NULL;
937
    }
938

939
    loc_wipe(&loc);
940

941
    if (inode)
942
        inode_unref(inode);
943

944
    if (fop_attr)
945
        dict_unref(fop_attr);
946

947
    if (xattr_req)
948
        dict_unref(xattr_req);
949

950
    if (ret && glfd) {
951
        GF_REF_PUT(glfd);
952
    } else if (glfd) {
953
        glfd_set_state_bind(glfd);
954
        *out_fd = glfd;
955
    }
956

957
    glfs_subvol_done(fs, subvol);
958

959
    __GLFS_EXIT_FS;
960

961
invalid_fs:
962
    return object;
963
}
964

965
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_mkdir, 3.4.2)
966
struct glfs_object *
967
pub_glfs_h_mkdir(struct glfs *fs, struct glfs_object *parent, const char *path,
968
                 mode_t mode, struct stat *stat)
969
{
970
    int ret = -1;
971
    xlator_t *subvol = NULL;
972
    inode_t *inode = NULL;
973
    loc_t loc = {
974
        0,
975
    };
976
    struct iatt iatt = {
977
        0,
978
    };
979
    uuid_t gfid;
980
    dict_t *xattr_req = NULL;
981
    struct glfs_object *object = NULL;
982

983
    /* validate in args */
984
    if ((fs == NULL) || (parent == NULL) || (path == NULL)) {
985
        errno = EINVAL;
986
        return NULL;
987
    }
988

989
    DECLARE_OLD_THIS;
990
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
991

992
    /* get the active volume */
993
    subvol = glfs_active_subvol(fs);
994
    if (!subvol) {
995
        ret = -1;
996
        errno = EIO;
997
        goto out;
998
    }
999

1000
    /* get/refresh the in arg objects inode in correlation to the xlator */
1001
    inode = glfs_resolve_inode(fs, subvol, parent);
1002
    if (!inode) {
1003
        errno = ESTALE;
1004
        goto out;
1005
    }
1006

1007
    xattr_req = dict_new();
1008
    if (!xattr_req) {
1009
        ret = -1;
1010
        errno = ENOMEM;
1011
        goto out;
1012
    }
1013

1014
    gf_uuid_generate(gfid);
1015
    ret = dict_set_gfuuid(xattr_req, "gfid-req", gfid, true);
1016
    if (ret) {
1017
        ret = -1;
1018
        errno = ENOMEM;
1019
        goto out;
1020
    }
1021

1022
    GLFS_LOC_FILL_PINODE(inode, loc, ret, errno, out, path);
1023

1024
    /* fop/op */
1025
    ret = syncop_mkdir(subvol, &loc, mode, &iatt, xattr_req, NULL);
1026
    DECODE_SYNCOP_ERR(ret);
1027

1028
    /* populate out args */
1029
    if (ret == 0) {
1030
        ret = glfs_loc_link(&loc, &iatt);
1031
        if (ret != 0) {
1032
            goto out;
1033
        }
1034

1035
        if (stat)
1036
            glfs_iatt_to_stat(fs, &iatt, stat);
1037

1038
        ret = glfs_create_object(&loc, &object);
1039
    }
1040

1041
out:
1042
    if (ret && object != NULL) {
1043
        glfs_h_close(object);
1044
        object = NULL;
1045
    }
1046

1047
    loc_wipe(&loc);
1048

1049
    if (inode)
1050
        inode_unref(inode);
1051

1052
    if (xattr_req)
1053
        dict_unref(xattr_req);
1054

1055
    glfs_subvol_done(fs, subvol);
1056

1057
    __GLFS_EXIT_FS;
1058

1059
invalid_fs:
1060
    return object;
1061
}
1062

1063
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_mknod, 3.4.2)
1064
struct glfs_object *
1065
pub_glfs_h_mknod(struct glfs *fs, struct glfs_object *parent, const char *path,
1066
                 mode_t mode, dev_t dev, struct stat *stat)
1067
{
1068
    int ret = -1;
1069
    xlator_t *subvol = NULL;
1070
    inode_t *inode = NULL;
1071
    loc_t loc = {
1072
        0,
1073
    };
1074
    struct iatt iatt = {
1075
        0,
1076
    };
1077
    uuid_t gfid;
1078
    dict_t *xattr_req = NULL;
1079
    struct glfs_object *object = NULL;
1080

1081
    /* validate in args */
1082
    if ((fs == NULL) || (parent == NULL) || (path == NULL)) {
1083
        errno = EINVAL;
1084
        return NULL;
1085
    }
1086

1087
    DECLARE_OLD_THIS;
1088
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
1089

1090
    /* get the active volume */
1091
    subvol = glfs_active_subvol(fs);
1092
    if (!subvol) {
1093
        ret = -1;
1094
        errno = EIO;
1095
        goto out;
1096
    }
1097

1098
    /* get/refresh the in arg objects inode in correlation to the xlator */
1099
    inode = glfs_resolve_inode(fs, subvol, parent);
1100
    if (!inode) {
1101
        errno = ESTALE;
1102
        goto out;
1103
    }
1104

1105
    xattr_req = dict_new();
1106
    if (!xattr_req) {
1107
        ret = -1;
1108
        errno = ENOMEM;
1109
        goto out;
1110
    }
1111

1112
    gf_uuid_generate(gfid);
1113
    ret = dict_set_gfuuid(xattr_req, "gfid-req", gfid, true);
1114
    if (ret) {
1115
        ret = -1;
1116
        errno = ENOMEM;
1117
        goto out;
1118
    }
1119

1120
    GLFS_LOC_FILL_PINODE(inode, loc, ret, errno, out, path);
1121

1122
    /* fop/op */
1123
    ret = syncop_mknod(subvol, &loc, mode, dev, &iatt, xattr_req, NULL);
1124
    DECODE_SYNCOP_ERR(ret);
1125

1126
    /* populate out args */
1127
    if (ret == 0) {
1128
        ret = glfs_loc_link(&loc, &iatt);
1129
        if (ret != 0) {
1130
            goto out;
1131
        }
1132

1133
        if (stat)
1134
            glfs_iatt_to_stat(fs, &iatt, stat);
1135

1136
        ret = glfs_create_object(&loc, &object);
1137
    }
1138
out:
1139
    if (ret && object != NULL) {
1140
        glfs_h_close(object);
1141
        object = NULL;
1142
    }
1143

1144
    loc_wipe(&loc);
1145

1146
    if (inode)
1147
        inode_unref(inode);
1148

1149
    if (xattr_req)
1150
        dict_unref(xattr_req);
1151

1152
    glfs_subvol_done(fs, subvol);
1153

1154
    __GLFS_EXIT_FS;
1155

1156
invalid_fs:
1157
    return object;
1158
}
1159

1160
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_unlink, 3.4.2)
1161
int
1162
pub_glfs_h_unlink(struct glfs *fs, struct glfs_object *parent, const char *path)
1163
{
1164
    int ret = -1;
1165
    xlator_t *subvol = NULL;
1166
    inode_t *inode = NULL;
1167
    loc_t loc = {
1168
        0,
1169
    };
1170

1171
    /* validate in args */
1172
    if ((fs == NULL) || (parent == NULL) || (path == NULL)) {
1173
        errno = EINVAL;
1174
        return -1;
1175
    }
1176

1177
    DECLARE_OLD_THIS;
1178
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
1179

1180
    /* get the active volume */
1181
    subvol = glfs_active_subvol(fs);
1182
    if (!subvol) {
1183
        ret = -1;
1184
        errno = EIO;
1185
        goto out;
1186
    }
1187

1188
    /* get/refresh the in arg objects inode in correlation to the xlator */
1189
    inode = glfs_resolve_inode(fs, subvol, parent);
1190
    if (!inode) {
1191
        errno = ESTALE;
1192
        goto out;
1193
    }
1194

1195
    ret = glfs_resolve_at(fs, subvol, inode, path, &loc, NULL, 0, 0);
1196
    if (ret != 0) {
1197
        goto out;
1198
    }
1199

1200
    if (!IA_ISDIR(loc.inode->ia_type)) {
1201
        ret = syncop_unlink(subvol, &loc, NULL, NULL);
1202
        DECODE_SYNCOP_ERR(ret);
1203
        if (ret != 0) {
1204
            goto out;
1205
        }
1206
    } else {
1207
        ret = syncop_rmdir(subvol, &loc, 0, NULL, NULL);
1208
        DECODE_SYNCOP_ERR(ret);
1209
        if (ret != 0) {
1210
            goto out;
1211
        }
1212
    }
1213

1214
    if (ret == 0)
1215
        ret = glfs_loc_unlink(&loc);
1216

1217
out:
1218
    loc_wipe(&loc);
1219

1220
    if (inode)
1221
        inode_unref(inode);
1222

1223
    glfs_subvol_done(fs, subvol);
1224

1225
    __GLFS_EXIT_FS;
1226

1227
invalid_fs:
1228
    return ret;
1229
}
1230

1231
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_opendir, 3.4.2)
1232
struct glfs_fd *
1233
pub_glfs_h_opendir(struct glfs *fs, struct glfs_object *object)
1234
{
1235
    int ret = -1;
1236
    struct glfs_fd *glfd = NULL;
1237
    xlator_t *subvol = NULL;
1238
    inode_t *inode = NULL;
1239
    loc_t loc = {
1240
        0,
1241
    };
1242

1243
    /* validate in args */
1244
    if ((fs == NULL) || (object == NULL)) {
1245
        errno = EINVAL;
1246
        return NULL;
1247
    }
1248

1249
    DECLARE_OLD_THIS;
1250
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
1251

1252
    /* get the active volume */
1253
    subvol = glfs_active_subvol(fs);
1254
    if (!subvol) {
1255
        ret = -1;
1256
        errno = EIO;
1257
        goto out;
1258
    }
1259

1260
    /* get/refresh the in arg objects inode in correlation to the xlator */
1261
    inode = glfs_resolve_inode(fs, subvol, object);
1262
    if (!inode) {
1263
        errno = ESTALE;
1264
        goto out;
1265
    }
1266

1267
    if (!IA_ISDIR(inode->ia_type)) {
1268
        ret = -1;
1269
        errno = ENOTDIR;
1270
        goto out;
1271
    }
1272

1273
    glfd = glfs_fd_new(fs);
1274
    if (!glfd)
1275
        goto out;
1276

1277
    INIT_LIST_HEAD(&glfd->entries);
1278

1279
    glfd->fd = fd_create(inode, getpid());
1280
    if (!glfd->fd) {
1281
        ret = -1;
1282
        errno = ENOMEM;
1283
        goto out;
1284
    }
1285

1286
    GLFS_LOC_FILL_INODE(inode, loc, out);
1287

1288
    /* fop/op */
1289
    ret = syncop_opendir(subvol, &loc, glfd->fd, NULL, NULL);
1290
    DECODE_SYNCOP_ERR(ret);
1291

1292
out:
1293
    loc_wipe(&loc);
1294

1295
    if (inode)
1296
        inode_unref(inode);
1297

1298
    if (ret && glfd) {
1299
        GF_REF_PUT(glfd);
1300
        glfd = NULL;
1301
    } else if (glfd) {
1302
        glfd_set_state_bind(glfd);
1303
    }
1304

1305
    glfs_subvol_done(fs, subvol);
1306

1307
    __GLFS_EXIT_FS;
1308

1309
invalid_fs:
1310
    return glfd;
1311
}
1312

1313
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_access, 3.6.0)
1314
int
1315
pub_glfs_h_access(struct glfs *fs, struct glfs_object *object, int mask)
1316
{
1317
    int ret = -1;
1318
    xlator_t *subvol = NULL;
1319
    inode_t *inode = NULL;
1320
    loc_t loc = {
1321
        0,
1322
    };
1323

1324
    DECLARE_OLD_THIS;
1325

1326
    /* validate in args */
1327
    if ((fs == NULL) || (object == NULL)) {
1328
        errno = EINVAL;
1329
        return ret;
1330
    }
1331

1332
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
1333

1334
    /* get the active volume */
1335
    subvol = glfs_active_subvol(fs);
1336
    if (!subvol) {
1337
        ret = -1;
1338
        errno = EIO;
1339
        goto out;
1340
    }
1341

1342
    /* get/refresh the in arg objects inode in correlation to the xlator */
1343
    inode = glfs_resolve_inode(fs, subvol, object);
1344
    if (!inode) {
1345
        errno = ESTALE;
1346
        goto out;
1347
    }
1348

1349
    GLFS_LOC_FILL_INODE(inode, loc, out);
1350

1351
    /* fop/op */
1352

1353
    ret = syncop_access(subvol, &loc, mask, NULL, NULL);
1354
    DECODE_SYNCOP_ERR(ret);
1355

1356
out:
1357
    loc_wipe(&loc);
1358

1359
    if (inode)
1360
        inode_unref(inode);
1361

1362
    glfs_subvol_done(fs, subvol);
1363

1364
    __GLFS_EXIT_FS;
1365

1366
invalid_fs:
1367
    return ret;
1368
}
1369

1370
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_extract_handle, 3.4.2)
1371
ssize_t
1372
pub_glfs_h_extract_handle(struct glfs_object *object, unsigned char *handle,
1373
                          int len)
1374
{
1375
    ssize_t ret = -1;
1376

1377
    /* validate in args */
1378
    if (object == NULL) {
1379
        errno = EINVAL;
1380
        goto out;
1381
    }
1382

1383
    if (!handle || !len) {
1384
        ret = GFAPI_HANDLE_LENGTH;
1385
        goto out;
1386
    }
1387

1388
    if (len < GFAPI_HANDLE_LENGTH) {
1389
        errno = ERANGE;
1390
        goto out;
1391
    }
1392

1393
    memcpy(handle, object->gfid, GFAPI_HANDLE_LENGTH);
1394

1395
    ret = GFAPI_HANDLE_LENGTH;
1396

1397
out:
1398
    return ret;
1399
}
1400

1401
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_create_from_handle, 3.4.2)
1402
struct glfs_object *
1403
pub_glfs_h_create_from_handle(struct glfs *fs, unsigned char *handle, int len,
1404
                              struct stat *stat)
1405
{
1406
    loc_t loc = {
1407
        0,
1408
    };
1409
    int ret = -1;
1410
    struct iatt iatt = {
1411
        0,
1412
    };
1413
    inode_t *newinode = NULL;
1414
    xlator_t *subvol = NULL;
1415
    struct glfs_object *object = NULL;
1416
    uint64_t ctx_value = LOOKUP_NOT_NEEDED;
1417
    gf_boolean_t lookup_needed = _gf_false;
1418

1419
    /* validate in args */
1420
    if ((fs == NULL) || (handle == NULL) || (len != GFAPI_HANDLE_LENGTH)) {
1421
        errno = EINVAL;
1422
        return NULL;
1423
    }
1424

1425
    DECLARE_OLD_THIS;
1426
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
1427

1428
    /* get the active volume */
1429
    subvol = glfs_active_subvol(fs);
1430
    if (!subvol) {
1431
        errno = EIO;
1432
        goto out;
1433
    }
1434

1435
    memcpy(loc.gfid, handle, GFAPI_HANDLE_LENGTH);
1436

1437
    /* make sure the gfid received is valid */
1438
    GF_VALIDATE_OR_GOTO("glfs_h_create_from_handle",
1439
                        !(gf_uuid_is_null(loc.gfid)), out);
1440

1441
    newinode = inode_find(subvol->itable, loc.gfid);
1442
    if (newinode) {
1443
        if (!stat) /* No need of lookup */
1444
            goto found;
1445

1446
        lookup_needed = inode_needs_lookup(newinode, THIS);
1447
        if (lookup_needed) {
1448
            loc.inode = newinode;
1449
        } else {
1450
            /* populate loc */
1451
            GLFS_LOC_FILL_INODE(newinode, loc, fill_out);
1452

1453
            /* fop/op */
1454
            ret = syncop_stat(subvol, &loc, &iatt, NULL, NULL);
1455
            DECODE_SYNCOP_ERR(ret);
1456

1457
            if (ret) {
1458
            fill_out:
1459
                /* Drop the reference hold in inode_find */
1460
                inode_unref(newinode);
1461
                goto out;
1462
            }
1463

1464
            glfs_iatt_to_stat(fs, &iatt, stat);
1465
            goto found;
1466
        }
1467
    } else {
1468
        loc.inode = inode_new(subvol->itable);
1469
        if (!loc.inode) {
1470
            errno = ENOMEM;
1471
            goto out;
1472
        }
1473
    }
1474

1475
    ret = syncop_lookup(subvol, &loc, &iatt, 0, 0, 0);
1476
    DECODE_SYNCOP_ERR(ret);
1477
    if (ret) {
1478
        gf_smsg(subvol->name, GF_LOG_WARNING, errno,
1479
                API_MSG_INODE_REFRESH_FAILED, "gfid=%s", uuid_utoa(loc.gfid),
1480
                "error=%s", strerror(errno), NULL);
1481
        goto out;
1482
    }
1483

1484
    newinode = inode_link(loc.inode, 0, 0, &iatt);
1485
    if (newinode) {
1486
        if (newinode == loc.inode) {
1487
            inode_ctx_set(newinode, THIS, &ctx_value);
1488
        }
1489
        inode_lookup(newinode);
1490
    } else {
1491
        gf_smsg(subvol->name, GF_LOG_WARNING, errno, API_MSG_INODE_LINK_FAILED,
1492
                "gfid=%s", uuid_utoa(loc.gfid), NULL);
1493
        goto out;
1494
    }
1495

1496
    /* populate stat */
1497
    if (stat)
1498
        glfs_iatt_to_stat(fs, &iatt, stat);
1499

1500
found:
1501
    object = GF_CALLOC(1, sizeof(struct glfs_object), glfs_mt_glfs_object_t);
1502
    if (object == NULL) {
1503
        errno = ENOMEM;
1504
        ret = -1;
1505
        goto out;
1506
    }
1507

1508
    /* populate the return object */
1509
    object->inode = newinode;
1510
    gf_uuid_copy(object->gfid, object->inode->gfid);
1511

1512
out:
1513
    /* TODO: Check where the inode ref is being held? */
1514
    loc_wipe(&loc);
1515

1516
    glfs_subvol_done(fs, subvol);
1517

1518
    __GLFS_EXIT_FS;
1519

1520
invalid_fs:
1521
    return object;
1522
}
1523

1524
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_close, 3.4.2)
1525
int
1526
pub_glfs_h_close(struct glfs_object *object)
1527
{
1528
    /* since glfs_h_* objects hold a reference to inode
1529
     * it is safe to keep lookup count to '0' */
1530
    inode_forget(object->inode, 0);
1531
    inode_unref(object->inode);
1532
    GF_FREE(object);
1533

1534
    return 0;
1535
}
1536

1537
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_truncate, 3.4.2)
1538
int
1539
pub_glfs_h_truncate(struct glfs *fs, struct glfs_object *object, off_t offset)
1540
{
1541
    loc_t loc = {
1542
        0,
1543
    };
1544
    int ret = -1;
1545
    xlator_t *subvol = NULL;
1546
    inode_t *inode = NULL;
1547

1548
    DECLARE_OLD_THIS;
1549

1550
    /* validate in args */
1551
    if (object == NULL) {
1552
        errno = EINVAL;
1553
        return -1;
1554
    }
1555

1556
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
1557

1558
    /* get the active volume */
1559
    subvol = glfs_active_subvol(fs);
1560
    if (!subvol) {
1561
        ret = -1;
1562
        errno = EIO;
1563
        goto out;
1564
    }
1565

1566
    /* get/refresh the in arg objects inode in correlation to the xlator */
1567
    inode = glfs_resolve_inode(fs, subvol, object);
1568
    if (!inode) {
1569
        errno = ESTALE;
1570
        goto out;
1571
    }
1572

1573
    GLFS_LOC_FILL_INODE(inode, loc, out);
1574

1575
    /* fop/op */
1576
    ret = syncop_truncate(subvol, &loc, (off_t)offset, NULL, NULL);
1577
    DECODE_SYNCOP_ERR(ret);
1578

1579
    /* populate out args */
1580
    if (ret == 0)
1581
        ret = glfs_loc_unlink(&loc);
1582

1583
out:
1584
    loc_wipe(&loc);
1585

1586
    if (inode)
1587
        inode_unref(inode);
1588

1589
    glfs_subvol_done(fs, subvol);
1590

1591
    __GLFS_EXIT_FS;
1592

1593
invalid_fs:
1594
    return ret;
1595
}
1596

1597
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_symlink, 3.4.2)
1598
struct glfs_object *
1599
pub_glfs_h_symlink(struct glfs *fs, struct glfs_object *parent,
1600
                   const char *name, const char *data, struct stat *stat)
1601
{
1602
    int ret = -1;
1603
    xlator_t *subvol = NULL;
1604
    inode_t *inode = NULL;
1605
    loc_t loc = {
1606
        0,
1607
    };
1608
    struct iatt iatt = {
1609
        0,
1610
    };
1611
    uuid_t gfid;
1612
    dict_t *xattr_req = NULL;
1613
    struct glfs_object *object = NULL;
1614

1615
    DECLARE_OLD_THIS;
1616

1617
    /* validate in args */
1618
    if ((parent == NULL) || (name == NULL) || (data == NULL)) {
1619
        errno = EINVAL;
1620
        return NULL;
1621
    }
1622

1623
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
1624

1625
    /* get the active volume */
1626
    subvol = glfs_active_subvol(fs);
1627
    if (!subvol) {
1628
        ret = -1;
1629
        errno = EIO;
1630
        goto out;
1631
    }
1632

1633
    /* get/refresh the in arg objects inode in correlation to the xlator */
1634
    inode = glfs_resolve_inode(fs, subvol, parent);
1635
    if (!inode) {
1636
        errno = ESTALE;
1637
        goto out;
1638
    }
1639

1640
    xattr_req = dict_new();
1641
    if (!xattr_req) {
1642
        ret = -1;
1643
        errno = ENOMEM;
1644
        goto out;
1645
    }
1646

1647
    gf_uuid_generate(gfid);
1648
    ret = dict_set_gfuuid(xattr_req, "gfid-req", gfid, true);
1649
    if (ret) {
1650
        ret = -1;
1651
        errno = ENOMEM;
1652
        goto out;
1653
    }
1654

1655
    GLFS_LOC_FILL_PINODE(inode, loc, ret, errno, out, name);
1656

1657
    /* fop/op */
1658
    ret = syncop_symlink(subvol, &loc, data, &iatt, xattr_req, NULL);
1659
    DECODE_SYNCOP_ERR(ret);
1660

1661
    /* populate out args */
1662
    if (ret == 0) {
1663
        ret = glfs_loc_link(&loc, &iatt);
1664
        if (ret != 0) {
1665
            goto out;
1666
        }
1667

1668
        if (stat)
1669
            glfs_iatt_to_stat(fs, &iatt, stat);
1670

1671
        ret = glfs_create_object(&loc, &object);
1672
    }
1673

1674
out:
1675
    if (ret && object != NULL) {
1676
        pub_glfs_h_close(object);
1677
        object = NULL;
1678
    }
1679

1680
    loc_wipe(&loc);
1681

1682
    if (inode)
1683
        inode_unref(inode);
1684

1685
    if (xattr_req)
1686
        dict_unref(xattr_req);
1687

1688
    glfs_subvol_done(fs, subvol);
1689

1690
    __GLFS_EXIT_FS;
1691

1692
invalid_fs:
1693
    return object;
1694
}
1695

1696
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_readlink, 3.4.2)
1697
int
1698
pub_glfs_h_readlink(struct glfs *fs, struct glfs_object *object, char *buf,
1699
                    size_t bufsiz)
1700
{
1701
    loc_t loc = {
1702
        0,
1703
    };
1704
    int ret = -1;
1705
    xlator_t *subvol = NULL;
1706
    inode_t *inode = NULL;
1707
    char *linkval = NULL;
1708

1709
    DECLARE_OLD_THIS;
1710

1711
    /* validate in args */
1712
    if ((object == NULL) || (buf == NULL)) {
1713
        errno = EINVAL;
1714
        return -1;
1715
    }
1716

1717
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
1718

1719
    /* get the active volume */
1720
    subvol = glfs_active_subvol(fs);
1721
    if (!subvol) {
1722
        ret = -1;
1723
        errno = EIO;
1724
        goto out;
1725
    }
1726

1727
    /* get/refresh the in arg objects inode in correlation to the xlator */
1728
    inode = glfs_resolve_inode(fs, subvol, object);
1729
    if (!inode) {
1730
        errno = ESTALE;
1731
        goto out;
1732
    }
1733

1734
    GLFS_LOC_FILL_INODE(inode, loc, out);
1735

1736
    /* fop/op */
1737
    ret = syncop_readlink(subvol, &loc, &linkval, bufsiz, NULL, NULL);
1738
    DECODE_SYNCOP_ERR(ret);
1739

1740
    /* populate out args */
1741
    if (ret > 0)
1742
        memcpy(buf, linkval, ret);
1743

1744
out:
1745
    loc_wipe(&loc);
1746

1747
    if (inode)
1748
        inode_unref(inode);
1749

1750
    if (linkval)
1751
        GF_FREE(linkval);
1752

1753
    glfs_subvol_done(fs, subvol);
1754

1755
    __GLFS_EXIT_FS;
1756

1757
invalid_fs:
1758
    return ret;
1759
}
1760

1761
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_link, 3.4.2)
1762
int
1763
pub_glfs_h_link(struct glfs *fs, struct glfs_object *linksrc,
1764
                struct glfs_object *parent, const char *name)
1765
{
1766
    int ret = -1;
1767
    xlator_t *subvol = NULL;
1768
    inode_t *inode = NULL;
1769
    inode_t *pinode = NULL;
1770
    loc_t oldloc = {
1771
        0,
1772
    };
1773
    loc_t newloc = {
1774
        0,
1775
    };
1776
    struct iatt iatt = {
1777
        0,
1778
    };
1779

1780
    DECLARE_OLD_THIS;
1781

1782
    /* validate in args */
1783
    if ((linksrc == NULL) || (parent == NULL) || (name == NULL)) {
1784
        errno = EINVAL;
1785
        return -1;
1786
    }
1787

1788
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
1789

1790
    /* get the active volume */
1791
    subvol = glfs_active_subvol(fs);
1792
    if (!subvol) {
1793
        ret = -1;
1794
        errno = EIO;
1795
        goto out;
1796
    }
1797

1798
    /* get/refresh the in arg objects inode in correlation to the xlator */
1799
    inode = glfs_resolve_inode(fs, subvol, linksrc);
1800
    if (!inode) {
1801
        errno = ESTALE;
1802
        goto out;
1803
    }
1804

1805
    if (inode->ia_type == IA_IFDIR) {
1806
        ret = -1;
1807
        errno = EISDIR;
1808
        goto out;
1809
    }
1810

1811
    GLFS_LOC_FILL_INODE(inode, oldloc, out);
1812

1813
    /* get/refresh the in arg objects inode in correlation to the xlator */
1814
    pinode = glfs_resolve_inode(fs, subvol, parent);
1815
    if (!pinode) {
1816
        errno = ESTALE;
1817
        goto out;
1818
    }
1819

1820
    /* setup newloc based on parent */
1821
    newloc.parent = inode_ref(pinode);
1822
    newloc.name = name;
1823
    ret = glfs_loc_touchup(&newloc);
1824
    if (ret != 0) {
1825
        errno = EINVAL;
1826
        goto out;
1827
    }
1828

1829
    /* Filling the inode of the hard link to be same as that of the
1830
     * original file
1831
     */
1832
    newloc.inode = inode_ref(inode);
1833

1834
    /* fop/op */
1835
    ret = syncop_link(subvol, &oldloc, &newloc, &iatt, NULL, NULL);
1836
    DECODE_SYNCOP_ERR(ret);
1837

1838
    if (ret == 0)
1839
        ret = glfs_loc_link(&newloc, &iatt);
1840
out:
1841
    loc_wipe(&oldloc);
1842
    loc_wipe(&newloc);
1843

1844
    if (inode)
1845
        inode_unref(inode);
1846

1847
    if (pinode)
1848
        inode_unref(pinode);
1849

1850
    glfs_subvol_done(fs, subvol);
1851

1852
    __GLFS_EXIT_FS;
1853

1854
invalid_fs:
1855
    return ret;
1856
}
1857

1858
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_rename, 3.4.2)
1859
int
1860
pub_glfs_h_rename(struct glfs *fs, struct glfs_object *olddir,
1861
                  const char *oldname, struct glfs_object *newdir,
1862
                  const char *newname)
1863
{
1864
    int ret = -1;
1865
    xlator_t *subvol = NULL;
1866
    inode_t *oldpinode = NULL;
1867
    inode_t *newpinode = NULL;
1868
    loc_t oldloc = {
1869
        0,
1870
    };
1871
    loc_t newloc = {
1872
        0,
1873
    };
1874
    struct iatt oldiatt = {
1875
        0,
1876
    };
1877
    struct iatt newiatt = {
1878
        0,
1879
    };
1880

1881
    DECLARE_OLD_THIS;
1882

1883
    /* validate in args */
1884
    if ((olddir == NULL) || (oldname == NULL) || (newdir == NULL) ||
1885
        (newname == NULL)) {
1886
        errno = EINVAL;
1887
        return -1;
1888
    }
1889

1890
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
1891

1892
    /* get the active volume */
1893
    subvol = glfs_active_subvol(fs);
1894
    if (!subvol) {
1895
        ret = -1;
1896
        errno = EIO;
1897
        goto out;
1898
    }
1899

1900
    /* get/refresh the in arg objects inode in correlation to the xlator */
1901
    oldpinode = glfs_resolve_inode(fs, subvol, olddir);
1902
    if (!oldpinode) {
1903
        errno = ESTALE;
1904
        goto out;
1905
    }
1906

1907
    ret = glfs_resolve_at(fs, subvol, oldpinode, oldname, &oldloc, &oldiatt, 0,
1908
                          0);
1909
    if (ret != 0) {
1910
        goto out;
1911
    }
1912

1913
    /* get/refresh the in arg objects inode in correlation to the xlator */
1914
    newpinode = glfs_resolve_inode(fs, subvol, newdir);
1915
    if (!newpinode) {
1916
        errno = ESTALE;
1917
        goto out;
1918
    }
1919

1920
    ret = glfs_resolve_at(fs, subvol, newpinode, newname, &newloc, &newiatt, 0,
1921
                          0);
1922

1923
    if (ret && errno != ENOENT && newloc.parent)
1924
        goto out;
1925

1926
    if (newiatt.ia_type != IA_INVAL) {
1927
        if ((oldiatt.ia_type == IA_IFDIR) != (newiatt.ia_type == IA_IFDIR)) {
1928
            /* Either both old and new must be dirs,
1929
             * or both must be non-dirs. Else, fail.
1930
             */
1931
            ret = -1;
1932
            errno = EEXIST;
1933
            goto out;
1934
        }
1935
    }
1936

1937
    /* TODO: check if new or old is a prefix of the other, and fail EINVAL */
1938

1939
    ret = syncop_rename(subvol, &oldloc, &newloc, NULL, NULL);
1940
    DECODE_SYNCOP_ERR(ret);
1941

1942
    if (ret == 0) {
1943
        inode_rename(oldloc.parent->table, oldloc.parent, oldloc.name,
1944
                     newloc.parent, newloc.name, oldloc.inode, &oldiatt);
1945

1946
        if (newloc.inode && !inode_has_dentry(newloc.inode))
1947
            inode_forget(newloc.inode, 0);
1948
    }
1949

1950
out:
1951
    loc_wipe(&oldloc);
1952
    loc_wipe(&newloc);
1953

1954
    if (oldpinode)
1955
        inode_unref(oldpinode);
1956

1957
    if (newpinode)
1958
        inode_unref(newpinode);
1959

1960
    glfs_subvol_done(fs, subvol);
1961

1962
    __GLFS_EXIT_FS;
1963

1964
invalid_fs:
1965
    return ret;
1966
}
1967

1968
/*
1969
 * Given a handle/gfid, find if the corresponding inode is present in
1970
 * the inode table. If yes create and return the corresponding glfs_object.
1971
 */
1972
struct glfs_object *
1973
glfs_h_find_handle(struct glfs *fs, unsigned char *handle, int len)
1974
{
1975
    inode_t *newinode = NULL;
1976
    xlator_t *subvol = NULL;
1977
    struct glfs_object *object = NULL;
1978
    uuid_t gfid;
1979

1980
    /* validate in args */
1981
    if ((fs == NULL) || (handle == NULL) || (len != GFAPI_HANDLE_LENGTH)) {
1982
        errno = EINVAL;
1983
        return NULL;
1984
    }
1985

1986
    DECLARE_OLD_THIS;
1987
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
1988

1989
    /* get the active volume */
1990
    subvol = glfs_active_subvol(fs);
1991
    if (!subvol) {
1992
        errno = EIO;
1993
        goto out;
1994
    }
1995

1996
    memcpy(gfid, handle, GFAPI_HANDLE_LENGTH);
1997

1998
    /* make sure the gfid received is valid */
1999
    GF_VALIDATE_OR_GOTO("glfs_h_find_handle", !(gf_uuid_is_null(gfid)), out);
2000

2001
    newinode = inode_find(subvol->itable, gfid);
2002
    if (!newinode) {
2003
        goto out;
2004
    }
2005

2006
    object = GF_CALLOC(1, sizeof(struct glfs_object), glfs_mt_glfs_object_t);
2007
    if (object == NULL) {
2008
        errno = ENOMEM;
2009
        goto out;
2010
    }
2011

2012
    /* populate the return object. The ref taken here
2013
     * is un'refed when the application does glfs_h_close() */
2014
    object->inode = inode_ref(newinode);
2015
    gf_uuid_copy(object->gfid, object->inode->gfid);
2016

2017
out:
2018
    /* inode_find takes a reference. Unref it. */
2019
    if (newinode)
2020
        inode_unref(newinode);
2021

2022
    glfs_subvol_done(fs, subvol);
2023

2024
    __GLFS_EXIT_FS;
2025

2026
invalid_fs:
2027
    return object;
2028
}
2029

2030
static void
2031
glfs_free_upcall_inode(void *to_free)
2032
{
2033
    struct glfs_upcall_inode *arg = to_free;
2034

2035
    if (!arg)
2036
        return;
2037

2038
    if (arg->object)
2039
        glfs_h_close(arg->object);
2040
    if (arg->p_object)
2041
        glfs_h_close(arg->p_object);
2042
    if (arg->oldp_object)
2043
        glfs_h_close(arg->oldp_object);
2044

2045
    GF_FREE(arg);
2046
}
2047

2048
int
2049
glfs_h_poll_cache_invalidation(struct glfs *fs, struct glfs_upcall *up_arg,
2050
                               struct gf_upcall *upcall_data)
2051
{
2052
    int ret = -1;
2053
    struct glfs_object *p_object = NULL;
2054
    struct glfs_object *oldp_object = NULL;
2055
    struct glfs_object *object = NULL;
2056
    struct gf_upcall_cache_invalidation *ca_data = NULL;
2057
    struct glfs_upcall_inode *up_inode_arg = NULL;
2058

2059
    ca_data = upcall_data->data;
2060
    GF_VALIDATE_OR_GOTO("glfs_h_poll_cache_invalidation", ca_data, out);
2061

2062
    object = glfs_h_find_handle(fs, upcall_data->gfid, GFAPI_HANDLE_LENGTH);
2063
    if (!object) {
2064
        /* The reason handle creation will fail is because we
2065
         * couldn't find the inode in the gfapi inode table.
2066
         *
2067
         * But since application would have taken inode_ref, the
2068
         * only case when this can happen is when it has closed
2069
         * the handle and hence will no more be interested in
2070
         * the upcall for this particular gfid.
2071
         */
2072
        gf_smsg(THIS->name, GF_LOG_DEBUG, errno, API_MSG_CREATE_HANDLE_FAILED,
2073
                "gfid=%s", uuid_utoa(upcall_data->gfid), NULL);
2074
        errno = ESTALE;
2075
        goto out;
2076
    }
2077

2078
    up_inode_arg = GF_CALLOC(1, sizeof(struct glfs_upcall_inode),
2079
                             glfs_mt_upcall_inode_t);
2080
    GF_VALIDATE_OR_GOTO("glfs_h_poll_cache_invalidation", up_inode_arg, out);
2081

2082
    up_inode_arg->object = object;
2083
    up_inode_arg->flags = ca_data->flags;
2084
    up_inode_arg->expire_time_attr = ca_data->expire_time_attr;
2085

2086
    /* XXX: Update stat as well in case of UP_*_TIMES.
2087
     * This will be addressed as part of INODE_UPDATE */
2088
    if (ca_data->flags & GFAPI_INODE_UPDATE_FLAGS) {
2089
        glfs_iatt_to_stat(fs, &ca_data->stat, &up_inode_arg->buf);
2090
    }
2091

2092
    if (ca_data->flags & GFAPI_UP_PARENT_TIMES) {
2093
        p_object = glfs_h_find_handle(fs, ca_data->p_stat.ia_gfid,
2094
                                      GFAPI_HANDLE_LENGTH);
2095
        if (!p_object) {
2096
            gf_smsg(THIS->name, GF_LOG_DEBUG, errno,
2097
                    API_MSG_CREATE_HANDLE_FAILED, "gfid=%s",
2098
                    uuid_utoa(ca_data->p_stat.ia_gfid), NULL);
2099
            errno = ESTALE;
2100
            goto out;
2101
        }
2102

2103
        glfs_iatt_to_stat(fs, &ca_data->p_stat, &up_inode_arg->p_buf);
2104
    }
2105
    up_inode_arg->p_object = p_object;
2106

2107
    /* In case of RENAME, update old parent as well */
2108
    if (ca_data->flags & GFAPI_UP_RENAME) {
2109
        oldp_object = glfs_h_find_handle(fs, ca_data->oldp_stat.ia_gfid,
2110
                                         GFAPI_HANDLE_LENGTH);
2111
        if (!oldp_object) {
2112
            gf_smsg(THIS->name, GF_LOG_DEBUG, errno,
2113
                    API_MSG_CREATE_HANDLE_FAILED, "gfid=%s",
2114
                    uuid_utoa(ca_data->oldp_stat.ia_gfid), NULL);
2115
            errno = ESTALE;
2116
            /* By the time we receive upcall old parent_dir may
2117
             * have got removed. We still need to send upcall
2118
             * for the file/dir and current parent handles. */
2119
            up_inode_arg->oldp_object = NULL;
2120
            ret = 0;
2121
        }
2122

2123
        glfs_iatt_to_stat(fs, &ca_data->oldp_stat, &up_inode_arg->oldp_buf);
2124
    }
2125
    up_inode_arg->oldp_object = oldp_object;
2126

2127
    up_arg->reason = GLFS_UPCALL_INODE_INVALIDATE;
2128
    up_arg->event = up_inode_arg;
2129
    up_arg->free_event = glfs_free_upcall_inode;
2130

2131
    ret = 0;
2132

2133
out:
2134
    if (ret) {
2135
        /* Close p_object and oldp_object as well if being referenced.*/
2136
        if (object)
2137
            glfs_h_close(object);
2138

2139
        /* Set reason to prevent applications from using ->event */
2140
        up_arg->reason = GLFS_UPCALL_EVENT_NULL;
2141
        GF_FREE(up_inode_arg);
2142
    }
2143
    return ret;
2144
}
2145

2146
void
2147
glfs_release_upcall(void *ptr)
2148
{
2149
    struct glfs_upcall *to_free = ptr;
2150

2151
    if (to_free->event)
2152
        to_free->free_event(to_free->event);
2153
}
2154

2155
/*
2156
 * This API is used to poll for upcall events stored in the upcall list.
2157
 * Current users of this API is NFS-Ganesha. In case of any event received, it
2158
 * will be mapped appropriately into 'glfs_upcall' along with the handle object
2159
 * to be passed to NFS-Ganesha.
2160
 *
2161
 * On success, applications need to check if up_arg is not-NULL or errno is not
2162
 * ENOENT. glfs_upcall_get_reason() can be used to decide what kind of event
2163
 * has been received.
2164
 *
2165
 * Current supported upcall_events:
2166
 *      GLFS_UPCALL_INODE_INVALIDATE
2167
 *
2168
 * After processing the event, applications need to free 'up_arg' by calling
2169
 * glfs_free().
2170
 *
2171
 * Also similar to I/Os, the application should ideally stop polling before
2172
 * calling glfs_fini(..). Hence making an assumption that 'fs' & ctx structures
2173
 * cannot be freed while in this routine.
2174
 */
2175
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_poll_upcall, 3.7.16)
2176
int
2177
pub_glfs_h_poll_upcall(struct glfs *fs, struct glfs_upcall **up_arg)
2178
{
2179
    upcall_entry *u_list = NULL;
2180
    upcall_entry *tmp = NULL;
2181
    xlator_t *subvol = NULL;
2182
    glusterfs_ctx_t *ctx = NULL;
2183
    int ret = -1;
2184
    struct gf_upcall *upcall_data = NULL;
2185

2186
    DECLARE_OLD_THIS;
2187

2188
    if (!up_arg) {
2189
        errno = EINVAL;
2190
        goto err;
2191
    }
2192

2193
    __GLFS_ENTRY_VALIDATE_FS(fs, err);
2194

2195
    /* get the active volume */
2196
    subvol = glfs_active_subvol(fs);
2197
    if (!subvol) {
2198
        errno = EIO;
2199
        goto restore;
2200
    }
2201

2202
    /* Ideally applications should stop polling before calling
2203
     * 'glfs_fini'. Yet cross check if cleanup has started. */
2204
    pthread_mutex_lock(&fs->mutex);
2205
    {
2206
        ctx = fs->ctx;
2207

2208
        if (ctx->cleanup_started) {
2209
            pthread_mutex_unlock(&fs->mutex);
2210
            goto out;
2211
        }
2212

2213
        fs->pin_refcnt++;
2214

2215
        /* once we call this function, the applications seems to be
2216
         * interested in events, enable caching them */
2217
        fs->cache_upcalls = _gf_true;
2218
    }
2219
    pthread_mutex_unlock(&fs->mutex);
2220

2221
    pthread_mutex_lock(&fs->upcall_list_mutex);
2222
    {
2223
        list_for_each_entry_safe(u_list, tmp, &fs->upcall_list, upcall_list)
2224
        {
2225
            list_del_init(&u_list->upcall_list);
2226
            upcall_data = &u_list->upcall_data;
2227
            break;
2228
        }
2229
    }
2230
    /* No other thread can delete this entry. So unlock it */
2231
    pthread_mutex_unlock(&fs->upcall_list_mutex);
2232

2233
    if (upcall_data) {
2234
        switch (upcall_data->event_type) {
2235
            case GF_UPCALL_CACHE_INVALIDATION:
2236
                *up_arg = GLFS_CALLOC(1, sizeof(struct gf_upcall),
2237
                                      glfs_release_upcall,
2238
                                      glfs_mt_upcall_entry_t);
2239
                if (!*up_arg) {
2240
                    errno = ENOMEM;
2241
                    break; /* goto free u_list */
2242
                }
2243

2244
                /* XXX: Need to revisit this to support
2245
                 * GLFS_UPCALL_INODE_UPDATE if required. */
2246
                ret = glfs_h_poll_cache_invalidation(fs, *up_arg, upcall_data);
2247
                if (ret || (*up_arg)->reason == GLFS_UPCALL_EVENT_NULL) {
2248
                    /* It could so happen that the file which got
2249
                     * upcall notification may have got deleted by
2250
                     * the same client. Irrespective of the error,
2251
                     * return with an error or success+ENOENT. */
2252
                    if ((*up_arg)->reason == GLFS_UPCALL_EVENT_NULL)
2253
                        errno = ENOENT;
2254

2255
                    GLFS_FREE(*up_arg);
2256
                    *up_arg = NULL;
2257
                }
2258
                break;
2259
            case GF_UPCALL_RECALL_LEASE:
2260
                gf_log("glfs_h_poll_upcall", GF_LOG_DEBUG,
2261
                       "UPCALL_RECALL_LEASE is not implemented yet");
2262
            /* fallthrough till we support leases */
2263
            case GF_UPCALL_EVENT_NULL:
2264
                /* no 'default:' label, to force handling all upcall events */
2265
                errno = ENOENT;
2266
                break;
2267
        }
2268

2269
        GF_FREE(u_list->upcall_data.data);
2270
        GF_FREE(u_list);
2271
    } else {
2272
        /* fs->upcall_list was empty, no upcall events cached */
2273
        errno = ENOENT;
2274
    }
2275

2276
    ret = 0;
2277

2278
out:
2279
    pthread_mutex_lock(&fs->mutex);
2280
    {
2281
        fs->pin_refcnt--;
2282
    }
2283
    pthread_mutex_unlock(&fs->mutex);
2284

2285
    glfs_subvol_done(fs, subvol);
2286

2287
restore:
2288
    __GLFS_EXIT_FS;
2289
err:
2290
    return ret;
2291
}
2292

2293
static gf_boolean_t log_upcall370 = _gf_true; /* log once */
2294

2295
/* The old glfs_h_poll_upcall interface requires intimate knowledge of the
2296
 * structures that are returned to the calling application. This is not
2297
 * recommended, as the returned structures need to returned correctly (handles
2298
 * closed, memory free'd with the unavailable GF_FREE(), and possibly more.)
2299
 *
2300
 * To the best of our knowledge, only NFS-Ganesha uses the upcall events
2301
 * through gfapi. We keep this backwards compatibility function around so that
2302
 * applications using the existing implementation do not break.
2303
 *
2304
 * WARNING: this function will be removed in the future.
2305
 */
2306
GFAPI_SYMVER_PUBLIC(glfs_h_poll_upcall370, glfs_h_poll_upcall, 3.7.0)
2307
int
2308
pub_glfs_h_poll_upcall370(struct glfs *fs, struct glfs_callback_arg *up_arg)
2309
{
2310
    struct glfs_upcall *upcall = NULL;
2311
    int ret = -1;
2312

2313
    if (log_upcall370) {
2314
        log_upcall370 = _gf_false;
2315
        gf_log(THIS->name, GF_LOG_WARNING,
2316
               "this application is "
2317
               "compiled against an old version of libgfapi, it "
2318
               "should use glfs_free() to release the structure "
2319
               "returned by glfs_h_poll_upcall() - for more details, "
2320
               "see http://review.gluster.org/14701");
2321
    }
2322

2323
    ret = pub_glfs_h_poll_upcall(fs, &upcall);
2324
    if (ret == 0) {
2325
        up_arg->fs = fs;
2326
        if ((errno == ENOENT) || !upcall || !upcall->event) {
2327
            up_arg->reason = GLFS_UPCALL_EVENT_NULL;
2328
            goto out;
2329
        }
2330

2331
        up_arg->reason = upcall->reason;
2332

2333
        if (upcall->reason == GLFS_UPCALL_INODE_INVALIDATE) {
2334
            struct glfs_callback_inode_arg *cb_inode = NULL;
2335
            struct glfs_upcall_inode *up_inode = NULL;
2336

2337
            cb_inode = GF_CALLOC(1, sizeof(struct glfs_callback_inode_arg),
2338
                                 glfs_mt_upcall_inode_t);
2339
            if (!cb_inode) {
2340
                errno = ENOMEM;
2341
                ret = -1;
2342
                goto out;
2343
            }
2344

2345
            up_inode = upcall->event;
2346

2347
            /* copy attributes one by one, the memory layout might
2348
             * be different between the old glfs_callback_inode_arg
2349
             * and new glfs_upcall_inode */
2350
            cb_inode->object = up_inode->object;
2351
            cb_inode->flags = up_inode->flags;
2352
            memcpy(&cb_inode->buf, &up_inode->buf, sizeof(struct stat));
2353
            cb_inode->expire_time_attr = up_inode->expire_time_attr;
2354
            cb_inode->p_object = up_inode->p_object;
2355
            memcpy(&cb_inode->p_buf, &up_inode->p_buf, sizeof(struct stat));
2356
            cb_inode->oldp_object = up_inode->oldp_object;
2357
            memcpy(&cb_inode->oldp_buf, &up_inode->oldp_buf,
2358
                   sizeof(struct stat));
2359

2360
            up_arg->event_arg = cb_inode;
2361
        }
2362
    }
2363

2364
out:
2365
    if (upcall) {
2366
        /* we can not use glfs_free() here, objects need to stay */
2367
        GF_FREE(upcall->event);
2368
        GF_FREE(upcall);
2369
    }
2370

2371
    return ret;
2372
}
2373

2374
#ifdef HAVE_ACL_LIBACL_H
2375
#include <glusterfs/glusterfs-acl.h>
2376
#include <acl/libacl.h>
2377

2378
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_acl_set, 3.7.0)
2379
int
2380
pub_glfs_h_acl_set(struct glfs *fs, struct glfs_object *object,
2381
                   const acl_type_t type, const acl_t acl)
2382
{
2383
    int ret = -1;
2384
    char *acl_s = NULL;
2385
    const char *acl_key = NULL;
2386
    struct glfs_object *new_object = NULL;
2387

2388
    DECLARE_OLD_THIS;
2389

2390
    if (!object || !acl) {
2391
        errno = EINVAL;
2392
        return ret;
2393
    }
2394

2395
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
2396

2397
    acl_key = gf_posix_acl_get_key(type);
2398
    if (!acl_key)
2399
        goto out;
2400

2401
    acl_s = acl_to_any_text(acl, NULL, ',', TEXT_ABBREVIATE | TEXT_NUMERIC_IDS);
2402
    if (!acl_s)
2403
        goto out;
2404

2405
    if (IA_ISLNK(object->inode->ia_type)) {
2406
        new_object = glfs_h_resolve_symlink(fs, object);
2407
        if (new_object == NULL)
2408
            goto out;
2409
    } else
2410
        new_object = object;
2411

2412
    ret = pub_glfs_h_setxattrs(fs, new_object, acl_key, acl_s,
2413
                               strlen(acl_s) + 1, 0);
2414

2415
    acl_free(acl_s);
2416

2417
out:
2418
    if (IA_ISLNK(object->inode->ia_type) && new_object)
2419
        glfs_h_close(new_object);
2420

2421
    __GLFS_EXIT_FS;
2422

2423
invalid_fs:
2424
    return ret;
2425
}
2426

2427
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_acl_get, 3.7.0)
2428
acl_t
2429
pub_glfs_h_acl_get(struct glfs *fs, struct glfs_object *object,
2430
                   const acl_type_t type)
2431
{
2432
    int ret = 0;
2433
    acl_t acl = NULL;
2434
    char *acl_s = NULL;
2435
    dict_t *xattr = NULL;
2436
    const char *acl_key = NULL;
2437
    struct glfs_object *new_object = NULL;
2438

2439
    DECLARE_OLD_THIS;
2440

2441
    if (!object) {
2442
        errno = EINVAL;
2443
        return NULL;
2444
    }
2445

2446
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
2447

2448
    acl_key = gf_posix_acl_get_key(type);
2449
    if (!acl_key)
2450
        goto out;
2451

2452
    if (IA_ISLNK(object->inode->ia_type)) {
2453
        new_object = glfs_h_resolve_symlink(fs, object);
2454
        if (new_object == NULL)
2455
            goto out;
2456
    } else
2457
        new_object = object;
2458

2459
    ret = glfs_h_getxattrs_common(fs, new_object, &xattr, acl_key, _gf_false);
2460
    if (ret)
2461
        goto out;
2462

2463
    ret = dict_get_str(xattr, (char *)acl_key, &acl_s);
2464
    if (ret)
2465
        goto out;
2466

2467
    acl = acl_from_text(acl_s);
2468

2469
out:
2470
    if (xattr)
2471
        dict_unref(xattr);
2472

2473
    if (IA_ISLNK(object->inode->ia_type) && new_object)
2474
        glfs_h_close(new_object);
2475

2476
    __GLFS_EXIT_FS;
2477

2478
invalid_fs:
2479
    return acl;
2480
}
2481
#else /* !HAVE_ACL_LIBACL_H */
2482
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_acl_get, 3.7.0)
2483
acl_t
2484
pub_glfs_h_acl_get(struct glfs *fs, struct glfs_object *object,
2485
                   const acl_type_t type)
2486
{
2487
    errno = ENOTSUP;
2488
    return NULL;
2489
}
2490

2491
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_acl_set, 3.7.0)
2492
int
2493
pub_glfs_h_acl_set(struct glfs *fs, struct glfs_object *object,
2494
                   const acl_type_t type, const acl_t acl)
2495
{
2496
    errno = ENOTSUP;
2497
    return -1;
2498
}
2499
#endif
2500

2501
/* The API to perform read using anonymous fd */
2502
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_anonymous_read, 3.7.0)
2503
ssize_t
2504
pub_glfs_h_anonymous_read(struct glfs *fs, struct glfs_object *object,
2505
                          const void *buf, size_t count, off_t offset)
2506
{
2507
    struct iovec iov = {
2508
        0,
2509
    };
2510
    ssize_t ret = 0;
2511

2512
    /* validate in args */
2513
    if ((fs == NULL) || (object == NULL)) {
2514
        errno = EINVAL;
2515
        return -1;
2516
    }
2517

2518
    iov.iov_base = (void *)buf;
2519
    iov.iov_len = count;
2520

2521
    ret = glfs_anonymous_preadv(fs, object, &iov, 1, offset, 0);
2522

2523
    return ret;
2524
}
2525

2526
/* The API to perform write using anonymous fd */
2527
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_anonymous_write, 3.7.0)
2528
ssize_t
2529
pub_glfs_h_anonymous_write(struct glfs *fs, struct glfs_object *object,
2530
                           const void *buf, size_t count, off_t offset)
2531
{
2532
    struct iovec iov = {
2533
        0,
2534
    };
2535
    ssize_t ret = 0;
2536

2537
    /* validate in args */
2538
    if ((fs == NULL) || (object == NULL)) {
2539
        errno = EINVAL;
2540
        return -1;
2541
    }
2542

2543
    iov.iov_base = (void *)buf;
2544
    iov.iov_len = count;
2545

2546
    ret = glfs_anonymous_pwritev(fs, object, &iov, 1, offset, 0);
2547

2548
    return ret;
2549
}
2550

2551
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_object_copy, 3.11.0)
2552
struct glfs_object *
2553
pub_glfs_object_copy(struct glfs_object *src)
2554
{
2555
    struct glfs_object *object = NULL;
2556

2557
    GF_VALIDATE_OR_GOTO("glfs_dup_object", src, out);
2558

2559
    object = GF_CALLOC(1, sizeof(struct glfs_object), glfs_mt_glfs_object_t);
2560
    if (object == NULL) {
2561
        errno = ENOMEM;
2562
        gf_smsg(THIS->name, GF_LOG_WARNING, errno, API_MSG_CREATE_HANDLE_FAILED,
2563
                "glfs_dup_object gfid=%s", uuid_utoa(src->inode->gfid), NULL);
2564
        return NULL;
2565
    }
2566

2567
    object->inode = inode_ref(src->inode);
2568
    gf_uuid_copy(object->gfid, src->inode->gfid);
2569

2570
out:
2571
    return object;
2572
}
2573

2574
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_xreaddirplus_get_object, 3.11.0)
2575
struct glfs_object *
2576
pub_glfs_xreaddirplus_get_object(struct glfs_xreaddirp_stat *xstat)
2577
{
2578
    GF_VALIDATE_OR_GOTO("glfs_xreaddirplus_get_object", xstat, out);
2579

2580
    if (!(xstat->flags_handled & GFAPI_XREADDIRP_HANDLE))
2581
        gf_smsg(THIS->name, GF_LOG_ERROR, errno, API_MSG_HANDLE_NOT_SET,
2582
                "GFAPI_XREADDIRP_HANDLE xstat=%p", xstat, "handle=%x",
2583
                xstat->flags_handled, NULL);
2584

2585
    return xstat->object;
2586

2587
out:
2588
    return NULL;
2589
}
2590

2591
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_lease, 4.0.0)
2592
int
2593
pub_glfs_h_lease(struct glfs *fs, struct glfs_object *object,
2594
                 struct glfs_lease *lease)
2595
{
2596
    int ret = -1;
2597
    xlator_t *subvol = NULL;
2598
    inode_t *inode = NULL;
2599
    loc_t loc = {
2600
        0,
2601
    };
2602
    struct gf_lease gf_lease = {
2603
        0,
2604
    };
2605

2606
    /* validate in args */
2607
    if ((fs == NULL) || (object == NULL)) {
2608
        errno = EINVAL;
2609
        return -1;
2610
    }
2611

2612
    DECLARE_OLD_THIS;
2613
    __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
2614

2615
    /* get the active volume */
2616
    subvol = glfs_active_subvol(fs);
2617
    if (!subvol) {
2618
        ret = -1;
2619
        errno = EIO;
2620
        goto out;
2621
    }
2622

2623
    /* get/refresh the in arg objects inode in correlation to the xlator */
2624
    inode = glfs_resolve_inode(fs, subvol, object);
2625
    if (!inode) {
2626
        errno = ESTALE;
2627
        goto out;
2628
    }
2629

2630
    /* populate loc */
2631
    GLFS_LOC_FILL_INODE(inode, loc, out);
2632

2633
    glfs_lease_to_gf_lease(lease, &gf_lease);
2634

2635
    ret = syncop_lease(subvol, &loc, &gf_lease, NULL, NULL);
2636
    DECODE_SYNCOP_ERR(ret);
2637

2638
    gf_lease_to_glfs_lease(&gf_lease, lease);
2639

2640
out:
2641
    loc_wipe(&loc);
2642

2643
    if (inode)
2644
        inode_unref(inode);
2645

2646
    glfs_subvol_done(fs, subvol);
2647

2648
    __GLFS_EXIT_FS;
2649

2650
invalid_fs:
2651
    return ret;
2652
}
2653

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.