summaryrefslogtreecommitdiffstats
path: root/xlators/features/upcall/src/upcall.h
blob: bcaf6b010864c55f42e2445d3cf1dfbed20d1990 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
   Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com>
   This file is part of GlusterFS.

   This file is licensed to you under your choice of the GNU Lesser
   General Public License, version 3 or any later version (LGPLv3 or
   later), or the GNU General Public License, version 2 (GPLv2), in all
   cases as published by the Free Software Foundation.
*/
#ifndef __UPCALL_H__
#define __UPCALL_H__

#include <glusterfs/compat-errno.h>
#include "upcall-mem-types.h"
#include <glusterfs/client_t.h>
#include "upcall-messages.h"
#include "upcall-cache-invalidation.h"
#include <glusterfs/upcall-utils.h>

#define EXIT_IF_UPCALL_OFF(this, label)                                        \
    do {                                                                       \
        if (!is_upcall_enabled(this))                                          \
            goto label;                                                        \
    } while (0)

#define UPCALL_STACK_UNWIND(fop, frame, params...)                             \
    do {                                                                       \
        upcall_local_t *__local = NULL;                                        \
        xlator_t *__xl = NULL;                                                 \
        if (frame) {                                                           \
            __xl = frame->this;                                                \
            __local = frame->local;                                            \
            frame->local = NULL;                                               \
        }                                                                      \
        STACK_UNWIND_STRICT(fop, frame, params);                               \
        upcall_local_wipe(__xl, __local);                                      \
    } while (0)

#define UPCALL_STACK_DESTROY(frame)                                            \
    do {                                                                       \
        upcall_local_t *__local = NULL;                                        \
        xlator_t *__xl = NULL;                                                 \
        __xl = frame->this;                                                    \
        __local = frame->local;                                                \
        frame->local = NULL;                                                   \
        STACK_DESTROY(frame->root);                                            \
        upcall_local_wipe(__xl, __local);                                      \
    } while (0)

struct _upcall_private {
    gf_boolean_t cache_invalidation_enabled;
    int32_t cache_invalidation_timeout;
    struct list_head inode_ctx_list;
    gf_lock_t inode_ctx_lk;
    gf_boolean_t reaper_init_done;
    pthread_t reaper_thr;
    int32_t fini;
    dict_t *xattrs; /* list of xattrs registered by clients
                       for receiving invalidation */
};
typedef struct _upcall_private upcall_private_t;

struct _upcall_client {
    struct list_head client_list;
    /* strdup to store client_uid, strdup. Free it explicitly */
    char *client_uid;
    time_t access_time; /* time last accessed */
    /* the amount of time which client can cache this entry */
    uint32_t expire_time_attr;
};
typedef struct _upcall_client upcall_client_t;

/* Upcall entries are maintained in inode_ctx */
struct _upcall_inode_ctx {
    struct list_head inode_ctx_list;
    struct list_head client_list;
    pthread_mutex_t client_list_lock; /* mutex for clients list
                                         of this upcall entry */
    int destroy;
    uuid_t gfid; /* gfid of the entry */
};
typedef struct _upcall_inode_ctx upcall_inode_ctx_t;

struct upcall_local {
    /* XXX: need to check if we can store
     * pointers in 'local' which may get freed
     * in future by other thread
     */
    inode_t *inode;
    loc_t rename_oldloc;
    loc_t loc; /* required for stat in *xattr_cbk */
    fd_t *fd;  /* required for fstat in *xattr_cbk */
    dict_t *xattr;
};
typedef struct upcall_local upcall_local_t;

void
upcall_local_wipe(xlator_t *this, upcall_local_t *local);
upcall_local_t *
upcall_local_init(call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd,
                  inode_t *inode, dict_t *xattr);

upcall_client_t *
add_upcall_client(call_frame_t *frame, client_t *client,
                  upcall_inode_ctx_t *up_inode_ctx);
upcall_client_t *
__add_upcall_client(call_frame_t *frame, client_t *client,
                    upcall_inode_ctx_t *up_inode_ctx);
upcall_client_t *
__get_upcall_client(call_frame_t *frame, client_t *client,
                    upcall_inode_ctx_t *up_inode_ctx);
int
__upcall_cleanup_client_entry(upcall_client_t *up_client);
int
upcall_cleanup_expired_clients(xlator_t *this,
                               upcall_inode_ctx_t *up_inode_ctx);

int
__upcall_inode_ctx_set(inode_t *inode, xlator_t *this);
upcall_inode_ctx_t *
__upcall_inode_ctx_get(inode_t *inode, xlator_t *this);
upcall_inode_ctx_t *
upcall_inode_ctx_get(inode_t *inode, xlator_t *this);
int
upcall_cleanup_inode_ctx(xlator_t *this, inode_t *inode);
void
upcall_cache_forget(xlator_t *this, inode_t *inode,
                    upcall_inode_ctx_t *up_inode_ctx);

void *
upcall_reaper_thread(void *data);
int
upcall_reaper_thread_init(xlator_t *this);

/* Xlator options */
gf_boolean_t
is_upcall_enabled(xlator_t *this);

/* Cache invalidation specific */
void
upcall_cache_invalidate(call_frame_t *frame, xlator_t *this, client_t *client,
                        inode_t *inode, uint32_t flags, struct iatt *stbuf,
                        struct iatt *p_stbuf, struct iatt *oldp_stbuf,
                        dict_t *xattr);
void
upcall_client_cache_invalidate(xlator_t *xl, uuid_t gfid,
                               upcall_client_t *up_client_entry, uint32_t flags,
                               struct iatt *stbuf, struct iatt *p_stbuf,
                               struct iatt *oldp_stbuf, dict_t *xattr);

int
up_filter_xattr(dict_t *xattr, dict_t *regd_xattrs);

int
up_compare_afr_xattr(dict_t *d, char *k, data_t *v, void *tmp);

gf_boolean_t
up_invalidate_needed(dict_t *xattrs);
#endif /* __UPCALL_H__ */