summaryrefslogtreecommitdiffstats
path: root/xlators/nfs/server/src/nfs3.h
blob: f6d98d9f308d53d02044f8f7db1e2d01f79d941a (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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
/*
  Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.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 _NFS3_H_
#define _NFS3_H_

#include "rpcsvc.h"
#include "dict.h"
#include "xlator.h"
#include "iobuf.h"
#include "nfs.h"
#include "nfs3-fh.h"
#include "nfs-common.h"
#include "xdr-nfs3.h"
#include "mem-pool.h"
#include "nlm4.h"
#include "acl3-xdr.h"
#include "acl3.h"
#include "refcount.h"
#include <sys/statvfs.h>

#define GF_NFS3 GF_NFS "-nfsv3"

#define GF_NFS3_DEFAULT_MEMFACTOR 15
#define GF_NFS3_IOBPOOL_MULT GF_NFS_CONCURRENT_OPS_MULT
#define GF_NFS3_CLTABLE_BUCKETS_MULT 2
#define GF_NFS3_FDTABLE_BUCKETS_MULT 2

/* Static values used for FSINFO
 * To change the maximum rsize and wsize supported by the NFS client, adjust
 * GF_NFS3_FILE_IO_SIZE_MAX. The Gluster NFS server defaults to 1MB(1048576)
 * (same as kernel NFS server). For slower network, rsize/wsize can be trimmed
 * to 16/32/64-KB. rsize and wsize can be tuned through nfs.read-size and
 * nfs.write-size respectively.
 *
 * NB: For Kernel-NFS, NFS_MAX_FILE_IO_SIZE is 1048576U (1MB).
 */
#define GF_NFS3_FILE_IO_SIZE_MAX (1 * GF_UNIT_MB) /* 1048576 */
#define GF_NFS3_FILE_IO_SIZE_MIN (4 * GF_UNIT_KB) /* 4096 */

#define GF_NFS3_FILE_IO_SIZE_DEF GF_NFS3_FILE_IO_SIZE_MAX

#define GF_NFS3_RTMAX GF_NFS3_FILE_IO_SIZE_MAX
#define GF_NFS3_RTMIN GF_NFS3_FILE_IO_SIZE_MIN
#define GF_NFS3_RTPREF GF_NFS3_FILE_IO_SIZE_DEF
#define GF_NFS3_RTMULT GF_NFS3_FILE_IO_SIZE_MIN

#define GF_NFS3_WTMAX GF_NFS3_FILE_IO_SIZE_MAX
#define GF_NFS3_WTMIN GF_NFS3_FILE_IO_SIZE_MIN
#define GF_NFS3_WTPREF GF_NFS3_FILE_IO_SIZE_DEF
#define GF_NFS3_WTMULT GF_NFS3_FILE_IO_SIZE_MIN

/* This can be tuned through nfs.readdir-size */
#define GF_NFS3_DTMAX GF_NFS3_FILE_IO_SIZE_MAX
#define GF_NFS3_DTMIN GF_NFS3_FILE_IO_SIZE_MIN
#define GF_NFS3_DTPREF GF_NFS3_FILE_IO_SIZE_DEF

#define GF_NFS3_MAXFILESIZE (1 * GF_UNIT_PB)

#define GF_NFS3_IO_SIZE 4096 /* 4-KB */
#define GF_NFS3_IO_SHIFT 12  /* 2^12 = 4KB */

/* FIXME: Handle time resolutions */
#define GF_NFS3_TIMEDELTA_SECS                                                 \
    {                                                                          \
        1, 0                                                                   \
    }
#define GF_NFS3_TIMEDELTA_NSECS                                                \
    {                                                                          \
        0, 1                                                                   \
    }
#define GF_NFS3_TIMEDELTA_MSECS                                                \
    {                                                                          \
        0, 1000000                                                             \
    }

#define GF_NFS3_FS_PROP                                                        \
    (FSF3_LINK | FSF3_SYMLINK | FSF3_HOMOGENEOUS | FSF3_CANSETTIME)

#define GF_NFS3_DIRFD_VALID 1
#define GF_NFS3_DIRFD_INVALID 0

#define GF_NFS3_VOLACCESS_RW 1
#define GF_NFS3_VOLACCESS_RO 2

#define GF_NFS3_FDCACHE_SIZE 512
/* This should probably be moved to a more generic layer so that if needed
 * different versions of NFS protocol can use the same thing.
 */
struct nfs3_fd_entry {
    fd_t *cachedfd;
    struct list_head list;
};

/* Per subvolume nfs3 specific state */
struct nfs3_export {
    struct list_head explist;
    xlator_t *subvol;
    uuid_t volumeid;
    int access;
    int trusted_sync;
    int trusted_write;
    int rootlookedup;
};

#define GF_NFS3_DEFAULT_VOLACCESS (GF_NFS3_VOLACCESS_RW)

/* The NFSv3 protocol state */
typedef struct nfs3_state {
    /* The NFS xlator pointer. The NFS xlator can be running
     * multiple versions of the NFS protocol.
     */
    xlator_t *nfsx;

    /* The iob pool from which memory allocations are made for receiving
     * and sending network messages.
     */
    struct iobuf_pool *iobpool;

    /* List of child subvolumes for the NFSv3 protocol.
     * Right now, is simply referring to the list of children in nfsx above.
     */
    xlator_list_t *exportslist;

    struct list_head exports;
    /* Mempool for allocations of struct nfs3_local */
    struct mem_pool *localpool;

    /* Server start-up timestamp, currently used for write verifier. */
    uint64_t serverstart;

    /* NFSv3 Protocol configurables */
    uint64_t readsize;
    uint64_t writesize;
    uint64_t readdirsize;

    /* Size of the iobufs used, depends on the sizes of the three params
     * above.
     */
    uint64_t iobsize;

    struct list_head fdlru;
    gf_lock_t fdlrulock;
    int fdcount;
    uint32_t occ_logger;
} nfs3_state_t;

typedef enum nfs3_lookup_type {
    GF_NFS3_REVALIDATE = 1,
    GF_NFS3_FRESH,
} nfs3_lookup_type_t;

typedef union args_ {
    nlm4_stat nlm4_stat;
    nlm4_holder nlm4_holder;
    nlm4_lock nlm4_lock;
    nlm4_share nlm4_share;
    nlm4_testrply nlm4_testrply;
    nlm4_testres nlm4_testres;
    nlm4_testargs nlm4_testargs;
    nlm4_res nlm4_res;
    nlm4_lockargs nlm4_lockargs;
    nlm4_cancargs nlm4_cancargs;
    nlm4_unlockargs nlm4_unlockargs;
    nlm4_shareargs nlm4_shareargs;
    nlm4_shareres nlm4_shareres;
    nlm4_freeallargs nlm4_freeallargs;
    getaclargs getaclargs;
    setaclargs setaclargs;
    getaclreply getaclreply;
    setaclreply setaclreply;
} args;

typedef int (*nfs3_resume_fn_t)(void *cs);
/* Structure used to communicate state between a fop and its callback.
 * Not all members are used at all times. Usage is fop and NFS request
 * dependent.
 *
 * I wish we could have a smaller structure for communicating state
 * between callers and callbacks. It could be broken into smaller parts
 * but I feel that will lead to a proliferation of types/structures and then
 * we'll just be tracking down which structure is used by which fop, not
 * to mention that having one type allows me to used a single mem-pool.
 * Imagine the chaos if we need a mem-pool for each one of those sub-structures.
 */
struct nfs3_local {
    GF_REF_DECL;

    rpcsvc_request_t *req;
    xlator_t *vol;
    nfs3_resume_fn_t resume_fn;
    xlator_t *nfsx;
    struct nfs3_state *nfs3state;

    /* The list hook to attach this call state to the inode's queue till
     * the opening of the fd on the inode completes.
     */
    struct list_head openwait_q;

    /* Per-NFSv3 Op state */
    struct nfs3_fh parent;
    struct nfs3_fh fh;
    fd_t *fd;
    uint32_t accessbits;
    int operrno;
    count3 dircount;
    count3 maxcount;
    struct statvfs fsstat;
    gf_dirent_t entries;
    struct iatt stbuf;
    struct iatt preparent;
    struct iatt postparent;
    int32_t setattr_valid;
    nfstime3 timestamp;
    loc_t oploc;
    int writetype;
    count3 datacount;
    offset3 dataoffset;
    struct iobuf *iob;
    struct iobref *iobref;
    createmode3 createmode;
    uint64_t cookieverf;
    int sattrguardcheck;
    char *pathname;
    ftype3 mknodtype;
    specdata3 devnums;
    cookie3 cookie;
    struct iovec datavec;
    mode_t mode;
    struct iatt attr_in;

    /* NFSv3 FH resolver state */
    int hardresolved;
    struct nfs3_fh resolvefh;
    loc_t resolvedloc;
    int resolve_ret;
    int resolve_errno;
    int hashidx;
    fd_t *resolve_dir_fd;
    char *resolventry;
    nfs3_lookup_type_t lookuptype;
    gf_dirent_t *hashmatch;
    gf_dirent_t *entrymatch;
    off_t lastentryoffset;
    struct flock flock;
    args args;
    nlm4_lkowner_t lkowner;
    char cookiebytes[1024];
    struct nfs3_fh lockfh;
    int monitor;
    rpc_transport_t *trans;
    call_frame_t *frame;

    /* ACL */
    aclentry aclentry[NFS_ACL_MAX_ENTRIES];
    aclentry daclentry[NFS_ACL_MAX_ENTRIES];
    int aclcount;
    char aclxattr[NFS_ACL_MAX_ENTRIES * 8 + 4];
    int daclcount;
    char daclxattr[NFS_ACL_MAX_ENTRIES * 8 + 4];
};

#define nfs3_is_revalidate_lookup(cst) ((cst)->lookuptype == GF_NFS3_REVALIDATE)
#define nfs3_lookup_op(cst) (rpcsvc_request_procnum(cst->req) == NFS3_LOOKUP)
#define nfs3_create_op(cst) (rpcsvc_request_procnum(cst->req) == NFS3_CREATE)
#define nfs3_create_exclusive_op(cst) ((cst)->createmode == EXCLUSIVE)

typedef struct nfs3_local nfs3_call_state_t;

/* Queue of ops waiting for open fop to return. */
struct inode_op_queue {
    struct list_head opq;
    pthread_mutex_t qlock;
};

extern rpcsvc_program_t *
nfs3svc_init(xlator_t *nfsx);

extern int
nfs3_reconfigure_state(xlator_t *nfsx, dict_t *options);

extern uint64_t
nfs3_request_xlator_deviceid(rpcsvc_request_t *req);

#endif